re PR rtl-optimization/63843 (wrong code generation at -O1 and higher)
authorJakub Jelinek <jakub@redhat.com>
Wed, 19 Nov 2014 08:18:53 +0000 (09:18 +0100)
committerJakub Jelinek <jakub@gcc.gnu.org>
Wed, 19 Nov 2014 08:18:53 +0000 (09:18 +0100)
PR rtl-optimization/63843
* simplify-rtx.c (simplify_binary_operation_1) <case ASHIFTRT>: For
optimization of ashiftrt of subreg of lshiftrt, check that code
is ASHIFTRT.

* gcc.c-torture/execute/pr63843.c: New test.

From-SVN: r217753

gcc/ChangeLog
gcc/simplify-rtx.c
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.c-torture/execute/pr63843.c [new file with mode: 0644]

index 7dcfba38c5add48c35f9f6480d8fb8fa8cef770a..b1bb78ffb0e745df257a7d201c12afd662d1a1eb 100644 (file)
@@ -1,3 +1,10 @@
+2014-11-19  Jakub Jelinek  <jakub@redhat.com>
+
+       PR rtl-optimization/63843
+       * simplify-rtx.c (simplify_binary_operation_1) <case ASHIFTRT>: For
+       optimization of ashiftrt of subreg of lshiftrt, check that code
+       is ASHIFTRT.
+
 2014-11-18  Andrew MacLeod  <amacleod@redhat.com>
 
        * attribs.c (decl_attributes): Remove always true condition,
index 8094c7584ac12aa718dfee2117fd2077d4811bd9..022e36fe7c0323c73404eacc0044dd2cd8caeac4 100644 (file)
@@ -3105,43 +3105,42 @@ simplify_binary_operation_1 (enum rtx_code code, machine_mode mode,
          && ! side_effects_p (op1))
        return op0;
       /* Given:
-         scalar modes M1, M2
-         scalar constants c1, c2
-         size (M2) > size (M1)
-         c1 == size (M2) - size (M1)
-         optimize:
-         (ashiftrt:M1 (subreg:M1 (lshiftrt:M2 (reg:M2)
-                                              (const_int <c1>))
-                                  <low_part>)
-                      (const_int <c2>))
-         to:
-         (subreg:M1 (ashiftrt:M2 (reg:M2)
-                                 (const_int <c1 + c2>))
-          <low_part>).  */
-      if (!VECTOR_MODE_P (mode)
-          && SUBREG_P (op0)
-          && CONST_INT_P (op1)
-          && (GET_CODE (SUBREG_REG (op0)) == LSHIFTRT)
-          && !VECTOR_MODE_P (GET_MODE (SUBREG_REG (op0)))
-          && CONST_INT_P (XEXP (SUBREG_REG (op0), 1))
-          && (GET_MODE_BITSIZE (GET_MODE (SUBREG_REG (op0)))
-              > GET_MODE_BITSIZE (mode))
-          && (INTVAL (XEXP (SUBREG_REG (op0), 1))
-              == (GET_MODE_BITSIZE (GET_MODE (SUBREG_REG (op0)))
-                  - GET_MODE_BITSIZE (mode)))
-          && subreg_lowpart_p (op0))
-        {
-          rtx tmp = GEN_INT (INTVAL (XEXP (SUBREG_REG (op0), 1))
-                             + INTVAL (op1));
-          machine_mode inner_mode = GET_MODE (SUBREG_REG (op0));
-          tmp = simplify_gen_binary (ASHIFTRT,
-                                     GET_MODE (SUBREG_REG (op0)),
-                                     XEXP (SUBREG_REG (op0), 0),
-                                     tmp);
-          return simplify_gen_subreg (mode, tmp, inner_mode,
-                                      subreg_lowpart_offset (mode,
-                                                             inner_mode));
-        }
+        scalar modes M1, M2
+        scalar constants c1, c2
+        size (M2) > size (M1)
+        c1 == size (M2) - size (M1)
+        optimize:
+        (ashiftrt:M1 (subreg:M1 (lshiftrt:M2 (reg:M2) (const_int <c1>))
+                                <low_part>)
+                     (const_int <c2>))
+        to:
+        (subreg:M1 (ashiftrt:M2 (reg:M2) (const_int <c1 + c2>))
+                   <low_part>).  */
+      if (code == ASHIFTRT
+         && !VECTOR_MODE_P (mode)
+         && SUBREG_P (op0)
+         && CONST_INT_P (op1)
+         && GET_CODE (SUBREG_REG (op0)) == LSHIFTRT
+         && !VECTOR_MODE_P (GET_MODE (SUBREG_REG (op0)))
+         && CONST_INT_P (XEXP (SUBREG_REG (op0), 1))
+         && (GET_MODE_BITSIZE (GET_MODE (SUBREG_REG (op0)))
+             > GET_MODE_BITSIZE (mode))
+         && (INTVAL (XEXP (SUBREG_REG (op0), 1))
+             == (GET_MODE_BITSIZE (GET_MODE (SUBREG_REG (op0)))
+                 - GET_MODE_BITSIZE (mode)))
+         && subreg_lowpart_p (op0))
+       {
+         rtx tmp = GEN_INT (INTVAL (XEXP (SUBREG_REG (op0), 1))
+                            + INTVAL (op1));
+         machine_mode inner_mode = GET_MODE (SUBREG_REG (op0));
+         tmp = simplify_gen_binary (ASHIFTRT,
+                                    GET_MODE (SUBREG_REG (op0)),
+                                    XEXP (SUBREG_REG (op0), 0),
+                                    tmp);
+         return simplify_gen_subreg (mode, tmp, inner_mode,
+                                     subreg_lowpart_offset (mode,
+                                                            inner_mode));
+       }
     canonicalize_shift:
       if (SHIFT_COUNT_TRUNCATED && CONST_INT_P (op1))
        {
index 1a56e1ac9edbdea8a188db8f647713ebe5c6d68a..118805c26e19f10ba56bbe747dec0ef4f6dfd430 100644 (file)
@@ -1,3 +1,8 @@
+2014-11-19  Jakub Jelinek  <jakub@redhat.com>
+
+       PR rtl-optimization/63843
+       * gcc.c-torture/execute/pr63843.c: New test.
+
 2014-11-18  James Greenhalgh  <james.greenhalgh@arm.com>
 
        PR target/63937
diff --git a/gcc/testsuite/gcc.c-torture/execute/pr63843.c b/gcc/testsuite/gcc.c-torture/execute/pr63843.c
new file mode 100644 (file)
index 0000000..9f6c7b0
--- /dev/null
@@ -0,0 +1,31 @@
+/* PR rtl-optimization/63843 */
+
+static inline __attribute__ ((always_inline))
+unsigned short foo (unsigned short v)
+{
+  return (v << 8) | (v >> 8);
+}
+
+unsigned short __attribute__ ((noinline, noclone, hot))
+bar (unsigned char *x)
+{
+  unsigned int a;
+  unsigned short b;
+  __builtin_memcpy (&a, &x[0], sizeof (a));
+  a ^= 0x80808080U;
+  __builtin_memcpy (&x[0], &a, sizeof (a));
+  __builtin_memcpy (&b, &x[2], sizeof (b));
+  return foo (b);
+}
+
+int
+main ()
+{
+  unsigned char x[8] = { 0x01, 0x01, 0x01, 0x01 };
+  if (__CHAR_BIT__ == 8
+      && sizeof (short) == 2
+      && sizeof (int) == 4
+      && bar (x) != 0x8181U)
+    __builtin_abort ();
+  return 0;
+}