This is an archive of the discontinued LLVM Phabricator instance.

[InstSimplify] Odd - X ==/!= X -> false/true
ClosedPublic

Authored by liaolucy on Aug 30 2022, 7:26 PM.

Diff Detail

Event Timeline

liaolucy created this revision.Aug 30 2022, 7:26 PM
Herald added a project: Restricted Project. · View Herald TranscriptAug 30 2022, 7:26 PM
Herald added a subscriber: hiraditya. · View Herald Transcript
liaolucy requested review of this revision.Aug 30 2022, 7:26 PM
Herald added a project: Restricted Project. · View Herald TranscriptAug 30 2022, 7:26 PM
nikic added a subscriber: nikic.Aug 31 2022, 12:02 AM

Please provide an alive proof and add tests for other predicates as well, as well as negative tests (e.g. 2 instead of 1, which should not fold).

Please provide an alive proof and add tests for other predicates as well, as well as negative tests (e.g. 2 instead of 1, which should not fold).

https://alive2.llvm.org/ce/z/DJqxNZ try to add alive, please correct me if it's not correct

Move this to InstSimplify rather than InstCombine. It should handle both equality preds at least (eq and ne). You should not create a fake instruction - create the expected constant directly.

https://alive2.llvm.org/ce/z/DJqxNZ try to add alive, please correct me if it's not correct

