139d628a0SDimitry Andric //===- AssumptionCache.cpp - Cache finding @llvm.assume calls -------------===//
239d628a0SDimitry Andric //
339d628a0SDimitry Andric // The LLVM Compiler Infrastructure
439d628a0SDimitry Andric //
539d628a0SDimitry Andric // This file is distributed under the University of Illinois Open Source
639d628a0SDimitry Andric // License. See LICENSE.TXT for details.
739d628a0SDimitry Andric //
839d628a0SDimitry Andric //===----------------------------------------------------------------------===//
939d628a0SDimitry Andric //
1039d628a0SDimitry Andric // This file contains a pass that keeps track of @llvm.assume intrinsics in
1139d628a0SDimitry Andric // the functions of a module.
1239d628a0SDimitry Andric //
1339d628a0SDimitry Andric //===----------------------------------------------------------------------===//
1439d628a0SDimitry Andric
1539d628a0SDimitry Andric #include "llvm/Analysis/AssumptionCache.h"
1639d628a0SDimitry Andric #include "llvm/ADT/STLExtras.h"
1739d628a0SDimitry Andric #include "llvm/ADT/SmallPtrSet.h"
1839d628a0SDimitry Andric #include "llvm/ADT/SmallVector.h"
1939d628a0SDimitry Andric #include "llvm/IR/BasicBlock.h"
2039d628a0SDimitry Andric #include "llvm/IR/Function.h"
21ff0cc061SDimitry Andric #include "llvm/IR/InstrTypes.h"
2239d628a0SDimitry Andric #include "llvm/IR/Instruction.h"
2339d628a0SDimitry Andric #include "llvm/IR/Instructions.h"
2439d628a0SDimitry Andric #include "llvm/IR/Intrinsics.h"
2539d628a0SDimitry Andric #include "llvm/IR/PassManager.h"
2639d628a0SDimitry Andric #include "llvm/IR/PatternMatch.h"
27*9b187003SDimitry Andric #include "llvm/Pass.h"
28f1a29dd3SDimitry Andric #include "llvm/Support/Casting.h"
29f1a29dd3SDimitry Andric #include "llvm/Support/CommandLine.h"
30f1a29dd3SDimitry Andric #include "llvm/Support/ErrorHandling.h"
31f1a29dd3SDimitry Andric #include "llvm/Support/raw_ostream.h"
32f1a29dd3SDimitry Andric #include <algorithm>
33f1a29dd3SDimitry Andric #include <cassert>
34f1a29dd3SDimitry Andric #include <utility>
35f1a29dd3SDimitry Andric
36f1a29dd3SDimitry Andric using namespace llvm;
37f1a29dd3SDimitry Andric using namespace llvm::PatternMatch;
38f1a29dd3SDimitry Andric
39f1a29dd3SDimitry Andric static cl::opt<bool>
40f1a29dd3SDimitry Andric VerifyAssumptionCache("verify-assumption-cache", cl::Hidden,
41f1a29dd3SDimitry Andric cl::desc("Enable verification of assumption cache"),
42f1a29dd3SDimitry Andric cl::init(false));
43f1a29dd3SDimitry Andric
44f1a29dd3SDimitry Andric SmallVector<WeakTrackingVH, 1> &
getOrInsertAffectedValues(Value * V)45f1a29dd3SDimitry Andric AssumptionCache::getOrInsertAffectedValues(Value *V) {
46f1a29dd3SDimitry Andric // Try using find_as first to avoid creating extra value handles just for the
47f1a29dd3SDimitry Andric // purpose of doing the lookup.
48f1a29dd3SDimitry Andric auto AVI = AffectedValues.find_as(V);
49f1a29dd3SDimitry Andric if (AVI != AffectedValues.end())
50f1a29dd3SDimitry Andric return AVI->second;
51f1a29dd3SDimitry Andric
52f1a29dd3SDimitry Andric auto AVIP = AffectedValues.insert(
53f1a29dd3SDimitry Andric {AffectedValueCallbackVH(V, this), SmallVector<WeakTrackingVH, 1>()});
54f1a29dd3SDimitry Andric return AVIP.first->second;
55f1a29dd3SDimitry Andric }
56f1a29dd3SDimitry Andric
updateAffectedValues(CallInst * CI)57f1a29dd3SDimitry Andric void AssumptionCache::updateAffectedValues(CallInst *CI) {
58f1a29dd3SDimitry Andric // Note: This code must be kept in-sync with the code in
59f1a29dd3SDimitry Andric // computeKnownBitsFromAssume in ValueTracking.
60f1a29dd3SDimitry Andric
61f1a29dd3SDimitry Andric SmallVector<Value *, 16> Affected;
62f1a29dd3SDimitry Andric auto AddAffected = [&Affected](Value *V) {
63f1a29dd3SDimitry Andric if (isa<Argument>(V)) {
64f1a29dd3SDimitry Andric Affected.push_back(V);
65f1a29dd3SDimitry Andric } else if (auto *I = dyn_cast<Instruction>(V)) {
66f1a29dd3SDimitry Andric Affected.push_back(I);
67f1a29dd3SDimitry Andric
68f1a29dd3SDimitry Andric // Peek through unary operators to find the source of the condition.
69f1a29dd3SDimitry Andric Value *Op;
70f1a29dd3SDimitry Andric if (match(I, m_BitCast(m_Value(Op))) ||
71f1a29dd3SDimitry Andric match(I, m_PtrToInt(m_Value(Op))) ||
72f1a29dd3SDimitry Andric match(I, m_Not(m_Value(Op)))) {
73f1a29dd3SDimitry Andric if (isa<Instruction>(Op) || isa<Argument>(Op))
74f1a29dd3SDimitry Andric Affected.push_back(Op);
75f1a29dd3SDimitry Andric }
76f1a29dd3SDimitry Andric }
77f1a29dd3SDimitry Andric };
78f1a29dd3SDimitry Andric
79f1a29dd3SDimitry Andric Value *Cond = CI->getArgOperand(0), *A, *B;
80f1a29dd3SDimitry Andric AddAffected(Cond);
81f1a29dd3SDimitry Andric
82f1a29dd3SDimitry Andric CmpInst::Predicate Pred;
83f1a29dd3SDimitry Andric if (match(Cond, m_ICmp(Pred, m_Value(A), m_Value(B)))) {
84f1a29dd3SDimitry Andric AddAffected(A);
85f1a29dd3SDimitry Andric AddAffected(B);
86f1a29dd3SDimitry Andric
87f1a29dd3SDimitry Andric if (Pred == ICmpInst::ICMP_EQ) {
88f1a29dd3SDimitry Andric // For equality comparisons, we handle the case of bit inversion.
89f1a29dd3SDimitry Andric auto AddAffectedFromEq = [&AddAffected](Value *V) {
90f1a29dd3SDimitry Andric Value *A;
91f1a29dd3SDimitry Andric if (match(V, m_Not(m_Value(A)))) {
92f1a29dd3SDimitry Andric AddAffected(A);
93f1a29dd3SDimitry Andric V = A;
94f1a29dd3SDimitry Andric }
95f1a29dd3SDimitry Andric
96f1a29dd3SDimitry Andric Value *B;
97f1a29dd3SDimitry Andric ConstantInt *C;
98f1a29dd3SDimitry Andric // (A & B) or (A | B) or (A ^ B).
99f1a29dd3SDimitry Andric if (match(V, m_BitwiseLogic(m_Value(A), m_Value(B)))) {
100f1a29dd3SDimitry Andric AddAffected(A);
101*9b187003SDimitry Andric AddAffected(B);
102f1a29dd3SDimitry Andric // (A << C) or (A >>_s C) or (A >>_u C) where C is some constant.
103f1a29dd3SDimitry Andric } else if (match(V, m_Shift(m_Value(A), m_ConstantInt(C)))) {
104f1a29dd3SDimitry Andric AddAffected(A);
105f1a29dd3SDimitry Andric }
106f1a29dd3SDimitry Andric };
107f1a29dd3SDimitry Andric
108f1a29dd3SDimitry Andric AddAffectedFromEq(A);
109f1a29dd3SDimitry Andric AddAffectedFromEq(B);
110f1a29dd3SDimitry Andric }
111f1a29dd3SDimitry Andric }
112f1a29dd3SDimitry Andric
113f1a29dd3SDimitry Andric for (auto &AV : Affected) {
114*9b187003SDimitry Andric auto &AVV = getOrInsertAffectedValues(AV);
115*9b187003SDimitry Andric if (std::find(AVV.begin(), AVV.end(), CI) == AVV.end())
116*9b187003SDimitry Andric AVV.push_back(CI);
117*9b187003SDimitry Andric }
118*9b187003SDimitry Andric }
119*9b187003SDimitry Andric
deleted()120*9b187003SDimitry Andric void AssumptionCache::AffectedValueCallbackVH::deleted() {
121*9b187003SDimitry Andric auto AVI = AC->AffectedValues.find(getValPtr());
122*9b187003SDimitry Andric if (AVI != AC->AffectedValues.end())
123*9b187003SDimitry Andric AC->AffectedValues.erase(AVI);
124*9b187003SDimitry Andric // 'this' now dangles!
125f1a29dd3SDimitry Andric }
126f1a29dd3SDimitry Andric
copyAffectedValuesInCache(Value * OV,Value * NV)127f1a29dd3SDimitry Andric void AssumptionCache::copyAffectedValuesInCache(Value *OV, Value *NV) {
128f1a29dd3SDimitry Andric auto &NAVV = getOrInsertAffectedValues(NV);
129f1a29dd3SDimitry Andric auto AVI = AffectedValues.find(OV);
130f1a29dd3SDimitry Andric if (AVI == AffectedValues.end())
131*9b187003SDimitry Andric return;
132*9b187003SDimitry Andric
133*9b187003SDimitry Andric for (auto &A : AVI->second)
134*9b187003SDimitry Andric if (std::find(NAVV.begin(), NAVV.end(), A) == NAVV.end())
135f1a29dd3SDimitry Andric NAVV.push_back(A);
136f1a29dd3SDimitry Andric }
13739d628a0SDimitry Andric
allUsesReplacedWith(Value * NV)13839d628a0SDimitry Andric void AssumptionCache::AffectedValueCallbackVH::allUsesReplacedWith(Value *NV) {
13939d628a0SDimitry Andric if (!isa<Instruction>(NV) && !isa<Argument>(NV))
14039d628a0SDimitry Andric return;
14139d628a0SDimitry Andric
14239d628a0SDimitry Andric // Any assumptions that affected this value now affect the new value.
14339d628a0SDimitry Andric
14439d628a0SDimitry Andric AC->copyAffectedValuesInCache(getValPtr(), NV);
14539d628a0SDimitry Andric // 'this' now might dangle! If the AffectedValues map was resized to add an
14639d628a0SDimitry Andric // entry for NV then this object might have been destroyed in favor of some
14739d628a0SDimitry Andric // copy in the grown map.
14839d628a0SDimitry Andric }
14939d628a0SDimitry Andric
scanFunction()150f1a29dd3SDimitry Andric void AssumptionCache::scanFunction() {
151f1a29dd3SDimitry Andric assert(!Scanned && "Tried to scan the function twice!");
152f1a29dd3SDimitry Andric assert(AssumeHandles.empty() && "Already have assumes when scanning!");
153f1a29dd3SDimitry Andric
15439d628a0SDimitry Andric // Go through all instructions in all blocks, add all calls to @llvm.assume
15539d628a0SDimitry Andric // to this cache.
15639d628a0SDimitry Andric for (BasicBlock &B : F)
15739d628a0SDimitry Andric for (Instruction &II : B)
15839d628a0SDimitry Andric if (match(&II, m_Intrinsic<Intrinsic::assume>()))
15939d628a0SDimitry Andric AssumeHandles.push_back(&II);
16039d628a0SDimitry Andric
16139d628a0SDimitry Andric // Mark the scan as complete.
16239d628a0SDimitry Andric Scanned = true;
16339d628a0SDimitry Andric
16439d628a0SDimitry Andric // Update affected values.
16539d628a0SDimitry Andric for (auto &A : AssumeHandles)
16639d628a0SDimitry Andric updateAffectedValues(cast<CallInst>(A));
16739d628a0SDimitry Andric }
16839d628a0SDimitry Andric
registerAssumption(CallInst * CI)16939d628a0SDimitry Andric void AssumptionCache::registerAssumption(CallInst *CI) {
17039d628a0SDimitry Andric assert(match(CI, m_Intrinsic<Intrinsic::assume>()) &&
17139d628a0SDimitry Andric "Registered call does not call @llvm.assume");
17239d628a0SDimitry Andric
17339d628a0SDimitry Andric // If we haven't scanned the function yet, just drop this assumption. It will
17439d628a0SDimitry Andric // be found when we scan later.
17539d628a0SDimitry Andric if (!Scanned)
17639d628a0SDimitry Andric return;
17739d628a0SDimitry Andric
17839d628a0SDimitry Andric AssumeHandles.push_back(CI);
17939d628a0SDimitry Andric
18039d628a0SDimitry Andric #ifndef NDEBUG
18139d628a0SDimitry Andric assert(CI->getParent() &&
18239d628a0SDimitry Andric "Cannot register @llvm.assume call not in a basic block");
18339d628a0SDimitry Andric assert(&F == CI->getParent()->getParent() &&
18439d628a0SDimitry Andric "Cannot register @llvm.assume call not in this function");
18539d628a0SDimitry Andric
18639d628a0SDimitry Andric // We expect the number of assumptions to be small, so in an asserts build
18739d628a0SDimitry Andric // check that we don't accumulate duplicates and that all assumptions point
18839d628a0SDimitry Andric // to the same function.
189f1a29dd3SDimitry Andric SmallPtrSet<Value *, 16> AssumptionSet;
190f1a29dd3SDimitry Andric for (auto &VH : AssumeHandles) {
19139d628a0SDimitry Andric if (!VH)
19239d628a0SDimitry Andric continue;
193d88c1a5aSDimitry Andric
194ff0cc061SDimitry Andric assert(&F == cast<Instruction>(VH)->getParent()->getParent() &&
195ff0cc061SDimitry Andric "Cached assumption not inside this function!");
196d88c1a5aSDimitry Andric assert(match(cast<CallInst>(VH), m_Intrinsic<Intrinsic::assume>()) &&
1973ca95b02SDimitry Andric "Cached something other than a call to @llvm.assume!");
198ff0cc061SDimitry Andric assert(AssumptionSet.insert(VH).second &&
199ff0cc061SDimitry Andric "Cache contains multiple copies of a call!");
200ff0cc061SDimitry Andric }
201ff0cc061SDimitry Andric #endif
202ff0cc061SDimitry Andric
203ff0cc061SDimitry Andric updateAffectedValues(CI);
204ff0cc061SDimitry Andric }
205ff0cc061SDimitry Andric
206ff0cc061SDimitry Andric AnalysisKey AssumptionAnalysis::Key;
20739d628a0SDimitry Andric
run(Function & F,FunctionAnalysisManager & AM)20839d628a0SDimitry Andric PreservedAnalyses AssumptionPrinterPass::run(Function &F,
20939d628a0SDimitry Andric FunctionAnalysisManager &AM) {
21039d628a0SDimitry Andric AssumptionCache &AC = AM.getResult<AssumptionAnalysis>(F);
21139d628a0SDimitry Andric
21239d628a0SDimitry Andric OS << "Cached assumptions for function: " << F.getName() << "\n";
21339d628a0SDimitry Andric for (auto &VH : AC.assumptions())
21439d628a0SDimitry Andric if (VH)
21539d628a0SDimitry Andric OS << " " << *cast<CallInst>(VH)->getArgOperand(0) << "\n";
21639d628a0SDimitry Andric
21739d628a0SDimitry Andric return PreservedAnalyses::all();
21839d628a0SDimitry Andric }
21939d628a0SDimitry Andric
deleted()22039d628a0SDimitry Andric void AssumptionCacheTracker::FunctionCallbackVH::deleted() {
22139d628a0SDimitry Andric auto I = ACT->AssumptionCaches.find_as(cast<Function>(getValPtr()));
22239d628a0SDimitry Andric if (I != ACT->AssumptionCaches.end())
22339d628a0SDimitry Andric ACT->AssumptionCaches.erase(I);
22439d628a0SDimitry Andric // 'this' now dangles!
22539d628a0SDimitry Andric }
22639d628a0SDimitry Andric
getAssumptionCache(Function & F)22739d628a0SDimitry Andric AssumptionCache &AssumptionCacheTracker::getAssumptionCache(Function &F) {
22839d628a0SDimitry Andric // We probe the function map twice to try and avoid creating a value handle
22939d628a0SDimitry Andric // around the function in common cases. This makes insertion a bit slower,
23039d628a0SDimitry Andric // but if we have to insert we're going to scan the whole function so that
23139d628a0SDimitry Andric // shouldn't matter.
23239d628a0SDimitry Andric auto I = AssumptionCaches.find_as(&F);
23339d628a0SDimitry Andric if (I != AssumptionCaches.end())
23439d628a0SDimitry Andric return *I->second;
23539d628a0SDimitry Andric
23639d628a0SDimitry Andric // Ok, build a new cache by scanning the function, insert it and the value
23739d628a0SDimitry Andric // handle into our map, and return the newly populated cache.
23839d628a0SDimitry Andric auto IP = AssumptionCaches.insert(std::make_pair(
23939d628a0SDimitry Andric FunctionCallbackVH(&F, this), llvm::make_unique<AssumptionCache>(F)));
24039d628a0SDimitry Andric assert(IP.second && "Scanning function already in the map?");
24139d628a0SDimitry Andric return *IP.first->second;
24239d628a0SDimitry Andric }
24339d628a0SDimitry Andric
verifyAnalysis() const24439d628a0SDimitry Andric void AssumptionCacheTracker::verifyAnalysis() const {
24539d628a0SDimitry Andric // FIXME: In the long term the verifier should not be controllable with a
24639d628a0SDimitry Andric // flag. We should either fix all passes to correctly update the assumption
24739d628a0SDimitry Andric // cache and enable the verifier unconditionally or somehow arrange for the
24839d628a0SDimitry Andric // assumption list to be updated automatically by passes.
24939d628a0SDimitry Andric if (!VerifyAssumptionCache)
25039d628a0SDimitry Andric return;
25139d628a0SDimitry Andric
25239d628a0SDimitry Andric SmallPtrSet<const CallInst *, 4> AssumptionSet;
25339d628a0SDimitry Andric for (const auto &I : AssumptionCaches) {
25439d628a0SDimitry Andric for (auto &VH : I.second->assumptions())
25539d628a0SDimitry Andric if (VH)
25639d628a0SDimitry Andric AssumptionSet.insert(cast<CallInst>(VH));
257
258 for (const BasicBlock &B : cast<Function>(*I.first))
259 for (const Instruction &II : B)
260 if (match(&II, m_Intrinsic<Intrinsic::assume>()) &&
261 !AssumptionSet.count(cast<CallInst>(&II)))
262 report_fatal_error("Assumption in scanned function not in cache");
263 }
264 }
265
AssumptionCacheTracker()266 AssumptionCacheTracker::AssumptionCacheTracker() : ImmutablePass(ID) {
267 initializeAssumptionCacheTrackerPass(*PassRegistry::getPassRegistry());
268 }
269
270 AssumptionCacheTracker::~AssumptionCacheTracker() = default;
271
272 char AssumptionCacheTracker::ID = 0;
273
274 INITIALIZE_PASS(AssumptionCacheTracker, "assumption-cache-tracker",
275 "Assumption Cache Tracker", false, true)
276