[Bug tree-optimization/95034] Failure to convert xor pattern (made out of or+and) to xor
jakub at gcc dot gnu.org
gcc-bugzilla@gcc.gnu.org
Tue Jan 12 12:12:02 GMT 2021
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=95034
--- Comment #4 from Jakub Jelinek <jakub at gcc dot gnu.org> ---
Tried
--- match.pd.jj1 2021-01-05 16:33:21.809960885 +0100
+++ match.pd 2021-01-12 12:47:11.232713918 +0100
@@ -1228,6 +1228,64 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
(bit_xor (bit_ior:c (bit_not @0) @1) (bit_ior:c @0 (bit_not @1)))
(bit_xor @0 @1))
+#if GENERIC
+/* Repeat the above simplifications for truth* for GENERIC.
+ It can be done even for truth_*if as both x and y are always evaluated.
+ Unfortunately :c on truth_*if aren't allowed (they aren't commutative,
+ but in this case we don't care). */
+(for andop (truth_and truth_andif)
+ orop (truth_or truth_orif)
+ /* (x || y) && !(x && y) -> x ^ y */
+ (simplify
+ (andop (orop @0 @1) (truth_not (andop @0 @1)))
+ (truth_xor @0 @1))
+ (simplify
+ (andop (truth_not (andop @0 @1)) (orop @0 @1))
+ (truth_xor @0 @1))
+
+ /* (x || y) && (!x ^ y) -> x && y */
+ (simplify
+ (andop (orop @0 @1) (truth_xor:c @1 (truth_not @0)))
+ (truth_and @0 @1))
+ (simplify
+ (andop (orop @1 @0) (truth_xor:c @1 (truth_not @0)))
+ (truth_and @0 @1))
+ (simplify
+ (andop (truth_xor:c @1 (truth_not @0)) (orop @0 @1))
+ (truth_and @0 @1))
+ (simplify
+ (andop (truth_xor:c @1 (truth_not @0)) (orop @1 @0))
+ (truth_and @0 @1))
+
+ /* (!x || y) && (x || !y) -> !(x ^ y) */
+ (simplify
+ (andop (orop:s (truth_not @0) @1) (orop:s @0 (truth_not @1)))
+ (truth_not (truth_xor @0 @1)))
+ (simplify
+ (andop (orop:s @1 (truth_not @0)) (orop:s @0 (truth_not @1)))
+ (truth_not (truth_xor @0 @1)))
+ (simplify
+ (andop (orop:s (truth_not @0) @1) (orop:s (truth_not @1) @0))
+ (truth_not (truth_xor @0 @1)))
+ (simplify
+ (andop (orop:s @1 (truth_not @0)) (orop:s (truth_not @1) @0))
+ (truth_not (truth_xor @0 @1)))
+
+ /* (!x || y) ^ (x || !y) -> x ^ y */
+ (simplify
+ (truth_xor (orop (truth_not @0) @1) (orop @0 (truth_not @1)))
+ (truth_xor @0 @1))
+ (simplify
+ (truth_xor (orop @1 (truth_not @0)) (orop @0 (truth_not @1)))
+ (truth_xor @0 @1))
+ (simplify
+ (truth_xor (orop (truth_not @0) @1) (orop (truth_not @1) @0))
+ (truth_xor @0 @1))
+ (simplify
+ (truth_xor (orop @1 (truth_not @0)) (orop (truth_not @1) @0))
+ (truth_xor @0 @1)))
+#endif
+
/* ((x & y) - (x | y)) - 1 -> ~(x ^ y) */
(simplify
(plus (nop_convert1? (minus@2 (nop_convert2? (bit_and:c @0 @1))
but in addition to it being lengthy (as one can't use :c on andop or orop
because truth_andif and truth_orif aren't commutative), it doesn't really work
here, because e.g. fold_truth_andor_1 optimizes that x || y into (x | y) != 0
before we can optimize it.
Another option is to code it in fold_truth_andor or fold_truth_andor_1.
More information about the Gcc-bugs
mailing list