From: Kyrylo Tkachov <[email protected]>
A lane of A | B is zero exactly when the corresponding lanes of A and of B
are both zero, so
(A == 0) & (B == 0) -> (A | B) == 0
and the De Morgan dual for the inequality. One vector comparison goes
away. Reassociation performs this for scalars, but it never runs on
vector masks, so the vector form is left alone today.
typedef int v4si __attribute__((vector_size (16)));
v4si f (v4si a, v4si b) { v4si z = {0,0,0,0}; return (a == z) & (b == z); }
aarch64 -O3 before:
cmeq v0.4s, v0.4s, #0
cmeq v1.4s, v1.4s, #0
and v0.16b, v0.16b, v1.16b
after:
orr v0.16b, v0.16b, v1.16b
cmeq v0.4s, v0.4s, #0
Bootstrapped and tested on aarch64-none-linux-gnu.
Ok for trunk?
Thanks,
Kyrill
gcc/ChangeLog:
* match.pd ((A == 0) & (B == 0), (A != 0) | (B != 0)): New
simplifications for vector operands.
gcc/testsuite/ChangeLog:
* gcc.dg/tree-ssa/vec-mask-zero-1.c: New test.
Signed-off-by: Kyrylo Tkachov <[email protected]>
---
gcc/match.pd | 14 ++++++++++++++
gcc/testsuite/gcc.dg/tree-ssa/vec-mask-zero-1.c | 12 ++++++++++++
2 files changed, 26 insertions(+)
create mode 100644 gcc/testsuite/gcc.dg/tree-ssa/vec-mask-zero-1.c
diff --git a/gcc/match.pd b/gcc/match.pd
index 22202af2cc1..fc81dfc5e66 100644
--- a/gcc/match.pd
+++ b/gcc/match.pd
@@ -3823,6 +3823,20 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
{ constant_boolean_node (true, type); })
))))))
+/* Combine two vector comparisons against zero into one:
+ (A == 0) & (B == 0) --> (A | B) == 0
+ (A != 0) | (B != 0) --> (A | B) != 0
+ Reassociation does this for scalars only, it never runs on vector
+ masks. */
+(for eqne (eq ne)
+ bitop (bit_and bit_ior)
+ (simplify
+ (bitop (eqne:s @0 integer_zerop) (eqne:s @1 integer_zerop))
+ (if (VECTOR_INTEGER_TYPE_P (TREE_TYPE (@0))
+ && types_match (TREE_TYPE (@0), TREE_TYPE (@1)))
+ (eqne (bit_ior @0 @1)
+ { build_zero_cst (TREE_TYPE (@0)); }))))
+
/* Optimize (a CMP b) ^ (a CMP b) */
/* Optimize (a CMP b) != (a CMP b) */
(for op (bit_xor ne)
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/vec-mask-zero-1.c
b/gcc/testsuite/gcc.dg/tree-ssa/vec-mask-zero-1.c
new file mode 100644
index 00000000000..f8c669636fd
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/vec-mask-zero-1.c
@@ -0,0 +1,12 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-optimized" } */
+/* A lane of A | B is zero exactly when both lanes are, so a pair of vector
+ comparisons against zero becomes one. Reassociation does this for
+ scalars but never runs on vector masks. */
+typedef int v4si __attribute__((vector_size (16)));
+v4si f (v4si a, v4si b) { v4si z = {0,0,0,0}; return (a == z) & (b == z); }
+v4si g (v4si a, v4si b) { v4si z = {0,0,0,0}; return (a != z) | (b != z); }
+/* { dg-final { scan-tree-dump-times " == " 1 "optimized" } } */
+/* { dg-final { scan-tree-dump-times " != " 1 "optimized" } } */
+/* Each function keeps one OR and one comparison. */
+/* { dg-final { scan-tree-dump-times " \\| " 2 "optimized" } } */
--
2.50.1 (Apple Git-155)