[PATCH][v2] match.pd: combine a pair of vector comparisons against zero
<[email protected]> Wed, 5 Aug 2026 13:45:18 +0200
| Newsgroups | gmane.comp.gcc.patches |
|---|---|
| Message-ID | <[email protected]> |
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 inequality. The existing scalar rule already implements this identity. Extend it to vector integers and use a view conversion when the operands differ only in element signedness. Extend the related all-ones rule in the same way. typedef int v4si __attribute__((vector_size (16))); v4si f (v4si a, v4si b) { return (a == 0) & (b == 0); } 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 Add vector_nop_conversion_p for the element-wise property shared by these rules and the existing nop_convert matcher. Bootstrapped and tested on aarch64-none-linux-gnu. Ok for trunk? Thanks, Kyrill gcc/ChangeLog: * match.pd (nop_convert): Use vector_nop_conversion_p. ((A == 0) & (B == 0), (A != 0) | (B != 0)): Extend the existing simplifications to vector operands. ((A == -1) & (B == -1), (A != -1) | (B != -1)): Likewise. * tree.cc (vector_nop_conversion_p): New function. * tree.h (vector_nop_conversion_p): Declare. gcc/testsuite/ChangeLog: * gcc.dg/tree-ssa/vec-mask-zero-1.c: New test. Signed-off-by: Kyrylo Tkachov <[email protected]> --- gcc/match.pd | 26 +++++++++++++------ .../gcc.dg/tree-ssa/vec-mask-zero-1.c | 17 ++++++++++++ gcc/tree.cc | 15 +++++++++++ gcc/tree.h | 1 + 4 files changed, 51 insertions(+), 8 deletions(-) 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 da002001399..efa821bff59 100644 --- a/gcc/match.pd +++ b/gcc/match.pd @@ -161,10 +161,7 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT) (if (tree_nop_conversion_p (type, TREE_TYPE (@0))))) (match (nop_convert @0) (view_convert @0) - (if (VECTOR_TYPE_P (type) && VECTOR_TYPE_P (TREE_TYPE (@0)) - && known_eq (TYPE_VECTOR_SUBPARTS (type), - TYPE_VECTOR_SUBPARTS (TREE_TYPE (@0))) - && tree_nop_conversion_p (TREE_TYPE (type), TREE_TYPE (TREE_TYPE (@0)))))) + (if (vector_nop_conversion_p (type, TREE_TYPE (@0))))) /* These are used by gimple_bitwise_inverted_equal_p to simplify detection of BIT_NOT and comparisons. */ @@ -1560,20 +1557,33 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT) (x == 0 & y == 0) -> (x | typeof(x)(y)) == 0. (x != 0 | y != 0) -> (x | typeof(x)(y)) != 0. */ (simplify - (bitop (cmp @0 integer_zerop@2) (cmp @1 integer_zerop)) + (bitop (cmp@3 @0 integer_zerop@2) (cmp@4 @1 integer_zerop)) + (switch (if (INTEGRAL_TYPE_P (TREE_TYPE (@0)) && INTEGRAL_TYPE_P (TREE_TYPE (@1)) && TYPE_PRECISION (TREE_TYPE (@0)) == TYPE_PRECISION (TREE_TYPE (@1))) - (cmp (bit_ior @0 (convert @1)) @2))) + (cmp (bit_ior @0 (convert @1)) @2)) + (if (VECTOR_INTEGER_TYPE_P (TREE_TYPE (@0)) + && VECTOR_INTEGER_TYPE_P (TREE_TYPE (@1)) + && vector_nop_conversion_p (TREE_TYPE (@0), TREE_TYPE (@1)) + && single_use (@3) && single_use (@4)) + (cmp (bit_ior @0 (view_convert @1)) @2)))) /* Transform: (x == -1 & y == -1) -> (x & typeof(x)(y)) == -1. (x != -1 | y != -1) -> (x & typeof(x)(y)) != -1. */ (simplify - (bitop (cmp @0 integer_all_onesp@2) (cmp @1 integer_all_onesp)) + (bitop (cmp@3 @0 integer_all_onesp@2) + (cmp@4 @1 integer_all_onesp)) + (switch (if (INTEGRAL_TYPE_P (TREE_TYPE (@0)) && INTEGRAL_TYPE_P (TREE_TYPE (@1)) && TYPE_PRECISION (TREE_TYPE (@0)) == TYPE_PRECISION (TREE_TYPE (@1))) - (cmp (bit_and @0 (convert @1)) @2)))) + (cmp (bit_and @0 (convert @1)) @2)) + (if (VECTOR_INTEGER_TYPE_P (TREE_TYPE (@0)) + && VECTOR_INTEGER_TYPE_P (TREE_TYPE (@1)) + && vector_nop_conversion_p (TREE_TYPE (@0), TREE_TYPE (@1)) + && single_use (@3) && single_use (@4)) + (cmp (bit_and @0 (view_convert @1)) @2))))) /* Fold (A & ~B) - (A & B) into (A ^ B) - B. */ (simplify 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..1b31f727488 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/vec-mask-zero-1.c @@ -0,0 +1,17 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-optimized" } */ +/* Combine pairs of vector comparisons against zero or all-ones. Use + different signedness for the operands to exercise the view conversion. */ +typedef int v4si __attribute__((vector_size (16))); +typedef unsigned int v4ui __attribute__((vector_size (16))); + +v4si f1 (v4si a, v4ui b) { return (a == 0) & (b == 0); } +v4si f2 (v4si a, v4ui b) { return (a != 0) | (b != 0); } +v4si f3 (v4si a, v4ui b) { return (a == -1) & (b == -1u); } +v4si f4 (v4si a, v4ui b) { return (a != -1) | (b != -1u); } + +/* Each function keeps one bitwise operation and one comparison. */ +/* { dg-final { scan-tree-dump-times " == " 2 "optimized" } } */ +/* { dg-final { scan-tree-dump-times " != " 2 "optimized" } } */ +/* { dg-final { scan-tree-dump-times " \\| " 2 "optimized" } } */ +/* { dg-final { scan-tree-dump-times " & " 2 "optimized" } } */ diff --git a/gcc/tree.cc b/gcc/tree.cc index c8aa42b3e10..157f453e49c 100644 --- a/gcc/tree.cc +++ b/gcc/tree.cc @@ -12384,6 +12384,21 @@ tree_nop_conversion_p (const_tree outer_type, const_tree inner_type) return TYPE_MODE (outer_type) == TYPE_MODE (inner_type); } +/* Return true iff a view conversion from vector type INNER_TYPE to vector + type OUTER_TYPE has the same number of elements and does not change the + representation of an element. */ + +bool +vector_nop_conversion_p (const_tree outer_type, const_tree inner_type) +{ + return (VECTOR_TYPE_P (outer_type) + && VECTOR_TYPE_P (inner_type) + && known_eq (TYPE_VECTOR_SUBPARTS (outer_type), + TYPE_VECTOR_SUBPARTS (inner_type)) + && tree_nop_conversion_p (TREE_TYPE (outer_type), + TREE_TYPE (inner_type))); +} + /* Return true iff conversion in EXP generates no instruction. Mark it inline so that we fully inline into the stripping functions even though we have two uses of this function. */ diff --git a/gcc/tree.h b/gcc/tree.h index 1ccbf848d9b..56863bdfc18 100644 --- a/gcc/tree.h +++ b/gcc/tree.h @@ -5784,6 +5784,7 @@ extern bool auto_var_p (const_tree); extern bool auto_var_in_fn_p (const_tree, const_tree); extern tree build_low_bits_mask (tree, unsigned); extern bool tree_nop_conversion_p (const_tree, const_tree); +extern bool vector_nop_conversion_p (const_tree, const_tree); extern tree tree_strip_nop_conversions (tree); extern tree tree_strip_sign_nop_conversions (tree); extern const_tree strip_invariant_refs (const_tree); -- 2.50.1 (Apple Git-155)