From: Pan Li <pan2...@intel.com> This patch would like to add the middle-end presentation for the unsigend saturation mul. Aka set the result of mul to the max when overflow.
Take uint8_t as example, we will have: * SAT_MUL (1, 127) => 127. * SAT_MUL (2, 127) => 254. * SAT_MUL (3, 127) => 255. * SAT_MUL (255, 127) => 255. Given below example for uint16_t from uint128_t #define DEF_SAT_U_MUL_FMT_1(NT, WT) \ NT __attribute__((noinline)) \ sat_u_mul_##NT##_from_##WT##_fmt_1 (NT a, NT b) \ { \ WT x = (WT)a * (WT)b; \ NT max = -1; \ if (x > (WT)(max)) \ return max; \ else \ return (NT)x; \ } DEF_SAT_U_MUL_FMT_1(uint16_t, uint128_t) Before this patch: 15 │ <bb 2> [local count: 1073741824]: 16 │ _1 = (__int128 unsigned) a_4(D); 17 │ _2 = (__int128 unsigned) b_5(D); 18 │ _9 = (unsigned long) _1; 19 │ _10 = (unsigned long) _2; 20 │ x_6 = _9 w* _10; 21 │ _7 = MIN_EXPR <x_6, 255>; 22 │ _3 = (uint8_t) _7; 23 │ return _3; After this patch: 9 │ <bb 2> [local count: 1073741824]: 10 │ _3 = .SAT_MUL (a_4(D), b_5(D)); [tail call] 11 │ return _3; gcc/ChangeLog: * internal-fn.cc (commutative_binary_fn_p): Add new case for SAT_MUL. * internal-fn.def (SAT_MUL): Add new IFN_SAT_MUL. * optabs.def (OPTAB_NL): Remove fixed point limitation. Signed-off-by: Pan Li <pan2...@intel.com> --- gcc/internal-fn.cc | 1 + gcc/internal-fn.def | 1 + gcc/optabs.def | 2 +- 3 files changed, 3 insertions(+), 1 deletion(-) diff --git a/gcc/internal-fn.cc b/gcc/internal-fn.cc index 3f4ac937367..184f72132cc 100644 --- a/gcc/internal-fn.cc +++ b/gcc/internal-fn.cc @@ -4423,6 +4423,7 @@ commutative_binary_fn_p (internal_fn fn) case IFN_ADD_OVERFLOW: case IFN_MUL_OVERFLOW: case IFN_SAT_ADD: + case IFN_SAT_MUL: case IFN_VEC_WIDEN_PLUS: case IFN_VEC_WIDEN_PLUS_LO: case IFN_VEC_WIDEN_PLUS_HI: diff --git a/gcc/internal-fn.def b/gcc/internal-fn.def index 8edfa3540f8..914ee9f278c 100644 --- a/gcc/internal-fn.def +++ b/gcc/internal-fn.def @@ -282,6 +282,7 @@ DEF_INTERNAL_SIGNED_OPTAB_FN (MULHRS, ECF_CONST | ECF_NOTHROW, first, 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_SIGNED_OPTAB_FN (SAT_MUL, ECF_CONST, first, ssmul, usmul, binary) DEF_INTERNAL_SIGNED_OPTAB_FN (SAT_TRUNC, ECF_CONST, first, sstrunc, ustrunc, unary_convert) diff --git a/gcc/optabs.def b/gcc/optabs.def index 0c1435d4ecd..ea049378112 100644 --- a/gcc/optabs.def +++ b/gcc/optabs.def @@ -135,7 +135,7 @@ OPTAB_NX(smul_optab, "mul$F$a3") OPTAB_VL(smulv_optab, "mulv$I$a3", MULT, "mul", '3', gen_intv_fp_libfunc) OPTAB_VX(smulv_optab, "mul$F$a3") OPTAB_NL(ssmul_optab, "ssmul$Q$a3", SS_MULT, "ssmul", '3', gen_signed_fixed_libfunc) -OPTAB_NL(usmul_optab, "usmul$Q$a3", US_MULT, "usmul", '3', gen_unsigned_fixed_libfunc) +OPTAB_NL(usmul_optab, "usmul$a3", US_MULT, "usmul", '3', gen_unsigned_fixed_libfunc) OPTAB_NL(sdiv_optab, "div$a3", DIV, "div", '3', gen_int_fp_signed_fixed_libfunc) OPTAB_VL(sdivv_optab, "divv$I$a3", DIV, "divv", '3', gen_int_libfunc) OPTAB_VX(sdivv_optab, "div$F$a3") -- 2.43.0