Commit 7dfc0fbe by Bernd Schmidt Committed by Bernd Schmidt

While building global lifetime information, keep track of which registers are…

While building global lifetime information, keep track of which registers are only conditionally set.

While building global lifetime information, keep track of which registers are
only conditionally set.  Use this to force rescans in more cases where they
are needed.

From-SVN: r37801
parent 5f6fa212
2000-11-27 Bernd Schmidt <bernds@redhat.co.uk>
* flow.c (entry_exit_blocks): Add entry for cond_local_set.
(struct propagate_block_info): Add new member cond_local_set.
(propagate_block): Accept new arg cond_local_set. All callers
changed.
(init_propagate_block_info): Likewise.
(calculate_global_regs_live): Allocate & free cond_local_set. Always
rescan if there's overlap between cond_local_set and new_live_at_end.
(mark_set_1): Set bits either in cond_local_set or local_set, as
appropriate.
* basic-block.h (struct basic_block_def): New field cond_local_set.
(propagate_block, init_propagate_block_info): Update prototypes.
Mon Nov 27 17:29:44 2000 kaz Kojima <kkojima@rr.iij4u.or.jp> Mon Nov 27 17:29:44 2000 kaz Kojima <kkojima@rr.iij4u.or.jp>
* gcc/config/sh/sh.md (udivsi3_i4, udivsi3_i4_single): Clobber * gcc/config/sh/sh.md (udivsi3_i4, udivsi3_i4_single): Clobber
......
...@@ -165,6 +165,7 @@ typedef struct basic_block_def { ...@@ -165,6 +165,7 @@ typedef struct basic_block_def {
not reflect the use of regs in phi functions, since the liveness not reflect the use of regs in phi functions, since the liveness
of these regs may depend on which edge was taken into the block. */ of these regs may depend on which edge was taken into the block. */
regset local_set; regset local_set;
regset cond_local_set;
regset global_live_at_start; regset global_live_at_start;
regset global_live_at_end; regset global_live_at_end;
...@@ -489,12 +490,13 @@ extern void life_analysis PARAMS ((rtx, FILE *, int)); ...@@ -489,12 +490,13 @@ extern void life_analysis PARAMS ((rtx, FILE *, int));
extern void update_life_info PARAMS ((sbitmap, enum update_life_extent, extern void update_life_info PARAMS ((sbitmap, enum update_life_extent,
int)); int));
extern int count_or_remove_death_notes PARAMS ((sbitmap, int)); extern int count_or_remove_death_notes PARAMS ((sbitmap, int));
extern void propagate_block PARAMS ((basic_block, regset, regset, int)); extern void propagate_block PARAMS ((basic_block, regset, regset, regset,
int));
struct propagate_block_info; struct propagate_block_info;
extern rtx propagate_one_insn PARAMS ((struct propagate_block_info *, rtx)); extern rtx propagate_one_insn PARAMS ((struct propagate_block_info *, rtx));
extern struct propagate_block_info *init_propagate_block_info extern struct propagate_block_info *init_propagate_block_info
PARAMS ((basic_block, regset, regset, int)); PARAMS ((basic_block, regset, regset, regset, int));
extern void free_propagate_block_info PARAMS ((struct propagate_block_info *)); extern void free_propagate_block_info PARAMS ((struct propagate_block_info *));
/* In lcm.c */ /* In lcm.c */
......
...@@ -193,6 +193,7 @@ struct basic_block_def entry_exit_blocks[2] ...@@ -193,6 +193,7 @@ struct basic_block_def entry_exit_blocks[2]
NULL, /* pred */ NULL, /* pred */
NULL, /* succ */ NULL, /* succ */
NULL, /* local_set */ NULL, /* local_set */
NULL, /* cond_local_set */
NULL, /* global_live_at_start */ NULL, /* global_live_at_start */
NULL, /* global_live_at_end */ NULL, /* global_live_at_end */
NULL, /* aux */ NULL, /* aux */
...@@ -207,6 +208,7 @@ struct basic_block_def entry_exit_blocks[2] ...@@ -207,6 +208,7 @@ struct basic_block_def entry_exit_blocks[2]
NULL, /* pred */ NULL, /* pred */
NULL, /* succ */ NULL, /* succ */
NULL, /* local_set */ NULL, /* local_set */
NULL, /* cond_local_set */
NULL, /* global_live_at_start */ NULL, /* global_live_at_start */
NULL, /* global_live_at_end */ NULL, /* global_live_at_end */
NULL, /* aux */ NULL, /* aux */
...@@ -293,9 +295,14 @@ struct propagate_block_info ...@@ -293,9 +295,14 @@ struct propagate_block_info
elimination. */ elimination. */
rtx mem_set_list; rtx mem_set_list;
/* If non-null, record the set of registers set in the basic block. */ /* If non-null, record the set of registers set unconditionally in the
basic block. */
regset local_set; regset local_set;
/* If non-null, record the set of registers set conditionally in the
basic block. */
regset cond_local_set;
#ifdef HAVE_conditional_execution #ifdef HAVE_conditional_execution
/* Indexed by register number, holds a reg_cond_life_info for each /* Indexed by register number, holds a reg_cond_life_info for each
register that is not unconditionally live or dead. */ register that is not unconditionally live or dead. */
...@@ -1544,7 +1551,7 @@ split_block (bb, insn) ...@@ -1544,7 +1551,7 @@ split_block (bb, insn)
at the end of the original basic block and get at the end of the original basic block and get
propagate_block to determine which registers are live. */ propagate_block to determine which registers are live. */
COPY_REG_SET (new_bb->global_live_at_start, bb->global_live_at_end); COPY_REG_SET (new_bb->global_live_at_start, bb->global_live_at_end);
propagate_block (new_bb, new_bb->global_live_at_start, NULL, 0); propagate_block (new_bb, new_bb->global_live_at_start, NULL, NULL, 0);
COPY_REG_SET (bb->global_live_at_end, COPY_REG_SET (bb->global_live_at_end,
new_bb->global_live_at_start); new_bb->global_live_at_start);
} }
...@@ -2966,7 +2973,7 @@ update_life_info (blocks, extent, prop_flags) ...@@ -2966,7 +2973,7 @@ update_life_info (blocks, extent, prop_flags)
basic_block bb = BASIC_BLOCK (i); basic_block bb = BASIC_BLOCK (i);
COPY_REG_SET (tmp, bb->global_live_at_end); COPY_REG_SET (tmp, bb->global_live_at_end);
propagate_block (bb, tmp, (regset) NULL, prop_flags); propagate_block (bb, tmp, NULL, NULL, prop_flags);
if (extent == UPDATE_LIFE_LOCAL) if (extent == UPDATE_LIFE_LOCAL)
verify_local_live_at_start (tmp, bb); verify_local_live_at_start (tmp, bb);
...@@ -2979,7 +2986,7 @@ update_life_info (blocks, extent, prop_flags) ...@@ -2979,7 +2986,7 @@ update_life_info (blocks, extent, prop_flags)
basic_block bb = BASIC_BLOCK (i); basic_block bb = BASIC_BLOCK (i);
COPY_REG_SET (tmp, bb->global_live_at_end); COPY_REG_SET (tmp, bb->global_live_at_end);
propagate_block (bb, tmp, (regset) NULL, prop_flags); propagate_block (bb, tmp, NULL, NULL, prop_flags);
if (extent == UPDATE_LIFE_LOCAL) if (extent == UPDATE_LIFE_LOCAL)
verify_local_live_at_start (tmp, bb); verify_local_live_at_start (tmp, bb);
...@@ -3378,6 +3385,7 @@ calculate_global_regs_live (blocks_in, blocks_out, flags) ...@@ -3378,6 +3385,7 @@ calculate_global_regs_live (blocks_in, blocks_out, flags)
if (bb->local_set == NULL) if (bb->local_set == NULL)
{ {
bb->local_set = OBSTACK_ALLOC_REG_SET (&flow_obstack); bb->local_set = OBSTACK_ALLOC_REG_SET (&flow_obstack);
bb->cond_local_set = OBSTACK_ALLOC_REG_SET (&flow_obstack);
rescan = 1; rescan = 1;
} }
else else
...@@ -3392,6 +3400,20 @@ calculate_global_regs_live (blocks_in, blocks_out, flags) ...@@ -3392,6 +3400,20 @@ calculate_global_regs_live (blocks_in, blocks_out, flags)
if (! rescan) if (! rescan)
{ {
/* If any of the registers in the new live_at_end set are
conditionally set in this basic block, we must rescan.
This is because conditional lifetimes at the end of the
block do not just take the live_at_end set into account,
but also the liveness at the start of each successor
block. We can miss changes in those sets if we only
compare the new live_at_end against the previous one. */
CLEAR_REG_SET (tmp);
rescan = bitmap_operation (tmp, new_live_at_end,
bb->cond_local_set, BITMAP_AND);
}
if (! rescan)
{
/* Find the set of changed bits. Take this opportunity /* Find the set of changed bits. Take this opportunity
to notice that this set is empty and early out. */ to notice that this set is empty and early out. */
CLEAR_REG_SET (tmp); CLEAR_REG_SET (tmp);
...@@ -3434,7 +3456,8 @@ calculate_global_regs_live (blocks_in, blocks_out, flags) ...@@ -3434,7 +3456,8 @@ calculate_global_regs_live (blocks_in, blocks_out, flags)
/* Rescan the block insn by insn to turn (a copy of) live_at_end /* Rescan the block insn by insn to turn (a copy of) live_at_end
into live_at_start. */ into live_at_start. */
propagate_block (bb, new_live_at_end, bb->local_set, flags); propagate_block (bb, new_live_at_end, bb->local_set,
bb->cond_local_set, flags);
/* If live_at start didn't change, no need to go farther. */ /* If live_at start didn't change, no need to go farther. */
if (REG_SET_EQUAL_P (bb->global_live_at_start, new_live_at_end)) if (REG_SET_EQUAL_P (bb->global_live_at_start, new_live_at_end))
...@@ -3467,6 +3490,7 @@ calculate_global_regs_live (blocks_in, blocks_out, flags) ...@@ -3467,6 +3490,7 @@ calculate_global_regs_live (blocks_in, blocks_out, flags)
{ {
basic_block bb = BASIC_BLOCK (i); basic_block bb = BASIC_BLOCK (i);
FREE_REG_SET (bb->local_set); FREE_REG_SET (bb->local_set);
FREE_REG_SET (bb->cond_local_set);
}); });
} }
else else
...@@ -3475,6 +3499,7 @@ calculate_global_regs_live (blocks_in, blocks_out, flags) ...@@ -3475,6 +3499,7 @@ calculate_global_regs_live (blocks_in, blocks_out, flags)
{ {
basic_block bb = BASIC_BLOCK (i); basic_block bb = BASIC_BLOCK (i);
FREE_REG_SET (bb->local_set); FREE_REG_SET (bb->local_set);
FREE_REG_SET (bb->cond_local_set);
} }
} }
...@@ -3811,10 +3836,9 @@ propagate_one_insn (pbi, insn) ...@@ -3811,10 +3836,9 @@ propagate_one_insn (pbi, insn)
the user can use the regsets provided here. */ the user can use the regsets provided here. */
struct propagate_block_info * struct propagate_block_info *
init_propagate_block_info (bb, live, local_set, flags) init_propagate_block_info (bb, live, local_set, cond_local_set, flags)
basic_block bb; basic_block bb;
regset live; regset live, local_set, cond_local_set;
regset local_set;
int flags; int flags;
{ {
struct propagate_block_info *pbi = xmalloc (sizeof (*pbi)); struct propagate_block_info *pbi = xmalloc (sizeof (*pbi));
...@@ -3823,6 +3847,7 @@ init_propagate_block_info (bb, live, local_set, flags) ...@@ -3823,6 +3847,7 @@ init_propagate_block_info (bb, live, local_set, flags)
pbi->reg_live = live; pbi->reg_live = live;
pbi->mem_set_list = NULL_RTX; pbi->mem_set_list = NULL_RTX;
pbi->local_set = local_set; pbi->local_set = local_set;
pbi->cond_local_set = cond_local_set;
pbi->cc0_live = 0; pbi->cc0_live = 0;
pbi->flags = flags; pbi->flags = flags;
...@@ -4000,20 +4025,28 @@ free_propagate_block_info (pbi) ...@@ -4000,20 +4025,28 @@ free_propagate_block_info (pbi)
When called, REG_LIVE contains those live at the end. On return, it When called, REG_LIVE contains those live at the end. On return, it
contains those live at the beginning. contains those live at the beginning.
LOCAL_SET, if non-null, will be set with all registers killed by LOCAL_SET, if non-null, will be set with all registers killed
this basic block. */ unconditionally by this basic block.
Likewise, COND_LOCAL_SET, if non-null, will be set with all registers
killed conditionally by this basic block. If there is any unconditional
set of a register, then the corresponding bit will be set in LOCAL_SET
and cleared in COND_LOCAL_SET.
It is valid for LOCAL_SET and COND_LOCAL_SET to be the same set. In this
case, the resulting set will be equal to the union of the two sets that
would otherwise be computed. */
void void
propagate_block (bb, live, local_set, flags) propagate_block (bb, live, local_set, cond_local_set, flags)
basic_block bb; basic_block bb;
regset live; regset live;
regset local_set; regset local_set;
regset cond_local_set;
int flags; int flags;
{ {
struct propagate_block_info *pbi; struct propagate_block_info *pbi;
rtx insn, prev; rtx insn, prev;
pbi = init_propagate_block_info (bb, live, local_set, flags); pbi = init_propagate_block_info (bb, live, local_set, cond_local_set, flags);
if (flags & PROP_REG_INFO) if (flags & PROP_REG_INFO)
{ {
...@@ -4635,7 +4668,16 @@ mark_set_1 (pbi, code, reg, cond, insn, flags) ...@@ -4635,7 +4668,16 @@ mark_set_1 (pbi, code, reg, cond, insn, flags)
{ {
int needed_regno = REGNO_REG_SET_P (pbi->reg_live, i); int needed_regno = REGNO_REG_SET_P (pbi->reg_live, i);
if (pbi->local_set) if (pbi->local_set)
SET_REGNO_REG_SET (pbi->local_set, i); {
/* Order of the set operation matters here since both
sets may be the same. */
CLEAR_REGNO_REG_SET (pbi->cond_local_set, i);
if (cond != NULL_RTX
&& ! REGNO_REG_SET_P (pbi->local_set, i))
SET_REGNO_REG_SET (pbi->cond_local_set, i);
else
SET_REGNO_REG_SET (pbi->local_set, i);
}
if (code != CLOBBER) if (code != CLOBBER)
SET_REGNO_REG_SET (pbi->new_set, i); SET_REGNO_REG_SET (pbi->new_set, i);
......
...@@ -1973,7 +1973,7 @@ dead_or_predicable (test_bb, merge_bb, other_bb, new_dest, reversep) ...@@ -1973,7 +1973,7 @@ dead_or_predicable (test_bb, merge_bb, other_bb, new_dest, reversep)
/* ??? bb->local_set is only valid during calculate_global_regs_live, /* ??? bb->local_set is only valid during calculate_global_regs_live,
so we must recompute usage for MERGE_BB. Not so bad, I suppose, so we must recompute usage for MERGE_BB. Not so bad, I suppose,
since we've already asserted that MERGE_BB is small. */ since we've already asserted that MERGE_BB is small. */
propagate_block (merge_bb, tmp, merge_set, 0); propagate_block (merge_bb, tmp, merge_set, merge_set, 0);
/* For small register class machines, don't lengthen lifetimes of /* For small register class machines, don't lengthen lifetimes of
hard registers before reload. */ hard registers before reload. */
...@@ -1993,7 +1993,8 @@ dead_or_predicable (test_bb, merge_bb, other_bb, new_dest, reversep) ...@@ -1993,7 +1993,8 @@ dead_or_predicable (test_bb, merge_bb, other_bb, new_dest, reversep)
Moreover, we're interested in the insns live from OTHER_BB. */ Moreover, we're interested in the insns live from OTHER_BB. */
COPY_REG_SET (test_live, other_bb->global_live_at_start); COPY_REG_SET (test_live, other_bb->global_live_at_start);
pbi = init_propagate_block_info (test_bb, test_live, test_set, 0); pbi = init_propagate_block_info (test_bb, test_live, test_set, test_set,
0);
for (insn = jump; ; insn = prev) for (insn = jump; ; insn = prev)
{ {
......
...@@ -3053,9 +3053,9 @@ peephole2_optimize (dump_file) ...@@ -3053,9 +3053,9 @@ peephole2_optimize (dump_file)
COPY_REG_SET (peep2_insn_data[MAX_INSNS_PER_PEEP2].live_before, live); COPY_REG_SET (peep2_insn_data[MAX_INSNS_PER_PEEP2].live_before, live);
#ifdef HAVE_conditional_execution #ifdef HAVE_conditional_execution
pbi = init_propagate_block_info (bb, live, NULL, 0); pbi = init_propagate_block_info (bb, live, NULL, NULL, 0);
#else #else
pbi = init_propagate_block_info (bb, live, NULL, PROP_DEATH_NOTES); pbi = init_propagate_block_info (bb, live, NULL, NULL, PROP_DEATH_NOTES);
#endif #endif
for (insn = bb->end; ; insn = prev) for (insn = bb->end; ; insn = prev)
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment