aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gcc/ChangeLog12
-rw-r--r--gcc/basic-block.h14
-rw-r--r--gcc/except.c26
-rw-r--r--gcc/flow.c43
-rw-r--r--gcc/global.c15
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 <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.
+
2006-09-13 Richard Sandiford <richard@codesourcery.com>
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 (&reg_obstack);
new_live_at_end = ALLOC_REG_SET (&reg_obstack);
- invalidated_by_call = ALLOC_REG_SET (&reg_obstack);
+ invalidated_by_eh_edge = ALLOC_REG_SET (&reg_obstack);
registers_made_dead = ALLOC_REG_SET (&reg_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