aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEric Botcazou <ebotcazou@libertysurf.fr>2003-10-25 12:55:18 +0000
committerEric Botcazou <ebotcazou@libertysurf.fr>2003-10-25 12:55:18 +0000
commit523cb3125fc1e2f3d2f80f062d8e12ec07be4fd9 (patch)
tree9c312b258a5817d52418700fabb9eb90a166cc5e
parent9e9ec3e2eab9c3fc5eb9344980b1ad36540c4be5 (diff)
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. git-svn-id: https://gcc.gnu.org/svn/gcc/trunk@72923 138bc75d-0d04-0410-961f-82ee72b054a4
-rw-r--r--gcc/ChangeLog9
-rw-r--r--gcc/reg-stack.c49
-rw-r--r--gcc/testsuite/ChangeLog4
-rw-r--r--gcc/testsuite/g++.dg/opt/reg-stack3.C21
4 files changed, 64 insertions, 19 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 71ce60db2d5..e4dd113d815 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -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
diff --git a/gcc/reg-stack.c b/gcc/reg-stack.c
index fe1bc23ff48..50bc63fcb0c 100644
--- a/gcc/reg-stack.c
+++ b/gcc/reg-stack.c
@@ -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 ();
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index dd43b9363b7..28a067b1a6d 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -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
index 00000000000..48dcb335b21
--- /dev/null
+++ b/gcc/testsuite/g++.dg/opt/reg-stack3.C
@@ -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);
+}