Generalize existing scalar gimple_fold rules to apply the same
    bitwise comparison simplifications to vector types.  Previously, an
    expression like

        (x < y) && (x > y)

    would fold to `false` if x and y are scalars, but equivalent vector
    comparisons were left untouched.  This patch enables folding of
    patterns of the form

        (cmp x y) bit_and (cmp x y)
        (cmp x y) bit_ior (cmp x y)

    for vector operands as well, ensuring consistent optimization across
    all data types.

    PR tree-optimization/119196

    gcc/ChangeLog:

      * match.pd: Allow scalar optimizations with bitwise AND/OR to apply to 
vectors.

    gcc/testsuite/ChangeLog:

      * gcc.target/aarch64/vector-compare-5.c: Add new test for vector compare 
simplification.

Signed-off-by: Icen Zeyada <icen.zeya...@arm.com>
---
 gcc/match.pd                                  | 19 +++++++--
 .../gcc.target/aarch64/vector-compare-5.c     | 41 +++++++++++++++++++
 2 files changed, 56 insertions(+), 4 deletions(-)
 create mode 100644 gcc/testsuite/gcc.target/aarch64/vector-compare-5.c

diff --git a/gcc/match.pd b/gcc/match.pd
index ab496d923cc0..a8a2e01e5e64 100644
--- a/gcc/match.pd
+++ b/gcc/match.pd
@@ -3620,7 +3620,7 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
    (bit_and:c (code1:c@3 @0 @1) (code2:c@4 (convert?@c0 @0) @2))
    (if ((TREE_CODE (@1) == INTEGER_CST
         && TREE_CODE (@2) == INTEGER_CST)
-       || ((INTEGRAL_TYPE_P (TREE_TYPE (@1))
+       || ((ANY_INTEGRAL_TYPE_P (TREE_TYPE (@1))
             || POINTER_TYPE_P (TREE_TYPE (@1)))
            && bitwise_equal_p (@1, @2)))
     (with
@@ -3697,7 +3697,7 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
   (bit_and (code1:c@3 @0 @1) (code2:c@4 @0 @2))
   (if ((TREE_CODE (@1) == INTEGER_CST
        && TREE_CODE (@2) == INTEGER_CST)
-       || ((INTEGRAL_TYPE_P (TREE_TYPE (@1))
+       || ((ANY_INTEGRAL_TYPE_P (TREE_TYPE (@1))
            || POINTER_TYPE_P (TREE_TYPE (@1)))
           && operand_equal_p (@1, @2)))
    (with
@@ -3747,7 +3747,7 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
    (bit_ior:c (code1:c@3 @0 @1) (code2:c@4 (convert?@c0 @0) @2))
    (if ((TREE_CODE (@1) == INTEGER_CST
         && TREE_CODE (@2) == INTEGER_CST)
-       || ((INTEGRAL_TYPE_P (TREE_TYPE (@1))
+       || ((ANY_INTEGRAL_TYPE_P (TREE_TYPE (@1))
            || POINTER_TYPE_P (TREE_TYPE (@1)))
            && bitwise_equal_p (@1, @2)))
     (with
@@ -3880,7 +3880,8 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
      rcmp (eq gt le eq ge lt)
  (simplify
   (eq:c (cmp1:c @0 @1) (cmp2 @0 @1))
-  (if (INTEGRAL_TYPE_P (TREE_TYPE (@0)) || POINTER_TYPE_P (TREE_TYPE (@0)))
+  (if (ANY_INTEGRAL_TYPE_P (TREE_TYPE (@0))
+               || POINTER_TYPE_P (TREE_TYPE (@0)))
     (rcmp @0 @1))))
 
 /* (type)([0,1]@a != 0) -> (type)a
@@ -6510,6 +6511,16 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
                { build_int_cst (integer_type_node, prec - 1);}))))))
 #endif
 
+(for op1 (simple_comparison)
+ (for op2 (simple_comparison)
+  (for lop (bit_and bit_ior)
+    (simplify
+         (lop
+          (vec_cond (op1 @0 @1) integer_minus_onep@2 integer_zerop@3)
+          (vec_cond (op2 @0 @1) integer_minus_onep@2 integer_zerop@3))
+         (with { tree op_type = truth_type_for (TREE_TYPE (@0)); }
+               (vec_cond (lop:op_type (op1 @0 @1) (op2 @0 @1)) @2 @3))))))
+
 (for cnd (cond vec_cond)
  /* (a != b) ? (a - b) : 0 -> (a - b) */
  (simplify
diff --git a/gcc/testsuite/gcc.target/aarch64/vector-compare-5.c 
b/gcc/testsuite/gcc.target/aarch64/vector-compare-5.c
new file mode 100644
index 000000000000..c4b95a21996d
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/vector-compare-5.c
@@ -0,0 +1,41 @@
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+/* { dg-additional-options "-fdump-tree-original-all" } */
+
+typedef int v4i __attribute__((vector_size(4*sizeof(int))));
+
+/* Ensure we can simplify `VEC_COND_EXPR(a OP1 b) OP2 VEC_COND_EXPR(a OP3 b)`
+ * into `VEC_COND_EXPR(a OP4 b)`
+ */
+
+void use (v4i const *z);
+
+void
+g (v4i *x, v4i const *y, v4i *z, v4i *t)
+{
+  *z = *x > *y | *x == *y; // expect >=
+  *t = *x > *y | *x <= *y; // expect true
+}
+
+void
+h (v4i *x, v4i const *y, v4i *z, v4i *t)
+{
+  *z = *x <= *y & *x >= *y; // expect x == y
+  *t = *x <= *y & *x != *y; // expect x<y
+}
+
+void
+i (v4i *x, v4i const *y, v4i *z, v4i *t)
+{
+  *z = *x == *y | *x != *y; // expect true
+  *t = *x == *y & *x != *y; // expect false
+}
+
+/* { dg-final { scan-tree-dump 
".*\\*zD\\.\\d+\\s*=\\s*VEC_COND_EXPR\\s*<\\s*\\*xD\\.\\d+\\s*>=\\s*VIEW_CONVERT_EXPR<v4iD\\.\\d+>\\(\\*yD\\.\\d+\\)\\s*,\\s*\\{\\s*-1(,\\s*-1){3}\\s*\\}\\s*,\\s*\\{\\s*0(,\\s*0){3}\\s*\\}\\s*>\\s*;"
 "original" } } */
+/* { dg-final { scan-tree-dump 
".*\\*tD\\.\\d+\\s*=\\s*\\{\\s*-1(,\\s*-1){3}\\s*\\}\\s*;" "original" } } */
+/* { dg-final { scan-tree-dump 
".*\\*zD\\.\\d+\\s*=\\s*VEC_COND_EXPR\\s*<\\s*\\*xD\\.\\d+\\s*==\\s*VIEW_CONVERT_EXPR<v4iD\\.\\d+>\\(\\*yD\\.\\d+\\)\\s*,\\s*\\{\\s*-1(,\\s*-1){3}\\s*\\}\\s*,\\s*\\{\\s*0(,\\s*0){3}\\s*\\}\\s*>\\s*;"
 "original" } } */
+/* { dg-final { scan-tree-dump 
".*\\*tD\\.\\d+\\s*=\\s*VEC_COND_EXPR\\s*<\\s*\\*xD\\.\\d+\\s*<\\s*VIEW_CONVERT_EXPR<v4iD\\.\\d+>\\(\\*yD\\.\\d+\\)\\s*,\\s*\\{\\s*-1(,\\s*-1){3}\\s*\\}\\s*,\\s*\\{\\s*0(,\\s*0){3}\\s*\\}\\s*>\\s*;"
 "original" } } */
+/* { dg-final { scan-tree-dump 
".*\\*zD\\.\\d+\\s*=\\s*\\{\\s*-1(,\\s*-1){3}\\s*\\}\\s*;" "original" } } */
+/* { dg-final { scan-tree-dump 
".*\\*tD\\.\\d+\\s*=\\s*\\{\\s*0(,\\s*0){3}\\s*\\}\\s*;" "original" } } */
+
+
-- 
2.43.0

Reply via email to