Movatterモバイル変換


[0]ホーム

URL:


LLVM 20.0.0git
AssumptionCache.cpp
Go to the documentation of this file.
1//===- AssumptionCache.cpp - Cache finding @llvm.assume calls -------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8//
9// This file contains a pass that keeps track of @llvm.assume intrinsics in
10// the functions of a module.
11//
12//===----------------------------------------------------------------------===//
13
14#include "llvm/Analysis/AssumptionCache.h"
15#include "llvm/ADT/STLExtras.h"
16#include "llvm/ADT/SmallPtrSet.h"
17#include "llvm/ADT/SmallVector.h"
18#include "llvm/Analysis/AssumeBundleQueries.h"
19#include "llvm/Analysis/TargetTransformInfo.h"
20#include "llvm/Analysis/ValueTracking.h"
21#include "llvm/IR/BasicBlock.h"
22#include "llvm/IR/Function.h"
23#include "llvm/IR/InstrTypes.h"
24#include "llvm/IR/Instruction.h"
25#include "llvm/IR/Instructions.h"
26#include "llvm/IR/PassManager.h"
27#include "llvm/IR/PatternMatch.h"
28#include "llvm/InitializePasses.h"
29#include "llvm/Pass.h"
30#include "llvm/Support/Casting.h"
31#include "llvm/Support/CommandLine.h"
32#include "llvm/Support/ErrorHandling.h"
33#include "llvm/Support/raw_ostream.h"
34#include <cassert>
35#include <utility>
36
37using namespacellvm;
38using namespacellvm::PatternMatch;
39
40staticcl::opt<bool>
41VerifyAssumptionCache("verify-assumption-cache",cl::Hidden,
42cl::desc("Enable verification of assumption cache"),
43cl::init(false));
44
45SmallVector<AssumptionCache::ResultElem, 1> &
46AssumptionCache::getOrInsertAffectedValues(Value *V) {
47// Try using find_as first to avoid creating extra value handles just for the
48// purpose of doing the lookup.
49auto AVI = AffectedValues.find_as(V);
50if (AVI != AffectedValues.end())
51return AVI->second;
52
53return AffectedValues[AffectedValueCallbackVH(V,this)];
54}
55
56staticvoid
57findAffectedValues(CallBase *CI,TargetTransformInfo *TTI,
58SmallVectorImpl<AssumptionCache::ResultElem> &Affected) {
59// Note: This code must be kept in-sync with the code in
60// computeKnownBitsFromAssume in ValueTracking.
61
62auto InsertAffected = [&Affected](Value *V) {
63 Affected.push_back({V,AssumptionCache::ExprResultIdx});
64 };
65
66auto AddAffectedVal = [&Affected](Value *V,unsignedIdx) {
67if (isa<Argument>(V) || isa<GlobalValue>(V) || isa<Instruction>(V)) {
68 Affected.push_back({V,Idx});
69 }
70 };
71
72for (unsignedIdx = 0;Idx != CI->getNumOperandBundles();Idx++) {
73OperandBundleUse Bundle = CI->getOperandBundleAt(Idx);
74if (Bundle.getTagName() =="separate_storage") {
75assert(Bundle.Inputs.size() == 2 &&
76"separate_storage must have two args");
77 AddAffectedVal(getUnderlyingObject(Bundle.Inputs[0]),Idx);
78 AddAffectedVal(getUnderlyingObject(Bundle.Inputs[1]),Idx);
79 }elseif (Bundle.Inputs.size() >ABA_WasOn &&
80 Bundle.getTagName() !=IgnoreBundleTag)
81 AddAffectedVal(Bundle.Inputs[ABA_WasOn],Idx);
82 }
83
84Value *Cond = CI->getArgOperand(0);
85findValuesAffectedByCondition(Cond,/*IsAssume=*/true, InsertAffected);
86
87if (TTI) {
88constValue *Ptr;
89unsigned AS;
90 std::tie(Ptr, AS) =TTI->getPredicatedAddrSpace(Cond);
91if (Ptr)
92 AddAffectedVal(const_cast<Value *>(Ptr->stripInBoundsOffsets()),
93AssumptionCache::ExprResultIdx);
94 }
95}
96
97voidAssumptionCache::updateAffectedValues(AssumeInst *CI) {
98SmallVector<AssumptionCache::ResultElem, 16> Affected;
99findAffectedValues(CI,TTI, Affected);
100
101for (auto &AV : Affected) {
102auto &AVV = getOrInsertAffectedValues(AV.Assume);
103if (llvm::none_of(AVV, [&](ResultElem &Elem) {
104return Elem.Assume == CI && Elem.Index == AV.Index;
105 }))
106 AVV.push_back({CI, AV.Index});
107 }
108}
109
110voidAssumptionCache::unregisterAssumption(AssumeInst *CI) {
111SmallVector<AssumptionCache::ResultElem, 16> Affected;
112findAffectedValues(CI,TTI, Affected);
113
114for (auto &AV : Affected) {
115auto AVI = AffectedValues.find_as(AV.Assume);
116if (AVI == AffectedValues.end())
117continue;
118bool Found =false;
119bool HasNonnull =false;
120for (ResultElem &Elem : AVI->second) {
121if (Elem.Assume == CI) {
122 Found =true;
123 Elem.Assume =nullptr;
124 }
125 HasNonnull |= !!Elem.Assume;
126if (HasNonnull && Found)
127break;
128 }
129assert(Found &&"already unregistered or incorrect cache state");
130if (!HasNonnull)
131 AffectedValues.erase(AVI);
132 }
133
134llvm::erase(AssumeHandles, CI);
135}
136
137void AssumptionCache::AffectedValueCallbackVH::deleted() {
138 AC->AffectedValues.erase(getValPtr());
139// 'this' now dangles!
140}
141
142void AssumptionCache::transferAffectedValuesInCache(Value *OV,Value *NV) {
143auto &NAVV = getOrInsertAffectedValues(NV);
144auto AVI = AffectedValues.find(OV);
145if (AVI == AffectedValues.end())
146return;
147
148for (auto &A : AVI->second)
149if (!llvm::is_contained(NAVV,A))
150 NAVV.push_back(A);
151 AffectedValues.erase(OV);
152}
153
154void AssumptionCache::AffectedValueCallbackVH::allUsesReplacedWith(Value *NV) {
155if (!isa<Instruction>(NV) && !isa<Argument>(NV))
156return;
157
158// Any assumptions that affected this value now affect the new value.
159
160 AC->transferAffectedValuesInCache(getValPtr(), NV);
161// 'this' now might dangle! If the AffectedValues map was resized to add an
162// entry for NV then this object might have been destroyed in favor of some
163// copy in the grown map.
164}
165
166void AssumptionCache::scanFunction() {
167assert(!Scanned &&"Tried to scan the function twice!");
168assert(AssumeHandles.empty() &&"Already have assumes when scanning!");
169
170// Go through all instructions in all blocks, add all calls to @llvm.assume
171// to this cache.
172for (BasicBlock &B : F)
173for (Instruction &I :B)
174if (isa<AssumeInst>(&I))
175 AssumeHandles.push_back({&I,ExprResultIdx});
176
177// Mark the scan as complete.
178 Scanned =true;
179
180// Update affected values.
181for (auto &A : AssumeHandles)
182updateAffectedValues(cast<AssumeInst>(A));
183}
184
185voidAssumptionCache::registerAssumption(AssumeInst *CI) {
186// If we haven't scanned the function yet, just drop this assumption. It will
187// be found when we scan later.
188if (!Scanned)
189return;
190
191 AssumeHandles.push_back({CI,ExprResultIdx});
192
193#ifndef NDEBUG
194assert(CI->getParent() &&
195"Cannot register @llvm.assume call not in a basic block");
196assert(&F == CI->getParent()->getParent() &&
197"Cannot register @llvm.assume call not in this function");
198
199// We expect the number of assumptions to be small, so in an asserts build
200// check that we don't accumulate duplicates and that all assumptions point
201// to the same function.
202SmallPtrSet<Value *, 16> AssumptionSet;
203for (auto &VH : AssumeHandles) {
204if (!VH)
205continue;
206
207assert(&F == cast<Instruction>(VH)->getParent()->getParent() &&
208"Cached assumption not inside this function!");
209assert(match(cast<CallInst>(VH), m_Intrinsic<Intrinsic::assume>()) &&
210"Cached something other than a call to @llvm.assume!");
211assert(AssumptionSet.insert(VH).second &&
212"Cache contains multiple copies of a call!");
213 }
214#endif
215
216updateAffectedValues(CI);
217}
218
219AssumptionCacheAssumptionAnalysis::run(Function &F,
220FunctionAnalysisManager &FAM) {
221auto &TTI =FAM.getResult<TargetIRAnalysis>(F);
222returnAssumptionCache(F, &TTI);
223}
224
225AnalysisKey AssumptionAnalysis::Key;
226
227PreservedAnalysesAssumptionPrinterPass::run(Function &F,
228FunctionAnalysisManager &AM) {
229AssumptionCache &AC = AM.getResult<AssumptionAnalysis>(F);
230
231 OS <<"Cached assumptions for function: " <<F.getName() <<"\n";
232for (auto &VH : AC.assumptions())
233if (VH)
234 OS <<" " << *cast<CallInst>(VH)->getArgOperand(0) <<"\n";
235
236returnPreservedAnalyses::all();
237}
238
239void AssumptionCacheTracker::FunctionCallbackVH::deleted() {
240autoI = ACT->AssumptionCaches.find_as(cast<Function>(getValPtr()));
241if (I != ACT->AssumptionCaches.end())
242 ACT->AssumptionCaches.erase(I);
243// 'this' now dangles!
244}
245
246AssumptionCache &AssumptionCacheTracker::getAssumptionCache(Function &F) {
247// We probe the function map twice to try and avoid creating a value handle
248// around the function in common cases. This makes insertion a bit slower,
249// but if we have to insert we're going to scan the whole function so that
250// shouldn't matter.
251autoI = AssumptionCaches.find_as(&F);
252if (I != AssumptionCaches.end())
253return *I->second;
254
255auto *TTIWP = getAnalysisIfAvailable<TargetTransformInfoWrapperPass>();
256auto *TTI = TTIWP ? &TTIWP->getTTI(F) :nullptr;
257
258// Ok, build a new cache by scanning the function, insert it and the value
259// handle into our map, and return the newly populated cache.
260auto IP = AssumptionCaches.insert(std::make_pair(
261 FunctionCallbackVH(&F,this), std::make_unique<AssumptionCache>(F,TTI)));
262assert(IP.second &&"Scanning function already in the map?");
263return *IP.first->second;
264}
265
266AssumptionCache *AssumptionCacheTracker::lookupAssumptionCache(Function &F) {
267autoI = AssumptionCaches.find_as(&F);
268if (I != AssumptionCaches.end())
269returnI->second.get();
270returnnullptr;
271}
272
273voidAssumptionCacheTracker::verifyAnalysis() const{
274// FIXME: In the long term the verifier should not be controllable with a
275// flag. We should either fix all passes to correctly update the assumption
276// cache and enable the verifier unconditionally or somehow arrange for the
277// assumption list to be updated automatically by passes.
278if (!VerifyAssumptionCache)
279return;
280
281SmallPtrSet<const CallInst *, 4> AssumptionSet;
282for (constauto &I : AssumptionCaches) {
283for (auto &VH :I.second->assumptions())
284if (VH)
285 AssumptionSet.insert(cast<CallInst>(VH));
286
287for (constBasicBlock &B : cast<Function>(*I.first))
288for (constInstruction &II :B)
289if (match(&II, m_Intrinsic<Intrinsic::assume>()) &&
290 !AssumptionSet.count(cast<CallInst>(&II)))
291report_fatal_error("Assumption in scanned function not in cache");
292 }
293}
294
295AssumptionCacheTracker::AssumptionCacheTracker() :ImmutablePass(ID) {
296initializeAssumptionCacheTrackerPass(*PassRegistry::getPassRegistry());
297}
298
299AssumptionCacheTracker::~AssumptionCacheTracker() =default;
300
301charAssumptionCacheTracker::ID = 0;
302
303INITIALIZE_PASS(AssumptionCacheTracker,"assumption-cache-tracker",
304"Assumption Cache Tracker",false,true)
AssumeBundleQueries.h
findAffectedValues
static void findAffectedValues(CallBase *CI, TargetTransformInfo *TTI, SmallVectorImpl< AssumptionCache::ResultElem > &Affected)
Definition:AssumptionCache.cpp:57
VerifyAssumptionCache
static cl::opt< bool > VerifyAssumptionCache("verify-assumption-cache", cl::Hidden, cl::desc("Enable verification of assumption cache"), cl::init(false))
AssumptionCache.h
getParent
static const Function * getParent(const Value *V)
Definition:BasicAliasAnalysis.cpp:863
B
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
A
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
Casting.h
CommandLine.h
Idx
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
Definition:DeadArgumentElimination.cpp:353
BasicBlock.h
Function.h
Instruction.h
PassManager.h
This header defines various interfaces for pass management in LLVM.
InitializePasses.h
InstrTypes.h
Instructions.h
F
#define F(x, y, z)
Definition:MD5.cpp:55
I
#define I(x, y, z)
Definition:MD5.cpp:58
II
uint64_t IntrinsicInst * II
Definition:NVVMIntrRange.cpp:51
FAM
FunctionAnalysisManager FAM
Definition:PassBuilderBindings.cpp:61
INITIALIZE_PASS
#define INITIALIZE_PASS(passName, arg, name, cfg, analysis)
Definition:PassSupport.h:38
Pass.h
PatternMatch.h
Cond
const SmallVectorImpl< MachineOperand > & Cond
Definition:RISCVRedundantCopyElimination.cpp:75
assert
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
STLExtras.h
This file contains some templates that are useful if you are working with the STL at all.
SmallPtrSet.h
This file defines the SmallPtrSet class.
SmallVector.h
This file defines the SmallVector class.
Ptr
@ Ptr
Definition:TargetLibraryInfo.cpp:77
TargetTransformInfo.h
This pass exposes codegen information to IR-level passes.
ValueTracking.h
llvm::AnalysisManager
A container for analyses that lazily runs them and caches their results.
Definition:PassManager.h:253
llvm::AnalysisManager::getResult
PassT::Result & getResult(IRUnitT &IR, ExtraArgTs... ExtraArgs)
Get the result of an analysis pass for a given IR unit.
Definition:PassManager.h:410
llvm::AssumeInst
This represents the llvm.assume intrinsic.
Definition:IntrinsicInst.h:1843
llvm::AssumptionAnalysis
A function analysis which provides an AssumptionCache.
Definition:AssumptionCache.h:173
llvm::AssumptionAnalysis::run
AssumptionCache run(Function &F, FunctionAnalysisManager &)
Definition:AssumptionCache.cpp:219
llvm::AssumptionCacheTracker
An immutable pass that tracks lazily created AssumptionCache objects.
Definition:AssumptionCache.h:204
llvm::AssumptionCacheTracker::~AssumptionCacheTracker
~AssumptionCacheTracker() override
llvm::AssumptionCacheTracker::lookupAssumptionCache
AssumptionCache * lookupAssumptionCache(Function &F)
Return the cached assumptions for a function if it has already been scanned.
Definition:AssumptionCache.cpp:266
llvm::AssumptionCacheTracker::ID
static char ID
Definition:AssumptionCache.h:253
llvm::AssumptionCacheTracker::verifyAnalysis
void verifyAnalysis() const override
verifyAnalysis() - This member can be implemented by a analysis pass to check state of analysis infor...
Definition:AssumptionCache.cpp:273
llvm::AssumptionCacheTracker::getAssumptionCache
AssumptionCache & getAssumptionCache(Function &F)
Get the cached assumptions for a function.
Definition:AssumptionCache.cpp:246
llvm::AssumptionCacheTracker::AssumptionCacheTracker
AssumptionCacheTracker()
Definition:AssumptionCache.cpp:295
llvm::AssumptionCache
A cache of @llvm.assume calls within a function.
Definition:AssumptionCache.h:42
llvm::AssumptionCache::registerAssumption
void registerAssumption(AssumeInst *CI)
Add an @llvm.assume intrinsic to this function's cache.
Definition:AssumptionCache.cpp:185
llvm::AssumptionCache::ExprResultIdx
@ ExprResultIdx
Definition:AssumptionCache.h:46
llvm::AssumptionCache::updateAffectedValues
void updateAffectedValues(AssumeInst *CI)
Update the cache of values being affected by this assumption (i.e.
Definition:AssumptionCache.cpp:97
llvm::AssumptionCache::assumptions
MutableArrayRef< ResultElem > assumptions()
Access the list of assumption handles currently tracked for this function.
Definition:AssumptionCache.h:150
llvm::AssumptionCache::unregisterAssumption
void unregisterAssumption(AssumeInst *CI)
Remove an @llvm.assume intrinsic from this function's cache if it has been added to the cache earlier...
Definition:AssumptionCache.cpp:110
llvm::AssumptionPrinterPass::run
PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM)
Definition:AssumptionCache.cpp:227
llvm::BasicBlock
LLVM Basic Block Representation.
Definition:BasicBlock.h:61
llvm::CallBase
Base class for all callable instructions (InvokeInst and CallInst) Holds everything related to callin...
Definition:InstrTypes.h:1112
llvm::CallBase::getOperandBundleAt
OperandBundleUse getOperandBundleAt(unsigned Index) const
Return the operand bundle at a specific index.
Definition:InstrTypes.h:2022
llvm::CallBase::getNumOperandBundles
unsigned getNumOperandBundles() const
Return the number of operand bundles associated with this User.
Definition:InstrTypes.h:1966
llvm::CallBase::getArgOperand
Value * getArgOperand(unsigned i) const
Definition:InstrTypes.h:1286
llvm::DenseMapBase::find
iterator find(const_arg_type_t< KeyT > Val)
Definition:DenseMap.h:156
llvm::DenseMapBase::erase
bool erase(const KeyT &Val)
Definition:DenseMap.h:321
llvm::DenseMapBase::find_as
iterator find_as(const LookupKeyT &Val)
Alternate version of find() which allows a different, and possibly less expensive,...
Definition:DenseMap.h:176
llvm::DenseMapBase::end
iterator end()
Definition:DenseMap.h:84
llvm::DenseMapBase::insert
std::pair< iterator, bool > insert(const std::pair< KeyT, ValueT > &KV)
Definition:DenseMap.h:211
llvm::Function
Definition:Function.h:63
llvm::ImmutablePass
ImmutablePass class - This class is used to provide information that does not need to be run.
Definition:Pass.h:281
llvm::Instruction
Definition:Instruction.h:68
llvm::PassRegistry::getPassRegistry
static PassRegistry * getPassRegistry()
getPassRegistry - Access the global registry object, which is automatically initialized at applicatio...
Definition:PassRegistry.cpp:24
llvm::PreservedAnalyses
A set of analyses that are preserved following a run of a transformation pass.
Definition:Analysis.h:111
llvm::PreservedAnalyses::all
static PreservedAnalyses all()
Construct a special preserved set that preserves all passes.
Definition:Analysis.h:117
llvm::SmallPtrSetImpl::count
size_type count(ConstPtrType Ptr) const
count - Return 1 if the specified pointer is in the set, 0 otherwise.
Definition:SmallPtrSet.h:452
llvm::SmallPtrSetImpl::insert
std::pair< iterator, bool > insert(PtrType Ptr)
Inserts Ptr if and only if there is no element in the container equal to Ptr.
Definition:SmallPtrSet.h:384
llvm::SmallPtrSet
SmallPtrSet - This class implements a set which is optimized for holding SmallSize or less elements.
Definition:SmallPtrSet.h:519
llvm::SmallVectorImpl
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
Definition:SmallVector.h:573
llvm::SmallVectorTemplateBase::push_back
void push_back(const T &Elt)
Definition:SmallVector.h:413
llvm::SmallVector
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Definition:SmallVector.h:1196
llvm::TargetIRAnalysis
Analysis pass providing the TargetTransformInfo.
Definition:TargetTransformInfo.h:3194
llvm::TargetTransformInfo
This pass provides access to the codegen interfaces that are needed for IR-level transformations.
Definition:TargetTransformInfo.h:212
llvm::TargetTransformInfo::getPredicatedAddrSpace
std::pair< const Value *, unsigned > getPredicatedAddrSpace(const Value *V) const
Definition:TargetTransformInfo.cpp:343
llvm::Value
LLVM Value Representation.
Definition:Value.h:74
llvm::cl::opt
Definition:CommandLine.h:1423
llvm::ilist_detail::node_parent_access::getParent
const ParentTy * getParent() const
Definition:ilist_node.h:32
unsigned
ErrorHandling.h
llvm::PatternMatch
Definition:PatternMatch.h:47
llvm::PatternMatch::match
bool match(Val *V, const Pattern &P)
Definition:PatternMatch.h:49
llvm::cl::Hidden
@ Hidden
Definition:CommandLine.h:137
llvm::cl::init
initializer< Ty > init(const Ty &Val)
Definition:CommandLine.h:443
llvm
This is an optimization pass for GlobalISel generic memory operations.
Definition:AddressRanges.h:18
llvm::IgnoreBundleTag
constexpr StringRef IgnoreBundleTag
Tag in operand bundle indicating that this bundle should be ignored.
Definition:AssumeBundleQueries.h:134
llvm::getUnderlyingObject
const Value * getUnderlyingObject(const Value *V, unsigned MaxLookup=6)
This method strips off any GEP address adjustments, pointer casts or llvm.threadlocal....
Definition:ValueTracking.cpp:6768
llvm::initializeAssumptionCacheTrackerPass
void initializeAssumptionCacheTrackerPass(PassRegistry &)
llvm::erase
void erase(Container &C, ValueType V)
Wrapper function to remove a value from a container:
Definition:STLExtras.h:2107
llvm::none_of
bool none_of(R &&Range, UnaryPredicate P)
Provide wrappers to std::none_of which take ranges instead of having to pass begin/end explicitly.
Definition:STLExtras.h:1753
llvm::report_fatal_error
void report_fatal_error(Error Err, bool gen_crash_diag=true)
Report a serious error, calling any installed error handler.
Definition:Error.cpp:167
llvm::is_contained
bool is_contained(R &&Range, const E &Element)
Returns true if Element is found in Range.
Definition:STLExtras.h:1903
llvm::ABA_WasOn
@ ABA_WasOn
Definition:AssumeBundleQueries.h:29
llvm::findValuesAffectedByCondition
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.
Definition:ValueTracking.cpp:10176
raw_ostream.h
llvm::AnalysisKey
A special type used by analysis passes to provide an address that identifies that particular analysis...
Definition:Analysis.h:28
llvm::AssumptionCache::ResultElem
Definition:AssumptionCache.h:48
llvm::AssumptionCache::ResultElem::Index
unsigned Index
contains either ExprResultIdx or the index of the operand bundle containing the knowledge.
Definition:AssumptionCache.h:53
llvm::AssumptionCache::ResultElem::Assume
WeakVH Assume
Definition:AssumptionCache.h:49
llvm::OperandBundleUse
A lightweight accessor for an operand bundle meant to be passed around by value.
Definition:InstrTypes.h:1007
llvm::OperandBundleUse::getTagName
StringRef getTagName() const
Return the tag of this operand bundle as a string.
Definition:InstrTypes.h:1026
llvm::OperandBundleUse::Inputs
ArrayRef< Use > Inputs
Definition:InstrTypes.h:1008
llvm::cl::desc
Definition:CommandLine.h:409

Generated on Thu Jul 17 2025 10:43:26 for LLVM by doxygen 1.9.6
[8]ページ先頭

©2009-2025 Movatter.jp