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
>

Reply via email to