[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