From 403c752036db9af05c6d40804df668d3f3cbaf52 Mon Sep 17 00:00:00 2001 From: Jakub Jelinek Date: Wed, 5 Aug 2009 14:36:34 +0200 Subject: [PATCH] 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 --- gcc/ChangeLog | 7 ++ gcc/dse.c | 140 ++++++++++++++----------- gcc/testsuite/ChangeLog | 5 + gcc/testsuite/g++.dg/torture/pr40924.C | 111 ++++++++++++++++++++ 4 files changed, 202 insertions(+), 61 deletions(-) create mode 100644 gcc/testsuite/g++.dg/torture/pr40924.C diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 075b612954e..7fec75887b5 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,10 @@ +2009-08-05 Jakub Jelinek + + 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 * graphite-sese-to-poly.c (build_pbb_drs): Remove build alias set diff --git a/gcc/dse.c b/gcc/dse.c index 0fc2aa9c1bf..2338d3240ba 100644 --- a/gcc/dse.c +++ b/gcc/dse.c @@ -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; } diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 77238de44b5..e34aa8d8b2e 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2009-08-05 Jakub Jelinek + + PR rtl-optimization/40924 + * g++.dg/torture/pr40924.C: New test. + 2009-08-05 Manuel López-Ibáñez PR c++/36069 diff --git a/gcc/testsuite/g++.dg/torture/pr40924.C b/gcc/testsuite/g++.dg/torture/pr40924.C new file mode 100644 index 00000000000..9140da3ba3b --- /dev/null +++ b/gcc/testsuite/g++.dg/torture/pr40924.C @@ -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 (); + } +}