]> 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:54:09 +0000 (21:54 +0000)
committerEric Botcazou <ebotcazou@gcc.gnu.org>
Thu, 4 Dec 2008 21:54:09 +0000 (21:54 +0000)
* cse.c (lookup_as_function): Delete mode frobbing code.
(fold_rtx_subreg): Re-implement it there for SUBREGs.

Co-Authored-By: Gary Funck <gary@intrepid.com>
From-SVN: r142446

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

index 81ef178612f4b571f638497ce57800065e50a6da..e6db964c29d3198678feeaf8ba960ab472e8bc22 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.
+       (fold_rtx_subreg): Re-implement it there for SUBREGs.
+
 2008-11-30  Eric Botcazou  <ebotcazou@adacore.com>
 
        PR target/38287
index 15a2a7af556c73602919d2e8520b5ff0d6d68ecd..31ee15c7656cda2cdc7c94b1da528983f54cf592 100644 (file)
--- a/gcc/cse.c
+++ b/gcc/cse.c
@@ -1455,17 +1455,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;
 
@@ -3258,6 +3247,7 @@ static rtx
 fold_rtx_subreg (rtx x, rtx insn)
 {
   enum machine_mode mode = GET_MODE (x);
+  enum machine_mode imode = GET_MODE (SUBREG_REG (x));
   rtx folded_arg0;
   rtx const_arg0;
   rtx new;
@@ -3267,6 +3257,21 @@ fold_rtx_subreg (rtx x, rtx insn)
       || (new = lookup_as_function (x, CONST_DOUBLE)) != 0)
     return new;
 
+  /* 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 = lookup_as_function (y, CONST_INT);
+         if (new)
+           return gen_lowpart (mode, new);
+       }
+    }
+
   /* If this is a paradoxical SUBREG, we have no idea what value the
      extra bits would have.  However, if the operand is equivalent to
      a SUBREG whose operand is the same as our mode, and all the modes
@@ -3275,9 +3280,8 @@ fold_rtx_subreg (rtx x, rtx insn)
 
      Similarly if we find an integer constant.  */
 
-  if (GET_MODE_SIZE (mode) > GET_MODE_SIZE (GET_MODE (SUBREG_REG (x))))
+  if (GET_MODE_SIZE (mode) > GET_MODE_SIZE (imode))
     {
-      enum machine_mode imode = GET_MODE (SUBREG_REG (x));
       struct table_elt *elt;
 
       if (GET_MODE_SIZE (mode) <= UNITS_PER_WORD
@@ -3310,8 +3314,7 @@ fold_rtx_subreg (rtx x, rtx insn)
 
   if (folded_arg0 != SUBREG_REG (x))
     {
-      new = simplify_subreg (mode, folded_arg0,
-                            GET_MODE (SUBREG_REG (x)), SUBREG_BYTE (x));
+      new = simplify_subreg (mode, folded_arg0, imode, SUBREG_BYTE (x));
       if (new)
        return new;
     }
index 53c1a0ba3583849117897ce9fbd04b7267e697aa..ec52ece7d1a53a3ff2c1a0ca9a00c529c0d4e2bc 100644 (file)
@@ -1,3 +1,7 @@
+2008-12-04  Eric Botcazou  <ebotcazou@adacore.com>
+
+       * gcc.dg/union-5.c: New test.
+
 2008-11-30  Eric Botcazou  <ebotcazou@adacore.com>
 
        * g++.dg/opt/reload3.C: New test.
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..d0dfaa0
--- /dev/null
@@ -0,0 +1,46 @@
+/* { dg-do run } */
+/* { dg-options "-O -fgcse" } */
+
+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;
+}