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
This commit is contained in:
parent
5f6fa21226
commit
7dfc0fbe59
@ -1,3 +1,17 @@
|
||||
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>
|
||||
|
||||
* gcc/config/sh/sh.md (udivsi3_i4, udivsi3_i4_single): Clobber
|
||||
|
@ -165,6 +165,7 @@ typedef struct basic_block_def {
|
||||
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. */
|
||||
regset local_set;
|
||||
regset cond_local_set;
|
||||
regset global_live_at_start;
|
||||
regset global_live_at_end;
|
||||
|
||||
@ -489,12 +490,13 @@ extern void life_analysis PARAMS ((rtx, FILE *, int));
|
||||
extern void update_life_info PARAMS ((sbitmap, enum update_life_extent,
|
||||
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;
|
||||
extern rtx propagate_one_insn PARAMS ((struct propagate_block_info *, rtx));
|
||||
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 *));
|
||||
|
||||
/* In lcm.c */
|
||||
|
68
gcc/flow.c
68
gcc/flow.c
@ -193,6 +193,7 @@ struct basic_block_def entry_exit_blocks[2]
|
||||
NULL, /* pred */
|
||||
NULL, /* succ */
|
||||
NULL, /* local_set */
|
||||
NULL, /* cond_local_set */
|
||||
NULL, /* global_live_at_start */
|
||||
NULL, /* global_live_at_end */
|
||||
NULL, /* aux */
|
||||
@ -207,6 +208,7 @@ struct basic_block_def entry_exit_blocks[2]
|
||||
NULL, /* pred */
|
||||
NULL, /* succ */
|
||||
NULL, /* local_set */
|
||||
NULL, /* cond_local_set */
|
||||
NULL, /* global_live_at_start */
|
||||
NULL, /* global_live_at_end */
|
||||
NULL, /* aux */
|
||||
@ -293,9 +295,14 @@ struct propagate_block_info
|
||||
elimination. */
|
||||
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;
|
||||
|
||||
/* If non-null, record the set of registers set conditionally in the
|
||||
basic block. */
|
||||
regset cond_local_set;
|
||||
|
||||
#ifdef HAVE_conditional_execution
|
||||
/* Indexed by register number, holds a reg_cond_life_info for each
|
||||
register that is not unconditionally live or dead. */
|
||||
@ -1544,7 +1551,7 @@ split_block (bb, insn)
|
||||
at the end of the original basic block and get
|
||||
propagate_block to determine which registers are live. */
|
||||
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,
|
||||
new_bb->global_live_at_start);
|
||||
}
|
||||
@ -2966,7 +2973,7 @@ update_life_info (blocks, extent, prop_flags)
|
||||
basic_block bb = BASIC_BLOCK (i);
|
||||
|
||||
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)
|
||||
verify_local_live_at_start (tmp, bb);
|
||||
@ -2979,7 +2986,7 @@ update_life_info (blocks, extent, prop_flags)
|
||||
basic_block bb = BASIC_BLOCK (i);
|
||||
|
||||
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)
|
||||
verify_local_live_at_start (tmp, bb);
|
||||
@ -3378,6 +3385,7 @@ calculate_global_regs_live (blocks_in, blocks_out, flags)
|
||||
if (bb->local_set == NULL)
|
||||
{
|
||||
bb->local_set = OBSTACK_ALLOC_REG_SET (&flow_obstack);
|
||||
bb->cond_local_set = OBSTACK_ALLOC_REG_SET (&flow_obstack);
|
||||
rescan = 1;
|
||||
}
|
||||
else
|
||||
@ -3390,6 +3398,20 @@ calculate_global_regs_live (blocks_in, blocks_out, flags)
|
||||
rescan = bitmap_operation (tmp, bb->global_live_at_end,
|
||||
new_live_at_end, BITMAP_AND_COMPL);
|
||||
|
||||
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
|
||||
@ -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
|
||||
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 (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)
|
||||
{
|
||||
basic_block bb = BASIC_BLOCK (i);
|
||||
FREE_REG_SET (bb->local_set);
|
||||
FREE_REG_SET (bb->cond_local_set);
|
||||
});
|
||||
}
|
||||
else
|
||||
@ -3475,6 +3499,7 @@ calculate_global_regs_live (blocks_in, blocks_out, flags)
|
||||
{
|
||||
basic_block bb = BASIC_BLOCK (i);
|
||||
FREE_REG_SET (bb->local_set);
|
||||
FREE_REG_SET (bb->cond_local_set);
|
||||
}
|
||||
}
|
||||
|
||||
@ -3811,10 +3836,9 @@ propagate_one_insn (pbi, insn)
|
||||
the user can use the regsets provided here. */
|
||||
|
||||
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;
|
||||
regset live;
|
||||
regset local_set;
|
||||
regset live, local_set, cond_local_set;
|
||||
int flags;
|
||||
{
|
||||
struct propagate_block_info *pbi = xmalloc (sizeof (*pbi));
|
||||
@ -3823,6 +3847,7 @@ init_propagate_block_info (bb, live, local_set, flags)
|
||||
pbi->reg_live = live;
|
||||
pbi->mem_set_list = NULL_RTX;
|
||||
pbi->local_set = local_set;
|
||||
pbi->cond_local_set = cond_local_set;
|
||||
pbi->cc0_live = 0;
|
||||
pbi->flags = flags;
|
||||
|
||||
@ -4000,20 +4025,28 @@ free_propagate_block_info (pbi)
|
||||
When called, REG_LIVE contains those live at the end. On return, it
|
||||
contains those live at the beginning.
|
||||
|
||||
LOCAL_SET, if non-null, will be set with all registers killed by
|
||||
this basic block. */
|
||||
LOCAL_SET, if non-null, will be set with all registers killed
|
||||
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
|
||||
propagate_block (bb, live, local_set, flags)
|
||||
propagate_block (bb, live, local_set, cond_local_set, flags)
|
||||
basic_block bb;
|
||||
regset live;
|
||||
regset local_set;
|
||||
regset cond_local_set;
|
||||
int flags;
|
||||
{
|
||||
struct propagate_block_info *pbi;
|
||||
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)
|
||||
{
|
||||
@ -4635,7 +4668,16 @@ mark_set_1 (pbi, code, reg, cond, insn, flags)
|
||||
{
|
||||
int needed_regno = REGNO_REG_SET_P (pbi->reg_live, i);
|
||||
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)
|
||||
SET_REGNO_REG_SET (pbi->new_set, i);
|
||||
|
||||
|
@ -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,
|
||||
so we must recompute usage for MERGE_BB. Not so bad, I suppose,
|
||||
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
|
||||
hard registers before reload. */
|
||||
@ -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. */
|
||||
|
||||
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)
|
||||
{
|
||||
|
@ -3053,9 +3053,9 @@ peephole2_optimize (dump_file)
|
||||
COPY_REG_SET (peep2_insn_data[MAX_INSNS_PER_PEEP2].live_before, live);
|
||||
|
||||
#ifdef HAVE_conditional_execution
|
||||
pbi = init_propagate_block_info (bb, live, NULL, 0);
|
||||
pbi = init_propagate_block_info (bb, live, NULL, NULL, 0);
|
||||
#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
|
||||
|
||||
for (insn = bb->end; ; insn = prev)
|
||||
|
Loading…
Reference in New Issue
Block a user