This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[PATCH] Fix PR C++/12712
- From: Eric Botcazou <ebotcazou at libertysurf dot fr>
- To: gcc-patches at gcc dot gnu dot org
- Date: Thu, 23 Oct 2003 23:29:45 +0200
- Subject: [PATCH] Fix PR C++/12712
Hi,
This is a regression introduced recently on mainline and 3.3 branch by
2003-09-22 Olivier Hainque <hainque@act-europe.fr>
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.
(that I installed on both branches).
The patch has a flaw: it unconditionally stacks the successors of a block
before the possible deletion of outgoing edges from this block. Now if it
happens that an outgoing edge to be deleted is the only incoming edge to a
successor, this successor becomes unreachable and the code is not prepared
to handle this situation, so the compiler segfaults.
After thinking (a while) about the problem, I came to the conclusion that
there is no way to preventively detect this case, so we must resort to an
ad-hoc solution.
Bootstrapped/regtested on i586-redhat-linux-gnu (3.3 branch except Ada).
2003-10-23 Eric Botcazou <ebotcazou@libertysurf.fr>
PR c++/12712
* reg-stack.c (convert_regs_1): Create an arbitrary input stack
if the block has no predecessors.
(convert_regs_2): Document the problem with successors whose
only predecessor is the block to be processed.
(convert_regs): Don't create the arbitrary input stack here.
2003-10-23 Eric Botcazou <ebotcazou@libertysurf.fr>
* g++.dg/opt/reg-stack3.C: New test.
--
Eric Botcazou
Index: reg-stack.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/reg-stack.c,v
retrieving revision 1.117.2.4
diff -u -p -r1.117.2.4 reg-stack.c
--- reg-stack.c 22 Sep 2003 07:11:22 -0000 1.117.2.4
+++ reg-stack.c 22 Oct 2003 11:19:01 -0000
@@ -2653,10 +2653,24 @@ convert_regs_1 (file, block)
beste = e;
}
- /* Entry block does have stack already initialized. */
+ /* Initialize stack at block entry. */
if (bi->stack_in.top == -2)
- inserted |= compensate_edge (beste, file);
+ {
+ if (beste)
+ inserted |= compensate_edge (beste, file);
+ else
+ {
+ /* No predecessors. Create an arbitrary input stack. */
+ int reg;
+
+ bi->stack_in.top = -1;
+ for (reg = LAST_STACK_REG; reg >= FIRST_STACK_REG; --reg)
+ if (TEST_HARD_REG_BIT (bi->stack_in.reg_set, reg))
+ bi->stack_in.reg[++bi->stack_in.top] = reg;
+ }
+ }
else
+ /* Entry blocks do have stack already initialized. */
beste = NULL;
current_block = block;
@@ -2813,12 +2827,19 @@ convert_regs_2 (file, block)
block = *--sp;
- /* 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. */
+ /* Processing BLOCK is achieved by convert_regs_1, which may purge
+ some dead EH outgoing edge after the deletion of the trapping
+ insn inside the block. Since the number of predecessors of
+ BLOCK's successors was computed based on the initial edge set,
+ we check the necessity to process some of these successors
+ before such an edge deletion may happen. However, there is
+ a pitfall: if BLOCK is the only predecessor of a successor and
+ the edge between them happens to be deleted, the successor
+ becomes unreachable and should not be processed. The problem
+ is that there is no way to preventively detect this case so we
+ stack the successor in all cases and hand over the task of
+ fixing up the discrepancy to convert_regs_1. */
+
for (e = block->succ; e ; e = e->succ_next)
if (! (e->flags & EDGE_DFS_BACK))
{
@@ -2869,17 +2890,7 @@ convert_regs (file)
block_info bi = BLOCK_INFO (b);
if (! bi->done)
- {
- int reg;
-
- /* Create an arbitrary input stack. */
- bi->stack_in.top = -1;
- for (reg = LAST_STACK_REG; reg >= FIRST_STACK_REG; --reg)
- if (TEST_HARD_REG_BIT (bi->stack_in.reg_set, reg))
- bi->stack_in.reg[++bi->stack_in.top] = reg;
-
- inserted |= convert_regs_2 (file, b);
- }
+ inserted |= convert_regs_2 (file, b);
}
clear_aux_for_blocks ();
// PR C++/12712
// Origin: Markus Schoder <gccbug@gammarayburst.de>
// This used to segfault on x86 because the reg-stack pass
// created an unreachable basic block by purging an outgoing
// edge, and was not prepared to handle it.
// { dg-do compile }
struct A
{
~A();
float f(float x);
float g() const {return 0;}
};
void h()
{
A a, b;
a.f(b.g() + 1);
}