From fcc42bcad4fac328cb9696186c30012e2454c3e2 Mon Sep 17 00:00:00 2001 From: Andreas Krebbel Date: Wed, 13 Sep 2006 10:59:03 +0000 Subject: flow.c (calculate_global_regs_live): Invalidate eh registers on eh edges. 2006-09-13 Andreas Krebbel * flow.c (calculate_global_regs_live): Invalidate eh registers on eh edges. Renamed invalidated_by_call to invalidated_by_eh_edge. (propagate_block): Handle eh registers as if they were set at basic block start. * except.c (dw2_build_landing_pads): Don't emit clobbers for eh registers. * global.c (global_conflicts): Make eh registers to conflict with pseudos live at basic block begin. * basic_block.h (bb_has_eh_pred): New function. From-SVN: r116920 --- gcc/ChangeLog | 12 ++++++++++++ gcc/basic-block.h | 14 ++++++++++++++ gcc/except.c | 26 -------------------------- gcc/flow.c | 43 ++++++++++++++++++++++++++++++++++++++----- gcc/global.c | 15 +++++++++++++++ 5 files changed, 79 insertions(+), 31 deletions(-) diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 0eab63e..63188b8 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,15 @@ +2006-09-13 Andreas Krebbel + + * flow.c (calculate_global_regs_live): Invalidate eh registers + on eh edges. Renamed invalidated_by_call to invalidated_by_eh_edge. + (propagate_block): Handle eh registers as if they were set at basic + block start. + * except.c (dw2_build_landing_pads): Don't emit clobbers for eh + registers. + * global.c (global_conflicts): Make eh registers to conflict with + pseudos live at basic block begin. + * basic_block.h (bb_has_eh_pred): New function. + 2006-09-13 Richard Sandiford PR rtl-optimization/28982 diff --git a/gcc/basic-block.h b/gcc/basic-block.h index bc9f665..a95e5b8 100644 --- a/gcc/basic-block.h +++ b/gcc/basic-block.h @@ -1175,4 +1175,18 @@ extern bool rtx_equiv_p (rtx *, rtx, int, struct equiv_info *); /* In cfgrtl.c */ extern bool condjump_equiv_p (struct equiv_info *, bool); +/* Return true when one of the predecessor edges of BB is marked with FLAGS. */ +static inline bool bb_has_eh_pred (basic_block bb) +{ + edge e; + edge_iterator ei; + + FOR_EACH_EDGE (e, ei, bb->preds) + { + if (e->flags & EDGE_EH) + return true; + } + return false; +} + #endif /* GCC_BASIC_BLOCK_H */ diff --git a/gcc/except.c b/gcc/except.c index 2e65340..b344087 100644 --- a/gcc/except.c +++ b/gcc/except.c @@ -1601,14 +1601,12 @@ static void dw2_build_landing_pads (void) { int i; - unsigned int j; for (i = cfun->eh->last_region_number; i > 0; --i) { struct eh_region *region; rtx seq; basic_block bb; - bool clobbers_hard_regs = false; edge e; region = VEC_index (eh_region, cfun->eh->region_array, i); @@ -1638,30 +1636,6 @@ dw2_build_landing_pads (void) #endif { /* Nothing */ } - /* If the eh_return data registers are call-saved, then we - won't have considered them clobbered from the call that - threw. Kill them now. */ - for (j = 0; ; ++j) - { - unsigned r = EH_RETURN_DATA_REGNO (j); - if (r == INVALID_REGNUM) - break; - if (! call_used_regs[r]) - { - emit_insn (gen_rtx_CLOBBER (VOIDmode, gen_rtx_REG (Pmode, r))); - clobbers_hard_regs = true; - } - } - - if (clobbers_hard_regs) - { - /* @@@ This is a kludge. Not all machine descriptions define a - blockage insn, but we must not allow the code we just generated - to be reordered by scheduling. So emit an ASM_INPUT to act as - blockage insn. */ - emit_insn (gen_rtx_ASM_INPUT (VOIDmode, "")); - } - emit_move_insn (cfun->eh->exc_ptr, gen_rtx_REG (ptr_mode, EH_RETURN_DATA_REGNO (0))); emit_move_insn (cfun->eh->filter, diff --git a/gcc/flow.c b/gcc/flow.c index 47e49f4..2b5d303 100644 --- a/gcc/flow.c +++ b/gcc/flow.c @@ -1040,7 +1040,7 @@ static void calculate_global_regs_live (sbitmap blocks_in, sbitmap blocks_out, int flags) { basic_block *queue, *qhead, *qtail, *qend, bb; - regset tmp, new_live_at_end, invalidated_by_call; + regset tmp, new_live_at_end, invalidated_by_eh_edge; regset registers_made_dead; bool failure_strategy_required = false; int *block_accesses; @@ -1063,13 +1063,24 @@ calculate_global_regs_live (sbitmap blocks_in, sbitmap blocks_out, int flags) tmp = ALLOC_REG_SET (®_obstack); new_live_at_end = ALLOC_REG_SET (®_obstack); - invalidated_by_call = ALLOC_REG_SET (®_obstack); + invalidated_by_eh_edge = ALLOC_REG_SET (®_obstack); registers_made_dead = ALLOC_REG_SET (®_obstack); /* Inconveniently, this is only readily available in hard reg set form. */ for (i = 0; i < FIRST_PSEUDO_REGISTER; ++i) if (TEST_HARD_REG_BIT (regs_invalidated_by_call, i)) - SET_REGNO_REG_SET (invalidated_by_call, i); + SET_REGNO_REG_SET (invalidated_by_eh_edge, i); + + /* The exception handling registers die at eh edges. */ +#ifdef EH_RETURN_DATA_REGNO + for (i = 0; ; ++i) + { + unsigned regno = EH_RETURN_DATA_REGNO (i); + if (regno == INVALID_REGNUM) + break; + SET_REGNO_REG_SET (invalidated_by_eh_edge, regno); + } +#endif /* Allocate space for the sets of local properties. */ local_sets = XCNEWVEC (bitmap, last_basic_block); @@ -1202,7 +1213,7 @@ calculate_global_regs_live (sbitmap blocks_in, sbitmap blocks_out, int flags) if (e->flags & EDGE_EH) bitmap_ior_and_compl_into (new_live_at_end, sb->il.rtl->global_live_at_start, - invalidated_by_call); + invalidated_by_eh_edge); else IOR_REG_SET (new_live_at_end, sb->il.rtl->global_live_at_start); @@ -1422,7 +1433,7 @@ calculate_global_regs_live (sbitmap blocks_in, sbitmap blocks_out, int flags) FREE_REG_SET (tmp); FREE_REG_SET (new_live_at_end); - FREE_REG_SET (invalidated_by_call); + FREE_REG_SET (invalidated_by_eh_edge); FREE_REG_SET (registers_made_dead); if (blocks_out) @@ -2214,6 +2225,28 @@ propagate_block (basic_block bb, regset live, regset local_set, break; } +#ifdef EH_RETURN_DATA_REGNO + if (bb_has_eh_pred (bb)) + { + unsigned int i; + for (i = 0; ; ++i) + { + unsigned regno = EH_RETURN_DATA_REGNO (i); + if (regno == INVALID_REGNUM) + break; + if (pbi->local_set) + { + CLEAR_REGNO_REG_SET (pbi->cond_local_set, regno); + SET_REGNO_REG_SET (pbi->local_set, regno); + } + if (REGNO_REG_SET_P (pbi->reg_live, regno)) + SET_REGNO_REG_SET (pbi->new_set, regno); + + regs_ever_live[regno] = 1; + } + } +#endif + free_propagate_block_info (pbi); return changed; diff --git a/gcc/global.c b/gcc/global.c index 7bc9233..229f862 100644 --- a/gcc/global.c +++ b/gcc/global.c @@ -743,6 +743,21 @@ global_conflicts (void) scan the instruction that makes either X or Y become live. */ record_conflicts (block_start_allocnos, ax); +#ifdef EH_RETURN_DATA_REGNO + if (bb_has_eh_pred (b)) + { + unsigned int i; + + for (i = 0; ; ++i) + { + unsigned int regno = EH_RETURN_DATA_REGNO (i); + if (regno == INVALID_REGNUM) + break; + record_one_conflict (regno); + } + } +#endif + /* Pseudos can't go in stack regs at the start of a basic block that is reached by an abnormal edge. Likewise for call clobbered regs, because caller-save, fixup_abnormal_edges and possibly the table -- cgit v1.1