aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gcc/match.pd16
-rw-r--r--gcc/tree-vect-patterns.cc5
2 files changed, 20 insertions, 1 deletions
diff --git a/gcc/match.pd b/gcc/match.pd
index a664be5..4cef965 100644
--- a/gcc/match.pd
+++ b/gcc/match.pd
@@ -3221,6 +3221,22 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
(bit_xor:c (negate (convert (lt @0 integer_zerop))) max_value))
(if (INTEGRAL_TYPE_P (type) && !TYPE_UNSIGNED (type))))
+/* Signed saturation add, case 3:
+ T sum = (T)((UT)X + (UT)Y)
+ SAT_S_ADD = (X ^ Y) < 0 && (X ^ sum) >= 0 ? (-(T)(X < 0) ^ MAX) : sum;
+
+ The T and UT are type pair like T=int8_t, UT=uint8_t. */
+(match (signed_integer_sat_add @0 @1)
+ (cond^ (bit_and:c (lt (bit_xor @0 (nop_convert@2 (plus (nop_convert @0)
+ (nop_convert @1))))
+ integer_zerop)
+ (ge (bit_xor:c @0 @1) integer_zerop))
+ (bit_xor:c (nop_convert (negate (nop_convert (convert
+ (lt @0 integer_zerop)))))
+ max_value)
+ @2)
+ (if (INTEGRAL_TYPE_P (type) && !TYPE_UNSIGNED (type))))
+
/* Unsigned saturation sub, case 1 (branch with gt):
SAT_U_SUB = X > Y ? X - Y : 0 */
(match (unsigned_integer_sat_sub @0 @1)
diff --git a/gcc/tree-vect-patterns.cc b/gcc/tree-vect-patterns.cc
index 3a0d4cb..a2bf90a 100644
--- a/gcc/tree-vect-patterns.cc
+++ b/gcc/tree-vect-patterns.cc
@@ -4497,6 +4497,8 @@ 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_signed_integer_sat_add (tree, tree*, tree (*)(tree));
+
static gimple *
vect_recog_build_binary_gimple_stmt (vec_info *vinfo, stmt_vec_info stmt_info,
internal_fn fn, tree *type_out,
@@ -4557,7 +4559,8 @@ vect_recog_sat_add_pattern (vec_info *vinfo, stmt_vec_info stmt_vinfo,
tree ops[2];
tree lhs = gimple_assign_lhs (last_stmt);
- if (gimple_unsigned_integer_sat_add (lhs, ops, NULL))
+ if (gimple_unsigned_integer_sat_add (lhs, ops, NULL)
+ || gimple_signed_integer_sat_add (lhs, ops, NULL))
{
if (TREE_CODE (ops[1]) == INTEGER_CST)
ops[1] = fold_convert (TREE_TYPE (ops[0]), ops[1]);