This is an archive of the discontinued LLVM Phabricator instance.

[InstCombine] remove fold that swaps xor/or with constants
ClosedPublic

Authored by spatel on May 10 2017, 9:38 AM.

Details

Summary

I can't see the value in this fold:
// (X ^ C1) | C2 --> (X | C2) ^ (C1&~C2)
as an optimization or canonicalization, so I'm proposing to remove it.

Some examples of where this might fire:

define i8 @not_or(i8 %x) {
  %xor = xor i8 %x, -1
  %or = or i8 %xor, 7
  ret i8 %or
}
define i8 @xor_or(i8 %x) {
  %xor = xor i8 %x, 32
  %or = or i8 %xor, 7
  ret i8 %or
}
define i8 @xor_or2(i8 %x) {
  %xor = xor i8 %x, 33
  %or = or i8 %xor, 7
  ret i8 %or
}

Regardless of whether we remove this fold, we get:

define i8 @not_or(i8 %x) {
  %xor = or i8 %x, 7
  %or = xor i8 %xor, -8
  ret i8 %or
}  
define i8 @xor_or(i8 %x) {
  %xor = or i8 %x, 7
  %or = xor i8 %xor, 32
  ret i8 %or
}
define i8 @xor_or2(i8 %x) {
  %xor = or i8 %x, 7
  %or = xor i8 %xor, 32
  ret i8 %or
}

There are no test changes because our current demanded-bits handling for xor constants will always remove set bits of the xor constant, and then we'll activate the fold a few lines later under the comment:

// (X^C)|Y -> (X|Y)^C iff Y&C == 0

The larger motivation for removing this code is that it could interfere with the fix for PR32706:
https://bugs.llvm.org/show_bug.cgi?id=32706

Ie, we're not checking if the 'xor' is actually a 'not', so we could reverse a 'not' optimization and cause an infinite loop by altering an 'xor X, -1'. We can restore this fold after the demanded-bits change is restored if we can find a reason it helps?

Diff Detail

Event Timeline

spatel created this revision.May 10 2017, 9:38 AM
efriedma accepted this revision.May 10 2017, 11:05 AM

It's a canonicalization of sorts; could help pick up more complicated patterns like ((a ^ c1) | c2) ^ c3. Please make sure we have a regression test like this for instcombine.

https://reviews.llvm.org/rL7264 for reference.

This revision is now accepted and ready to land.May 10 2017, 11:05 AM

It's a canonicalization of sorts; could help pick up more complicated patterns like ((a ^ c1) | c2) ^ c3. Please make sure we have a regression test like this for instcombine.

https://reviews.llvm.org/rL7264 for reference.

Ah, the commit message makes the motivation clear - we want to sink xors down/out, so it's easier to combine the constant operands. There's surprisingly little regression testing for this (otherwise, I would've found the inf-loop potential of rL300977 sooner!). I'll add tests. For reference, the 'and' side of rL7264 was removed here:
https://reviews.llvm.org/rL299384

This revision was automatically updated to reflect the committed changes.