]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
re PR target/36613 (likely codegen bug)
authorMichael Matz <matz@suse.de>
Wed, 6 Aug 2008 15:34:45 +0000 (15:34 +0000)
committerMichael Matz <matz@gcc.gnu.org>
Wed, 6 Aug 2008 15:34:45 +0000 (15:34 +0000)
        PR target/36613

        * reload.c (push_reload): Merge in,out,in_reg,out_reg members
        for reused reload, instead of overwriting them.

        * gcc.target/i386/pr36613.c: New testcase.

From-SVN: r138807

gcc/ChangeLog
gcc/reload.c
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.target/i386/pr36613.c [new file with mode: 0644]

index a22491f20e07f31d53fdeb5f1335a8e04232b5f0..a08bd6e6f691208b73fb26f97cd37cb49cc998d0 100644 (file)
@@ -1,3 +1,9 @@
+2008-08-06  Michael Matz  <matz@suse.de>
+
+       PR target/36613
+       * reload.c (push_reload): Merge in,out,in_reg,out_reg members
+       for reused reload, instead of overwriting them.
+
 2008-08-06  H.J. Lu  <hongjiu.lu@intel.com>
 
        PR middle-end/37009
index 93fff40456985e8d35fb91e7800909682405d75a..5a79c44e8745e44a4ad701796c57a4e1736edc40 100644 (file)
@@ -1403,13 +1403,36 @@ push_reload (rtx in, rtx out, rtx *inloc, rtx *outloc,
              else
                remove_address_replacements (rld[i].in);
            }
-         rld[i].in = in;
-         rld[i].in_reg = in_reg;
+         /* When emitting reloads we don't necessarily look at the in-
+            and outmode, but also directly at the operands (in and out).
+            So we can't simply overwrite them with whatever we have found
+            for this (to-be-merged) reload, we have to "merge" that too.
+            Reusing another reload already verified that we deal with the
+            same operands, just possibly in different modes.  So we
+            overwrite the operands only when the new mode is larger.
+            See also PR33613.  */
+         if (!rld[i].in
+             || GET_MODE_SIZE (GET_MODE (in))
+                  > GET_MODE_SIZE (GET_MODE (rld[i].in)))
+           rld[i].in = in;
+         if (!rld[i].in_reg
+             || (in_reg
+                 && GET_MODE_SIZE (GET_MODE (in_reg))
+                    > GET_MODE_SIZE (GET_MODE (rld[i].in_reg))))
+           rld[i].in_reg = in_reg;
        }
       if (out != 0)
        {
-         rld[i].out = out;
-         rld[i].out_reg = outloc ? *outloc : 0;
+         if (!rld[i].out
+             || (out
+                 && GET_MODE_SIZE (GET_MODE (out))
+                    > GET_MODE_SIZE (GET_MODE (rld[i].out))))
+           rld[i].out = out;
+         if (outloc
+             && (!rld[i].out_reg
+                 || GET_MODE_SIZE (GET_MODE (*outloc))
+                    > GET_MODE_SIZE (GET_MODE (rld[i].out_reg))))
+           rld[i].out_reg = *outloc;
        }
       if (reg_class_subset_p (rclass, rld[i].rclass))
        rld[i].rclass = rclass;
index ead96385f803049f6928b4ddc22c14410c301447..d5b229a70e23f44ad7c152bd005237aae2df0b5b 100644 (file)
@@ -1,3 +1,8 @@
+2008-08-06  Michael Matz  <matz@suse.de>
+
+       PR target/36613
+       * gcc.target/i386/pr36613.c: New testcase.
+
 2008-08-06  H.J. Lu  <hongjiu.lu@intel.com>
 
        PR middle-end/37009
diff --git a/gcc/testsuite/gcc.target/i386/pr36613.c b/gcc/testsuite/gcc.target/i386/pr36613.c
new file mode 100644 (file)
index 0000000..e9d7d11
--- /dev/null
@@ -0,0 +1,44 @@
+/* { dg-do run { target { { i?86-*-linux* x86_64-*-linux* } && ilp32 } } } */
+/* { dg-options "-Os" } */
+/* PR target/36613 */
+
+extern void abort (void);
+
+static inline int
+lshifts (int val, int cnt)
+{
+  if (val < 0)
+    return val;
+  return val << cnt;
+}
+
+static inline unsigned int
+lshiftu (unsigned int val, unsigned int cnt)
+{
+  if (cnt >= sizeof (unsigned int) * __CHAR_BIT__
+      || val > ((__INT_MAX__ * 2U) >> cnt))
+    return val;
+  return val << cnt;
+}
+
+static inline int
+rshifts (int val, unsigned int cnt)
+{
+  if (val < 0 || cnt >= sizeof (int) * __CHAR_BIT__)
+    return val;
+  return val >> cnt;
+}
+
+int
+foo (unsigned int val)
+{
+  return rshifts (1 + val, lshifts (lshiftu (val, val), 1));
+}
+
+int
+main (void)
+{
+  if (foo (1) != 0)
+    abort ();
+  return 0;
+}