This is an archive of the discontinued LLVM Phabricator instance.

[LVI] Look through negations when evaluating conditions
ClosedPublic

Authored by loladiro on Jan 3 2023, 6:02 PM.

Details

Summary

This teaches LVI (and thus CVP) to extract range information
from branches whose condition is negated using (xor %c, true).
The implementation is relatively straightforward, simply computing
the inverse of the relevant lattice information.

I think the biggest question here is why this negation shows up
here at all. After all, it should always be possible for some
other pass to fold such a negation into a branch, comparison or
some other logical operation. Indeed, instcombine does just that.
However, these negations can be otherwise fairly persistent, e.g.
instsimplify is not able to exchange branch conditions from
negations. In addition, jumpthreading, which sits at the same
point in default pass pipeline also handles this pattern, which
adds further evidence that we might expect these negations to
not have been canonicalized away yet at this point in the pass
pipeline.

In the particular case I was looking at there was a bit of a
circular dependency where flags computed by cvp were needed
by instcombine, and incstombine's folding of the negation was
needed for cvp. Adding a second instombine pass would have
worked of course, but instcombine can be somewhat expensive,
so it appeared desirable to not require it to have run
before cvp (as is the case in the default pass pipeline).

Diff Detail

Event Timeline

loladiro created this revision.Jan 3 2023, 6:02 PM
Herald added a project: Restricted Project. · View Herald TranscriptJan 3 2023, 6:02 PM
Herald added a subscriber: hiraditya. · View Herald Transcript
loladiro requested review of this revision.Jan 3 2023, 6:02 PM
Herald added a project: Restricted Project. · View Herald TranscriptJan 3 2023, 6:02 PM
nikic requested changes to this revision.Jan 4 2023, 1:40 AM
nikic added inline comments.
llvm/lib/Analysis/LazyValueInfo.cpp
1197

Hm, I don't think this is correct if N is and and/or, or generally in any case where the returned lattice value does not represent the condition exactly, but is a superset. Inversion would exclude that difference between the exact set and superset. I'd suggest adding a test case for some case where getValueFromCondition() performs an approximation.

Could we instead flip isTrueDest, i.e. do something like this at the top?

Value *N;
if (match(Cond, m_Not(m_Value(N)))) {
  isTrueDest = !isTrueDest;
  Cond = N;
}
This revision now requires changes to proceed.Jan 4 2023, 1:40 AM
loladiro added inline comments.Jan 4 2023, 6:12 AM
llvm/lib/Analysis/LazyValueInfo.cpp
1197

Good catch, though I don't think that would be correct either, because then the caching logic is incorrect. However, I think we could just add isTrueDest to the cache key and then this should work fine. Let me do that.

loladiro updated this revision to Diff 486382.Jan 4 2023, 1:40 PM

Updated to fix bug when lattice overapproximates a value

nikic accepted this revision.Jan 5 2023, 2:19 PM

LGTM

In the particular case I was looking at there was a bit of a
circular dependency where flags computed by cvp were needed
by instcombine, and incstombine's folding of the negation was
needed for cvp

You might want to add a PhaseOrdering test to make sure your case keeps working.

llvm/lib/Analysis/LazyValueInfo.cpp
1169

interested

This revision is now accepted and ready to land.Jan 5 2023, 2:19 PM
This revision was landed with ongoing or failed builds.Jan 5 2023, 3:05 PM
This revision was automatically updated to reflect the committed changes.