This is an archive of the discontinued LLVM Phabricator instance.

Make processing @llvm.assume more efficient - Add affected values to the assumption cache
ClosedPublic

Authored by hfinkel on Jan 8 2017, 12:21 PM.

Details

Summary

Here's my second try at making @llvm.assume processing more efficient. My previous attempt, which leveraged operand bundles, r289755, didn't end up working: it did make assume processing more efficient but eliminating the assumption cache made ephemeral value computation too expensive. This is a more-targeted change. We'll keep the assumption cache, but extend it to keep a map of affected values (i.e. values about which an assumption might provide some information) to the corresponding assumption intrinsics. This allows ValueTracking and LVI to find assumptions relevant to the value being queried without scanning all assumptions in the function. The fact that ValueTracking started doing O(number of assumptions in the function) work, for every known-bits query, has become prohibitively expensive in some cases.

Diff Detail

Repository
rL LLVM

Event Timeline

hfinkel updated this revision to Diff 83570.Jan 8 2017, 12:21 PM
hfinkel retitled this revision from to Make processing @llvm.assume more efficient - Add affected values to the assumption cache.
hfinkel updated this object.
hfinkel added a subscriber: llvm-commits.
davide edited edge metadata.Jan 8 2017, 1:25 PM

I'm going to try this on the testcases where your previous approach regressed and review again. In the meanwhile, some early comments.

