https://gcc.gnu.org/bugzilla/show_bug.cgi?id=122843
--- Comment #5 from Richard Biener <rguenth at gcc dot gnu.org> ---
I can see
/* (X ^ Y) ^ (X ^ Z) -> Y ^ Z */
(simplify
(bit_xor (convert1? (bit_xor:c @0 @1)) (convert2? (bit_xor:c @0 @2)))
(if (tree_nop_conversion_p (type, TREE_TYPE (@1))
&& tree_nop_conversion_p (type, TREE_TYPE (@2)))
(bit_xor (convert @1) (convert @2))))
plus
(for bitop (bit_and bit_ior bit_xor)
(simplify
(bitop (convert@2 @0) (convert?@3 @1))
...
(convert (bitop @0 (convert @1)))))
simplify a deeply nested XOR chain. Even the first pattern on its own.
But I also note we do
gimple_simplified to _1816 = _9 ^ p_17$f1_52;
_1817 = (signed char) _1816;
_1818 = (signed char) _1816;
_1819 = (signed char) _1816;
_1809 = _1816;
so we create a lot of garbage that we'll re-fold. In particular the
loop over stmts in forwprop doesn't seem to ignore trivial zero-use
stmts?
So the above seem to happen when we create (convert ..) of something
that's already a conversion. We code-generate
2113 if (type != res_op->type
2114 && !useless_type_conversion_p (type, res_op->type))
2115 {
2116 if (!(res_op->ops[0] = maybe_push_res_to_seq (res_op,
lseq))) goto next_after_fail651;
2117 res_op->set_op (NOP_EXPR, type, 1);
2118 res_op->resimplify (lseq, valueize);
but if the two conversions combine we've already pushed garbage to seq.
So what we'd instead want here is check if res_op can be converted
in-place.