This is an archive of the discontinued LLVM Phabricator instance.

[InstCombine] canonicalize cmp-of-bitcast-of-vector-cmp to use zero constant
ClosedPublic

Authored by spatel on Jul 30 2021, 8:25 AM.

Details

Summary

We can invert a compare constant and compare predicate and preserve the logic as shown in this sampling:
https://alive2.llvm.org/ce/z/YAXbfs
(In theory, we could deal with non-all-ones/zero as well, but it doesn't seem worthwhile.)

I noticed this as a part of the x86 codegen difference in https://llvm.org/PR51259 - that ends up using "test" instead of "not + cmp" in that example.

This pattern also shows up in https://llvm.org/PR41312 and https://llvm.org/PR50798 .

Diff Detail

Event Timeline

spatel created this revision.Jul 30 2021, 8:25 AM
spatel requested review of this revision.Jul 30 2021, 8:25 AM
Herald added a project: Restricted Project. · View Herald TranscriptJul 30 2021, 8:25 AM

The actual pattern here is: https://alive2.llvm.org/ce/z/GKG6Sy
Can you generalize this somewhat by making use of isFreeToInvert() on the bitcast's argument?

The actual pattern here is: https://alive2.llvm.org/ce/z/GKG6Sy
Can you generalize this somewhat by making use of isFreeToInvert() on the bitcast's argument?

Yes, that's better. I'll add some tests and then update here.

spatel updated this revision to Diff 363224.Jul 30 2021, 3:23 PM

Patch updated:
Use isFreeToInvert for more general pattern match. I added some tests to exercise that, and it also gives a few more diffs in the existing PhaseOrdering test file via matching fcmp.

lebedev.ri accepted this revision.Jul 30 2021, 3:36 PM

LG, thank you.

This revision is now accepted and ready to land.Jul 30 2021, 3:36 PM

Hm, to be noted, this is still only a subpattern, with further generalization being: (https://alive2.llvm.org/ seems to be down)

define i1 @src(i8 %x, i8 %y) {
  %nx = xor i8 %x, -1
  %r = icmp eq i8 %nx, %y
  ret i1 %r
}

define i1 @tgt(i8 %x, i8 %y) {
  %ny = xor i8 %y, -1
  %r = icmp eq i8 %x, %ny
  ret i1 %r
}
----------------------------------------
define i1 @src(i8 %x, i8 %y) {
%0:
  %nx = xor i8 %x, 255
  %r = icmp eq i8 %nx, %y
  ret i1 %r
}
=>
define i1 @tgt(i8 %x, i8 %y) {
%0:
  %ny = xor i8 %y, 255
  %r = icmp eq i8 %x, %ny
  ret i1 %r
}
Transformation seems to be correct!

and

define i8 @src(<2 x i4> %x) {
  %s = bitcast <2 x i4> %x to i8
  %r = xor i8 %s, -1
  ret i8 %r
}

define i8 @tgt(<2 x i4> %x) {
  %nx = xor <2 x i4> %x, <i4 -1, i4 -1>
  %r = bitcast <2 x i4> %nx to i8
  ret i8 %r
}
----------------------------------------
define i8 @src(<2 x i4> %x) {
%0:
  %s = bitcast <2 x i4> %x to i8
  %r = xor i8 %s, 255
  ret i8 %r
}
=>
define i8 @tgt(<2 x i4> %x) {
%0:
  %nx = xor <2 x i4> %x, { 15, 15 }
  %r = bitcast <2 x i4> %nx to i8
  ret i8 %r
}
Transformation seems to be correct!

Hm, to be noted, this is still only a subpattern, with further generalization being: (https://alive2.llvm.org/ seems to be down)

Thanks! I'll put a TODO note on this. At first glance, I'm not sure what steps would be needed in the more generalized forms. We do have foldBitCastBitwiseLogic(), but there's a comment in there about changing ops from scalar <-> vector.

This revision was landed with ongoing or failed builds.Jul 31 2021, 10:52 AM
This revision was automatically updated to reflect the committed changes.

Hm, to be noted, this is still only a subpattern, with further generalization being: (https://alive2.llvm.org/ seems to be down)

Thanks! I'll put a TODO note on this. At first glance, I'm not sure what steps would be needed in the more generalized forms. We do have foldBitCastBitwiseLogic(), but there's a comment in there about changing ops from scalar <-> vector.

Mainly the next step is: there shouldn't be isFreeToInvert(), it should be InstCombineInverter (a.k.a InstCombineNegator, but for inversion)