diff options
author | Eric Botcazou <ebotcazou@gcc.gnu.org> | 2003-09-22 06:59:51 +0000 |
---|---|---|
committer | Eric Botcazou <ebotcazou@gcc.gnu.org> | 2003-09-22 06:59:51 +0000 |
commit | de582cfbb98b6f155499b2a261a6e336f951b625 (patch) | |
tree | 617ef40caca7262bca17e44852b596b9b9383ef0 /gcc/reg-stack.c | |
parent | 316b38c83c3e81c1d3c1b68cba91b2b77051f2fd (diff) | |
download | gcc-de582cfbb98b6f155499b2a261a6e336f951b625.tar.gz |
re PR target/9786 (Ice in fixup_abnormal_edges with -fnon-call-exceptions -O2)
PR target/9786
* reg-stack.c (convert_regs_1): Purge possible dead eh edges
after potential deletion of trapping insn. Avoids later ICE
from call to fixup_abnormal_edges.
(convert_regs_2): Stack the current block successors before
processing this block, that is, before the potential deletion of
dead edges by convert_regs_1, because these edges have been used
to initialize the predecessors count.
From-SVN: r71644
Diffstat (limited to 'gcc/reg-stack.c')
-rw-r--r-- | gcc/reg-stack.c | 34 |
1 files changed, 31 insertions, 3 deletions
diff --git a/gcc/reg-stack.c b/gcc/reg-stack.c index fd707e21e83..f432cf1b54d 100644 --- a/gcc/reg-stack.c +++ b/gcc/reg-stack.c @@ -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,6 +2817,10 @@ convert_regs_2 (FILE *file, basic_block block) basic_block *stack, *sp; int inserted; + /* 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; @@ -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); |