diff options
author | Eric Botcazou <ebotcazou@libertysurf.fr> | 2003-10-25 12:55:18 +0000 |
---|---|---|
committer | Eric Botcazou <ebotcazou@libertysurf.fr> | 2003-10-25 12:55:18 +0000 |
commit | 523cb3125fc1e2f3d2f80f062d8e12ec07be4fd9 (patch) | |
tree | 9c312b258a5817d52418700fabb9eb90a166cc5e | |
parent | 9e9ec3e2eab9c3fc5eb9344980b1ad36540c4be5 (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/ChangeLog | 9 | ||||
-rw-r--r-- | gcc/reg-stack.c | 49 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 4 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/opt/reg-stack3.C | 21 |
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); +} |