https://gcc.gnu.org/bugzilla/show_bug.cgi?id=109986

--- Comment #3 from Ivan Sorokin <vanyacpp at gmail dot com> ---
I tried to investigate why GCC is able to simplify `(a | b) ^ a` and `(a | ~b)
^ a` from comment 2, but not similarly looking `(~a | b) ^ a` from comment 0.

`(a | b) ^ a` matches the following pattern from match.pd:

/* (X | Y) ^ X -> Y & ~ X*/
(simplify
 (bit_xor:c (convert1? (bit_ior:c @@0 @1)) (convert2? @0))
 (if (tree_nop_conversion_p (type, TREE_TYPE (@0)))
  (convert (bit_and @1 (bit_not @0)))))

`(a | ~b) ^ a` matches another pattern:

/* (~X | C) ^ D -> (X | C) ^ (~D ^ C) if (~D ^ C) can be simplified.  */
(simplify
 (bit_xor:c (bit_ior:cs (bit_not:s @0) @1) @2)
  (bit_xor (bit_ior @0 @1) (bit_xor! (bit_not! @2) @1)))

With substitution `X = b, C = a, D = a` it gives:

(b | a) ^ (~a ^ a)
(b | a) ^ -1
~(b | a)

`(~a | b) ^ a` is not simplifiable by this pattern because it requires that `~D
^ C` is simplifiable further, but `~a ^ b` is not. In any case, even if it were
applicable it would produce `(a | b) ^ (~a ^ b)` which has more operations than
the original expression.

Reply via email to