reg-stack.c (compensate_edge): Remove original prototype.

* reg-stack.c (compensate_edge): Remove original prototype.
	(propagate_stack): New function to copy the stack layout
	at the start of a basic block from the layout at the end of
	one of its predecessors.
	(compensate_edge): Assume that both source and destination
	blocks have already had their stack layouts defined.
	(compensate_edges): Traverse all non-entry edges in the CFG
	and call compensate_edge on each in turn.
	(convert_regs_1): Change return type to void.  Call
	propagate_stack instead of compensate_edge.
	(convert_regs_2): Change return type to void.  Update call
	to convert_regs_1 to ignore the (now void) return value.
	(convert_regs): Update calls to convert_regs_2 to ignore
	the (now void) return value.  After all the basic blocks have
	been processed, call compensate_edges to actually emit new
	insns.
	(reg_to_stack): Initialize the aux info for each basic block
	with FOR_EACH_BB instead of which FOR_EACH_BB_REVERSE.

From-SVN: r100283
This commit is contained in:
Roger Sayle 2005-05-27 22:57:39 +00:00 committed by Roger Sayle
parent b59fa6cf91
commit 1c320f82ab
2 changed files with 97 additions and 55 deletions

View File

@ -1,3 +1,24 @@
2005-05-27 Roger Sayle <roger@eyesopen.com>
* reg-stack.c (compensate_edge): Remove original prototype.
(propagate_stack): New function to copy the stack layout
at the start of a basic block from the layout at the end of
one of its predecessors.
(compensate_edge): Assume that both source and destination
blocks have already had their stack layouts defined.
(compensate_edges): Traverse all non-entry edges in the CFG
and call compensate_edge on each in turn.
(convert_regs_1): Change return type to void. Call
propagate_stack instead of compensate_edge.
(convert_regs_2): Change return type to void. Update call
to convert_regs_1 to ignore the (now void) return value.
(convert_regs): Update calls to convert_regs_2 to ignore
the (now void) return value. After all the basic blocks have
been processed, call compensate_edges to actually emit new
insns.
(reg_to_stack): Initialize the aux info for each basic block
with FOR_EACH_BB instead of which FOR_EACH_BB_REVERSE.
2005-05-28 Jan Hubicka <jh@suse.cz> 2005-05-28 Jan Hubicka <jh@suse.cz>
* except.c (can_throw_internal_1, can_throw_external_1): Add * except.c (can_throw_internal_1, can_throw_external_1): Add

View File

