[PATCH PR82439][simplify-rtx] Simplify (x | y) == x -> (y & ~x) == 0
authorSudakshina Das <sudi.das@arm.com>
Fri, 5 Jan 2018 10:45:37 +0000 (10:45 +0000)
committerSudakshina Das <sudi@gcc.gnu.org>
Fri, 5 Jan 2018 10:45:37 +0000 (10:45 +0000)
This patch add support for the missing transformation of
(x | y) == x -> (y & ~x) == 0. The transformation for (x & y) == x case
already exists in simplify-rtx.c since 2014 as of r218503 and this patch
only adds a couple of extra patterns for the IOR case. This benefits
targets that have the BICS instruction to generate better code. For
targets that do not have the BICS instructions, it still results in
no worse code generation and gives out 2 instructions.

ChangeLog Entries:

*** gcc/ChangeLog ***

2018-01-05  Sudakshina Das  <sudi.das@arm.com>

PR target/82439
* simplify-rtx.c (simplify_relational_operation_1): Add simplifications
of (x|y) == x for BICS pattern.

*** gcc/testsuite/ChangeLog ***

2018-01-05  Sudakshina Das  <sudi.das@arm.com>

PR target/82439
* gcc.target/aarch64/bics_5.c: New test.
* gcc.target/arm/bics_5.c: Likewise.

From-SVN: r256275

gcc/ChangeLog
gcc/simplify-rtx.c
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.target/aarch64/bics_5.c [new file with mode: 0644]
gcc/testsuite/gcc.target/arm/bics_5.c [new file with mode: 0644]

index 14cd939eb3f0717d213689eeb0080f751edbb760..d9b9efd92bf36e4e4d38d26cf4d731ebf8ba687d 100644 (file)
@@ -1,3 +1,9 @@
+2018-01-05  Sudakshina Das  <sudi.das@arm.com>
+
+       PR target/82439
+       * simplify-rtx.c (simplify_relational_operation_1): Add simplifications
+       of (x|y) == x for BICS pattern.
+
 2018-01-05  Jakub Jelinek  <jakub@redhat.com>
 
        PR tree-optimization/83605
index e7273a4fdb40ae7a2d1ddc023f7896999fe5eae8..6cb5a6e5d244f40013de114e0cf0ce4c37ecf12f 100644 (file)
@@ -5051,34 +5051,38 @@ simplify_relational_operation_1 (enum rtx_code code, machine_mode mode,
                                    simplify_gen_binary (XOR, cmp_mode,
                                                         XEXP (op0, 1), op1));
 
-  /* (eq/ne (and x y) x) simplifies to (eq/ne (and (not y) x) 0), which
-     can be implemented with a BICS instruction on some targets, or
-     constant-folded if y is a constant.  */
+  /* Simplify eq/ne (and/ior x y) x/y) for targets with a BICS instruction or
+     constant folding if x/y is a constant.  */
   if ((code == EQ || code == NE)
-      && op0code == AND
-      && rtx_equal_p (XEXP (op0, 0), op1)
+      && (op0code == AND || op0code == IOR)
       && !side_effects_p (op1)
       && op1 != CONST0_RTX (cmp_mode))
     {
-      rtx not_y = simplify_gen_unary (NOT, cmp_mode, XEXP (op0, 1), cmp_mode);
-      rtx lhs = simplify_gen_binary (AND, cmp_mode, not_y, XEXP (op0, 0));
+      /* Both (eq/ne (and x y) x) and (eq/ne (ior x y) y) simplify to
+        (eq/ne (and (not y) x) 0).  */
+      if ((op0code == AND && rtx_equal_p (XEXP (op0, 0), op1))
+         || (op0code == IOR && rtx_equal_p (XEXP (op0, 1), op1)))
+       {
+         rtx not_y = simplify_gen_unary (NOT, cmp_mode, XEXP (op0, 1),
+                                         cmp_mode);
+         rtx lhs = simplify_gen_binary (AND, cmp_mode, not_y, XEXP (op0, 0));
 
-      return simplify_gen_relational (code, mode, cmp_mode, lhs,
-                                     CONST0_RTX (cmp_mode));
-    }
+         return simplify_gen_relational (code, mode, cmp_mode, lhs,
+                                         CONST0_RTX (cmp_mode));
+       }
 
-  /* Likewise for (eq/ne (and x y) y).  */
-  if ((code == EQ || code == NE)
-      && op0code == AND
-      && rtx_equal_p (XEXP (op0, 1), op1)
-      && !side_effects_p (op1)
-      && op1 != CONST0_RTX (cmp_mode))
-    {
-      rtx not_x = simplify_gen_unary (NOT, cmp_mode, XEXP (op0, 0), cmp_mode);
-      rtx lhs = simplify_gen_binary (AND, cmp_mode, not_x, XEXP (op0, 1));
+      /* Both (eq/ne (and x y) y) and (eq/ne (ior x y) x) simplify to
+        (eq/ne (and (not x) y) 0).  */
+      if ((op0code == AND && rtx_equal_p (XEXP (op0, 1), op1))
+         || (op0code == IOR && rtx_equal_p (XEXP (op0, 0), op1)))
+       {
+         rtx not_x = simplify_gen_unary (NOT, cmp_mode, XEXP (op0, 0),
+                                         cmp_mode);
+         rtx lhs = simplify_gen_binary (AND, cmp_mode, not_x, XEXP (op0, 1));
 
-      return simplify_gen_relational (code, mode, cmp_mode, lhs,
-                                     CONST0_RTX (cmp_mode));
+         return simplify_gen_relational (code, mode, cmp_mode, lhs,
+                                         CONST0_RTX (cmp_mode));
+       }
     }
 
   /* (eq/ne (bswap x) C1) simplifies to (eq/ne x C2) with C2 swapped.  */
