aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPan Li <pan2.li@intel.com>2025-07-02 09:59:26 +0800
committerPan Li <pan2.li@intel.com>2025-07-07 21:15:25 +0800
commitdc30f404170f538af6bf2457ccff252b08302dec (patch)
tree7157e1ad852cf688f09486a6889f8fdad8c03e31
parent35f5a18872127e18aadcbbc08df7885974280c79 (diff)
downloadgcc-dc30f404170f538af6bf2457ccff252b08302dec.zip
gcc-dc30f404170f538af6bf2457ccff252b08302dec.tar.gz
gcc-dc30f404170f538af6bf2457ccff252b08302dec.tar.bz2
Widening-Mul: Support unsigned scalar SAT_MUL form 1
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. 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.li@intel.com>
-rw-r--r--gcc/match.pd31
-rw-r--r--gcc/tree-ssa-math-opts.cc26
2 files changed, 57 insertions, 0 deletions
diff --git a/gcc/match.pd b/gcc/match.pd
index 10c2b97..ec2f560 100644
--- a/gcc/match.pd
+++ b/gcc/match.pd
@@ -3583,6 +3583,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 4cfcc42..ca98205 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));
@@ -4217,6 +4218,30 @@ match_unsigned_saturation_sub (gimple_stmt_iterator *gsi, gassign *stmt)
}
/*
+ * 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]:
* if (x_2(D) > y_3(D))
@@ -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;