combine: Take known zero bits into account when checking extraction.
authorDominik Vogt <vogt@linux.vnet.ibm.com>
Fri, 27 May 2016 11:38:59 +0000 (11:38 +0000)
committerAndreas Krebbel <krebbel@gcc.gnu.org>
Fri, 27 May 2016 11:38:59 +0000 (11:38 +0000)
gcc/ChangeLog:

* combine.c (make_compound_operation): Take known zero bits into
account when checking for possible zero_extend.

gcc/testsuite/ChangeLog:

* gcc.dg/zero_bits_compound-1.c: New test.
* gcc.dg/zero_bits_compound-2.c: New test.

From-SVN: r236813

gcc/ChangeLog
gcc/combine.c
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.dg/zero_bits_compound-1.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/zero_bits_compound-2.c [new file with mode: 0644]

index 2d59cb5032b38da56d32acbf8f76ee595a9616af..59aa6d1f09ad708acc3d5e7dd3109bd46a0548cc 100644 (file)
@@ -1,3 +1,8 @@
+2016-05-27  Dominik Vogt  <vogt@linux.vnet.ibm.com>
+
+       * combine.c (make_compound_operation): Take known zero bits into
+       account when checking for possible zero_extend.
+
 2016-05-27  Kyrylo Tkachov  <kyrylo.tkachov@arm.com>
 
        * config/aarch64/aarch64.md (ashl<mode>3, SHORT modes):
index cd864ccb0d4f203aad27f267bbd2e1b1b2981d21..4db11b03df1ae447790256cc9ecc62b84dad497e 100644 (file)
@@ -7988,6 +7988,34 @@ make_compound_operation (rtx x, enum rtx_code in_code)
                                                        next_code),
                               i, NULL_RTX, 1, 1, 0, 1);
 
+      /* If the one operand is a paradoxical subreg of a register or memory and
+        the constant (limited to the smaller mode) has only zero bits where
+        the sub expression has known zero bits, this can be expressed as
+        a zero_extend.  */
+      else if (GET_CODE (XEXP (x, 0)) == SUBREG)
+       {
+         rtx sub;
+
+         sub = XEXP (XEXP (x, 0), 0);
+         machine_mode sub_mode = GET_MODE (sub);
+         if ((REG_P (sub) || MEM_P (sub))
+             && GET_MODE_PRECISION (sub_mode) < mode_width)
+           {
+             unsigned HOST_WIDE_INT mode_mask = GET_MODE_MASK (sub_mode);
+             unsigned HOST_WIDE_INT mask;
+
+             /* original AND constant with all the known zero bits set */
+             mask = UINTVAL (XEXP (x, 1)) | (~nonzero_bits (sub, sub_mode));
+             if ((mask & mode_mask) == mode_mask)
+               {
+                 new_rtx = make_compound_operation (sub, next_code);
+                 new_rtx = make_extraction (mode, new_rtx, 0, 0,
+                                            GET_MODE_PRECISION (sub_mode),
+                                            1, 0, in_code == COMPARE);
+               }
+           }
+       }
+
       break;
 
     case LSHIFTRT:
index a9593257eba10d8f6665661a0794af6fd4468070..c209d98a547c6f321f6f689bce3bef57860f5ace 100644 (file)
@@ -1,3 +1,8 @@
+2016-05-27  Dominik Vogt  <vogt@linux.vnet.ibm.com>
+
+       * gcc.dg/zero_bits_compound-1.c: New test.
+       * gcc.dg/zero_bits_compound-2.c: New test.
+
 2016-05-27  Ilya Enkovich  <ilya.enkovich@intel.com>
 
        PR middle-end/71279
diff --git a/gcc/testsuite/gcc.dg/zero_bits_compound-1.c b/gcc/testsuite/gcc.dg/zero_bits_compound-1.c
new file mode 100644 (file)
index 0000000..d78dc43
--- /dev/null
@@ -0,0 +1,42 @@
+/* Test whether an AND mask or'ed with the know zero bits that equals a mode
+   mask is a candidate for zero extendion.  */
+
+/* Note: This test requires that char, int and long have different sizes and the
+   target has a way to do 32 -> 64 bit zero extension other than AND.  */
+
+/* { dg-do compile { target x86_64-*-* s390*-*-* } } */
+/* { dg-require-effective-target lp64 } */
+/* { dg-options "-O3 -dP" } */
+
+unsigned long foo (unsigned char c)
+{
+  unsigned long l;
+  unsigned int i;
+
+  i = ((unsigned int)c) << 8;
+  i |= ((unsigned int)c) << 20;
+  asm volatile ("":::);
+  i = i & 0x0ff0ff00;
+  asm volatile ("":::);
+  l = (unsigned long)i;
+
+  return l;
+}
+
+unsigned long bar (unsigned char c)
+{
+  unsigned long l;
+  unsigned int i;
+
+  i = ((unsigned int)c) << 8;
+  i |= ((unsigned int)c) << 20;
+  asm volatile ("":::);
+  i = i & 0x0ffffff0;
+  asm volatile ("":::);
+  l = (unsigned long)i;
+
+  return l;
+}
+
+/* Check that no pattern containing an AND expression was used.  */
+/* { dg-final { scan-assembler-not "\\(and:" } } */
diff --git a/gcc/testsuite/gcc.dg/zero_bits_compound-2.c b/gcc/testsuite/gcc.dg/zero_bits_compound-2.c
new file mode 100644 (file)
index 0000000..80fd363
--- /dev/null
@@ -0,0 +1,39 @@
+/* Test whether an AND mask or'ed with the know zero bits that equals a mode
+   mask is a candidate for zero extendion.  */
+
+/* { dg-do compile { target x86_64-*-* s390*-*-* } } */
+/* { dg-require-effective-target lp64 } */
+/* { dg-options "-O3 -dP" } */
+
+unsigned long foo (unsigned char c)
+{
+  unsigned long l;
+  unsigned int i;
+
+  i = ((unsigned int)c) << 8;
+  i |= ((unsigned int)c) << 20;
+  asm volatile ("":::);
+  i = i & 0x0fe0fe00;
+  asm volatile ("":::);
+  l = (unsigned long)i;
+
+  return l;
+}
+
+unsigned long bar (unsigned char c)
+{
+  unsigned long l;
+  unsigned int i;
+
+  i = ((unsigned int)c) << 8;
+  i |= ((unsigned int)c) << 20;
+  asm volatile ("":::);
+  i = i & 0x07f007f0;
+  asm volatile ("":::);
+  l = (unsigned long)i;
+
+  return l;
+}
+
+/* Check that an AND expression was used.  */
+/* { dg-final { scan-assembler-times "\\(and:" 2 } } */