This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[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);
}

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]