include/llvm/Analysis/AssumptionCache.h
125–128 ↗(On Diff #83570)

I prefer using the ternary operator here, but up to you.

lib/Analysis/AssumptionCache.cpp
39–42 ↗(On Diff #83570)

I see why you need this, but, can we think of a way of sharing (at least partially) the code between this and ValueTracking?
I'm very worried the two implementations going out of sync quickly.

78–82 ↗(On Diff #83570)

I would add a comment on this matchers (and the others).

chandlerc edited edge metadata.Jan 8 2017, 1:28 PM

Can you provide an explanation at a high level for why you're going with this approach rather than having the AC for ephemeral value finding and operand bundles for affected values? Essentially, why not just use both previous approaches rather than adding the affected values to the AC? (I'm not questioning what you've done here, just trying to understand the thought process behind it.)

Can you provide an explanation at a high level for why you're going with this approach rather than having the AC for ephemeral value finding and operand bundles for affected values? Essentially, why not just use both previous approaches rather than adding the affected values to the AC? (I'm not questioning what you've done here, just trying to understand the thought process behind it.)

There are potential downsides to the operand-bundle approach. First, values in operand bundles are, by default, assumed to be captured, alias, etc. which could cause undesirable side effects for pointer-typed values. This could have been fixed, but there is another issue which is that adding all of the extra uses on intermediate values could inhibit simplification of more--complex conditions because of hasOneUse interference. Perhaps a minor problem, but a less tractable one. Also, depending on how you look at it, having the affected values "cached" in the IR, and having a dependence on InstCombine for them to work even for other passes, was suboptimal. As a result, I think that if we can't get rid of the assumption cache, we should use it.

hfinkel added inline comments.Jan 8 2017, 2:00 PM
lib/Analysis/AssumptionCache.cpp
39–42 ↗(On Diff #83570)

I'm worried about this too. I tried to make the code here as general as possible, without casting too wide a net, to mitigate this as much as possible.

When I first started working on this, I tried to think of a way to share the matching patterns between ValueTracking and here (perhaps with some small generalization to pick up things that LVI needs that wouldn't otherwise be covered by ValueTracking's patterns. This was the best thing I could come up with. Part of the problem is that, in ValueTracking, we're matching against specific values. Here, we want to find all potentially-matching values. If you can think of a better way, I'l all ears :-)

78–82 ↗(On Diff #83570)

You mean like this?

// A & B or A | B or A ^ B.
davide added inline comments.Jan 8 2017, 2:07 PM
lib/Analysis/AssumptionCache.cpp
39–42 ↗(On Diff #83570)

Yeah, unfortunately, I don't think there's an easy way to generalize. The best we can do here is trying to be very careful when reviewing new changes (and I think your comment in ValueTracking is pretty much needed to make sure we don't forget about this in a month or two).

78–82 ↗(On Diff #83570)

Yes, exactly.

hfinkel updated this revision to Diff 83574.Jan 8 2017, 2:28 PM
hfinkel edited edge metadata.

Added some comments to the non-trivial matchers.

Prazek added inline comments.Jan 8 2017, 2:54 PM
lib/Analysis/AssumptionCache.cpp
34 ↗(On Diff #83574)

emplace(first, second) or insert({first, second})

hfinkel updated this revision to Diff 83578.Jan 8 2017, 4:07 PM
hfinkel marked 2 inline comments as done.

Use {} instead of make_pair.

Prazek edited edge metadata.Jan 9 2017, 10:54 AM

Are you planning to put it in 4.0 release? Sorry for only syntactic comments, didn't have time to go through code in details.

include/llvm/Analysis/AssumptionCache.h
55 ↗(On Diff #83578)

using

57 ↗(On Diff #83578)

explicit?

65 ↗(On Diff #83578)

using?

Are you planning to put it in 4.0 release? Sorry for only syntactic comments, didn't have time to go through code in details.

I'd like to.

Prazek added inline comments.Jan 10 2017, 2:23 AM
lib/Analysis/AssumptionCache.cpp
52 ↗(On Diff #83578)

auto *Op = I->getOperand(0)

reassigning V can be easy to miss

59–63 ↗(On Diff #83578)

A and B are undefined, and they are not assigned in m_Value, so what is going on here?
I am just not familiar with this matcher library, but it looks very odd.

hfinkel added inline comments.Jan 10 2017, 6:09 AM
lib/Analysis/AssumptionCache.cpp
59–63 ↗(On Diff #83578)

They are assigned in m_Value (as in the example at the very top of include/llvm/IR/PatternMatch.h). You might be thinking of m_Specific, which matches a specific provided value.

hfinkel marked 3 inline comments as done.Jan 10 2017, 6:40 AM
hfinkel added inline comments.
include/llvm/Analysis/AssumptionCache.h
57 ↗(On Diff #83578)

No, DenseMap won't work if this is explicit (because we're using Value*'s KeyInfo).

hfinkel updated this revision to Diff 83805.Jan 10 2017, 6:41 AM
hfinkel edited edge metadata.

Updated per review comments.

Any other comments? I'd like to get this in before we branch for 4.0 if possible.

Sorry for the delay, Hal.
I just checked and this doesn't regress the cases your previous change regressed, so we should be good on that side.
I somehow share Dan's feeling that this could be solved with an infrastructural changes rather than caching, but I don't feel to be in a position to hinder progress without a concrete/implemented alternative.

Sorry for the delay, Hal.
I just checked and this doesn't regress the cases your previous change regressed, so we should be good on that side.
I somehow share Dan's feeling that this could be solved with an infrastructural changes rather than caching, but I don't feel to be in a position to hinder progress without a concrete/implemented alternative.

For those wondering, I mean http://lists.llvm.org/pipermail/llvm-commits/Week-of-Mon-20170102/416193.html

Sorry for the delay, Hal.
I just checked and this doesn't regress the cases your previous change regressed, so we should be good on that side.
I somehow share Dan's feeling that this could be solved with an infrastructural changes rather than caching, but I don't feel to be in a position to hinder progress without a concrete/implemented alternative.

For those wondering, I mean http://lists.llvm.org/pipermail/llvm-commits/Week-of-Mon-20170102/416193.html

@dberlin , @chandlerc , et al. does anyone object to me committing this solution at this point? I'm obviously happy to help replace it later with something based on an extended SSA form once we figure out how that should work. In the mean time, this fixes the compile-time problems, which users are certainly hitting, in a fairly transparent way.

Sorry for the delay, Hal.
I just checked and this doesn't regress the cases your previous change regressed, so we should be good on that side.

Also, thanks for checking!

Sorry for the delay, Hal.
I just checked and this doesn't regress the cases your previous change regressed, so we should be good on that side.
I somehow share Dan's feeling that this could be solved with an infrastructural changes rather than caching, but I don't feel to be in a position to hinder progress without a concrete/implemented alternative.

For those wondering, I mean http://lists.llvm.org/pipermail/llvm-commits/Week-of-Mon-20170102/416193.html

@dberlin , @chandlerc , et al. does anyone object to me committing this solution at this point? I'm obviously happy to help replace it later with something based on an extended SSA form once we figure out how that should work. In the mean time, this fixes the compile-time problems, which users are certainly hitting, in a fairly transparent way.

I think you should land this, at the very least for 4.0. But I'm not thrilled about it. It seems pragmatic and to address a very real set of problems, but as we've discussed several times here and elsewhere, I look forward to more principled or just less invasive approaches.

Anyways, LGTM.

chandlerc accepted this revision.Jan 10 2017, 7:38 PM
chandlerc edited edge metadata.
This revision is now accepted and ready to land.Jan 10 2017, 7:38 PM
dyung edited edge metadata.Jan 10 2017, 7:38 PM

Hi, I just wanted to say I applied your patch to the top of trunk, built it, and then used it to compile the example that previously resulted in a big compile time increase. I am happy to report that this patch did not meaningfully increase the compile time.

Hi, I just wanted to say I applied your patch to the top of trunk, built it, and then used it to compile the example that previously resulted in a big compile time increase. I am happy to report that this patch did not meaningfully increase the compile time.

Thanks for checking!

Sorry for the delay, Hal.
I just checked and this doesn't regress the cases your previous change regressed, so we should be good on that side.
I somehow share Dan's feeling that this could be solved with an infrastructural changes rather than caching, but I don't feel to be in a position to hinder progress without a concrete/implemented alternative.

For those wondering, I mean http://lists.llvm.org/pipermail/llvm-commits/Week-of-Mon-20170102/416193.html

@dberlin , @chandlerc , et al. does anyone object to me committing this solution at this point? I'm obviously happy to help replace it later with something based on an extended SSA form once we figure out how that should work. In the mean time, this fixes the compile-time problems, which users are certainly hitting, in a fairly transparent way.

I think you should land this, at the very least for 4.0. But I'm not thrilled about it. It seems pragmatic and to address a very real set of problems, but as we've discussed several times here and elsewhere, I look forward to more principled or just less invasive approaches.

Anyways, LGTM.

Thanks. To be clear, we're all on the same page here.

This revision was automatically updated to reflect the committed changes.