PR tree-optimization/98602 shows that vector conditional min/max
expressions can be missed after comparison canonicalization.  For
example,

  X > -100 ? X : -100
is canonicalized to
  X >= -99 ? X : -100.

The existing VEC_COND_EXPR min/max patterns require the comparison and
result constants to be equal, so they do not recognize the canonicalized
off-by-one form.

Add patterns for the GE/LT forms produced from negative signed maximum
expressions and for the LE/GT forms produced from positive signed or
unsigned minimum expressions.  Handle both normal and reversed
conditional arms.

gcc/ChangeLog:
        PR tree-optimization/98602
        * match.pd (vec_cond (ge @0 INTEGER_CST) @0 INTEGER_CST):
        New simplification.
        (vec_cond (lt @0 INTEGER_CST) INTEGER_CST @0): Likewise.
        (vec_cond (le @0 INTEGER_CST) @0 INTEGER_CST): Likewise.
        (vec_cond (gt @0 INTEGER_CST) INTEGER_CST @0): Likewise.

gcc/testsuite/ChangeLog:
        PR tree-optimization/98602
        * g++.target/aarch64/sve/max_1.C: Remove fixed XFAILs.
        * g++.target/aarch64/sve/min_1.C: Likewise.

Signed-off-by: Naveen <[email protected]>
---
 gcc/match.pd                                 | 59 ++++++++++++++++++++
 gcc/testsuite/g++.target/aarch64/sve/max_1.C | 10 ++--
 gcc/testsuite/g++.target/aarch64/sve/min_1.C | 44 +++++++--------
 3 files changed, 86 insertions(+), 27 deletions(-)

diff --git a/gcc/match.pd b/gcc/match.pd
index d1a12c35ed3..9832b821173 100644
--- a/gcc/match.pd
+++ b/gcc/match.pd
@@ -6818,6 +6818,65 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
        && target_supports_op_p (type, MINMAX, optab_vector))
     (minmax @0 @1))))
 
