]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
cse.c (lookup_as_function): Delete mode frobbing code.
authorEric Botcazou <ebotcazou@adacore.com>
Thu, 4 Dec 2008 21:47:13 +0000 (21:47 +0000)
committerEric Botcazou <ebotcazou@gcc.gnu.org>
Thu, 4 Dec 2008 21:47:13 +0000 (21:47 +0000)
* 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

gcc/ChangeLog
gcc/cse.c
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.dg/union-5.c [new file with mode: 0644]

index d9b81fede57c4fbd91bd541eeacc1a350cb76f67..e46adae3a5358e0531162136e2514a0ea7c2325e 100644 (file)
@@ -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
index f52f0a9c93d06366c6f3335c2e1608c7e0538f6c..91cb108e94c7cf0133f9d9b39f4dc767fa6c08d5 100644 (file)
--- 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;
     }
index 9c9d674083cfc8038de778e06b17fcecb4737e97..715ecd67264da29c2cbec6dd5563bed039a22237 100644 (file)
@@ -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 (file)
index 0000000..ac5322b
--- /dev/null
@@ -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;
+}