https://gcc.gnu.org/g:edb9556068ae47e1a3cbad69249424ab7cce5b7c
commit r17-4378-gedb9556068ae47e1a3cbad69249424ab7cce5b7c Author: Andrea Pinski <[email protected]> Date: Fri Sep 11 17:58:42 2026 -0700 match: `minmax (a - c, b) + c -> minmax (a, b + c)` in some cases [PR127103] This adds a pattern to optimize `minmax (a - c, b) + c` into `minmax (a, b + c)` when `b + c` is known not to overflow. This is a simplified version from previous one where we only handle the `a - c` case rather than the generic This shows up in std::vector::push_back : ``` # RANGE [irange] const size_type [0, 2147483647] MASK 0x7fffffff VALUE 0x0 __room_33 = 2147483647 - _32; ... # RANGE [irange] long unsigned int [1, 2147483646] MASK 0x7fffffff VALUE 0x0 _35 = MIN_EXPR <__room_33, _34>; # RANGE [irange] long unsigned int [1, 4294967292] _36 = _32 + _35; ``` _32 has a range of `[0, 2147483647]`, _34 has a range of `[1, 2147483646]`. This is transformed into: _t = _32 + _34; _36 = MIN_EXPR<_t, 2147483647> This then allows to remove a condition that was never could be executed too. This is currently limited to unsigned types as overflow_free_p does not tell me if we are going to introduce new undefined overflow; it will return true for all TYPE_OVERFLOW_UNDEFINED types. I filed PR 127356 to add a modified version of overflow_free_p. But since the types in push_back is unsigned this is enough for now. When that goes in; I will combine r17-4210-g9d734bb468e714 with this pattern and remove the special case of 0. Changes since v1: * v2: Only handle the case where we have `a - c` as the operand to minmax. Bootstrapped and tested on x86_64-linux-gnu. PR tree-optimization/127103 gcc/ChangeLog: * match.pd (`minmax (a - c, b) + c`): New pattern. gcc/testsuite/ChangeLog: * gcc.dg/tree-ssa/minmax-plus-1.c: New test. Signed-off-by: Andrea Pinski <[email protected]> Diff: --- gcc/match.pd | 11 ++++++++ gcc/testsuite/gcc.dg/tree-ssa/minmax-plus-1.c | 39 +++++++++++++++++++++++++++ 2 files changed, 50 insertions(+) diff --git a/gcc/match.pd b/gcc/match.pd index 82cf6ae0a3c6..1c0393d11cde 100644 --- a/gcc/match.pd +++ b/gcc/match.pd @@ -532,6 +532,17 @@ 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. */ +(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_range_of_expr (vr0, @0) + && gimple_match_range_of_expr (vr2, @2, @3) + && range_op_handler (PLUS_EXPR).overflow_free_p (vr0, vr2)) + (minmax @1 (plus @2 @0)))))) + #endif /* X * 1, X / 1 -> X. */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/minmax-plus-1.c b/gcc/testsuite/gcc.dg/tree-ssa/minmax-plus-1.c new file mode 100644 index 000000000000..75067fdb962d --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/minmax-plus-1.c @@ -0,0 +1,39 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-optimized-raw" } */ +/* minmax (a, b) + c -> minmax (a + c, b + c) */ +/* PR tree-optimization/127103 */ + +__attribute__((always_inline)) +static inline unsigned +min(unsigned a, unsigned b) +{ + if (a > b) + return b; + return a; +} +__attribute__((always_inline)) +static inline unsigned +max(unsigned a, unsigned b) +{ + if (a < b) + return b; + return a; +} + +unsigned f(unsigned a, unsigned t1) +{ + if (a > __INT_MAX__) + return 0; + unsigned t = __INT_MAX__ - a; + return a + min(t, a); +} + +unsigned f1(unsigned a, unsigned t1) +{ + if (a > __INT_MAX__) + return 0; + unsigned t = __INT_MAX__ - a; + return a + max(t, a); +} + +/* { dg-final { scan-tree-dump-times "gimple_assign <mult_expr, _\[0-9\], a_\[0-9\].D., 2" 2 "optimized" } } */