+/* Comparison canonicalization changes X > C to X >= C + 1 for
+   negative C and X < C to X <= C - 1 for positive C.  Handle the
+   resulting off-by-one constants here.  */
+(simplify
+ (vec_cond (ge @0 uniform_integer_cst_p@1) @0 uniform_integer_cst_p@2)
+ (with {
+   tree cmp_cst = uniform_integer_cst_p (@1);
+   tree res_cst = uniform_integer_cst_p (@2);
+  }
+  (if (VECTOR_INTEGER_TYPE_P (type)
+       && target_supports_op_p (type, MAX_EXPR, optab_vector)
+       && tree_int_cst_sgn (res_cst) == -1
+       && wi::eq_p (wi::to_wide (cmp_cst),
+                    wi::to_wide (res_cst) + 1))
+   (max @0 @2))))
+
+/* Also handle the equivalent maximum form with the conditional arms
+   reversed and the comparison inverted.  */
+(simplify
+ (vec_cond (lt @0 uniform_integer_cst_p@1) uniform_integer_cst_p@2 @0)
+ (with {
+   tree cmp_cst = uniform_integer_cst_p (@1);
+   tree res_cst = uniform_integer_cst_p (@2);
+  }
+  (if (VECTOR_INTEGER_TYPE_P (type)
+       && target_supports_op_p (type, MAX_EXPR, optab_vector)
+       && tree_int_cst_sgn (res_cst) == -1
+       && wi::eq_p (wi::to_wide (cmp_cst),
+                    wi::to_wide (res_cst) + 1))
+   (max @0 @2))))
+
+(simplify
+ (vec_cond (le @0 uniform_integer_cst_p@1) @0 uniform_integer_cst_p@2)
+ (with {
+   tree cmp_cst = uniform_integer_cst_p (@1);
+   tree res_cst = uniform_integer_cst_p (@2);
+  }
+  (if (VECTOR_INTEGER_TYPE_P (type)
+       && target_supports_op_p (type, MIN_EXPR, optab_vector)
+       && tree_int_cst_sgn (res_cst) == 1
+       && wi::eq_p (wi::to_wide (cmp_cst),
+                    wi::to_wide (res_cst) - 1))
+   (min @0 @2))))
+
+/* Also handle the equivalent minimum form with the conditional arms
+   reversed and the comparison inverted.  */
+(simplify
+ (vec_cond (gt @0 uniform_integer_cst_p@1) uniform_integer_cst_p@2 @0)
+ (with {
+   tree cmp_cst = uniform_integer_cst_p (@1);
+   tree res_cst = uniform_integer_cst_p (@2);
+  }
+  (if (VECTOR_INTEGER_TYPE_P (type)
+       && target_supports_op_p (type, MIN_EXPR, optab_vector)
+       && tree_int_cst_sgn (res_cst) == 1
+       && wi::eq_p (wi::to_wide (cmp_cst),
+                    wi::to_wide (res_cst) - 1))
+   (min @0 @2))))
+
 /* Try to optimize x < 0 ? -1 : 0 into (signed) x >> 31
    and x < 0 ? 1 : 0 into (unsigned) x >> 31.  */
 (simplify
diff --git a/gcc/testsuite/g++.target/aarch64/sve/max_1.C 
b/gcc/testsuite/g++.target/aarch64/sve/max_1.C
index caf9d7cd9bb..6328d5a1b38 100644
--- a/gcc/testsuite/g++.target/aarch64/sve/max_1.C
+++ b/gcc/testsuite/g++.target/aarch64/sve/max_1.C
@@ -39,11 +39,11 @@ TEST_TYPE (uint32_t, 128, 7, 255)
 /* { dg-final { scan-assembler-times {\tumax\tz[0-9]+\.h, p[0-7]/m, 
z[0-9]+\.h, z[0-9]+\.h\n} 2 } } */
 /* { dg-final { scan-assembler-times {\tumax\tz[0-9]+\.s, p[0-7]/m, 
z[0-9]+\.s, z[0-9]+\.s\n} 1 } } */
 
-/* { dg-final { scan-assembler-times {\tsmax\tz[0-9]+\.b, z[0-9]+\.b, #-100\n} 
1 { xfail *-*-* } } } */
-/* { dg-final { scan-assembler-times {\tsmax\tz[0-9]+\.b, z[0-9]+\.b, #-110\n} 
1 { xfail *-*-* } } } */
-/* { dg-final { scan-assembler-times {\tsmax\tz[0-9]+\.b, z[0-9]+\.b, #-120\n} 
1 { xfail *-*-* } } } */
-/* { dg-final { scan-assembler-times {\tsmax\tz[0-9]+\.h, z[0-9]+\.h, #-128\n} 
2 { xfail *-*-* } } } */
-/* { dg-final { scan-assembler-times {\tsmax\tz[0-9]+\.s, z[0-9]+\.s, #-128\n} 
1 { xfail *-*-* } } } */
+/* { dg-final { scan-assembler-times {\tsmax\tz[0-9]+\.b, z[0-9]+\.b, #-100\n} 
1 } } */
+/* { dg-final { scan-assembler-times {\tsmax\tz[0-9]+\.b, z[0-9]+\.b, #-110\n} 
1 } } */
+/* { dg-final { scan-assembler-times {\tsmax\tz[0-9]+\.b, z[0-9]+\.b, #-120\n} 
1 } } */
+/* { dg-final { scan-assembler-times {\tsmax\tz[0-9]+\.h, z[0-9]+\.h, #-128\n} 
2 } } */
+/* { dg-final { scan-assembler-times {\tsmax\tz[0-9]+\.s, z[0-9]+\.s, #-128\n} 
1 } } */
 
 /* { dg-final { scan-assembler-times {\tsmax\tz[0-9]+\.b, z[0-9]+\.b, #50\n} 3 
} } */
 /* { dg-final { scan-assembler-times {\tsmax\tz[0-9]+\.h, z[0-9]+\.h, #50\n} 2 
} } */
diff --git a/gcc/testsuite/g++.target/aarch64/sve/min_1.C 
b/gcc/testsuite/g++.target/aarch64/sve/min_1.C
index 9c84690cd1b..172fa6a9da5 100644
--- a/gcc/testsuite/g++.target/aarch64/sve/min_1.C
+++ b/gcc/testsuite/g++.target/aarch64/sve/min_1.C
@@ -45,29 +45,29 @@ TEST_TYPE (uint32_t, 128, 7, 255)
 /* { dg-final { scan-assembler-times {\tsmin\tz[0-9]+\.h, z[0-9]+\.h, #-128\n} 
2 } } */
 /* { dg-final { scan-assembler-times {\tsmin\tz[0-9]+\.s, z[0-9]+\.s, #-128\n} 
1 } } */
 
-/* { dg-final { scan-assembler-times {\tsmin\tz[0-9]+\.b, z[0-9]+\.b, #50\n} 3 
{ xfail *-*-* } } } */
-/* { dg-final { scan-assembler-times {\tsmin\tz[0-9]+\.h, z[0-9]+\.h, #50\n} 2 
{ xfail *-*-* } } } */
-/* { dg-final { scan-assembler-times {\tsmin\tz[0-9]+\.s, z[0-9]+\.s, #50\n} 1 
{ xfail *-*-* } } } */
+/* { dg-final { scan-assembler-times {\tsmin\tz[0-9]+\.b, z[0-9]+\.b, #50\n} 3 
} } */
+/* { dg-final { scan-assembler-times {\tsmin\tz[0-9]+\.h, z[0-9]+\.h, #50\n} 2 
} } */
+/* { dg-final { scan-assembler-times {\tsmin\tz[0-9]+\.s, z[0-9]+\.s, #50\n} 1 
} } */
 
-/* { dg-final { scan-assembler-times {\tsmin\tz[0-9]+\.b, z[0-9]+\.b, #100\n} 
1 { xfail *-*-* } } } */
-/* { dg-final { scan-assembler-times {\tsmin\tz[0-9]+\.b, z[0-9]+\.b, #110\n} 
1 { xfail *-*-* } } } */
-/* { dg-final { scan-assembler-times {\tsmin\tz[0-9]+\.b, z[0-9]+\.b, #120\n} 
1 { xfail *-*-* } } } */
-/* { dg-final { scan-assembler-times {\tsmin\tz[0-9]+\.h, z[0-9]+\.h, #127\n} 
2 { xfail *-*-* } } } */
-/* { dg-final { scan-assembler-times {\tsmin\tz[0-9]+\.s, z[0-9]+\.s, #127\n} 
1 { xfail *-*-* } } } */
+/* { dg-final { scan-assembler-times {\tsmin\tz[0-9]+\.b, z[0-9]+\.b, #100\n} 
1 } } */
+/* { dg-final { scan-assembler-times {\tsmin\tz[0-9]+\.b, z[0-9]+\.b, #110\n} 
1 } } */
+/* { dg-final { scan-assembler-times {\tsmin\tz[0-9]+\.b, z[0-9]+\.b, #120\n} 
1 } } */
+/* { dg-final { scan-assembler-times {\tsmin\tz[0-9]+\.h, z[0-9]+\.h, #127\n} 
2 } } */
+/* { dg-final { scan-assembler-times {\tsmin\tz[0-9]+\.s, z[0-9]+\.s, #127\n} 
1 } } */
 
-/* { dg-final { scan-assembler-times {\tumin\tz[0-9]+\.b, z[0-9]+\.b, #2\n} 1 
{ xfail *-*-* } } } */
-/* { dg-final { scan-assembler-times {\tumin\tz[0-9]+\.b, z[0-9]+\.b, #3\n} 1 
{ xfail *-*-* } } } */
-/* { dg-final { scan-assembler-times {\tumin\tz[0-9]+\.h, z[0-9]+\.h, #4\n} 1 
{ xfail *-*-* } } } */
-/* { dg-final { scan-assembler-times {\tumin\tz[0-9]+\.b, z[0-9]+\.b, #5\n} 1 
{ xfail *-*-* } } } */
-/* { dg-final { scan-assembler-times {\tumin\tz[0-9]+\.h, z[0-9]+\.h, #6\n} 1 
{ xfail *-*-* } } } */
-/* { dg-final { scan-assembler-times {\tumin\tz[0-9]+\.s, z[0-9]+\.s, #7\n} 1 
{ xfail *-*-* } } } */
+/* { dg-final { scan-assembler-times {\tumin\tz[0-9]+\.b, z[0-9]+\.b, #2\n} 1 
} } */
+/* { dg-final { scan-assembler-times {\tumin\tz[0-9]+\.b, z[0-9]+\.b, #3\n} 1 
} } */
+/* { dg-final { scan-assembler-times {\tumin\tz[0-9]+\.h, z[0-9]+\.h, #4\n} 1 
} } */
+/* { dg-final { scan-assembler-times {\tumin\tz[0-9]+\.b, z[0-9]+\.b, #5\n} 1 
} } */
+/* { dg-final { scan-assembler-times {\tumin\tz[0-9]+\.h, z[0-9]+\.h, #6\n} 1 
} } */
+/* { dg-final { scan-assembler-times {\tumin\tz[0-9]+\.s, z[0-9]+\.s, #7\n} 1 
} } */
 
-/* { dg-final { scan-assembler-times {\tumin\tz[0-9]+\.b, z[0-9]+\.b, #50\n} 3 
{ xfail *-*-* } } } */
-/* { dg-final { scan-assembler-times {\tumin\tz[0-9]+\.h, z[0-9]+\.h, #50\n} 2 
{ xfail *-*-* } } } */
-/* { dg-final { scan-assembler-times {\tumin\tz[0-9]+\.s, z[0-9]+\.s, #50\n} 1 
{ xfail *-*-* } } } */
+/* { dg-final { scan-assembler-times {\tumin\tz[0-9]+\.b, z[0-9]+\.b, #50\n} 3 
} } */
+/* { dg-final { scan-assembler-times {\tumin\tz[0-9]+\.h, z[0-9]+\.h, #50\n} 2 
} } */
+/* { dg-final { scan-assembler-times {\tumin\tz[0-9]+\.s, z[0-9]+\.s, #50\n} 1 
} } */
 
-/* { dg-final { scan-assembler-times {\tumin\tz[0-9]+\.b, z[0-9]+\.b, #250\n} 
1 { xfail *-*-* } } } */
-/* { dg-final { scan-assembler-times {\tumin\tz[0-9]+\.b, z[0-9]+\.b, #251\n} 
1 { xfail *-*-* } } } */
-/* { dg-final { scan-assembler-times {\tumin\tz[0-9]+\.b, z[0-9]+\.b, #253\n} 
1 { xfail *-*-* } } } */
-/* { dg-final { scan-assembler-times {\tumin\tz[0-9]+\.h, z[0-9]+\.h, #255\n} 
2 { xfail *-*-* } } } */
-/* { dg-final { scan-assembler-times {\tumin\tz[0-9]+\.s, z[0-9]+\.s, #255\n} 
1 { xfail *-*-* } } } */
+/* { dg-final { scan-assembler-times {\tumin\tz[0-9]+\.b, z[0-9]+\.b, #250\n} 
1 } } */
+/* { dg-final { scan-assembler-times {\tumin\tz[0-9]+\.b, z[0-9]+\.b, #251\n} 
1 } } */
+/* { dg-final { scan-assembler-times {\tumin\tz[0-9]+\.b, z[0-9]+\.b, #253\n} 
1 } } */
+/* { dg-final { scan-assembler-times {\tumin\tz[0-9]+\.h, z[0-9]+\.h, #255\n} 
2 } } */
+/* { dg-final { scan-assembler-times {\tumin\tz[0-9]+\.s, z[0-9]+\.s, #255\n} 
1 } } */
-- 
2.34.1

Reply via email to