re PR target/11087 (gcc miscompiles raid1.c from linux kernel)
PR target/11087 * loop.c (basic_induction_var): Check if convert_modes emitted any instructions. Remove them and return 0 if so. * gcc.c-torture/execute/20030717-1.c: New test. From-SVN: r69552
This commit is contained in:
parent
2d5f9af2bf
commit
16f6812f86
4 changed files with 110 additions and 3 deletions
|
@ -1,3 +1,9 @@
|
|||
2003-07-17 Jakub Jelinek <jakub@redhat.com>
|
||||
|
||||
PR target/11087
|
||||
* loop.c (basic_induction_var): Check if convert_modes emitted any
|
||||
instructions. Remove them and return 0 if so.
|
||||
|
||||
2003-07-18 Eric Botcazou <ebotcazou@libertysurf.fr>
|
||||
|
||||
PR optimization/11083
|
||||
|
|
33
gcc/loop.c
33
gcc/loop.c
|
@ -6197,7 +6197,7 @@ basic_induction_var (const struct loop *loop, rtx x, enum machine_mode mode,
|
|||
{
|
||||
enum rtx_code code;
|
||||
rtx *argp, arg;
|
||||
rtx insn, set = 0;
|
||||
rtx insn, set = 0, last, inc;
|
||||
|
||||
code = GET_CODE (x);
|
||||
*location = NULL;
|
||||
|
@ -6225,7 +6225,26 @@ basic_induction_var (const struct loop *loop, rtx x, enum machine_mode mode,
|
|||
if (loop_invariant_p (loop, arg) != 1)
|
||||
return 0;
|
||||
|
||||
*inc_val = convert_modes (GET_MODE (dest_reg), GET_MODE (x), arg, 0);
|
||||
/* convert_modes can emit new instructions, e.g. when arg is a loop
|
||||
invariant MEM and dest_reg has a different mode.
|
||||
These instructions would be emitted after the end of the function
|
||||
and then *inc_val would be an unitialized pseudo.
|
||||
Detect this and bail in this case.
|
||||
Other alternatives to solve this can be introducing a convert_modes
|
||||
variant which is allowed to fail but not allowed to emit new
|
||||
instructions, emit these instructions before loop start and let
|
||||
it be garbage collected if *inc_val is never used or saving the
|
||||
*inc_val initialization sequence generated here and when *inc_val
|
||||
is going to be actually used, emit it at some suitable place. */
|
||||
last = get_last_insn ();
|
||||
inc = convert_modes (GET_MODE (dest_reg), GET_MODE (x), arg, 0);
|
||||
if (get_last_insn () != last)
|
||||
{
|
||||
delete_insns_since (last);
|
||||
return 0;
|
||||
}
|
||||
|
||||
*inc_val = inc;
|
||||
*mult_val = const1_rtx;
|
||||
*location = argp;
|
||||
return 1;
|
||||
|
@ -6306,7 +6325,15 @@ basic_induction_var (const struct loop *loop, rtx x, enum machine_mode mode,
|
|||
&& GET_MODE_CLASS (mode) != MODE_CC)
|
||||
{
|
||||
/* Possible bug here? Perhaps we don't know the mode of X. */
|
||||
*inc_val = convert_modes (GET_MODE (dest_reg), mode, x, 0);
|
||||
last = get_last_insn ();
|
||||
inc = convert_modes (GET_MODE (dest_reg), mode, x, 0);
|
||||
if (get_last_insn () != last)
|
||||
{
|
||||
delete_insns_since (last);
|
||||
return 0;
|
||||
}
|
||||
|
||||
*inc_val = inc;
|
||||
*mult_val = const0_rtx;
|
||||
return 1;
|
||||
}
|
||||
|
|
|
@ -1,3 +1,8 @@
|
|||
2003-07-17 Jakub Jelinek <jakub@redhat.com>
|
||||
|
||||
PR target/11087
|
||||
* gcc.c-torture/execute/20030717-1.c: New test.
|
||||
|
||||
2003-07-18 Eric Botcazou <ebotcazou@libertysurf.fr>
|
||||
|
||||
* g++.dg/opt/cfg1.C: New test.
|
||||
|
|
69
gcc/testsuite/gcc.c-torture/execute/20030717-1.c
Normal file
69
gcc/testsuite/gcc.c-torture/execute/20030717-1.c
Normal file
|
@ -0,0 +1,69 @@
|
|||
/* PR target/11087
|
||||
This testcase was miscompiled on ppc64, because basic_induction_var called
|
||||
convert_modes, yet did not expect it to emit any new instructions.
|
||||
Those were emitted at the end of the function and destroyed during life
|
||||
analysis, while the program used uninitialized pseudos created by
|
||||
convert_modes. */
|
||||
|
||||
struct A
|
||||
{
|
||||
unsigned short a1;
|
||||
unsigned long a2;
|
||||
};
|
||||
|
||||
struct B
|
||||
{
|
||||
int b1, b2, b3, b4, b5;
|
||||
};
|
||||
|
||||
struct C
|
||||
{
|
||||
struct B c1[1];
|
||||
int c2, c3;
|
||||
};
|
||||
|
||||
static
|
||||
int foo (int x)
|
||||
{
|
||||
return x < 0 ? -x : x;
|
||||
}
|
||||
|
||||
int bar (struct C *x, struct A *y)
|
||||
{
|
||||
int a = x->c3;
|
||||
const int b = y->a1 >> 9;
|
||||
const unsigned long c = y->a2;
|
||||
int d = a;
|
||||
unsigned long e, f;
|
||||
|
||||
f = foo (c - x->c1[d].b4);
|
||||
do
|
||||
{
|
||||
if (d <= 0)
|
||||
d = x->c2;
|
||||
d--;
|
||||
|
||||
e = foo (c-x->c1[d].b4);
|
||||
if (e < f)
|
||||
a = d;
|
||||
}
|
||||
while (d != x->c3);
|
||||
x->c1[a].b4 = c + b;
|
||||
return a;
|
||||
}
|
||||
|
||||
int
|
||||
main ()
|
||||
{
|
||||
struct A a;
|
||||
struct C b;
|
||||
int c;
|
||||
|
||||
a.a1 = 512;
|
||||
a.a2 = 4242;
|
||||
__builtin_memset (&b, 0, sizeof (b));
|
||||
b.c1[0].b3 = 424242;
|
||||
b.c2 = 1;
|
||||
c = bar (&b, &a);
|
||||
return 0;
|
||||
}
|
Loading…
Add table
Reference in a new issue