From de582cfbb98b6f155499b2a261a6e336f951b625 Mon Sep 17 00:00:00 2001 From: Eric Botcazou Date: Mon, 22 Sep 2003 06:59:51 +0000 Subject: [PATCH] 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 --- gcc/ChangeLog | 11 +++++++++ gcc/reg-stack.c | 34 ++++++++++++++++++++++++--- gcc/testsuite/ChangeLog | 4 ++++ gcc/testsuite/g++.dg/opt/reg-stack2.C | 34 +++++++++++++++++++++++++++ 4 files changed, 80 insertions(+), 3 deletions(-) create mode 100644 gcc/testsuite/g++.dg/opt/reg-stack2.C diff --git a/gcc/ChangeLog b/gcc/ChangeLog index c171f9fa24a..b66b5e43e19 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,14 @@ +2003-09-22 Olivier Hainque + + 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. + 2003-09-22 Eric Botcazou * real.c: Fix several nits in the head comment. 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); diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 11c7cff5343..5c9c984ed45 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,7 @@ +2003-09-22 Eric Botcazou + + * g++.dg/opt/reg-stack2.C: New test. + 2003-09-21 Christian Ehrhardt * g++.dg/eh/delayslot1.C: New test. diff --git a/gcc/testsuite/g++.dg/opt/reg-stack2.C b/gcc/testsuite/g++.dg/opt/reg-stack2.C new file mode 100644 index 00000000000..08cd590b471 --- /dev/null +++ b/gcc/testsuite/g++.dg/opt/reg-stack2.C @@ -0,0 +1,34 @@ +// PR target/9786 +// Origin: + +// This used to fail on x86 because the reg-stack pass deleted +// an insn that could seemingly trap (but actually doesn't) +// without updating the CFG. + +// { dg-do compile } +// { dg-options "-O2 -fnon-call-exceptions" } + +struct D1 { + float l; + D1 GS() const {D1 d;float f=.299*l;d.l=f;return d;} + static D1 G() {return D1();} +}; + +struct D2 { + D1 g; + D2(const D1& gi) : g(gi) {} + D2 GS() const {return D2(g.GS());} +}; + +class A { + public: + virtual ~A() {} +}; + +class B : public A { + public: + B(const D2& mi); + D2 fm; +}; + +B::B(const D2 &mi) : fm(mi.GS()) {} -- 2.30.2