summaryrefslogtreecommitdiff
path: root/gcc/match.pd
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/match.pd')
-rw-r--r--gcc/match.pd94
1 files changed, 90 insertions, 4 deletions
diff --git a/gcc/match.pd b/gcc/match.pd
index 63566df3205..f27073994b6 100644
--- a/gcc/match.pd
+++ b/gcc/match.pd
@@ -355,6 +355,11 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
(rdiv @0 (rdiv:s @1 @2))
(mult (rdiv @0 @1) @2)))
+/* Simplify x / (- y) to -x / y. */
+(simplify
+ (rdiv @0 (negate @1))
+ (rdiv (negate @0) @1))
+
/* Optimize (X & (-A)) / A where A is a power of 2, to X >> log2(A) */
(for div (trunc_div ceil_div floor_div round_div exact_div)
(simplify
@@ -606,6 +611,19 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
&& tree_nop_conversion_p (type, TREE_TYPE (@1)))
(lshift @0 @2)))
+/* Fold (1 << (C - x)) where C = precision(type) - 1
+ into ((1 << C) >> x). */
+(simplify
+ (lshift integer_onep@0 (minus@1 INTEGER_CST@2 @3))
+ (if (INTEGRAL_TYPE_P (type)
+ && wi::eq_p (wi::to_wide (@2), TYPE_PRECISION (type) - 1)
+ && single_use (@1))
+ (if (TYPE_UNSIGNED (type))
+ (rshift (lshift @0 @2) @3)
+ (with
+ { tree utype = unsigned_type_for (type); }
+ (convert (rshift (lshift (convert:utype @0) @2) @3))))))
+
/* Fold (C1/X)*C2 into (C1*C2)/X. */
(simplify
(mult (rdiv@3 REAL_CST@0 @1) REAL_CST@2)
@@ -686,6 +704,42 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
(bit_ior:c (bit_xor:c @0 @1) @0)
(bit_ior @0 @1))
+/* (a & ~b) | (a ^ b) --> a ^ b */
+(simplify
+ (bit_ior:c (bit_and:c @0 (bit_not @1)) (bit_xor:c@2 @0 @1))
+ @2)
+
+/* (a & ~b) ^ ~a --> ~(a & b) */
+(simplify
+ (bit_xor:c (bit_and:cs @0 (bit_not @1)) (bit_not @0))
+ (bit_not (bit_and @0 @1)))
+
+/* (a | b) & ~(a ^ b) --> a & b */
+(simplify
+ (bit_and:c (bit_ior @0 @1) (bit_not (bit_xor:c @0 @1)))
+ (bit_and @0 @1))
+
+/* a | ~(a ^ b) --> a | ~b */
+(simplify
+ (bit_ior:c @0 (bit_not:s (bit_xor:c @0 @1)))
+ (bit_ior @0 (bit_not @1)))
+
+/* (a | b) | (a &^ b) --> a | b */
+(for op (bit_and bit_xor)
+ (simplify
+ (bit_ior:c (bit_ior@2 @0 @1) (op:c @0 @1))
+ @2))
+
+/* (a & b) | ~(a ^ b) --> ~(a ^ b) */
+(simplify
+ (bit_ior:c (bit_and:c @0 @1) (bit_not@2 (bit_xor @0 @1)))
+ @2)
+
+/* ~(~a & b) --> a | ~b */
+(simplify
+ (bit_not (bit_and:cs (bit_not @0) @1))
+ (bit_ior @0 (bit_not @1)))
+
/* Simplify (~X & Y) to X ^ Y if we know that (X & ~Y) is 0. */
#if GIMPLE
(simplify
@@ -962,6 +1016,12 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
(match negate_expr_p
VEC_DUPLICATE_CST
(if (FLOAT_TYPE_P (TREE_TYPE (type)) || TYPE_OVERFLOW_WRAPS (type))))
+(match negate_expr_p
+ (minus @0 @1)
+ (if ((ANY_INTEGRAL_TYPE_P (type) && TYPE_OVERFLOW_WRAPS (type))
+ || (FLOAT_TYPE_P (type)
+ && !HONOR_SIGN_DEPENDENT_ROUNDING (type)
+ && !HONOR_SIGNED_ZEROS (type)))))
/* (-A) * (-B) -> A * B */
(simplify
@@ -977,6 +1037,15 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
&& !HONOR_SIGNED_ZEROS (element_mode (type)))
(minus (negate @1) @0)))
+/* -(A - B) -> B - A. */
+(simplify
+ (negate (minus @0 @1))
+ (if ((ANY_INTEGRAL_TYPE_P (type) && !TYPE_OVERFLOW_SANITIZED (type))
+ || (FLOAT_TYPE_P (type)
+ && !HONOR_SIGN_DEPENDENT_ROUNDING (type)
+ && !HONOR_SIGNED_ZEROS (type)))
+ (minus @1 @0)))
+
/* A - B -> A + (-B) if B is easily negatable. */
(simplify
(minus @0 negate_expr_p@1)
@@ -1093,6 +1162,11 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
|| !TYPE_UNSIGNED (TREE_TYPE (@0)))
(convert (minus @0 { build_each_one_cst (TREE_TYPE (@0)); }))))
+/* Convert - (~A) to A + 1. */
+(simplify
+ (negate (nop_convert (bit_not @0)))
+ (plus (view_convert @0) { build_each_one_cst (type); }))
+
/* Convert ~ (A - 1) or ~ (A + -1) to -A. */
(simplify
(bit_not (convert? (minus @0 integer_each_onep)))
@@ -1115,6 +1189,12 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
(if (tree_nop_conversion_p (type, TREE_TYPE (@0)))
(convert (bit_xor @0 @1))))
+/* Otherwise prefer ~(X ^ Y) to ~X ^ Y as more canonical. */
+(simplify
+ (bit_xor:c (nop_convert:s (bit_not:s @0)) @1)
+ (if (tree_nop_conversion_p (type, TREE_TYPE (@0)))
+ (bit_not (bit_xor (view_convert @0) @1))))
+
/* (x & ~m) | (y & m) -> ((x ^ y) & m) ^ x */
(simplify
(bit_ior:c (bit_and:cs @0 (bit_not @2)) (bit_and:cs @1 @2))
@@ -1734,7 +1814,7 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
/* Simplifications of MIN_EXPR, MAX_EXPR, fmin() and fmax(). */
-(for minmax (min max FMIN FMAX)
+(for minmax (min max FMIN FMIN_FN FMAX FMAX_FN)
(simplify
(minmax @0 @0)
@0))
@@ -1812,7 +1892,7 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
&& TYPE_PRECISION (TREE_TYPE (@0)) > TYPE_PRECISION (type))
(minmax @1 (convert @2)))))
-(for minmax (FMIN FMAX)
+(for minmax (FMIN FMIN_FN FMAX FMAX_FN)
/* If either argument is NaN, return the other one. Avoid the
transformation if we get (and honor) a signalling NaN. */
(simplify
@@ -1830,11 +1910,17 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
(FMIN @0 @1)
(min @0 @1))
(simplify
+ (FMIN_FN @0 @1)
+ (min @0 @1))
+ (simplify
(FMAX @0 @1)
+ (max @0 @1))
+ (simplify
+ (FMAX_FN @0 @1)
(max @0 @1)))
/* min (-A, -B) -> -max (A, B) */
-(for minmax (min max FMIN FMAX)
- maxmin (max min FMAX FMIN)
+(for minmax (min max FMIN FMIN_FN FMAX FMAX_FN)
+ maxmin (max min FMAX FMAX_FN FMIN FMAX_FN)
(simplify
(minmax (negate:s@2 @0) (negate:s@3 @1))
(if (FLOAT_TYPE_P (TREE_TYPE (@0))