LLVM API Documentation
00001 //===- llvm/Analysis/AssumptionTracker.h - Track @llvm.assume ---*- C++ -*-===// 00002 // 00003 // The LLVM Compiler Infrastructure 00004 // 00005 // This file is distributed under the University of Illinois Open Source 00006 // License. See LICENSE.TXT for details. 00007 // 00008 //===----------------------------------------------------------------------===// 00009 // 00010 // This file contains a pass that keeps track of @llvm.assume intrinsics in 00011 // the functions of a module (allowing assumptions within any function to be 00012 // found cheaply by other parts of the optimizer). 00013 // 00014 //===----------------------------------------------------------------------===// 00015 00016 #ifndef LLVM_ANALYSIS_ASSUMPTIONTRACKER_H 00017 #define LLVM_ANALYSIS_ASSUMPTIONTRACKER_H 00018 00019 #include "llvm/ADT/DenseMap.h" 00020 #include "llvm/ADT/DenseSet.h" 00021 #include "llvm/ADT/SmallSet.h" 00022 #include "llvm/IR/Function.h" 00023 #include "llvm/IR/Instructions.h" 00024 #include "llvm/IR/ValueHandle.h" 00025 #include "llvm/Pass.h" 00026 #include <memory> 00027 00028 namespace llvm { 00029 00030 /// An immutable pass that tracks @llvm.assume intrinsics in a module. 00031 class AssumptionTracker : public ImmutablePass { 00032 /// A callback value handle applied to function objects, which we use to 00033 /// delete our cache of intrinsics for a function when it is deleted. 00034 class FunctionCallbackVH : public CallbackVH { 00035 AssumptionTracker *AT; 00036 void deleted() override; 00037 00038 public: 00039 typedef DenseMapInfo<Value *> DMI; 00040 00041 FunctionCallbackVH(Value *V, AssumptionTracker *AT = nullptr) 00042 : CallbackVH(V), AT(AT) {} 00043 }; 00044 00045 /// A callback value handle applied to call instructions, which keeps 00046 /// track of the call's parent function so that we can remove a 00047 /// assumption intrinsic call from our cache when the instruction is 00048 /// deleted. 00049 class CallCallbackVH : public CallbackVH { 00050 AssumptionTracker *AT; 00051 void deleted() override; 00052 00053 // We store the function here because we need it to lookup the set 00054 // containing this handle when the underlying CallInst is being deleted. 00055 Function *F; 00056 00057 public: 00058 typedef DenseMapInfo<Instruction *> DMI; 00059 00060 CallCallbackVH(Instruction *I, AssumptionTracker *AT = nullptr) 00061 : CallbackVH(I), AT(AT), F(nullptr) { 00062 if (I != DMI::getEmptyKey() && I != DMI::getTombstoneKey()) 00063 F = I->getParent()->getParent(); 00064 } 00065 00066 operator CallInst*() const { 00067 Value *V = getValPtr(); 00068 if (V == DMI::getEmptyKey() || V == DMI::getTombstoneKey()) 00069 return reinterpret_cast<CallInst*>(V); 00070 00071 return cast<CallInst>(V); 00072 } 00073 00074 CallInst *operator->() const { return cast<CallInst>(getValPtr()); } 00075 CallInst &operator*() const { return *cast<CallInst>(getValPtr()); } 00076 }; 00077 00078 friend FunctionCallbackVH; 00079 friend CallCallbackVH; 00080 00081 // FIXME: SmallSet might be better here, but it currently has no iterators. 00082 typedef DenseSet<CallCallbackVH, CallCallbackVH::DMI> CallHandleSet; 00083 typedef DenseMap<FunctionCallbackVH, std::unique_ptr<CallHandleSet>, 00084 FunctionCallbackVH::DMI> FunctionCallsMap; 00085 FunctionCallsMap CachedAssumeCalls; 00086 00087 /// Scan the provided function for @llvm.assume intrinsic calls. Returns an 00088 /// iterator to the set for this function in the CachedAssumeCalls map. 00089 FunctionCallsMap::iterator scanFunction(Function *F); 00090 00091 public: 00092 /// Remove the cache of @llvm.assume intrinsics for the given function. 00093 void forgetCachedAssumptions(Function *F); 00094 00095 /// Add an @llvm.assume intrinsic to the cache for its parent function. 00096 void registerAssumption(CallInst *CI); 00097 00098 typedef CallHandleSet::iterator assumption_iterator; 00099 typedef iterator_range<assumption_iterator> assumption_range; 00100 00101 inline assumption_range assumptions(Function *F) { 00102 FunctionCallsMap::iterator I = CachedAssumeCalls.find(F); 00103 if (I == CachedAssumeCalls.end()) { 00104 I = scanFunction(F); 00105 } 00106 00107 return assumption_range(I->second->begin(), I->second->end()); 00108 } 00109 00110 AssumptionTracker(); 00111 ~AssumptionTracker(); 00112 00113 void releaseMemory() override { 00114 CachedAssumeCalls.shrink_and_clear(); 00115 } 00116 00117 void verifyAnalysis() const override; 00118 bool doFinalization(Module &) override { 00119 verifyAnalysis(); 00120 return false; 00121 } 00122 00123 static char ID; // Pass identification, replacement for typeid 00124 }; 00125 00126 } // end namespace llvm 00127 00128 #endif