r17-4378 folds minmax (a - c, b) + c to minmax (a, b + c) when b + c
cannot overflow. The fold also needs a - c not to wrap: for unsigned
a = 0, b = 0, c = 1, MIN (a - c, b) + c is 1 but MIN (a, b + c) is 0,
and the MAX form gives 0 against 1. Require that with
gimple_match_no_overflow_p. The std::vector::push_back case from the
PR, where a is 2147483647, still folds.
Bootstrapped and regression tested on x86_64-pc-linux-gnu, and dg.exp,
tree-ssa.exp and execute.exp on aarch64-linux-gnu under qemu.
Assisted-by: Claude Opus 5 (Anthropic)
PR tree-optimization/127103
gcc/ChangeLog:
* match.pd (minmax (a - c, b) + c): Also require that a - c
does not overflow.
gcc/testsuite/ChangeLog:
* gcc.dg/torture/pr127103.c: New test.
Signed-off-by: Dominic P <[email protected]>
---
OK for trunk?
Vector types are unaffected: without ranges for them the rule never fires,
before or after the patch.
gcc/match.pd | 3 ++-
gcc/testsuite/gcc.dg/torture/pr127103.c | 33 +++++++++++++++++++++++++
2 files changed, 35 insertions(+), 1 deletion(-)
create mode 100644 gcc/testsuite/gcc.dg/torture/pr127103.c
diff --git a/gcc/match.pd b/gcc/match.pd
index c70a8e6d6d2..33a573cfcb2 100644
--- a/gcc/match.pd
+++ b/gcc/match.pd
@@ -531,12 +531,13 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
(if (gimple_match_range_of_expr (vr0, @0, @2)
&& range_op_handler (PLUS_EXPR).overflow_free_p (vr0, vr0))
(max (plus @0 @0) @1)))))
-/* minmax (a - c, b) + c -> minmax (a, b + c) if b+c don't overflow. */
+/* minmax (a - c, b) + c -> minmax (a, b + c) if a-c and b+c don't overflow.
*/
(for minmax (min max)
(simplify
(plus:c @0 (minmax:cs@3 (minus @1 @0) @2))
(with { int_range_max vr0, vr2; }
(if (TYPE_UNSIGNED (type)
+ && gimple_match_no_overflow_p (MINUS_EXPR, type, @1, @0, @3)
&& gimple_match_range_of_expr (vr0, @0)
&& gimple_match_range_of_expr (vr2, @2, @3)
&& range_op_handler (PLUS_EXPR).overflow_free_p (vr0, vr2))
diff --git a/gcc/testsuite/gcc.dg/torture/pr127103.c
b/gcc/testsuite/gcc.dg/torture/pr127103.c
new file mode 100644
index 00000000000..3b622d3388f
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/pr127103.c
@@ -0,0 +1,33 @@
+/* { dg-do run } */
+/* minmax (a - c, b) + c must not become minmax (a, b + c) when a - c
+ can wrap. */
+
+__attribute__((noipa)) unsigned
+f_min (unsigned a, unsigned b, unsigned c)
+{
+ c &= 1;
+ b &= 1;
+ unsigned t = a - c;
+ t = t < b ? t : b;
+ return t + c;
+}
+
+__attribute__((noipa)) unsigned
+f_max (unsigned a, unsigned b, unsigned c)
+{
+ c &= 1;
+ b &= 1;
+ unsigned t = a - c;
+ t = t > b ? t : b;
+ return t + c;
+}
+
+int
+main (void)
+{
+ if (f_min (0, 0, 1) != 1)
+ __builtin_abort ();
+ if (f_max (0, 0, 1) != 0)
+ __builtin_abort ();
+ return 0;
+}
--
2.55.0