@ -261,7 +261,6 @@ static bool subst_stack_regs (rtx, stack);
static void change_stack (rtx, stack, stack, enum emit_where); static void change_stack (rtx, stack, stack, enum emit_where);
static void print_stack (FILE *, stack); static void print_stack (FILE *, stack);
static rtx next_flags_user (rtx); static rtx next_flags_user (rtx);
static bool compensate_edge (edge, FILE *);
/* Return nonzero if any stack register is mentioned somewhere within PAT. */ /* Return nonzero if any stack register is mentioned somewhere within PAT. */
@ -2579,9 +2578,35 @@ convert_regs_exit (void)
} }
} }
/* Adjust the stack of this block on exit to match the stack of the /* If the stack of the target block hasn't been processed yet,
target block, or copy stack info into the stack of the successor copy the stack info from the source block. */
of the successor hasn't been processed yet. */
static void
propagate_stack (edge e)
{
basic_block dest = e->dest;
stack dest_stack = &BLOCK_INFO (dest)->stack_in;
if (dest_stack->top == -2)
{
basic_block src = e->src;
stack src_stack = &BLOCK_INFO (src)->stack_out;
int reg;
/* Preserve the order of the original stack, but check whether
any pops are needed. */
dest_stack->top = -1;
for (reg = 0; reg <= src_stack->top; ++reg)
if (TEST_HARD_REG_BIT (dest_stack->reg_set, src_stack->reg[reg]))
dest_stack->reg[++dest_stack->top] = src_stack->reg[reg];
}
}
/* Adjust the stack of edge E's source block on exit to match the stack
of it's target block upon input. The stack layouts of both blocks
should have been defined by now. */
static bool static bool
compensate_edge (edge e, FILE *file) compensate_edge (edge e, FILE *file)
{ {
@ -2596,50 +2621,27 @@ compensate_edge (edge e, FILE *file)
if (file) if (file)
fprintf (file, "Edge %d->%d: ", block->index, target->index); fprintf (file, "Edge %d->%d: ", block->index, target->index);
if (target_stack->top == -2) gcc_assert (target_stack->top != -2);
/* Check whether stacks are identical. */
if (target_stack->top == regstack.top)
{ {
/* The target block hasn't had a stack order selected. for (reg = target_stack->top; reg >= 0; --reg)
We need merely ensure that no pops are needed. */ if (target_stack->reg[reg] != regstack.reg[reg])
for (reg = regstack.top; reg >= 0; --reg)
if (!TEST_HARD_REG_BIT (target_stack->reg_set, regstack.reg[reg]))
break; break;
if (reg == -1) if (reg == -1)
{ {
if (file) if (file)
fprintf (file, "new block; copying stack position\n"); fprintf (file, "no changes needed\n");
/* change_stack kills values in regstack. */
tmpstack = regstack;
change_stack (BB_END (block), &tmpstack, target_stack, EMIT_AFTER);
return false; return false;
} }
if (file)
fprintf (file, "new block; pops needed\n");
} }
else
if (file)
{ {
if (target_stack->top == regstack.top) fprintf (file, "correcting stack to ");
{ print_stack (file, target_stack);
for (reg = target_stack->top; reg >= 0; --reg)
if (target_stack->reg[reg] != regstack.reg[reg])
break;
if (reg == -1)
{
if (file)
fprintf (file, "no changes needed\n");
return false;
}
}
if (file)
{
fprintf (file, "correcting stack to ");
print_stack (file, target_stack);
}
} }
/* Care for non-call EH edges specially. The normal return path have /* Care for non-call EH edges specially. The normal return path have
@ -2714,20 +2716,41 @@ compensate_edge (edge e, FILE *file)
return false; return false;
} }
/* Traverse all non-entry edges in the CFG, and emit the necessary
edge compensation code to change the stack from stack_out of the
source block to the stack_in of the destination block. */
static bool
compensate_edges (FILE *file)
{
bool inserted = false;
basic_block bb;
FOR_EACH_BB (bb)
if (bb != ENTRY_BLOCK_PTR)
{
edge e;
edge_iterator ei;
FOR_EACH_EDGE (e, ei, bb->succs)
inserted |= compensate_edge (e, file);
}
return inserted;
}
/* Convert stack register references in one block. */ /* Convert stack register references in one block. */
static int static void
convert_regs_1 (FILE *file, basic_block block) convert_regs_1 (FILE *file, basic_block block)
{ {
struct stack_def regstack; struct stack_def regstack;
block_info bi = BLOCK_INFO (block); block_info bi = BLOCK_INFO (block);
int inserted, reg; int reg;
rtx insn, next; rtx insn, next;
edge e, beste = NULL; edge e, beste = NULL;
bool control_flow_insn_deleted = false; bool control_flow_insn_deleted = false;
edge_iterator ei; edge_iterator ei;
inserted = 0;
any_malformed_asm = false; any_malformed_asm = false;
/* Find the edge we will copy stack from. It should be the most frequent /* Find the edge we will copy stack from. It should be the most frequent
@ -2763,7 +2786,7 @@ convert_regs_1 (FILE *file, basic_block block)
if (bi->stack_in.top == -2) if (bi->stack_in.top == -2)
{ {
if (beste) if (beste)
inserted |= compensate_edge (beste, file); propagate_stack (beste);
else else
{ {
/* No predecessors. Create an arbitrary input stack. */ /* No predecessors. Create an arbitrary input stack. */
@ -2887,29 +2910,27 @@ convert_regs_1 (FILE *file, basic_block block)
{ {
gcc_assert (BLOCK_INFO (e->dest)->done gcc_assert (BLOCK_INFO (e->dest)->done
|| e->dest == block); || e->dest == block);
inserted |= compensate_edge (e, file); propagate_stack (e);
} }
} }
FOR_EACH_EDGE (e, ei, block->preds) FOR_EACH_EDGE (e, ei, block->preds)
{ {
if (e != beste && !(e->flags & EDGE_DFS_BACK) if (e != beste && !(e->flags & EDGE_DFS_BACK)
&& e->src != ENTRY_BLOCK_PTR) && e->src != ENTRY_BLOCK_PTR)
{ {
gcc_assert (BLOCK_INFO (e->src)->done); gcc_assert (BLOCK_INFO (e->src)->done);
inserted |= compensate_edge (e, file); propagate_stack (e);
} }
} }
return inserted;
} }
/* Convert registers in all blocks reachable from BLOCK. */ /* Convert registers in all blocks reachable from BLOCK. */
static int static void
convert_regs_2 (FILE *file, basic_block block) convert_regs_2 (FILE *file, basic_block block)
{ {
basic_block *stack, *sp; basic_block *stack, *sp;
int inserted;
/* We process the blocks in a top-down manner, in a way such that one block /* We process the blocks in a top-down manner, in a way such that one block
is only processed after all its predecessors. The number of predecessors is only processed after all its predecessors. The number of predecessors
@ -2920,7 +2941,6 @@ convert_regs_2 (FILE *file, basic_block block)
*sp++ = block; *sp++ = block;
inserted = 0;
do do
{ {
edge e; edge e;
@ -2949,14 +2969,12 @@ convert_regs_2 (FILE *file, basic_block block)
*sp++ = e->dest; *sp++ = e->dest;
} }
inserted |= convert_regs_1 (file, block); convert_regs_1 (file, block);
BLOCK_INFO (block)->done = 1; BLOCK_INFO (block)->done = 1;
} }
while (sp != stack); while (sp != stack);
free (stack); free (stack);
return inserted;
} }
/* Traverse all basic blocks in a function, converting the register /* Traverse all basic blocks in a function, converting the register
@ -2984,7 +3002,7 @@ convert_regs (FILE *file)
/* Process all blocks reachable from all entry points. */ /* Process all blocks reachable from all entry points. */
FOR_EACH_EDGE (e, ei, ENTRY_BLOCK_PTR->succs) FOR_EACH_EDGE (e, ei, ENTRY_BLOCK_PTR->succs)
inserted |= convert_regs_2 (file, e->dest); convert_regs_2 (file, e->dest);
/* ??? Process all unreachable blocks. Though there's no excuse /* ??? Process all unreachable blocks. Though there's no excuse
for keeping these even when not optimizing. */ for keeping these even when not optimizing. */
@ -2993,8 +3011,11 @@ convert_regs (FILE *file)
block_info bi = BLOCK_INFO (b); block_info bi = BLOCK_INFO (b);
if (! bi->done) if (! bi->done)
inserted |= convert_regs_2 (file, b); convert_regs_2 (file, b);
} }
inserted |= compensate_edges (file);
clear_aux_for_blocks (); clear_aux_for_blocks ();
fixup_abnormal_edges (); fixup_abnormal_edges ();
@ -3046,7 +3067,7 @@ reg_to_stack (FILE *file)
/* Set up block info for each basic block. */ /* Set up block info for each basic block. */
alloc_aux_for_blocks (sizeof (struct block_info_def)); alloc_aux_for_blocks (sizeof (struct block_info_def));
FOR_EACH_BB_REVERSE (bb) FOR_EACH_BB (bb)
{ {
block_info bi = BLOCK_INFO (bb); block_info bi = BLOCK_INFO (bb);
edge_iterator ei; edge_iterator ei;