index 990cefa3452eb960e8825135b7a62190fe3aee01..5f1c7716415c1afdf14eb5c9b5a77f0a83cefd3a 100644 (file)
@@ -1,3 +1,9 @@
+2018-01-05  Sudakshina Das  <sudi.das@arm.com>
+
+       PR target/82439
+       * gcc.target/aarch64/bics_5.c: New test.
+       * gcc.target/arm/bics_5.c: Likewise.
+
 2018-01-05  Jakub Jelinek  <jakub@redhat.com>
 
        PR tree-optimization/83605
diff --git a/gcc/testsuite/gcc.target/aarch64/bics_5.c b/gcc/testsuite/gcc.target/aarch64/bics_5.c
new file mode 100644 (file)
index 0000000..b9c2c40
--- /dev/null
@@ -0,0 +1,86 @@
+/* { dg-do run } */
+/* { dg-options "-O2 --save-temps -fno-inline" } */
+
+extern void abort (void);
+
+int
+bics_si_test1 (int a, int b, int c)
+{
+  if ((a | b) == a)
+    return a;
+  else
+    return c;
+}
+
+int
+bics_si_test2 (int a, int b, int c)
+{
+  if ((a | b) == b)
+    return b;
+  else
+    return c;
+}
+
+typedef long long s64;
+
+s64
+bics_di_test1 (s64 a, s64 b, s64 c)
+{
+  if ((a | b) == a)
+    return a;
+  else
+    return c;
+}
+
+s64
+bics_di_test2 (s64 a, s64 b, s64 c)
+{
+  if ((a | b) == b)
+    return b;
+  else
+    return c;
+}
+
+int
+main ()
+{
+  int x;
+  s64 y;
+
+  x = bics_si_test1 (0xf00d, 0xf11f, 0);
+  if (x != 0)
+    abort ();
+
+  x = bics_si_test1 (0xf11f, 0xf00d, 0);
+  if (x != 0xf11f)
+    abort ();
+
+  x = bics_si_test2 (0xf00d, 0xf11f, 0);
+  if (x != 0xf11f)
+    abort ();
+
+  x = bics_si_test2 (0xf11f, 0xf00d, 0);
+  if (x != 0)
+    abort ();
+
+  y = bics_di_test1 (0x10001000f00dll, 0x12341000f00dll, 0ll);
+  if (y != 0)
+    abort ();
+
+  y = bics_di_test1 (0x12341000f00dll, 0x10001000f00dll, 0ll);
+  if (y != 0x12341000f00dll)
+    abort ();
+
+  y = bics_di_test2 (0x10001000f00dll, 0x12341000f00dll, 0ll);
+  if (y != 0x12341000f00dll)
+    abort ();
+
+  y = bics_di_test2 (0x12341000f00dll, 0x10001000f00dll, 0ll);
+  if (y != 0)
+    abort ();
+
+  return 0;
+}
+
+/* { dg-final { scan-assembler-times "bics\twzr, w\[0-9\]+, w\[0-9\]+" 2 } } */
+/* { dg-final { scan-assembler-times "bics\txzr, x\[0-9\]+, x\[0-9\]+" 2 } } */
diff --git a/gcc/testsuite/gcc.target/arm/bics_5.c b/gcc/testsuite/gcc.target/arm/bics_5.c
new file mode 100644 (file)
index 0000000..6f84902
--- /dev/null
@@ -0,0 +1,46 @@
+/* { dg-do run } */
+/* { dg-options "-O2 --save-temps -fno-inline" } */
+/* { dg-require-effective-target arm32 } */
+extern void abort (void);
+int
+bics_si_test1 (int a, int b, int c)
+{
+  if ((a | b) == a)
+    return a;
+  else
+    return c;
+}
+
+int
+bics_si_test2 (int a, int b, int c)
+{
+  if ((a | b) == b)
+    return b;
+  else
+    return c;
+}
+
+int
+main ()
+{
+  int x;
+  x = bics_si_test1 (0xf00d, 0xf11f, 0);
+  if (x != 0)
+    abort ();
+
+  x = bics_si_test1 (0xf11f, 0xf00d, 0);
+  if (x != 0xf11f)
+    abort ();
+
+  x = bics_si_test2 (0xf00d, 0xf11f, 0);
+  if (x != 0xf11f)
+    abort ();
+
+  x = bics_si_test2 (0xf11f, 0xf00d, 0);
+  if (x != 0)
+    abort ();
+
+  return 0;
+}
+
+/* { dg-final { scan-assembler-times "bics\tr\[0-9\]+, r\[0-9\]+, r\[0-9\]+" 2 } } */