From: Bernd Schmidt Date: Mon, 27 Nov 2000 17:50:11 +0000 (+0000) Subject: While building global lifetime information, keep track of which registers are only... X-Git-Tag: prereleases/libstdc++-2.92~2666 X-Git-Url: https://gcc.gnu.org/git/?a=commitdiff_plain;h=7dfc0fbe59f074e254e6c1b10e2a62158044efd3;p=gcc.git 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 --- diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 6412e06c8309..1d540a957cf3 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,17 @@ +2000-11-27 Bernd Schmidt + + * 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 * gcc/config/sh/sh.md (udivsi3_i4, udivsi3_i4_single): Clobber diff --git a/gcc/basic-block.h b/gcc/basic-block.h index f3ed1a990a3e..1f6edf1cb9cd 100644 --- a/gcc/basic-block.h +++ b/gcc/basic-block.h @@ -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 */ diff --git a/gcc/flow.c b/gcc/flow.c index 28d23cc4175d..0a20f4837e5e 100644 --- a/gcc/flow.c +++ b/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); diff --git a/gcc/ifcvt.c b/gcc/ifcvt.c index 6ad1d35ee824..e4955a74477a 100644 --- a/gcc/ifcvt.c +++ b/gcc/ifcvt.c @@ -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) { diff --git a/gcc/recog.c b/gcc/recog.c index c01f884ebb4f..4257d7c08c05 100644 --- a/gcc/recog.c +++ b/gcc/recog.c @@ -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)