re PR rtl-optimization/20290 (Miscompilation on ppc/arm with -Os)

gcc/ChangeLog:
PR rtl-optimization/20290
* loop.c (for_each_insn_in_loop): Don't assume the loop body runs
in every iteration if the entry point is the exit test.
gcc/testsuite/ChangeLog:
PR rtl-optimization/20290
* gcc.c-torture/execute/loop-ivopts-2.c: New.

From-SVN: r97441
This commit is contained in:
Alexandre Oliva 2005-04-02 16:53:44 +00:00 committed by Alexandre Oliva
parent 3a5afdfc20
commit 9f05ff0a19
4 changed files with 76 additions and 7 deletions

View File

@ -1,3 +1,9 @@
2005-04-02 Alexandre Oliva <aoliva@redhat.com>
PR rtl-optimization/20290
* loop.c (for_each_insn_in_loop): Don't assume the loop body runs
in every iteration if the entry point is the exit test.
2005-04-02 Hans-Peter Nilsson <hp@axis.com>
* config/cris/cris.md (attribute "length"): Define.

View File

@ -4654,12 +4654,18 @@ for_each_insn_in_loop (struct loop *loop, loop_insn_callback fncall)
int not_every_iteration = 0;
int maybe_multiple = 0;
int past_loop_latch = 0;
bool exit_test_is_entry = false;
rtx p;
/* If loop_scan_start points to the loop exit test, we have to be wary of
subversive use of gotos inside expression statements. */
/* If loop_scan_start points to the loop exit test, the loop body
cannot be counted on running on every iteration, and we have to
be wary of subversive use of gotos inside expression
statements. */
if (prev_nonnote_insn (loop->scan_start) != prev_nonnote_insn (loop->start))
maybe_multiple = back_branch_in_range_p (loop, loop->scan_start);
{
exit_test_is_entry = true;
maybe_multiple = back_branch_in_range_p (loop, loop->scan_start);
}
/* Scan through loop and update NOT_EVERY_ITERATION and MAYBE_MULTIPLE. */
for (p = next_insn_in_loop (loop, loop->scan_start);
@ -4717,10 +4723,12 @@ for_each_insn_in_loop (struct loop *loop, loop_insn_callback fncall)
beginning, don't set not_every_iteration for that.
This can be any kind of jump, since we want to know if insns
will be executed if the loop is executed. */
&& !(JUMP_LABEL (p) == loop->top
&& ((NEXT_INSN (NEXT_INSN (p)) == loop->end
&& any_uncondjump_p (p))
|| (NEXT_INSN (p) == loop->end && any_condjump_p (p)))))
&& (exit_test_is_entry
|| !(JUMP_LABEL (p) == loop->top
&& ((NEXT_INSN (NEXT_INSN (p)) == loop->end
&& any_uncondjump_p (p))
|| (NEXT_INSN (p) == loop->end
&& any_condjump_p (p))))))
{
rtx label = 0;

View File

@ -1,3 +1,8 @@
2005-04-02 Alexandre Oliva <aoliva@redhat.com>
PR rtl-optimization/20290
* gcc.c-torture/execute/loop-ivopts-2.c: New.
2005-04-02 Geoffrey Keating <geoffk@apple.com>
* gcc.dg/rs6000-fpint.c: New.

View File

@ -0,0 +1,50 @@
/* PR rtl-optimization/20290 */
/* We used to mis-optimize the second loop in main on at least ppc and
arm, because tree loop would change the loop to something like:
ivtmp.65 = &l[i];
ivtmp.16 = 113;
goto <bb 4> (<L4>);
<L3>:;
*(ivtmp.65 + 4294967292B) = 9;
i = i + 1;
<L4>:;
ivtmp.16 = ivtmp.16 - 1;
ivtmp.65 = ivtmp.65 + 4B;
if (ivtmp.16 != 0) goto <L3>;
We used to consider the increment of i as executed in every
iteration, so we'd miscompute the final value. */
extern void abort (void);
void
check (unsigned int *l)
{
int i;
for (i = 0; i < 288; i++)
if (l[i] != 7 + (i < 256 || i >= 280) + (i >= 144 && i < 256))
abort ();
}
int
main (void)
{
int i;
unsigned int l[288];
for (i = 0; i < 144; i++)
l[i] = 8;
for (; i < 256; i++)
l[i] = 9;
for (; i < 280; i++)
l[i] = 7;
for (; i < 288; i++)
l[i] = 8;
check (l);
return 0;
}