Skip to content

Commit

Permalink
2006-09-13 Andreas Krebbel <[email protected]>
Browse files Browse the repository at this point in the history
	* 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.



git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@116920 138bc75d-0d04-0410-961f-82ee72b054a4
  • Loading branch information
krebbel committed Sep 13, 2006
1 parent 23c79c0 commit 467b5d3
Show file tree
Hide file tree
Showing 5 changed files with 79 additions and 31 deletions.
12 changes: 12 additions & 0 deletions gcc/ChangeLog
Original file line number Diff line number Diff line change
@@ -1,3 +1,15 @@
2006-09-13 Andreas Krebbel <[email protected]>

* 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 <[email protected]>

PR rtl-optimization/28982
Expand Down
14 changes: 14 additions & 0 deletions gcc/basic-block.h
Original file line number Diff line number Diff line change
Expand Up @@ -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 */
26 changes: 0 additions & 26 deletions gcc/except.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -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,
Expand Down
43 changes: 38 additions & 5 deletions gcc/flow.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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);
Expand Down Expand Up @@ -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);

Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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;
Expand Down
15 changes: 15 additions & 0 deletions gcc/global.c
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down

0 comments on commit 467b5d3

Please sign in to comment.