aboutsummaryrefslogtreecommitdiff
path: root/gcc/reg-stack.c
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/reg-stack.c')
-rw-r--r--gcc/reg-stack.c50
1 files changed, 39 insertions, 11 deletions
diff --git a/gcc/reg-stack.c b/gcc/reg-stack.c
index 299ba0e6501..f432cf1b54d 100644
--- a/gcc/reg-stack.c
+++ b/gcc/reg-stack.c
@@ -630,7 +630,7 @@ check_asm_stack_operands (rtx insn)
if (GET_CODE (body) == PARALLEL)
{
- clobber_reg = (rtx *) alloca (XVECLEN (body, 0) * sizeof (rtx));
+ clobber_reg = alloca (XVECLEN (body, 0) * sizeof (rtx));
for (i = 0; i < XVECLEN (body, 0); i++)
if (GET_CODE (XVECEXP (body, 0, i)) == CLOBBER)
@@ -802,7 +802,7 @@ stack_result (tree decl)
/* If the value is supposed to be returned in memory, then clearly
it is not returned in a stack register. */
- if (aggregate_value_p (DECL_RESULT (decl)))
+ if (aggregate_value_p (DECL_RESULT (decl), decl))
return 0;
result = DECL_RTL_IF_SET (DECL_RESULT (decl));
@@ -1946,9 +1946,9 @@ subst_asm_stack_regs (rtx insn, stack regstack)
for (i = 0, note = REG_NOTES (insn); note; note = XEXP (note, 1))
i++;
- note_reg = (rtx *) alloca (i * sizeof (rtx));
- note_loc = (rtx **) alloca (i * sizeof (rtx *));
- note_kind = (enum reg_note *) alloca (i * sizeof (enum reg_note));
+ note_reg = alloca (i * sizeof (rtx));
+ note_loc = alloca (i * sizeof (rtx *));
+ note_kind = alloca (i * sizeof (enum reg_note));
n_notes = 0;
for (note = REG_NOTES (insn); note; note = XEXP (note, 1))
@@ -1979,8 +1979,8 @@ subst_asm_stack_regs (rtx insn, stack regstack)
if (GET_CODE (body) == PARALLEL)
{
- clobber_reg = (rtx *) alloca (XVECLEN (body, 0) * sizeof (rtx));
- clobber_loc = (rtx **) alloca (XVECLEN (body, 0) * sizeof (rtx *));
+ clobber_reg = alloca (XVECLEN (body, 0) * sizeof (rtx));
+ clobber_loc = alloca (XVECLEN (body, 0) * sizeof (rtx *));
for (i = 0; i < XVECLEN (body, 0); i++)
if (GET_CODE (XVECEXP (body, 0, i)) == CLOBBER)
@@ -2638,11 +2638,12 @@ convert_regs_1 (FILE *file, basic_block block)
{
struct stack_def regstack;
block_info bi = BLOCK_INFO (block);
- int inserted, reg;
+ int deleted, inserted, reg;
rtx insn, next;
edge e, beste = NULL;
inserted = 0;
+ deleted = 0;
any_malformed_asm = false;
/* Find the edge we will copy stack from. It should be the most frequent
@@ -2715,6 +2716,7 @@ convert_regs_1 (FILE *file, basic_block block)
print_stack (file, &regstack);
}
subst_stack_regs (insn, &regstack);
+ deleted |= (GET_CODE (insn) == NOTE || INSN_DELETED_P (insn));
}
}
while (next);
@@ -2754,8 +2756,23 @@ convert_regs_1 (FILE *file, basic_block block)
nan);
insn = emit_insn_after (set, insn);
subst_stack_regs (insn, &regstack);
+ deleted |= (GET_CODE (insn) == NOTE || INSN_DELETED_P (insn));
}
}
+
+ /* Amongst the insns possibly deleted during the substitution process above,
+ might have been the only trapping insn in the block. We purge the now
+ possibly dead EH edges here to avoid an ICE from fixup_abnormal_edges,
+ called at the end of convert_regs. The order in which we process the
+ blocks ensures that we never delete an already processed edge.
+
+ ??? We are normally supposed not to delete trapping insns, so we pretend
+ that the insns deleted above don't actually trap. It would have been
+ better to detect this earlier and avoid creating the EH edge in the first
+ place, still, but we don't have enough information at that time. */
+
+ if (deleted)
+ purge_dead_edges (block);
/* Something failed if the stack lives don't match. If we had malformed
asms, we zapped the instruction itself, but that didn't produce the
@@ -2800,7 +2817,11 @@ convert_regs_2 (FILE *file, basic_block block)
basic_block *stack, *sp;
int inserted;
- stack = (basic_block *) xmalloc (sizeof (*stack) * n_basic_blocks);
+ /* 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
+ of every block has already been computed. */
+
+ stack = xmalloc (sizeof (*stack) * n_basic_blocks);
sp = stack;
*sp++ = block;
@@ -2811,9 +2832,13 @@ convert_regs_2 (FILE *file, basic_block block)
edge e;
block = *--sp;
- inserted |= convert_regs_1 (file, block);
- BLOCK_INFO (block)->done = 1;
+ /* Processing "block" is achieved by convert_regs_1, which may purge
+ some dead EH outgoing edge after the possible deletion of the
+ trapping insn inside the block. Since the number of predecessors of
+ "block"'s successors has been computed based on the initial edge set,
+ we check for the possiblity to process some of these successors
+ before such an edge deletion may happen. */
for (e = block->succ; e ; e = e->succ_next)
if (! (e->flags & EDGE_DFS_BACK))
{
@@ -2821,6 +2846,9 @@ convert_regs_2 (FILE *file, basic_block block)
if (!BLOCK_INFO (e->dest)->predecessors)
*sp++ = e->dest;
}
+
+ inserted |= convert_regs_1 (file, block);
+ BLOCK_INFO (block)->done = 1;
}
while (sp != stack);