On Tue, Sep 29, 2026 at 11:52 PM Dominic P <[email protected]> wrote: > > 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 > range_op_handler (MINUS_EXPR).overflow_free_p on the ranges of a and c. > 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.
Ok/ > > 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]> > --- > Changes in v2: the MINUS_EXPR check uses the ranges directly, as you > suggested. > > OK for trunk? > > gcc/match.pd | 6 +++-- > gcc/testsuite/gcc.dg/torture/pr127103.c | 33 +++++++++++++++++++++++++ > 2 files changed, 37 insertions(+), 2 deletions(-) > create mode 100644 gcc/testsuite/gcc.dg/torture/pr127103.c > > diff --git a/gcc/match.pd b/gcc/match.pd > index c70a8e6d6d2..2d1161b860b 100644 > --- a/gcc/match.pd > +++ b/gcc/match.pd > @@ -531,13 +531,15 @@ 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; } > + (with { int_range_max vr0, vr1, vr2; } > (if (TYPE_UNSIGNED (type) > && gimple_match_range_of_expr (vr0, @0) > + && gimple_match_range_of_expr (vr1, @1, @3) > + && range_op_handler (MINUS_EXPR).overflow_free_p (vr1, vr0) > && gimple_match_range_of_expr (vr2, @2, @3) > && range_op_handler (PLUS_EXPR).overflow_free_p (vr0, vr2)) > (minmax @1 (plus @2 @0)))))) > 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 >
