diff options
author | Jakub Jelinek <jakub@redhat.com> | 2009-08-05 12:54:21 +0000 |
---|---|---|
committer | Jakub Jelinek <jakub@redhat.com> | 2009-08-05 12:54:21 +0000 |
commit | a9dc0d14ccbd7c728613f4cceddd97656a04324a (patch) | |
tree | 8b51893298d3d147ebf2ef364d303b2bfa268f2f | |
parent | 77684cd2f9278bddbdc204bb8cfdd114e4063c13 (diff) |
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.
git-svn-id: https://gcc.gnu.org/svn/gcc/branches/gcc-4_4-branch@150484 138bc75d-0d04-0410-961f-82ee72b054a4
-rw-r--r-- | gcc/ChangeLog | 7 | ||||
-rw-r--r-- | gcc/dse.c | 116 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 5 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/torture/pr40924.C | 111 |
4 files changed, 190 insertions, 49 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 66a3bba4620..bed7b9f88a4 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -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-03 Janis Johnson <janis187@us.ibm.com> PR c/39902 diff --git a/gcc/dse.c b/gcc/dse.c index 3298b4f0754..f7a1cbb007a 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 + /* 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++) + { + if (expanded) + { + /* 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; + r_x = base + offset; + val = *r_x; - by making it into - - val = *(base + offset); - */ - - expanded_address = cselib_expand_value_rtx (mem_address, scratch, 5); + by making it into - /* If this fails, just go with the mem_address. */ - if (!expanded_address) - expanded_address = mem_address; + val = *(base + offset); */ - /* Split the address into canonical BASE + OFFSET terms. */ - address = canon_rtx (expanded_address); + expanded_address = cselib_expand_value_rtx (mem_address, + scratch, 5); - *offset = 0; + /* If this fails, just go with the address from first + iteration. */ + if (!expanded_address) + break; + } + else + expanded_address = mem_address; - if (dump_file) - { - fprintf (dump_file, "\n after cselib_expand address: "); - print_inline_rtx (dump_file, expanded_address, 0); - fprintf (dump_file, "\n"); + /* Split the address into canonical BASE + OFFSET terms. */ + address = canon_rtx (expanded_address); - fprintf (dump_file, "\n after canon_rtx address: "); - print_inline_rtx (dump_file, address, 0); - fprintf (dump_file, "\n"); - } + *offset = 0; - if (GET_CODE (address) == CONST) - address = XEXP (address, 0); + if (dump_file) + { + if (expanded) + { + fprintf (dump_file, "\n after cselib_expand address: "); + print_inline_rtx (dump_file, expanded_address, 0); + fprintf (dump_file, "\n"); + } - if (GET_CODE (address) == PLUS && GET_CODE (XEXP (address, 1)) == CONST_INT) - { - *offset = INTVAL (XEXP (address, 1)); - address = XEXP (address, 0); - } + fprintf (dump_file, "\n after canon_rtx address: "); + print_inline_rtx (dump_file, address, 0); + fprintf (dump_file, "\n"); + } - if (const_or_frame_p (address)) - { - group_info_t group = get_group_info (address); + if (GET_CODE (address) == CONST) + address = XEXP (address, 0); - 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 (GET_CODE (address) == PLUS + && GET_CODE (XEXP (address, 1)) == CONST_INT) + { + *offset = INTVAL (XEXP (address, 1)); + address = XEXP (address, 0); + } - if (*base == NULL) + if (const_or_frame_p (address)) { + group_info_t group = get_group_info (address); + if (dump_file) - fprintf (dump_file, " no cselib val - should be a wild read.\n"); - return false; + 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, " varying cselib base=%d offset = %d\n", - (*base)->value, (int)*offset); + 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 c0d87a44bfd..53eca796403 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -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-04 Jerry DeLisle <jvdelisle@gcc.gnu.org> PR libfortran/40853 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 (); + } +} |