re PR target/12712 (ICE on short legit C++ code fragment with gcc 3.3.2)
authorEric Botcazou <ebotcazou@libertysurf.fr>
Sat, 25 Oct 2003 12:55:18 +0000 (14:55 +0200)
committerEric Botcazou <ebotcazou@gcc.gnu.org>
Sat, 25 Oct 2003 12:55:18 +0000 (12:55 +0000)
PR target/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.

From-SVN: r72923

gcc/ChangeLog
gcc/reg-stack.c
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/opt/reg-stack3.C [new file with mode: 0644]

index 71ce60db2d5855296ad40c4bd73c3077de85f8d7..e4dd113d815cca5e25ebe83572107dfaa07ef481 100644 (file)
@@ -1,3 +1,12 @@
+2003-10-25  Eric Botcazou  <ebotcazou@libertysurf.fr>
+
+       PR target/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-24  Zack Weinberg  <zack@codesourcery.com>
 
        * genmodes.c (struct mode_data): Add contained and next_cont
index fe1bc23ff48a003bacc2e517e4ac0bb652b3b15e..50bc63fcb0c6c90873b98e9872f7058564630d25 100644 (file)
@@ -2675,10 +2675,24 @@ convert_regs_1 (FILE *file, basic_block 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;
@@ -2833,12 +2847,19 @@ convert_regs_2 (FILE *file, basic_block 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 possibility 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))
          {
@@ -2888,17 +2909,7 @@ convert_regs (FILE *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 ();
 
index dd43b9363b72b6b75c58d9a23379d216081b26c8..28a067b1a6d5f9a0e5c5997dbb9e3ac3ecf73fd2 100644 (file)
@@ -1,3 +1,7 @@
+2003-10-25  Eric Botcazou  <ebotcazou@libertysurf.fr>
+
+       * g++.dg/opt/reg-stack3.C: New test.
+
 2003-10-24  Joseph S. Myers  <jsm@polyomino.org.uk>
 
        * gcc.dg/c99-arraydecl-2.c: New test.  PR c/11943.
diff --git a/gcc/testsuite/g++.dg/opt/reg-stack3.C b/gcc/testsuite/g++.dg/opt/reg-stack3.C
new file mode 100644 (file)
index 0000000..48dcb33
--- /dev/null
@@ -0,0 +1,21 @@
+// PR target/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);
+}