aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEric Botcazou <ebotcazou@adacore.com>2008-12-04 21:47:13 +0000
committerEric Botcazou <ebotcazou@gcc.gnu.org>2008-12-04 21:47:13 +0000
commitf5f8d79dec035521d9c869e65b37636d934f66a3 (patch)
tree77e1652f735ed18f6ab1eb91f6bcdb8d0f99468b
parentf782c65c3da796b4eb907daa55a160f1203ee5e6 (diff)
downloadgcc-f5f8d79dec035521d9c869e65b37636d934f66a3.zip
gcc-f5f8d79dec035521d9c869e65b37636d934f66a3.tar.gz
gcc-f5f8d79dec035521d9c869e65b37636d934f66a3.tar.bz2
cse.c (lookup_as_function): Delete mode frobbing code.
* cse.c (lookup_as_function): Delete mode frobbing code. (equiv_constant): Re-implement it there for SUBREGs. Co-Authored-By: Gary Funck <gary@intrepid.com> From-SVN: r142443
-rw-r--r--gcc/ChangeLog6
-rw-r--r--gcc/cse.c32
-rw-r--r--gcc/testsuite/ChangeLog4
-rw-r--r--gcc/testsuite/gcc.dg/union-5.c46
4 files changed, 75 insertions, 13 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index d9b81fe..e46adae 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,9 @@
+2008-12-04 Eric Botcazou <ebotcazou@adacore.com>
+ Gary Funck <gary@intrepid.com>
+
+ * cse.c (lookup_as_function): Delete mode frobbing code.
+ (equiv_constant): Re-implement it there for SUBREGs.
+
2008-12-04 Richard Guenther <rguenther@suse.de>
PR middle-end/36509
diff --git a/gcc/cse.c b/gcc/cse.c
index f52f0a9..91cb108 100644
--- a/gcc/cse.c
+++ b/gcc/cse.c
@@ -1364,17 +1364,6 @@ lookup_as_function (rtx x, enum rtx_code code)
struct table_elt *p
= lookup (x, SAFE_HASH (x, VOIDmode), GET_MODE (x));
- /* If we are looking for a CONST_INT, the mode doesn't really matter, as
- long as we are narrowing. So if we looked in vain for a mode narrower
- than word_mode before, look for word_mode now. */
- if (p == 0 && code == CONST_INT
- && GET_MODE_SIZE (GET_MODE (x)) < GET_MODE_SIZE (word_mode))
- {
- x = copy_rtx (x);
- PUT_MODE (x, word_mode);
- p = lookup (x, SAFE_HASH (x, VOIDmode), word_mode);
- }
-
if (p == 0)
return 0;
@@ -3641,6 +3630,8 @@ equiv_constant (rtx x)
if (GET_CODE (x) == SUBREG)
{
+ enum machine_mode mode = GET_MODE (x);
+ enum machine_mode imode = GET_MODE (SUBREG_REG (x));
rtx new_rtx;
/* See if we previously assigned a constant value to this SUBREG. */
@@ -3649,10 +3640,25 @@ equiv_constant (rtx x)
|| (new_rtx = lookup_as_function (x, CONST_FIXED)) != 0)
return new_rtx;
+ /* If we didn't and if doing so makes sense, see if we previously
+ assigned a constant value to the enclosing word mode SUBREG. */
+ if (GET_MODE_SIZE (mode) < GET_MODE_SIZE (word_mode)
+ && GET_MODE_SIZE (word_mode) < GET_MODE_SIZE (imode))
+ {
+ int byte = SUBREG_BYTE (x) - subreg_lowpart_offset (mode, word_mode);
+ if (byte >= 0 && (byte % UNITS_PER_WORD) == 0)
+ {
+ rtx y = gen_rtx_SUBREG (word_mode, SUBREG_REG (x), byte);
+ new_rtx = lookup_as_function (y, CONST_INT);
+ if (new_rtx)
+ return gen_lowpart (mode, new_rtx);
+ }
+ }
+
+ /* Otherwise see if we already have a constant for the inner REG. */
if (REG_P (SUBREG_REG (x))
&& (new_rtx = equiv_constant (SUBREG_REG (x))) != 0)
- return simplify_subreg (GET_MODE (x), new_rtx,
- GET_MODE (SUBREG_REG (x)), SUBREG_BYTE (x));
+ return simplify_subreg (mode, new_rtx, imode, SUBREG_BYTE (x));
return 0;
}
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 9c9d674..715ecd6 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,7 @@
+2008-12-04 Eric Botcazou <ebotcazou@adacore.com>
+
+ * gcc.dg/union-5.c: New test.
+
2008-12-04 Jason Merrill <jason@redhat.com>
PR c++/37906
diff --git a/gcc/testsuite/gcc.dg/union-5.c b/gcc/testsuite/gcc.dg/union-5.c
new file mode 100644
index 0000000..ac5322b
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/union-5.c
@@ -0,0 +1,46 @@
+/* { dg-do run } */
+/* { dg-options "-O -fgcse -fno-split-wide-types" } */
+
+extern void abort(void);
+
+typedef unsigned short int uint16_t;
+typedef unsigned int uint32_t;
+typedef unsigned long long uint64_t;
+
+typedef struct
+{
+ uint16_t thread;
+ uint16_t phase;
+} s32;
+
+typedef union
+{
+ uint32_t i;
+ s32 s;
+} u32;
+
+typedef union
+{
+ uint64_t i;
+ u32 u;
+} u64;
+
+static __attribute__((noinline))
+void foo(int val)
+{
+ u64 data;
+ uint32_t thread;
+
+ data.u.i = 0x10000L;
+ thread = data.u.s.thread;
+ if (val)
+ abort ();
+ if (thread)
+ abort ();
+}
+
+int main(void)
+{
+ foo (0);
+ return 0;
+}