Thanks Richard, will commit after the rebased pass the regression test. Pan
-----Original Message----- From: Richard Biener <richard.guent...@gmail.com> Sent: Wednesday, June 5, 2024 3:19 PM To: Li, Pan2 <pan2...@intel.com> Cc: gcc-patches@gcc.gnu.org; juzhe.zh...@rivai.ai; kito.ch...@gmail.com; tamar.christ...@arm.com Subject: Re: [PATCH v1] Internal-fn: Support new IFN SAT_SUB for unsigned scalar int On Tue, May 28, 2024 at 10:29 AM <pan2...@intel.com> wrote: > > From: Pan Li <pan2...@intel.com> > > This patch would like to add the middle-end presentation for the > saturation sub. Aka set the result of add to the min when downflow. > It will take the pattern similar as below. > > SAT_SUB (x, y) => (x - y) & (-(TYPE)(x >= y)); > > For example for uint8_t, we have > > * SAT_SUB (255, 0) => 255 > * SAT_SUB (1, 2) => 0 > * SAT_SUB (254, 255) => 0 > * SAT_SUB (0, 255) => 0 > > Given below SAT_SUB for uint64 > > uint64_t sat_sub_u64 (uint64_t x, uint64_t y) > { > return (x + y) & (- (uint64_t)((x >= y))); > } > > Before this patch: > uint64_t sat_sub_u_0_uint64_t (uint64_t x, uint64_t y) > { > _Bool _1; > long unsigned int _3; > uint64_t _6; > > ;; basic block 2, loop depth 0 > ;; pred: ENTRY > _1 = x_4(D) >= y_5(D); > _3 = x_4(D) - y_5(D); > _6 = _1 ? _3 : 0; > return _6; > ;; succ: EXIT > } > > After this patch: > uint64_t sat_sub_u_0_uint64_t (uint64_t x, uint64_t y) > { > uint64_t _6; > > ;; basic block 2, loop depth 0 > ;; pred: ENTRY > _6 = .SAT_SUB (x_4(D), y_5(D)); [tail call] > return _6; > ;; succ: EXIT > } > > The below tests are running for this patch: > *. The riscv fully regression tests. > *. The x86 bootstrap tests. > *. The x86 fully regression tests. OK. Thanks, Richard. > PR target/51492 > PR target/112600 > > gcc/ChangeLog: > > * internal-fn.def (SAT_SUB): Add new IFN define for SAT_SUB. > * match.pd: Add new match for SAT_SUB. > * optabs.def (OPTAB_NL): Remove fixed-point for ussub/ssub. > * tree-ssa-math-opts.cc (gimple_unsigned_integer_sat_sub): Add > new decl for generated in match.pd. > (build_saturation_binary_arith_call): Add new helper function > to build the gimple call to binary SAT alu. > (match_saturation_arith): Rename from. > (match_unsigned_saturation_add): Rename to. > (match_unsigned_saturation_sub): Add new func to match the > unsigned sat sub. > (math_opts_dom_walker::after_dom_children): Add SAT_SUB matching > try when COND_EXPR. > > Signed-off-by: Pan Li <pan2...@intel.com> > --- > gcc/internal-fn.def | 1 + > gcc/match.pd | 14 ++++++++ > gcc/optabs.def | 4 +-- > gcc/tree-ssa-math-opts.cc | 67 +++++++++++++++++++++++++++------------ > 4 files changed, 64 insertions(+), 22 deletions(-) > > diff --git a/gcc/internal-fn.def b/gcc/internal-fn.def > index 25badbb86e5..24539716e5b 100644 > --- a/gcc/internal-fn.def > +++ b/gcc/internal-fn.def > @@ -276,6 +276,7 @@ DEF_INTERNAL_SIGNED_OPTAB_FN (MULHRS, ECF_CONST | > ECF_NOTHROW, first, > smulhrs, umulhrs, binary) > > DEF_INTERNAL_SIGNED_OPTAB_FN (SAT_ADD, ECF_CONST, first, ssadd, usadd, > binary) > +DEF_INTERNAL_SIGNED_OPTAB_FN (SAT_SUB, ECF_CONST, first, sssub, ussub, > binary) > > DEF_INTERNAL_COND_FN (ADD, ECF_CONST, add, binary) > DEF_INTERNAL_COND_FN (SUB, ECF_CONST, sub, binary) > diff --git a/gcc/match.pd b/gcc/match.pd > index 024e3350465..3e334533ff8 100644 > --- a/gcc/match.pd > +++ b/gcc/match.pd > @@ -3086,6 +3086,20 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT) > (match (unsigned_integer_sat_add @0 @1) > (bit_ior:c (usadd_left_part_2 @0 @1) (usadd_right_part_2 @0 @1))) > > +/* Unsigned saturation sub, case 1 (branch with gt): > + SAT_U_SUB = X > Y ? X - Y : 0 */ > +(match (unsigned_integer_sat_sub @0 @1) > + (cond (gt @0 @1) (minus @0 @1) integer_zerop) > + (if (INTEGRAL_TYPE_P (type) && TYPE_UNSIGNED (type) > + && types_match (type, @0, @1)))) > + > +/* Unsigned saturation sub, case 2 (branch with ge): > + SAT_U_SUB = X >= Y ? X - Y : 0. */ > +(match (unsigned_integer_sat_sub @0 @1) > + (cond (ge @0 @1) (minus @0 @1) integer_zerop) > + (if (INTEGRAL_TYPE_P (type) && TYPE_UNSIGNED (type) > + && types_match (type, @0, @1)))) > + > /* x > y && x != XXX_MIN --> x > y > x > y && x == XXX_MIN --> false . */ > (for eqne (eq ne) > diff --git a/gcc/optabs.def b/gcc/optabs.def > index 3f2cb46aff8..bc2611abdc2 100644 > --- a/gcc/optabs.def > +++ b/gcc/optabs.def > @@ -118,8 +118,8 @@ OPTAB_NX(sub_optab, "sub$F$a3") > OPTAB_NX(sub_optab, "sub$Q$a3") > OPTAB_VL(subv_optab, "subv$I$a3", MINUS, "sub", '3', gen_intv_fp_libfunc) > OPTAB_VX(subv_optab, "sub$F$a3") > -OPTAB_NL(sssub_optab, "sssub$Q$a3", SS_MINUS, "sssub", '3', > gen_signed_fixed_libfunc) > -OPTAB_NL(ussub_optab, "ussub$Q$a3", US_MINUS, "ussub", '3', > gen_unsigned_fixed_libfunc) > +OPTAB_NL(sssub_optab, "sssub$a3", SS_MINUS, "sssub", '3', > gen_signed_fixed_libfunc) > +OPTAB_NL(ussub_optab, "ussub$a3", US_MINUS, "ussub", '3', > gen_unsigned_fixed_libfunc) > OPTAB_NL(smul_optab, "mul$Q$a3", MULT, "mul", '3', gen_int_fp_fixed_libfunc) > OPTAB_NX(smul_optab, "mul$P$a3") > OPTAB_NX(smul_optab, "mul$F$a3") > diff --git a/gcc/tree-ssa-math-opts.cc b/gcc/tree-ssa-math-opts.cc > index 62da1c5ee08..4717302b728 100644 > --- a/gcc/tree-ssa-math-opts.cc > +++ b/gcc/tree-ssa-math-opts.cc > @@ -4087,33 +4087,56 @@ 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)); > + > +static void > +build_saturation_binary_arith_call (gimple_stmt_iterator *gsi, internal_fn > fn, > + tree lhs, tree op_0, tree op_1) > +{ > + if (direct_internal_fn_supported_p (fn, TREE_TYPE (lhs), > OPTIMIZE_FOR_BOTH)) > + { > + gcall *call = gimple_build_call_internal (fn, 2, op_0, op_1); > + gimple_call_set_lhs (call, lhs); > + gsi_replace (gsi, call, /* update_eh_info */ true); > + } > +} > > /* > - * Try to match saturation arith pattern(s). > - * 1. SAT_ADD (unsigned) > - * _7 = _4 + _6; > - * _8 = _4 > _7; > - * _9 = (long unsigned int) _8; > - * _10 = -_9; > - * _12 = _7 | _10; > - * => > - * _12 = .SAT_ADD (_4, _6); */ > + * Try to match saturation unsigned add. > + * _7 = _4 + _6; > + * _8 = _4 > _7; > + * _9 = (long unsigned int) _8; > + * _10 = -_9; > + * _12 = _7 | _10; > + * => > + * _12 = .SAT_ADD (_4, _6); */ > + > static void > -match_saturation_arith (gimple_stmt_iterator *gsi, gassign *stmt) > +match_unsigned_saturation_add (gimple_stmt_iterator *gsi, gassign *stmt) > { > - gcall *call = NULL; > + tree ops[2]; > + tree lhs = gimple_assign_lhs (stmt); > > + if (gimple_unsigned_integer_sat_add (lhs, ops, NULL)) > + build_saturation_binary_arith_call (gsi, IFN_SAT_ADD, lhs, ops[0], > ops[1]); > +} > + > +/* > + * Try to match saturation unsigned sub. > + * _1 = _4 >= _5; > + * _3 = _4 - _5; > + * _6 = _1 ? _3 : 0; > + * => > + * _6 = .SAT_SUB (_4, _5); */ > + > +static void > +match_unsigned_saturation_sub (gimple_stmt_iterator *gsi, gassign *stmt) > +{ > tree ops[2]; > tree lhs = gimple_assign_lhs (stmt); > > - if (gimple_unsigned_integer_sat_add (lhs, ops, NULL) > - && direct_internal_fn_supported_p (IFN_SAT_ADD, TREE_TYPE (lhs), > - OPTIMIZE_FOR_BOTH)) > - { > - call = gimple_build_call_internal (IFN_SAT_ADD, 2, ops[0], ops[1]); > - gimple_call_set_lhs (call, lhs); > - gsi_replace (gsi, call, true); > - } > + if (gimple_unsigned_integer_sat_sub (lhs, ops, NULL)) > + build_saturation_binary_arith_call (gsi, IFN_SAT_SUB, lhs, ops[0], > ops[1]); > } > > /* Recognize for unsigned x > @@ -6078,7 +6101,7 @@ math_opts_dom_walker::after_dom_children (basic_block > bb) > break; > > case BIT_IOR_EXPR: > - match_saturation_arith (&gsi, as_a<gassign *> (stmt)); > + match_unsigned_saturation_add (&gsi, as_a<gassign *> (stmt)); > /* fall-through */ > case BIT_XOR_EXPR: > match_uaddc_usubc (&gsi, stmt, code); > @@ -6089,6 +6112,10 @@ math_opts_dom_walker::after_dom_children (basic_block > bb) > match_single_bit_test (&gsi, stmt); > break; > > + case COND_EXPR: > + match_unsigned_saturation_sub (&gsi, as_a<gassign *> (stmt)); > + break; > + > default:; > } > } > -- > 2.34.1 >