This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
Re: [PATCH] Don't emit CLOBBERs for eh registers
Hello,
I've committed the attached patch to mainline after a successful bootstrap
on s390, s390x and i686. No testsuite regressions occured.
Bye,
-Andreas-
2006-09-13 Andreas Krebbel <krebbel1@de.ibm.com>
* 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.
Index: gcc/flow.c
===================================================================
*** gcc/flow.c.orig 2006-09-08 21:14:30.000000000 +0200
--- gcc/flow.c 2006-09-13 09:01:31.000000000 +0200
*************** static void
*** 1040,1046 ****
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 registers_made_dead;
bool failure_strategy_required = false;
int *block_accesses;
--- 1040,1046 ----
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_eh_edge;
regset registers_made_dead;
bool failure_strategy_required = false;
int *block_accesses;
*************** calculate_global_regs_live (sbitmap bloc
*** 1063,1075 ****
tmp = ALLOC_REG_SET (®_obstack);
new_live_at_end = ALLOC_REG_SET (®_obstack);
! invalidated_by_call = 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);
/* Allocate space for the sets of local properties. */
local_sets = XCNEWVEC (bitmap, last_basic_block);
--- 1063,1086 ----
tmp = ALLOC_REG_SET (®_obstack);
new_live_at_end = 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_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);
*************** calculate_global_regs_live (sbitmap bloc
*** 1202,1208 ****
if (e->flags & EDGE_EH)
bitmap_ior_and_compl_into (new_live_at_end,
sb->il.rtl->global_live_at_start,
! invalidated_by_call);
else
IOR_REG_SET (new_live_at_end, sb->il.rtl->global_live_at_start);
--- 1213,1219 ----
if (e->flags & EDGE_EH)
bitmap_ior_and_compl_into (new_live_at_end,
sb->il.rtl->global_live_at_start,
! invalidated_by_eh_edge);
else
IOR_REG_SET (new_live_at_end, sb->il.rtl->global_live_at_start);
*************** calculate_global_regs_live (sbitmap bloc
*** 1422,1428 ****
FREE_REG_SET (tmp);
FREE_REG_SET (new_live_at_end);
! FREE_REG_SET (invalidated_by_call);
FREE_REG_SET (registers_made_dead);
if (blocks_out)
--- 1433,1439 ----
FREE_REG_SET (tmp);
FREE_REG_SET (new_live_at_end);
! FREE_REG_SET (invalidated_by_eh_edge);
FREE_REG_SET (registers_made_dead);
if (blocks_out)
*************** propagate_block (basic_block bb, regset
*** 2214,2219 ****
--- 2225,2252 ----
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;
Index: gcc/except.c
===================================================================
*** gcc/except.c.orig 2006-09-08 21:14:30.000000000 +0200
--- gcc/except.c 2006-09-11 09:50:15.000000000 +0200
*************** static void
*** 1601,1614 ****
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);
--- 1601,1612 ----
*************** dw2_build_landing_pads (void)
*** 1638,1667 ****
#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,
--- 1636,1641 ----
Index: gcc/global.c
===================================================================
*** gcc/global.c.orig 2006-09-08 21:14:30.000000000 +0200
--- gcc/global.c 2006-09-13 09:04:18.000000000 +0200
*************** global_conflicts (void)
*** 743,748 ****
--- 743,763 ----
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
Index: gcc/basic-block.h
===================================================================
*** gcc/basic-block.h.orig 2006-09-08 21:14:30.000000000 +0200
--- gcc/basic-block.h 2006-09-13 08:56:48.000000000 +0200
*************** extern bool rtx_equiv_p (rtx *, rtx, int
*** 1175,1178 ****
--- 1175,1192 ----
/* 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 */