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

            Bug ID: 101676
           Summary: ^ not changed to | if the non-zero don't overlap
           Product: gcc
           Version: 12.0
            Status: UNCONFIRMED
          Keywords: missed-optimization
          Severity: normal
          Priority: P3
         Component: tree-optimization
          Assignee: unassigned at gcc dot gnu.org
          Reporter: pinskia at gcc dot gnu.org
  Target Milestone: ---

Take:
int f(int a, int b)
{
    if (a & ~8) __builtin_unreachable();
    if (b & 8) __builtin_unreachable();
    return a ^ b;
}
----- CUT -----
The xor here can converted into ior as a and b non-zero bits don't overlap.
Note clang does this optimization.

But clang does not do the following (which we should be able to do too).
Take:
int f(int a, int b)
{
    if (a & 8) __builtin_unreachable();
    if (b & ~1) __builtin_unreachable();
    return (a) ^ (b<<3);
}
This should be able to turn into a bit insert of b into a.
Right now both GCC (and really clang) turn this on aarch64:
        eor     w0, w0, w1, lsl 3 ;;;clang uses orr

Both can handle the following though:
int f(int a, int b)
{
 //   if (a & 8) __builtin_unreachable();
  //  if (b & ~1) __builtin_unreachable();
    return (a&~8) ^ ((b&1)<<3);
}
Unless you uncomment out the condtionals :).

Reply via email to