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 return AffectedValues[AffectedValueCallbackVH(V,
this)];
62 auto InsertAffected = [&Affected](
Value *V) {
66 auto AddAffectedVal = [&Affected](
Value *V,
unsigned Idx) {
67 if (isa<Argument>(V) || isa<GlobalValue>(V) || isa<Instruction>(V)) {
74 if (Bundle.
getTagName() ==
"separate_storage") {
76 "separate_storage must have two args");
92 AddAffectedVal(
const_cast<Value *
>(
Ptr->stripInBoundsOffsets()),
101 for (
auto &AV : Affected) {
102 auto &AVV = getOrInsertAffectedValues(AV.Assume);
104 return Elem.
Assume == CI && Elem.
Index == AV.Index;
106 AVV.push_back({CI, AV.Index});
114 for (
auto &AV : Affected) {
115 auto AVI = AffectedValues.
find_as(AV.Assume);
116 if (AVI == AffectedValues.
end())
119 bool HasNonnull =
false;
125 HasNonnull |= !!Elem.
Assume;
126 if (HasNonnull && Found)
129 assert(Found &&
"already unregistered or incorrect cache state");
131 AffectedValues.
erase(AVI);
137void AssumptionCache::AffectedValueCallbackVH::deleted() {
138 AC->AffectedValues.erase(getValPtr());
142void AssumptionCache::transferAffectedValuesInCache(
Value *OV,
Value *NV) {
143 auto &NAVV = getOrInsertAffectedValues(NV);
144 auto AVI = AffectedValues.
find(OV);
145 if (AVI == AffectedValues.
end())
148 for (
auto &
A : AVI->second)
151 AffectedValues.
erase(OV);
154void AssumptionCache::AffectedValueCallbackVH::allUsesReplacedWith(
Value *NV) {
155 if (!isa<Instruction>(NV) && !isa<Argument>(NV))
160 AC->transferAffectedValuesInCache(getValPtr(), NV);
166void AssumptionCache::scanFunction() {
167 assert(!Scanned &&
"Tried to scan the function twice!");
168 assert(AssumeHandles.empty() &&
"Already have assumes when scanning!");
174 if (isa<AssumeInst>(&
I))
181 for (
auto &
A : AssumeHandles)
195 "Cannot register @llvm.assume call not in a basic block");
197 "Cannot register @llvm.assume call not in this function");
203 for (
auto &VH : AssumeHandles) {
208 "Cached assumption not inside this function!");
209 assert(
match(cast<CallInst>(VH), m_Intrinsic<Intrinsic::assume>()) &&
210 "Cached something other than a call to @llvm.assume!");
212 "Cache contains multiple copies of a call!");
231 OS <<
"Cached assumptions for function: " <<
F.getName() <<
"\n";
234 OS <<
" " << *cast<CallInst>(VH)->getArgOperand(0) <<
"\n";
239void AssumptionCacheTracker::FunctionCallbackVH::deleted() {
240 auto I = ACT->AssumptionCaches.find_as(cast<Function>(getValPtr()));
241 if (
I != ACT->AssumptionCaches.end())
242 ACT->AssumptionCaches.erase(
I);
252 if (
I != AssumptionCaches.
end())
255 auto *TTIWP = getAnalysisIfAvailable<TargetTransformInfoWrapperPass>();
256 auto *
TTI = TTIWP ? &TTIWP->getTTI(
F) :
nullptr;
260 auto IP = AssumptionCaches.
insert(std::make_pair(
261 FunctionCallbackVH(&
F,
this), std::make_unique<AssumptionCache>(
F,
TTI)));
262 assert(IP.second &&
"Scanning function already in the map?");
263 return *IP.first->second;
268 if (
I != AssumptionCaches.
end())
269 return I->second.get();
282 for (
const auto &
I : AssumptionCaches) {
283 for (
auto &VH :
I.second->assumptions())
285 AssumptionSet.
insert(cast<CallInst>(VH));
289 if (
match(&
II, m_Intrinsic<Intrinsic::assume>()) &&
290 !AssumptionSet.
count(cast<CallInst>(&
II)))
304 "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
This header defines various interfaces for pass management in LLVM.
uint64_t IntrinsicInst * II
FunctionAnalysisManager FAM
#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.
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.
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.
const ParentTy * getParent() const
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.