re PR rtl-optimization/40924 (miscompiles with -O3 (seemingly related to attribute may_alias))

PR rtl-optimization/40924
	* dse.c (canon_address): Before calling cselib_expand_value_rtx
	make sure canon_rtx (mem_address) isn't simpler than
	canon_rtx (expanded_mem_address).

	* g++.dg/torture/pr40924.C: New test.

From-SVN: r150483
This commit is contained in:
Jakub Jelinek 2009-08-05 14:36:34 +02:00 committed by Jakub Jelinek
parent 64393e407d
commit 403c752036
4 changed files with 202 additions and 61 deletions

View File

@ -1,3 +1,10 @@
2009-08-05 Jakub Jelinek <jakub@redhat.com>
PR rtl-optimization/40924
* dse.c (canon_address): Before calling cselib_expand_value_rtx
make sure canon_rtx (mem_address) isn't simpler than
canon_rtx (expanded_mem_address).
2009-08-05 Li Feng <nemokingdom@gmail.com>
* graphite-sese-to-poly.c (build_pbb_drs): Remove build alias set

140
gcc/dse.c
View File

@ -1070,6 +1070,8 @@ canon_address (rtx mem,
{
rtx mem_address = XEXP (mem, 0);
rtx expanded_address, address;
int expanded;
/* Make sure that cselib is has initialized all of the operands of
the address before asking it to do the subst. */
@ -1114,72 +1116,88 @@ canon_address (rtx mem,
fprintf (dump_file, "\n");
}
/* Use cselib to replace all of the reg references with the full
expression. This will take care of the case where we have
r_x = base + offset;
val = *r_x;
by making it into
val = *(base + offset);
*/
expanded_address = cselib_expand_value_rtx (mem_address, scratch, 5);
/* If this fails, just go with the mem_address. */
if (!expanded_address)
expanded_address = mem_address;
/* Split the address into canonical BASE + OFFSET terms. */
address = canon_rtx (expanded_address);
*offset = 0;
if (dump_file)
/* First see if just canon_rtx (mem_address) is const or frame,
if not, try cselib_expand_value_rtx and call canon_rtx on that. */
address = NULL_RTX;
for (expanded = 0; expanded < 2; expanded++)
{
fprintf (dump_file, "\n after cselib_expand address: ");
print_inline_rtx (dump_file, expanded_address, 0);
fprintf (dump_file, "\n");
fprintf (dump_file, "\n after canon_rtx address: ");
print_inline_rtx (dump_file, address, 0);
fprintf (dump_file, "\n");
}
if (GET_CODE (address) == CONST)
address = XEXP (address, 0);
if (GET_CODE (address) == PLUS && CONST_INT_P (XEXP (address, 1)))
{
*offset = INTVAL (XEXP (address, 1));
address = XEXP (address, 0);
}
if (const_or_frame_p (address))
{
group_info_t group = get_group_info (address);
if (dump_file)
fprintf (dump_file, " gid=%d offset=%d \n", group->id, (int)*offset);
*base = NULL;
*group_id = group->id;
}
else
{
*base = cselib_lookup (address, Pmode, true);
*group_id = -1;
if (*base == NULL)
if (expanded)
{
if (dump_file)
fprintf (dump_file, " no cselib val - should be a wild read.\n");
return false;
/* Use cselib to replace all of the reg references with the full
expression. This will take care of the case where we have
r_x = base + offset;
val = *r_x;
by making it into
val = *(base + offset); */
expanded_address = cselib_expand_value_rtx (mem_address,
scratch, 5);
/* If this fails, just go with the address from first
iteration. */
if (!expanded_address)
break;
}
else
expanded_address = mem_address;
/* Split the address into canonical BASE + OFFSET terms. */
address = canon_rtx (expanded_address);
*offset = 0;
if (dump_file)
fprintf (dump_file, " varying cselib base=%d offset = %d\n",
(*base)->value, (int)*offset);
{
if (expanded)
{
fprintf (dump_file, "\n after cselib_expand address: ");
print_inline_rtx (dump_file, expanded_address, 0);
fprintf (dump_file, "\n");
}
fprintf (dump_file, "\n after canon_rtx address: ");
print_inline_rtx (dump_file, address, 0);
fprintf (dump_file, "\n");
}
if (GET_CODE (address) == CONST)
address = XEXP (address, 0);
if (GET_CODE (address) == PLUS
&& CONST_INT_P (XEXP (address, 1)))
{
*offset = INTVAL (XEXP (address, 1));
address = XEXP (address, 0);
}
if (const_or_frame_p (address))
{
group_info_t group = get_group_info (address);
if (dump_file)
fprintf (dump_file, " gid=%d offset=%d \n",
group->id, (int)*offset);
*base = NULL;
*group_id = group->id;
return true;
}
}
*base = cselib_lookup (address, Pmode, true);
*group_id = -1;
if (*base == NULL)
{
if (dump_file)
fprintf (dump_file, " no cselib val - should be a wild read.\n");
return false;
}
if (dump_file)
fprintf (dump_file, " varying cselib base=%d offset = %d\n",
(*base)->value, (int)*offset);
return true;
}

View File

@ -1,3 +1,8 @@
2009-08-05 Jakub Jelinek <jakub@redhat.com>
PR rtl-optimization/40924
* g++.dg/torture/pr40924.C: New test.
2009-08-05 Manuel López-Ibáñez <manu@gcc.gnu.org>
PR c++/36069

View File

@ -0,0 +1,111 @@
// PR rtl-optimization/40924
// { dg-do run }
extern "C" void abort (void);
#define MAY_ALIAS __attribute__((__may_alias__))
typedef struct { float v[2]; } floata;
typedef struct { int v[2]; } inta;
typedef unsigned int uint MAY_ALIAS;
typedef signed int sint MAY_ALIAS;
typedef float flt MAY_ALIAS;
static inline unsigned short
less_than (inta a, inta b)
{
unsigned short r = 0;
const uint *p1 = (const uint *) &a;
const uint *p2 = (const uint *) &b;
for (int i=0; i < 2; i++)
if (p1[i] < p2[i]) r |= (1 << i);
return r;
}
static inline inta
multiply (inta b, inta c)
{
inta r;
sint *p3 = (sint *) &c;
for (int i=0; i < 2; i++)
r.v[i] = (int) (b.v[i] * p3[i] & 0xFFFFFFFF);
return r;
}
static inline floata
gather (inta indexes, const void *baseAddr)
{
floata r;
sint *idx = (sint *) &indexes;
flt *src = (flt *) baseAddr;
for (int i=0; i < 2; i++)
r.v[i] = *(src + idx[i]);
return r;
}
static inline inta
add (const inta &b, const inta &c)
{
inta result;
sint *r = (sint *) &result;
for (int i=0; i < 2; i++)
r[i] = b.v[i] + c.v[i];
return result;
}
struct uintv
{
inta data;
inline uintv () { data.v[0] = 0; data.v[1] = 1; }
inline uintv (unsigned int a)
{
for (int i=0; i < 2; i++)
*(uint *) &data.v[i] = a;
}
inline uintv (inta x) : data (x) {}
inline uintv operator* (const uintv &x) const
{ return multiply (data, x.data); }
inline uintv operator+ (const uintv &x) const
{ return uintv (add (data, x.data)); }
inline unsigned short operator< (const uintv &x) const
{ return less_than (data, x.data); }
};
struct floatv
{
floata data;
explicit inline floatv (const uintv &x)
{
uint *p2 = (uint *) &x.data;
for (int i=0; i < 2; i++)
data.v[i] = p2[i];
}
inline floatv (const float *array, const uintv &indexes)
{
const uintv &offsets = indexes * uintv (1);
data = gather (offsets.data, array);
}
unsigned short operator== (const floatv &x) const
{
unsigned short r = 0;
for (int i=0; i < 2; i++)
if (data.v[i] == x.data.v[i]) r |= (1 << i);
return r;
}
};
int
main ()
{
const float array[2] = { 2, 3 };
for (uintv i; (i < 2) == 3; i = i + 2)
{
const floatv ii (i + 2);
floatv a (array, i);
if ((a == ii) != 3)
abort ();
}
}