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 >