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.