diff options
Diffstat (limited to 'gcc/reg-stack.c')
-rw-r--r-- | gcc/reg-stack.c | 50 |
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, ®stack); } subst_stack_regs (insn, ®stack); + 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, ®stack); + 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); |