re PR rtl-optimization/57130 (Incorrect "and --> extract" conversion in combine)
authorJakub Jelinek <jakub@redhat.com>
Fri, 3 May 2013 12:56:12 +0000 (14:56 +0200)
committerJakub Jelinek <jakub@gcc.gnu.org>
Fri, 3 May 2013 12:56:12 +0000 (14:56 +0200)
PR rtl-optimization/57130
* combine.c (make_compound_operation) <case SUBREG>: Pass
SET instead of COMPARE as in_code to the recursive call
if needed.

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

From-SVN: r198579

gcc/ChangeLog
gcc/combine.c
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.c-torture/execute/pr57130.c [new file with mode: 0644]

index 2b906eb..4bd0ea7 100644 (file)
@@ -1,3 +1,10 @@
+2013-05-03  Jakub Jelinek  <jakub@redhat.com>
+
+       PR rtl-optimization/57130
+       * combine.c (make_compound_operation) <case SUBREG>: Pass
+       SET instead of COMPARE as in_code to the recursive call
+       if needed.
+
 2013-05-03  Uros Bizjak  <ubizjak@gmail.com>
 
        * config/i386/i386.md (isa): Add x64_sse4_noavx and x64_avx members.
index 6d58b19..0792ba3 100644 (file)
@@ -7697,8 +7697,24 @@ make_compound_operation (rtx x, enum rtx_code in_code)
         what it originally did, do this SUBREG as a force_to_mode.  */
       {
        rtx inner = SUBREG_REG (x), simplified;
-       
-       tem = make_compound_operation (inner, in_code);
+       enum rtx_code subreg_code = in_code;
+
+       /* If in_code is COMPARE, it isn't always safe to pass it through
+          to the recursive make_compound_operation call.  */
+       if (subreg_code == COMPARE
+           && (!subreg_lowpart_p (x)
+               || GET_CODE (inner) == SUBREG
+               /* (subreg:SI (and:DI (reg:DI) (const_int 0x800000000)) 0)
+                  is (const_int 0), rather than
+                  (subreg:SI (lshiftrt:DI (reg:DI) (const_int 35)) 0).  */
+               || (GET_CODE (inner) == AND
+                   && CONST_INT_P (XEXP (inner, 1))
+                   && GET_MODE_SIZE (mode) < GET_MODE_SIZE (GET_MODE (inner))
+                   && exact_log2 (UINTVAL (XEXP (inner, 1)))
+                      >= GET_MODE_BITSIZE (mode))))
+         subreg_code = SET;
+
+       tem = make_compound_operation (inner, subreg_code);
 
        simplified
          = simplify_subreg (mode, tem, GET_MODE (inner), SUBREG_BYTE (x));
index e40150a..25a131c 100644 (file)
@@ -1,3 +1,8 @@
+2013-05-03  Jakub Jelinek  <jakub@redhat.com>
+
+       PR rtl-optimization/57130
+       * gcc.c-torture/execute/pr57130.c: New test.
+
 2013-05-03  Uros Bizjak  <ubizjak@gmail.com>
 
        * gcc.target/i386/sse2-init-v2di-2.c: Update scan assembler string.
diff --git a/gcc/testsuite/gcc.c-torture/execute/pr57130.c b/gcc/testsuite/gcc.c-torture/execute/pr57130.c
new file mode 100644 (file)
index 0000000..6113203
--- /dev/null
@@ -0,0 +1,21 @@
+/* PR rtl-optimization/57130 */
+
+struct S { int a, b, c, d; } s[2] = { { 6, 8, -8, -5 }, { 0, 2, -1, 2 } };
+
+__attribute__((noinline, noclone)) void
+foo (struct S r)
+{
+  static int cnt;
+  if (__builtin_memcmp (&r, &s[cnt++], sizeof r) != 0)
+    __builtin_abort ();
+}
+
+int
+main ()
+{
+  struct S r = { 6, 8, -8, -5 };
+  foo (r);
+  r = (struct S) { 0, 2, -1, 2 };
+  foo (r);
+  return 0;
+}