On Sat, Sep 12, 2026 at 9:25 AM Andrea Pinski
<[email protected]> wrote:
>
> This adds a pattern to optimize `minmax (a, b) + c` into `minmax (a + c, b + 
> c)` when
> `a + c` and `b + c` are known not to overflow and either `a + c` or `b + c` 
> simplifies.

Why is this good if either simplifies?  Both would be obvious, but
either?  Also your
pattern picks the 2nd operand for simplifies and uses :c to test the
other variant.
That's of course more expensive than a way to tell genmatch to accept either
operand simplifying ...

> 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.
>
> Bootstrapped and tested on x86_64-linux-gnu.
>
>         PR tree-optimization/127103
> gcc/ChangeLog:
>
>         * match.pd (`minmax (a, b) + c`): New pattern.
>
> gcc/testsuite/ChangeLog:
>
>         * gcc.dg/tree-ssa/minmax-plus-1.c: New test.
>
> Signed-off-by: Andrea Pinski <[email protected]>
> ---
>  gcc/match.pd                                  | 15 +++++++
>  gcc/testsuite/gcc.dg/tree-ssa/minmax-plus-1.c | 39 +++++++++++++++++++
>  2 files changed, 54 insertions(+)
>  create mode 100644 gcc/testsuite/gcc.dg/tree-ssa/minmax-plus-1.c
>
> diff --git a/gcc/match.pd b/gcc/match.pd
> index d6ece84e186..81734b73a7d 100644
> --- a/gcc/match.pd
> +++ b/gcc/match.pd
> @@ -532,6 +532,21 @@ 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, b) + c -> minmax (a + c, b + c)
> +   if a+c or b+c simplifies and a+c/b+c don't overlfow */
> +(for minmax (min max)
> + (simplify
> +  (plus:c @0 (minmax:cs@3 @1 @2))
> +  (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)
> +       && gimple_match_range_of_expr (vr2, @2, @3)
> +       && range_op_handler (PLUS_EXPR).overflow_free_p (vr0, vr1)
> +       && range_op_handler (PLUS_EXPR).overflow_free_p (vr0, vr2))
> +    (minmax (plus @0 @1) (plus! @0 @2))))))
> +
>  #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 00000000000..75067fdb962
> --- /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" } } */
> --
> 2.43.0
>

Reply via email to