I think we can generalize the transform at least in one direction - the constant does not have to be 1:
https://alive2.llvm.org/ce/z/bPYNJT
(not sure if there's some other relationship for non-equality predicates)

liaolucy updated this revision to Diff 457491.Sep 1 2022, 8:33 PM

iupdate to InstSimplify, transform:
(sub nsw|nuw C, X) == X, C is odd --> false
https://alive2.llvm.org/ce/z/dyn2Z2

(sub nsw|nuw C, X) != X, C is odd --> true
https://alive2.llvm.org/ce/z/5aSkqc

(sub 1, X) == X --> false
(sub 1, X) != X --> true
https://alive2.llvm.org/ce/z/DJqxNZ

liaolucy retitled this revision from [InstCombine] fold 1 - X == X to false to [InstSimplify] Odd - X ==/!= X -> false/true .Sep 1 2022, 8:34 PM

I think we can generalize the transform at least in one direction - the constant does not have to be 1:
https://alive2.llvm.org/ce/z/bPYNJT
(not sure if there's some other relationship for non-equality predicates)

I am trying to understand the example, get odd constant value from more instructions(>1), I don't know how to implement it, any suggestions?

spatel added a comment.Sep 2 2022, 6:21 AM

I think we can generalize the transform at least in one direction - the constant does not have to be 1:
https://alive2.llvm.org/ce/z/bPYNJT
(not sure if there's some other relationship for non-equality predicates)

I am trying to understand the example, get odd constant value from more instructions(>1), I don't know how to implement it, any suggestions?

The proof just shows that the transform is valid for any value with low-bit cleared.

If the value is a constant, then it is easy to detect. If the value is not constant, then we have to try more expensive (in compile-time) analysis - see ValueTracking's computeKnownBits() for example.

If we do not have a real-world example that shows the more expensive transform is needed, then we should not add it. In other words, the patch is mostly fine as implemented. But I do not understand why we have no-wrap requirements. The transform is correct without those:
https://alive2.llvm.org/ce/z/h4ZFVD

llvm/test/Transforms/InstCombine/icmp-sub.ll
570 ↗(On Diff #457491)

No need to include "entry" label in a minimum test like this.

572 ↗(On Diff #457491)

What happens if %sub and %x are swapped in this test?

576 ↗(On Diff #457491)

Change this to a vector type to confirm that the transform works in that case too. We should have one test where the vector constant includes a "poison" element too.

587 ↗(On Diff #457491)

We need at least one negative test with an even constant. That shows that the transform is not happening when it should not.

spatel added a comment.Sep 2 2022, 6:30 AM

The proof just shows that the transform is valid for any value with low-bit cleared.

Sorry - that was supposed to be "any value with low-bit set".

liaolucy updated this revision to Diff 457599.Sep 2 2022, 7:58 AM
liaolucy retitled this revision from [InstSimplify] Odd - X ==/!= X -> false/true to [InstSimplify] Odd - X ==/!= X -> false/true.
  1. Add more test case.
  2. Delete no-wrap check.

If we do not have a real-world example that shows the more expensive transform is needed, then we should not add it. In other words, the patch is mostly fine as implemented. But I do not understand why we have no-wrap requirements. The transform is correct without those:
https://alive2.llvm.org/ce/z/h4ZFVD

Actually, I'm not sure if just using srem(2) is correct.

spatel added a comment.Sep 2 2022, 8:11 AM

If we do not have a real-world example that shows the more expensive transform is needed, then we should not add it. In other words, the patch is mostly fine as implemented. But I do not understand why we have no-wrap requirements. The transform is correct without those:
https://alive2.llvm.org/ce/z/h4ZFVD

Actually, I'm not sure if just using srem(2) is correct.

I think it would be a little more efficient/readable to code this as "*C & 1".

But we need to be certain that the transform is correct to proceed. Do you have a counter-example that shows an incorrect result?

liaolucy updated this revision to Diff 457846.Sep 4 2022, 2:28 AM

Use *C & 1 to find odd constant value

RKSimon added inline comments.Sep 4 2022, 3:52 AM
llvm/lib/Analysis/InstructionSimplify.cpp
3310

Can we use knownbits here instead to support non-uniform constant vectors?

I'm never very clear on when we're allowed to use value tracking in instsimplify as its more expensive....

spatel added a comment.Sep 4 2022, 7:32 AM
  1. Did you determine that the transform is valid without nsw/nuw?
  1. My request for a vector test with poison element was not handled. Please mark inline questions as completed when they are answered.
  1. The tests should be in the tests/Transforms/InstSimplify directory, and the RUN line should only use -instsimplify.
llvm/lib/Analysis/InstructionSimplify.cpp
3308–3309

Reduce to match() with m_Specific()?

3310

Yes, I mentioned that in an earlier comment.

I think we could handle the non-uniform constant pattern even without knownbits - check the compare of a constant expression? But I'd say let's do that as a follow-up to keep this patch simpler.

liaolucy updated this revision to Diff 457886.Sep 4 2022, 8:29 PM
liaolucy marked 5 inline comments as done.
  1. Move testcases to tests/Transforms/InstSimplify
  2. Use m_Specific
  1. Did you determine that the transform is valid without nsw/nuw?

Yes, it is correct without nsw/nuw, some testcases have been added.

spatel added inline comments.Sep 5 2022, 6:08 AM
llvm/lib/Analysis/InstructionSimplify.cpp
3254–3261

Can you add this match inside of simplifyICmpWithBinOpOnLHS()? Then the swapped pattern is handled automatically.

3308

The nullptr and equality checks are redundant - that is handled by the match().

llvm/test/Transforms/InstSimplify/icmp.ll
215

Please pre-commit the baseline tests and then update this patch so it shows the diffs.

liaolucy updated this revision to Diff 457990.Sep 5 2022, 7:18 AM
liaolucy marked 2 inline comments as done.

Move to simplifyICmpWithBinOpOnLHS()

liaolucy updated this revision to Diff 458015.Sep 5 2022, 8:29 AM
liaolucy marked an inline comment as done.

address comments , thanks spatel. rebase.

spatel accepted this revision.Sep 5 2022, 8:50 AM

LGTM

llvm/lib/Analysis/InstructionSimplify.cpp
3134

This can be shortened like the code above:

return getFalse(ITy);
...
return getTrue(ITy);
This revision is now accepted and ready to land.Sep 5 2022, 8:50 AM
This revision was landed with ongoing or failed builds.Sep 5 2022, 8:51 AM
This revision was automatically updated to reflect the committed changes.
liaolucy added inline comments.Sep 5 2022, 9:01 AM
llvm/lib/Analysis/InstructionSimplify.cpp
3134
3134