On Wed, Jul 2, 2025 at 7:31 AM <pan2...@intel.com> wrote:
>
> From: Pan Li <pan2...@intel.com>
>
> This patch would like to try to match the SAT_MUL during
> widening-mul pass, aka below pattern.
>
>   NT __attribute__((noinline))
>   sat_u_mul_##NT##_fmt_1 (NT a, NT b)
>   {
>     uint128_t x = (uint128_t)a * (uint128_t)b;
>     NT max = -1;
>     if (x > (uint128_t)(max))
>       return max;
>     else
>       return (NT)x;
>   }
>
> while the NT can be uint8_t, uint16_t, uint32_t and uint64_t.

OK.

Richard.

> gcc/ChangeLog:
>
>         * match.pd: Add new match pattern for unsigned SAT_MUL.
>         * tree-ssa-math-opts.cc (gimple_unsigned_integer_sat_mul):
>         new decl for pattern match func.
>         (match_unsigned_saturation_mul): Add new func to match unsigned
>         SAT_MUL.
>         (math_opts_dom_walker::after_dom_children): Try to match
>         unsigned SAT_MUL on NOP.
>
> Signed-off-by: Pan Li <pan2...@intel.com>
> ---
>  gcc/match.pd              | 31 +++++++++++++++++++++++++++++++
>  gcc/tree-ssa-math-opts.cc | 26 ++++++++++++++++++++++++++
>  2 files changed, 57 insertions(+)
>
> diff --git a/gcc/match.pd b/gcc/match.pd
> index f4416d9172c..c8addf9b421 100644
> --- a/gcc/match.pd
> +++ b/gcc/match.pd
> @@ -3572,6 +3572,37 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
>          || (wi::eq_p (int_cst_1, itype_max) && wi::eq_p (int_cst_2, 
> limit_1)))
>          && wi::eq_p (int_cst_3, otype_max)))))))
>
> +/* Saturation mult for unsigned integer.  */
> +(if (INTEGRAL_TYPE_P (type) && TYPE_UNSIGNED (type))
> +  (match (unsigned_integer_sat_mul @0 @1)
> +   /* SAT_U_MUL (X, Y) = {
> +       WT x = (WT)a * (WT)b;
> +       T max = -1;
> +       if (x > (WT)(max))
> +         return max;
> +       else
> +         return (T)x;
> +      }
> +      while WT is uint128_t, T is uint8_t, uint16_t, uint32_t or uint64_t.  
> */
> +   (convert@4 (min (widen_mult:c@3 (convert@5 (convert @0))
> +                                  (convert@6 (convert @1)))
> +                  INTEGER_CST@2))
> +   (if (types_match (type, @0, @1) && types_match (type, @4))
> +    (with
> +     {
> +      unsigned prec = TYPE_PRECISION (type);
> +      unsigned widen_prec = TYPE_PRECISION (TREE_TYPE (@3));
> +      unsigned cvt5_prec = TYPE_PRECISION (TREE_TYPE (@5));
> +      unsigned cvt6_prec = TYPE_PRECISION (TREE_TYPE (@6));
> +      unsigned hw_int_prec = sizeof (HOST_WIDE_INT) * 8;
> +      wide_int c2 = wi::to_wide (@2);
> +      wide_int max = wi::mask (prec, false, widen_prec);
> +      bool c2_is_max_p = wi::eq_p (c2, max);
> +      bool widen_mult_p = cvt5_prec == cvt6_prec && hw_int_prec == cvt5_prec;
> +     }
> +     (if (widen_prec > prec && c2_is_max_p && widen_mult_p)))))
> +)
> +
>  /* The boundary condition for case 10: IMM = 1:
>     SAT_U_SUB = X >= IMM ? (X - IMM) : 0.
>     simplify (X != 0 ? X + ~0 : 0) to X - (X != 0).  */
> diff --git a/gcc/tree-ssa-math-opts.cc b/gcc/tree-ssa-math-opts.cc
> index 4cfcc420fea..ca98205d58f 100644
> --- a/gcc/tree-ssa-math-opts.cc
> +++ b/gcc/tree-ssa-math-opts.cc
> @@ -4064,6 +4064,7 @@ arith_overflow_check_p (gimple *stmt, gimple 
> *cast_stmt, gimple *&use_stmt,
>  extern bool gimple_unsigned_integer_sat_add (tree, tree*, tree (*)(tree));
>  extern bool gimple_unsigned_integer_sat_sub (tree, tree*, tree (*)(tree));
>  extern bool gimple_unsigned_integer_sat_trunc (tree, tree*, tree (*)(tree));
> +extern bool gimple_unsigned_integer_sat_mul (tree, tree*, tree (*)(tree));
>
>  extern bool gimple_signed_integer_sat_add (tree, tree*, tree (*)(tree));
>  extern bool gimple_signed_integer_sat_sub (tree, tree*, tree (*)(tree));
> @@ -4216,6 +4217,30 @@ match_unsigned_saturation_sub (gimple_stmt_iterator 
> *gsi, gassign *stmt)
>                                                     ops[0], ops[1]);
>  }
>
> +/*
> + * Try to match saturation unsigned mul.
> + *   _1 = (unsigned int) a_6(D);
> + *   _2 = (unsigned int) b_7(D);
> + *   x_8 = _1 * _2;
> + *   overflow_9 = x_8 > 255;
> + *   _3 = (unsigned char) overflow_9;
> + *   _4 = -_3;
> + *   _5 = (unsigned char) x_8;
> + *   _10 = _4 | _5;
> + *   =>
> + *   _10 = .SAT_SUB (a_6, b_7);  */
> +
> +static void
> +match_unsigned_saturation_mul (gimple_stmt_iterator *gsi, gassign *stmt)
> +{
> +  tree ops[2];
> +  tree lhs = gimple_assign_lhs (stmt);
> +
> +  if (gimple_unsigned_integer_sat_mul (lhs, ops, NULL))
> +    build_saturation_binary_arith_call_and_replace (gsi, IFN_SAT_MUL, lhs,
> +                                                   ops[0], ops[1]);
> +}
> +
>  /*
>   * Try to match saturation unsigned sub.
>   *  <bb 2> [local count: 1073741824]:
> @@ -6469,6 +6494,7 @@ math_opts_dom_walker::after_dom_children (basic_block 
> bb)
>               break;
>
>             case NOP_EXPR:
> +             match_unsigned_saturation_mul (&gsi, as_a<gassign *> (stmt));
>               match_unsigned_saturation_trunc (&gsi, as_a<gassign *> (stmt));
>               match_saturation_add_with_assign (&gsi, as_a<gassign *> (stmt));
>               break;
> --
> 2.43.0
>

Reply via email to