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

--- Comment #2 from Richard Biener <rguenth at gcc dot gnu.org> ---
so it's _10 == _10 ^ 1 vs. (short) _2 == (short)(((char) _2) ^ 1)

likely simplified using logical_inverted_value which works fine for the first
but not the second form.  We're now doing more simplification (looking
through some extra conversions), but that prevents this pattern from matching.

By the time we compute the ranges necessary the conversions are already
pickled too far before simplifying the conditional.

Handling possible variants with patterns is a bit difficult, instead what
looks necessary here is some sort of symbolic equivalence processing that
would include bit ops so it tracks that _6 is _2 and _22 is _2 ^ 1.

What would also help here is simplifying

  # RANGE [0, 1] NONZERO 1
  _2 = 1 >> b.1_1;
  # RANGE [0, 1] NONZERO 1
  iftmp.0_10 = (char) _2;
  # RANGE [0, 1] NONZERO 1
  _4 = iftmp.0_10 ^ 1;
  # RANGE [0, 1] NONZERO 1
  _5 = (int) _4;
  # RANGE [0, 1] NONZERO 1
  iftmp.6_22 = (short int) _5;

via ((char)_2) ^ 1 -> (char)(_2 ^ 1) though we generally do not widen ops.
Which means doing it one level more outer at (int)((char) _2) ^ 1)
-> _2 ^ 1 which is possible because the truncation is a no-op.  That could
be applied to all bit ops when we have range info on the non-constant
operand for the case where the wider type fits in a GPR.

Reply via email to