This is an archive of the discontinued LLVM Phabricator instance.

[IPT] Restructure cache to allow lazy update following invalidation [NFC]
AbandonedPublic

Authored by reames on Oct 13 2021, 4:39 PM.

Details

Summary

This change restructures the cache used in IPT to point not to the first special instruction, but to the first instruction which *could* be special. That is, the cached reference is always equal to the first special, or comes before it in the block.

This avoids expensive block scans when we are removing special instructions from the beginning of the block. At the moment, this case is not heavily used, though it does trigger in GVN when doing CSE of calls. The main motivation was a change I'm no longer planning to move forward with, but the cache optimization seemed worthwhile as a minor perf win at low cost.

Diff Detail

Event Timeline

reames created this revision.Oct 13 2021, 4:39 PM
reames requested review of this revision.Oct 13 2021, 4:39 PM
Herald added a project: Restricted Project. · View Herald TranscriptOct 13 2021, 4:39 PM
mkazantsev added inline comments.Oct 13 2021, 10:06 PM
llvm/lib/Analysis/InstructionPrecedenceTracking.cpp
96

This loosens the validation. What if I is not special? We used to check this and now we don't.

128

This looks correct, but it's not entirely an NFC. We used to completely drop cache, assuming that after the removal we could insert smth in the beginning of this block and this will be fine. Now, if we insert a special instruction before this point, it will not be found. Could you please review the users of removeInstruction and confirm that we never use it as invalidation for insertion (which we shouldn't be doing, but not a fact that we don't).

Please mark [NFC] if you don't expect it to have any other implications than compile time improvement.

reames added inline comments.Oct 14 2021, 8:41 AM
llvm/lib/Analysis/InstructionPrecedenceTracking.cpp
96

We check to see if I is special just below. And as indicated in the comment, the cached result does not need to be special, just before any special instruction.

128

This was never the documented public interface of this class, but in theory it's a risk. I have glanced at existing usage, and didn't see anything suspicious.

reames retitled this revision from [IPT] Restructure cache to allow lazy update following invalidation to [IPT] Restructure cache to allow lazy update following invalidation [NFC].Oct 14 2021, 8:42 AM

Not seeing any practical impact from this, but the change generally looks reasonable to me.

llvm/lib/Analysis/InstructionPrecedenceTracking.cpp
52

To avoid doing the BB lookup three times, use something like this?

auto It = FirstSpecialInsts.try_emplace(BB, &BB->front()).first;
Instruction *CurI = It->second;
// ...
It->second = Res;
mkazantsev added inline comments.Oct 15 2021, 12:14 AM
llvm/lib/Analysis/InstructionPrecedenceTracking.cpp
96

If I is not special but it somehow got into the It->second, where do you detect that?

reames added inline comments.Oct 15 2021, 10:00 AM
llvm/lib/Analysis/InstructionPrecedenceTracking.cpp
52

I'll be honest here and say that I find the try_emplace style code simply unreadable. I tried to write something based on your suggestion, and gave up when I couldn't decipher the error messages.

I doubt this will be performance critical. The hot path is the second if, so at most we have two lookups on the fast path.

I'd strongly prefer to leave this as is.

96

Max, you appear to be missing the point of the change. The cached entry (e.g. It->second) is by design no longer always special. It's simply guaranteed to comeBefore the first special instruction. It is not an error for the cached instruction not to be special. It's only an error for there to be a special instruction before the cached one.

This revision is now accepted and ready to land.Oct 20 2021, 5:13 PM
This revision was landed with ongoing or failed builds.Oct 21 2021, 9:16 AM
This revision was automatically updated to reflect the committed changes.

It looks like this caused an assertion failure on buildbots, would you mind reverting?

https://lab.llvm.org/buildbot/#/builders/77/builds/10715
https://lab.llvm.org/buildbot/#/builders/98/builds/7617/

Assertion `!isSpecialInstruction(&I) && "Cached first special instruction is wrong!"' failed.
...
#10 0x0000000004e1519d LookupBucketFor<const llvm::BasicBlock *> /var/lib/buildbot/sanitizer-buildbot6/sanitizer-x86_64-linux-android/build/llvm-project/llvm/include/llvm/ADT/DenseMap.h:622:5
#11 0x0000000004e1519d find /var/lib/buildbot/sanitizer-buildbot6/sanitizer-x86_64-linux-android/build/llvm-project/llvm/include/llvm/ADT/DenseMap.h:161:9
#12 0x0000000004e1519d llvm::InstructionPrecedenceTracking::validate(llvm::BasicBlock const*) const /var/lib/buildbot/sanitizer-buildbot6/sanitizer-x86_64-linux-android/build/llvm-project/llvm/lib/Analysis/InstructionPrecedenceTracking.cpp:89:31
#13 0x0000000004e14b0c llvm::InstructionPrecedenceTracking::getFirstSpecialInstruction(llvm::BasicBlock const*) /var/lib/buildbot/sanitizer-buildbot6/sanitizer-x86_64-linux-android/build/llvm-project/llvm/lib/Analysis/InstructionPrecedenceTracking.cpp:50:8
#14 0x0000000004e1523d llvm::InstructionPrecedenceTracking::isPreceededBySpecialInstruction(llvm::Instruction const*) /var/lib/buildbot/sanitizer-buildbot6/sanitizer-x86_64-linux-android/build/llvm-project/llvm/lib/Analysis/InstructionPrecedenceTracking.cpp:84:10
#15 0x0000000005a8a0de isDominatedByICFIFromSameBlock /var/lib/buildbot/sanitizer-buildbot6/sanitizer-x86_64-linux-android/build/llvm-project/llvm/include/llvm/Analysis/InstructionPrecedenceTracking.h:114:12

I've gone ahead and reverted this

I've gone ahead and reverted this

Thanks.

reames reopened this revision.Oct 22 2021, 4:59 PM
This revision is now accepted and ready to land.Oct 22 2021, 4:59 PM
reames abandoned this revision.Oct 22 2021, 5:01 PM

I spent time looking into the assertion failure reported, and haven't made much progress. Given this patch was of minor importance, I'm simply going to abandon it until further need comes up.

The assert looks like a missing update in GVN, but I can't find any such thing. Unfortunately, all of the builders which failed are fairly complicated, and none of them captured detail IR or anything which is easily reproducible locally.