This is an archive of the discontinued LLVM Phabricator instance.

Improve clamp recognition in ValueTracking.
ClosedPublic

Authored by ArturGainullin on Oct 4 2017, 1:37 AM.

Details

Summary

ValueTracking was recognizing not all variations of clamp. Swapping of
true value and false value of select was added to fix this problem. This
change breaks the canonical form of cmp inside the matchMinMax function,
that is why additional checks for compare predicates is needed. Added
corresponding test cases.

Also there is a reverse transformation for cmp instruction:

icmp smin(x, PositiveValue), 0 -> icmp x, 0

We should only do this after checking for min/max to prevent infinite
looping caused by a reverse canonicalization of these patterns. That is
why this transformation was moved to place after the mentioned check.
Test case was also added to check that we don't go to infinite loop.

Diff Detail

Repository
rL LLVM

Event Timeline

ArturGainullin created this revision.Oct 4 2017, 1:37 AM
spatel edited edge metadata.

I think this makes sense, but adding reviewers for more potential opinions.

But I suggest that we split the "foldICmpMinConstant" part into its own patch as a preliminary step. I went ahead and checked in the tests at rL315461, so I could understand how these things interact.

If I'm seeing it correctly, we'll get one test case (clamp_check_for_no_infinite_loop1) that will become a canonical clamp pattern with the code movement in InstCombineCompares, so we can do that before the value tracking change.

lib/Analysis/ValueTracking.cpp
4085–4086 ↗(On Diff #117633)

Didn't the caller (llvm::matchSelectPattern()) already check for this?

lib/Transforms/InstCombine/InstCombineCompares.cpp
1322 ↗(On Diff #117633)

This name confused me because when I see "min constant", I think of 0x8000...
How about "foldICmpSgtZeroMinPos" ?

But shouldn't there be an smax sibling for this fold?
For reference, the fold was added with D17873.

1327 ↗(On Diff #117633)

Use m_Zero() to simplify this.

1330 ↗(On Diff #117633)

Don't need to explicitly set to nullptr here?

4470 ↗(On Diff #117633)

typo: after after

efriedma added inline comments.Oct 11 2017, 6:58 PM
lib/Transforms/InstCombine/InstCombineCompares.cpp
1331 ↗(On Diff #117633)

Slightly more general transform:

https://rise4fun.com/Alive/AKv

In any case, this should probably be a separate patch.

Created separate patch to move folding of cmp instruction: D38934. I will be able to update this differential revision when it will be committed.
I have renamed function so that we will be able to add an smax sibling for this fold with separate commit.

As far as I understood efriedma proposes to implement more general transformation (changed it a little bit so that it is more evident that it is related to current transformation):

Precondition: C2 s> C1

icmp sgt smin(a, C2), C1 -> icmp sgt a, C1

https://rise4fun.com/Alive/oFF
I agree that this should be done as a separate commit.

Rebase after committing foldICmpWithZero as a separate change.
Also made changes according to comments.

spatel requested changes to this revision.Oct 16 2017, 8:24 AM

This patch can miscompile because it's not checking predicates correctly. I'm not sure how to expose this in an IR test because we don't canonicalize enough yet, so I added x86 tests at rL315913.

This revision now requires changes to proceed.Oct 16 2017, 8:24 AM
ArturGainullin edited edge metadata.
ArturGainullin marked an inline comment as done.

We need to check that predicate is signed before matching patterns after clamp.
This condition was removed by mistake. Fixed.

spatel accepted this revision.Oct 16 2017, 2:54 PM

LGTM.

If you want to change that first equality predicate check (the one that was removed from the top of the function) into an assert, I think that would be good since it's not obvious that we've filtered those cases out before we call this function.

This revision is now accepted and ready to land.Oct 16 2017, 2:54 PM
This revision was automatically updated to reflect the committed changes.