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