From b2bbb6552cd35b778247d4a5fb88d7d55f297f59 Mon Sep 17 00:00:00 2001 From: bernds Date: Mon, 27 Nov 2000 17:50:11 +0000 Subject: [PATCH] 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. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@37801 138bc75d-0d04-0410-961f-82ee72b054a4 --- gcc/ChangeLog | 14 ++++++++++++ gcc/basic-block.h | 6 +++-- gcc/flow.c | 68 ++++++++++++++++++++++++++++++++++++++++++++----------- gcc/ifcvt.c | 5 ++-- gcc/recog.c | 4 ++-- 5 files changed, 78 insertions(+), 19 deletions(-) diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 6412e06c830..1d540a957cf 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 f3ed1a990a3..1f6edf1cb9c 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 28d23cc4175..0a20f4837e5 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 @@ -3392,6 +3400,20 @@ calculate_global_regs_live (blocks_in, blocks_out, flags) 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 to notice that this set is empty and early out. */ CLEAR_REG_SET (tmp); @@ -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 6ad1d35ee82..e4955a74477 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 c01f884ebb4..4257d7c08c0 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) -- 2.11.4.GIT