summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorsudi <sudi@138bc75d-0d04-0410-961f-82ee72b054a4>2018-01-05 10:45:37 +0000
committersudi <sudi@138bc75d-0d04-0410-961f-82ee72b054a4>2018-01-05 10:45:37 +0000
commit5b6f66f36f1a121514d0a104fad25b8cb6603a39 (patch)
tree0d732f1a8c2df27c03d68a309676fa6b4895de39
parent8c9c312599ad7ea97348d8afaa8f430dd0b5cdda (diff)
downloadgcc-5b6f66f36f1a121514d0a104fad25b8cb6603a39.tar.gz
[PATCH PR82439][simplify-rtx] Simplify (x | y) == x -> (y & ~x) == 0
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. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@256275 138bc75d-0d04-0410-961f-82ee72b054a4
-rw-r--r--gcc/ChangeLog6
-rw-r--r--gcc/simplify-rtx.c46
-rw-r--r--gcc/testsuite/ChangeLog6
-rw-r--r--gcc/testsuite/gcc.target/aarch64/bics_5.c86
-rw-r--r--gcc/testsuite/gcc.target/arm/bics_5.c46
5 files changed, 169 insertions, 21 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 14cd939eb3f..d9b9efd92bf 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -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
diff --git a/gcc/simplify-rtx.c b/gcc/simplify-rtx.c
index e7273a4fdb4..6cb5a6e5d24 100644
--- a/gcc/simplify-rtx.c
+++ b/gcc/simplify-rtx.c
@@ -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. */
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 990cefa3452..5f1c7716415 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -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
index 00000000000..b9c2c40082d
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/bics_5.c
@@ -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
index 00000000000..6f84902923d
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/bics_5.c
@@ -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 } } */