aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJakub Jelinek <jakub@redhat.com>2009-08-05 12:54:21 +0000
committerJakub Jelinek <jakub@redhat.com>2009-08-05 12:54:21 +0000
commita9dc0d14ccbd7c728613f4cceddd97656a04324a (patch)
tree8b51893298d3d147ebf2ef364d303b2bfa268f2f
parent77684cd2f9278bddbdc204bb8cfdd114e4063c13 (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/ChangeLog7
-rw-r--r--gcc/dse.c116
-rw-r--r--gcc/testsuite/ChangeLog5
-rw-r--r--gcc/testsuite/g++.dg/torture/pr40924.C111
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 ();
+ }
+}