42 cl::desc(
"Enable verification of assumption cache"),
46AssumptionCache::getOrInsertAffectedValues(
Value *V) {
49 auto AVI = AffectedValues.
find_as(V);
50 if (AVI != AffectedValues.
end())
53 auto AVIP = AffectedValues.
insert(
55 return AVIP.first->second;
64 auto InsertAffected = [&Affected](
Value *V) {
68 auto AddAffectedVal = [&Affected](
Value *V,
unsigned Idx) {
69 if (isa<Argument>(V) || isa<GlobalValue>(V) || isa<Instruction>(V)) {
76 if (Bundle.
getTagName() ==
"separate_storage") {
78 "separate_storage must have two args");
94 AddAffectedVal(
const_cast<Value *
>(
Ptr->stripInBoundsOffsets()),
103 for (
auto &AV : Affected) {
104 auto &AVV = getOrInsertAffectedValues(AV.Assume);
106 return Elem.
Assume == CI && Elem.
Index == AV.Index;
108 AVV.push_back({CI, AV.Index});
116 for (
auto &AV : Affected) {
117 auto AVI = AffectedValues.
find_as(AV.Assume);
118 if (AVI == AffectedValues.
end())
121 bool HasNonnull =
false;
127 HasNonnull |= !!Elem.
Assume;
128 if (HasNonnull && Found)
131 assert(Found &&
"already unregistered or incorrect cache state");
133 AffectedValues.
erase(AVI);
139void AssumptionCache::AffectedValueCallbackVH::deleted() {
140 AC->AffectedValues.erase(getValPtr());
144void AssumptionCache::transferAffectedValuesInCache(
Value *OV,
Value *NV) {
145 auto &NAVV = getOrInsertAffectedValues(NV);
146 auto AVI = AffectedValues.
find(OV);
147 if (AVI == AffectedValues.
end())
150 for (
auto &
A : AVI->second)
153 AffectedValues.
erase(OV);
156void AssumptionCache::AffectedValueCallbackVH::allUsesReplacedWith(
Value *NV) {
157 if (!isa<Instruction>(NV) && !isa<Argument>(NV))
162 AC->transferAffectedValuesInCache(getValPtr(), NV);
168void AssumptionCache::scanFunction() {
169 assert(!Scanned &&
"Tried to scan the function twice!");
170 assert(AssumeHandles.empty() &&
"Already have assumes when scanning!");
176 if (isa<AssumeInst>(&
I))
183 for (
auto &
A : AssumeHandles)
197 "Cannot register @llvm.assume call not in a basic block");
199 "Cannot register @llvm.assume call not in this function");
205 for (
auto &VH : AssumeHandles) {
210 "Cached assumption not inside this function!");
211 assert(
match(cast<CallInst>(VH), m_Intrinsic<Intrinsic::assume>()) &&
212 "Cached something other than a call to @llvm.assume!");
214 "Cache contains multiple copies of a call!");
233 OS <<
"Cached assumptions for function: " <<
F.getName() <<
"\n";
236 OS <<
" " << *cast<CallInst>(VH)->getArgOperand(0) <<
"\n";
241void AssumptionCacheTracker::FunctionCallbackVH::deleted() {
242 auto I = ACT->AssumptionCaches.find_as(cast<Function>(getValPtr()));
243 if (
I != ACT->AssumptionCaches.end())
244 ACT->AssumptionCaches.erase(
I);
254 if (
I != AssumptionCaches.
end())
257 auto *TTIWP = getAnalysisIfAvailable<TargetTransformInfoWrapperPass>();
258 auto *
TTI = TTIWP ? &TTIWP->getTTI(
F) :
nullptr;
262 auto IP = AssumptionCaches.
insert(std::make_pair(
263 FunctionCallbackVH(&
F,
this), std::make_unique<AssumptionCache>(
F,
TTI)));
264 assert(IP.second &&
"Scanning function already in the map?");
265 return *IP.first->second;
270 if (
I != AssumptionCaches.
end())
271 return I->second.get();
284 for (
const auto &
I : AssumptionCaches) {
285 for (
auto &VH :
I.second->assumptions())
287 AssumptionSet.
insert(cast<CallInst>(VH));
291 if (
match(&II, m_Intrinsic<Intrinsic::assume>()) &&
292 !AssumptionSet.
count(cast<CallInst>(&II)))
306 "Assumption Cache Tracker",
false,
true)
static void findAffectedValues(CallBase *CI, TargetTransformInfo *TTI, SmallVectorImpl< AssumptionCache::ResultElem > &Affected)
static cl::opt< bool > VerifyAssumptionCache("verify-assumption-cache", cl::Hidden, cl::desc("Enable verification of assumption cache"), cl::init(false))
static const Function * getParent(const Value *V)
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
Returns the sub type a function will return at a given Idx Should correspond to the result type of an ExtractValue instruction executed with just that one unsigned Idx
FunctionAnalysisManager FAM
This header defines various interfaces for pass management in LLVM.
#define INITIALIZE_PASS(passName, arg, name, cfg, analysis)
const SmallVectorImpl< MachineOperand > & Cond
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
This file defines the SmallPtrSet class.
This file defines the SmallVector class.
A container for analyses that lazily runs them and caches their results.
PassT::Result & getResult(IRUnitT &IR, ExtraArgTs... ExtraArgs)
Get the result of an analysis pass for a given IR unit.
This represents the llvm.assume intrinsic.
A function analysis which provides an AssumptionCache.
AssumptionCache run(Function &F, FunctionAnalysisManager &)
An immutable pass that tracks lazily created AssumptionCache objects.
~AssumptionCacheTracker() override
AssumptionCache * lookupAssumptionCache(Function &F)
Return the cached assumptions for a function if it has already been scanned.
void verifyAnalysis() const override
verifyAnalysis() - This member can be implemented by a analysis pass to check state of analysis infor...
AssumptionCache & getAssumptionCache(Function &F)
Get the cached assumptions for a function.
A cache of @llvm.assume calls within a function.
void registerAssumption(AssumeInst *CI)
Add an @llvm.assume intrinsic to this function's cache.
void updateAffectedValues(AssumeInst *CI)
Update the cache of values being affected by this assumption (i.e.
MutableArrayRef< ResultElem > assumptions()
Access the list of assumption handles currently tracked for this function.
void unregisterAssumption(AssumeInst *CI)
Remove an @llvm.assume intrinsic from this function's cache if it has been added to the cache earlier...
PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM)
LLVM Basic Block Representation.
const Function * getParent() const
Return the enclosing method, or null if none.
Base class for all callable instructions (InvokeInst and CallInst) Holds everything related to callin...
OperandBundleUse getOperandBundleAt(unsigned Index) const
Return the operand bundle at a specific index.
unsigned getNumOperandBundles() const
Return the number of operand bundles associated with this User.
Value * getArgOperand(unsigned i) const
iterator find(const_arg_type_t< KeyT > Val)
bool erase(const KeyT &Val)
iterator find_as(const LookupKeyT &Val)
Alternate version of find() which allows a different, and possibly less expensive,...
std::pair< iterator, bool > insert(const std::pair< KeyT, ValueT > &KV)
ImmutablePass class - This class is used to provide information that does not need to be run.
const BasicBlock * getParent() const
static PassRegistry * getPassRegistry()
getPassRegistry - Access the global registry object, which is automatically initialized at applicatio...
A set of analyses that are preserved following a run of a transformation pass.
static PreservedAnalyses all()
Construct a special preserved set that preserves all passes.
size_type count(ConstPtrType Ptr) const
count - Return 1 if the specified pointer is in the set, 0 otherwise.
std::pair< iterator, bool > insert(PtrType Ptr)
Inserts Ptr if and only if there is no element in the container equal to Ptr.
SmallPtrSet - This class implements a set which is optimized for holding SmallSize or less elements.
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Analysis pass providing the TargetTransformInfo.
LLVM Value Representation.
bool match(Val *V, const Pattern &P)
initializer< Ty > init(const Ty &Val)
This is an optimization pass for GlobalISel generic memory operations.
constexpr StringRef IgnoreBundleTag
Tag in operand bundle indicating that this bundle should be ignored.
const Value * getUnderlyingObject(const Value *V, unsigned MaxLookup=6)
This method strips off any GEP address adjustments, pointer casts or llvm.threadlocal....
void initializeAssumptionCacheTrackerPass(PassRegistry &)
void erase(Container &C, ValueType V)
Wrapper function to remove a value from a container:
bool none_of(R &&Range, UnaryPredicate P)
Provide wrappers to std::none_of which take ranges instead of having to pass begin/end explicitly.
void report_fatal_error(Error Err, bool gen_crash_diag=true)
Report a serious error, calling any installed error handler.
bool is_contained(R &&Range, const E &Element)
Returns true if Element is found in Range.
void findValuesAffectedByCondition(Value *Cond, bool IsAssume, function_ref< void(Value *)> InsertAffected)
Call InsertAffected on all Values whose known bits / value may be affected by the condition Cond.
A special type used by analysis passes to provide an address that identifies that particular analysis...
unsigned Index
contains either ExprResultIdx or the index of the operand bundle containing the knowledge.
A lightweight accessor for an operand bundle meant to be passed around by value.
StringRef getTagName() const
Return the tag of this operand bundle as a string.