aboutsummaryrefslogtreecommitdiff
path: root/gcc/match.pd
diff options
context:
space:
mode:
authorMCC CS <deswurstes@users.noreply.github.com>2018-10-01 11:25:45 +0000
committerRichard Biener <rguenth@gcc.gnu.org>2018-10-01 11:25:45 +0000
commit03cc70b5f1999fe04354c0ba2227fce733308ad4 (patch)
tree5a3793f5ff39ac349b32705b43bfed6b3c5d1f2e /gcc/match.pd
parent6cc430c19a9c94835d31f171065f32f5b1863183 (diff)
downloadgcc-03cc70b5f1999fe04354c0ba2227fce733308ad4.zip
gcc-03cc70b5f1999fe04354c0ba2227fce733308ad4.tar.gz
gcc-03cc70b5f1999fe04354c0ba2227fce733308ad4.tar.bz2
re PR tree-optimization/87261 (Optimize bool expressions)
2018-10-01 MCC CS <deswurstes@users.noreply.github.com> PR tree-optimization/87261 * match.pd: Remove trailing whitespace. Add (x & y) | ~(x | y) -> ~(x ^ y), (~x | y) ^ (x ^ y) -> x | ~y and (x ^ y) | ~(x | y) -> ~(x & y) * gcc.dg/pr87261.c: New test. From-SVN: r264744
Diffstat (limited to 'gcc/match.pd')
-rw-r--r--gcc/match.pd49
1 files changed, 37 insertions, 12 deletions
diff --git a/gcc/match.pd b/gcc/match.pd
index ae26ec2..db0e4a8 100644
--- a/gcc/match.pd
+++ b/gcc/match.pd
@@ -92,7 +92,7 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
IFN_FMA IFN_FMS IFN_FNMA IFN_FNMS)
(define_operator_list COND_TERNARY
IFN_COND_FMA IFN_COND_FMS IFN_COND_FNMA IFN_COND_FNMS)
-
+
/* As opposed to convert?, this still creates a single pattern, so
it is not a suitable replacement for convert? in all cases. */
(match (nop_convert @0)
@@ -106,7 +106,7 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
&& tree_nop_conversion_p (TREE_TYPE (type), TREE_TYPE (TREE_TYPE (@0))))))
/* This one has to be last, or it shadows the others. */
(match (nop_convert @0)
- @0)
+ @0)
/* Transform likes of (char) ABS_EXPR <(int) x> into (char) ABSU_EXPR <x>
ABSU_EXPR returns unsigned absolute value of the operand and the operand
@@ -285,7 +285,7 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
And not for _Fract types where we can't build 1. */
(if (!integer_zerop (@0) && !ALL_FRACT_MODE_P (TYPE_MODE (type)))
{ build_one_cst (type); }))
- /* X / abs (X) is X < 0 ? -1 : 1. */
+ /* X / abs (X) is X < 0 ? -1 : 1. */
(simplify
(div:C @0 (abs @0))
(if (INTEGRAL_TYPE_P (type)
@@ -929,6 +929,31 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
(bitop:c @0 (bit_not (bitop:cs @0 @1)))
(bitop @0 (bit_not @1))))
+/* (~x & y) | ~(x | y) -> ~x */
+(simplify
+ (bit_ior:c (bit_and:c (bit_not@2 @0) @1) (bit_not (bit_ior:c @0 @1)))
+ @2)
+
+/* (x | y) ^ (x | ~y) -> ~x */
+(simplify
+ (bit_xor:c (bit_ior:c @0 @1) (bit_ior:c @0 (bit_not @1)))
+ (bit_not @0))
+
+/* (x & y) | ~(x | y) -> ~(x ^ y) */
+(simplify
+ (bit_ior:c (bit_and:s @0 @1) (bit_not:s (bit_ior:s @0 @1)))
+ (bit_not (bit_xor @0 @1)))
+
+/* (~x | y) ^ (x ^ y) -> x | ~y */
+(simplify
+ (bit_xor:c (bit_ior:cs (bit_not @0) @1) (bit_xor:s @0 @1))
+ (bit_ior @0 (bit_not @1)))
+
+/* (x ^ y) | ~(x | y) -> ~(x & y) */
+(simplify
+ (bit_ior:c (bit_xor:s @0 @1) (bit_not:s (bit_ior:s @0 @1)))
+ (bit_not (bit_and @0 @1)))
+
/* (x | y) & ~x -> y & ~x */
/* (x & y) | ~x -> y | ~x */
(for bitop (bit_and bit_ior)
@@ -1139,7 +1164,7 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
(if (tree_nop_conversion_p (type, TREE_TYPE (@0))
&& tree_nop_conversion_p (type, TREE_TYPE (@1)))
(mult (convert @0) (convert (negate @1)))))
-
+
/* -(A + B) -> (-B) - A. */
(simplify
(negate (plus:c @0 negate_expr_p@1))
@@ -3099,7 +3124,7 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
(if (tree_int_cst_sgn (@1) < 0)
(scmp @0 @2)
(cmp @0 @2))))))
-
+
/* Simplify comparison of something with itself. For IEEE
floating-point, we can only do some of these simplifications. */
(for cmp (eq ge le)
@@ -3170,11 +3195,11 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
}
tree newtype
= (TYPE_PRECISION (TREE_TYPE (@0)) > TYPE_PRECISION (type1)
- ? TREE_TYPE (@0) : type1);
+ ? TREE_TYPE (@0) : type1);
}
(if (TYPE_PRECISION (TREE_TYPE (@2)) > TYPE_PRECISION (newtype))
(cmp (convert:newtype @0) (convert:newtype @1))))))
-
+
(simplify
(cmp @0 REAL_CST@1)
/* IEEE doesn't distinguish +0 and -0 in comparisons. */
@@ -3422,7 +3447,7 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
(FTYPE) N == CST -> 0
(FTYPE) N != CST -> 1. */
(if (cmp == EQ_EXPR || cmp == NE_EXPR)
- { constant_boolean_node (cmp == NE_EXPR, type); })
+ { constant_boolean_node (cmp == NE_EXPR, type); })
/* Otherwise replace with sensible integer constant. */
(with
{
@@ -3666,7 +3691,7 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
(simplify
(cmp (bit_and@2 @0 integer_pow2p@1) @1)
(icmp @2 { build_zero_cst (TREE_TYPE (@0)); })))
-
+
/* If we have (A & C) != 0 ? D : 0 where C and D are powers of 2,
convert this into a shift followed by ANDing with D. */
(simplify
@@ -3886,7 +3911,7 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
(if (cmp == LE_EXPR)
(ge (convert:st @0) { build_zero_cst (st); })
(lt (convert:st @0) { build_zero_cst (st); }))))))))))
-
+
(for cmp (unordered ordered unlt unle ungt unge uneq ltgt)
/* If the second operand is NaN, the result is constant. */
(simplify
@@ -4540,7 +4565,7 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
(if (wi::to_wide (@1) == -1)
(rdiv { build_real (type, dconst1); } @0))))
-/* Narrowing of arithmetic and logical operations.
+/* Narrowing of arithmetic and logical operations.
These are conceptually similar to the transformations performed for
the C/C++ front-ends by shorten_binary_op and shorten_compare. Long
@@ -4612,7 +4637,7 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
(convert (bit_and (op (convert:utype @0) (convert:utype @1))
(convert:utype @4))))))))
-/* Transform (@0 < @1 and @0 < @2) to use min,
+/* Transform (@0 < @1 and @0 < @2) to use min,
(@0 > @1 and @0 > @2) to use max */
(for logic (bit_and bit_and bit_and bit_and bit_ior bit_ior bit_ior bit_ior)
op (lt le gt ge lt le gt ge )