aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorDominik Vogt <vogt@linux.vnet.ibm.com>2016-05-27 11:38:59 +0000
committerAndreas Krebbel <krebbel@gcc.gnu.org>2016-05-27 11:38:59 +0000
commit6a813c9659aec29ba18173f5d070c846a0919d60 (patch)
tree0fff9490dbeec47e35828223b26554340ab7390f /gcc
parent4bc72f35f3322302a0672165bc9dc90ca0fc4b97 (diff)
downloadgcc-6a813c9659aec29ba18173f5d070c846a0919d60.zip
gcc-6a813c9659aec29ba18173f5d070c846a0919d60.tar.gz
gcc-6a813c9659aec29ba18173f5d070c846a0919d60.tar.bz2
combine: Take known zero bits into account when checking extraction.
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
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog5
-rw-r--r--gcc/combine.c28
-rw-r--r--gcc/testsuite/ChangeLog5
-rw-r--r--gcc/testsuite/gcc.dg/zero_bits_compound-1.c42
-rw-r--r--gcc/testsuite/gcc.dg/zero_bits_compound-2.c39
5 files changed, 119 insertions, 0 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 2d59cb5..59aa6d1 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -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):
diff --git a/gcc/combine.c b/gcc/combine.c
index cd864cc..4db11b0 100644
--- a/gcc/combine.c
+++ b/gcc/combine.c
@@ -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:
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index a959325..c209d98 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -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
index 0000000..d78dc43
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/zero_bits_compound-1.c
@@ -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
index 0000000..80fd363
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/zero_bits_compound-2.c
@@ -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 } } */