summaryrefslogtreecommitdiff
path: root/gcc/match.pd
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/match.pd')
-rw-r--r--gcc/match.pd21
1 files changed, 20 insertions, 1 deletions
diff --git a/gcc/match.pd b/gcc/match.pd
index 60b4ad5f706..3e54e2cf5a6 100644
--- a/gcc/match.pd
+++ b/gcc/match.pd
@@ -38,7 +38,8 @@ along with GCC; see the file COPYING3. If not see
uniform_integer_cst_p
HONOR_NANS
uniform_vector_p
- expand_vec_cmp_expr_p)
+ expand_vec_cmp_expr_p
+ bitmask_inv_cst_vector_p)
/* Operator lists. */
(define_operator_list tcc_comparison
@@ -5207,6 +5208,24 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
(eqcmp (bit_and @1 { wide_int_to_tree (ty, mask - rhs); })
{ build_zero_cst (ty); }))))))
+/* Transform comparisons of the form (X & Y) CMP 0 to X CMP2 Z
+ where ~Y + 1 == pow2 and Z = ~Y. */
+(for cst (VECTOR_CST INTEGER_CST)
+ (for cmp (le eq ne ge gt)
+ icmp (le le gt le gt)
+ (simplify
+ (cmp (bit_and:c@2 @0 cst@1) integer_zerop)
+ (with { tree csts = bitmask_inv_cst_vector_p (@1); }
+ (switch
+ (if (csts && TYPE_UNSIGNED (TREE_TYPE (@1))
+ && (VECTOR_TYPE_P (TREE_TYPE (@1)) || single_use (@2)))
+ (icmp @0 { csts; }))
+ (if (csts && !TYPE_UNSIGNED (TREE_TYPE (@1))
+ && (cmp == EQ_EXPR || cmp == NE_EXPR)
+ && (VECTOR_TYPE_P (TREE_TYPE (@1)) || single_use (@2)))
+ (with { tree utype = unsigned_type_for (TREE_TYPE (@1)); }
+ (icmp (convert:utype @0) { csts; }))))))))
+
/* -A CMP -B -> B CMP A. */
(for cmp (tcc_comparison)
scmp (swapped_tcc_comparison)