diff options
author | Jason Merrill <jason@redhat.com> | 2003-03-25 15:24:42 -0500 |
---|---|---|
committer | Jason Merrill <jason@gcc.gnu.org> | 2003-03-25 15:24:42 -0500 |
commit | 2e2255ffff45da118ea54715fbe880624f29b9cf (patch) | |
tree | c48ce8d00c0de5784247bb6050aa914358fd8591 /gcc | |
parent | 8725a499793a072329573c0f71fbd703c09feef2 (diff) | |
download | gcc-2e2255ffff45da118ea54715fbe880624f29b9cf.zip gcc-2e2255ffff45da118ea54715fbe880624f29b9cf.tar.gz gcc-2e2255ffff45da118ea54715fbe880624f29b9cf.tar.bz2 |
re PR rtl-optimization/10171 (wrong code for inlined function)
PR optimization/10171
* unroll.c (unroll_loop): Don't delete the jump at the end unless
we also delete a jump at the beginning.
From-SVN: r64863
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/ChangeLog | 6 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/loop-2.c | 20 | ||||
-rw-r--r-- | gcc/unroll.c | 44 |
3 files changed, 51 insertions, 19 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index b5f7edc..791d08c 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,9 @@ +2003-03-21 Jason Merrill <jason@redhat.com> + + PR optimization/10171 + * unroll.c (unroll_loop): Don't delete the jump at the end unless + we also delete a jump at the beginning. + 2003-03-25 Stephane Carrez <stcarrez@nerim.fr> * doc/contrib.texi (Contributors): Mention self as 68HC11/68HC12 diff --git a/gcc/testsuite/gcc.dg/loop-2.c b/gcc/testsuite/gcc.dg/loop-2.c new file mode 100644 index 0000000..e939f32 --- /dev/null +++ b/gcc/testsuite/gcc.dg/loop-2.c @@ -0,0 +1,20 @@ +/* PR optimization/10171 */ +/* Bug: unroll_loop misoptimized the function so that we got + 0 iterations of the loop rather than the correct 1. */ +/* { dg-do run } */ + +inline int tag() { return 0; } + +void f (); + +int main() { + int i; + for (i = 0; i < (tag() ? 2 : 1); i++) + f(); + abort (); +} + +void f () +{ + exit (0); +} diff --git a/gcc/unroll.c b/gcc/unroll.c index 3b5dd7c..9db9975 100644 --- a/gcc/unroll.c +++ b/gcc/unroll.c @@ -305,9 +305,11 @@ unroll_loop (loop, insn_count, strength_reduce_p) jump to the loop condition. Make sure to delete the jump insn, otherwise the loop body will never execute. */ + /* FIXME this actually checks for a jump to the continue point, which + is not the same as the condition in a for loop. As a result, this + optimization fails for most for loops. We should really use flow + information rather than instruction pattern matching. */ rtx ujump = ujump_to_loop_cont (loop->start, loop->cont); - if (ujump) - delete_related_insns (ujump); /* If number of iterations is exactly 1, then eliminate the compare and branch at the end of the loop since they will never be taken. @@ -319,9 +321,10 @@ unroll_loop (loop, insn_count, strength_reduce_p) if (GET_CODE (last_loop_insn) == BARRIER) { /* Delete the jump insn. This will delete the barrier also. */ - delete_related_insns (PREV_INSN (last_loop_insn)); + last_loop_insn = PREV_INSN (last_loop_insn); } - else if (GET_CODE (last_loop_insn) == JUMP_INSN) + + if (ujump && GET_CODE (last_loop_insn) == JUMP_INSN) { #ifdef HAVE_cc0 rtx prev = PREV_INSN (last_loop_insn); @@ -333,24 +336,27 @@ unroll_loop (loop, insn_count, strength_reduce_p) if (only_sets_cc0_p (prev)) delete_related_insns (prev); #endif - } - /* Remove the loop notes since this is no longer a loop. */ - if (loop->vtop) - delete_related_insns (loop->vtop); - if (loop->cont) - delete_related_insns (loop->cont); - if (loop_start) - delete_related_insns (loop_start); - if (loop_end) - delete_related_insns (loop_end); + delete_related_insns (ujump); - return; + /* Remove the loop notes since this is no longer a loop. */ + if (loop->vtop) + delete_related_insns (loop->vtop); + if (loop->cont) + delete_related_insns (loop->cont); + if (loop_start) + delete_related_insns (loop_start); + if (loop_end) + delete_related_insns (loop_end); + + return; + } } - else if (loop_info->n_iterations > 0 - /* Avoid overflow in the next expression. */ - && loop_info->n_iterations < (unsigned) MAX_UNROLLED_INSNS - && loop_info->n_iterations * insn_count < (unsigned) MAX_UNROLLED_INSNS) + + if (loop_info->n_iterations > 0 + /* Avoid overflow in the next expression. */ + && loop_info->n_iterations < (unsigned) MAX_UNROLLED_INSNS + && loop_info->n_iterations * insn_count < (unsigned) MAX_UNROLLED_INSNS) { unroll_number = loop_info->n_iterations; unroll_type = UNROLL_COMPLETELY; |