35#define DEBUG_TYPE "globalsmodref-aa"
38 "Number of global vars without address taken");
39STATISTIC(NumNonAddrTakenFunctions,
"Number of functions without address taken");
40STATISTIC(NumNoMemFunctions,
"Number of functions that do not access memory");
41STATISTIC(NumReadMemFunctions,
"Number of functions that only read memory");
42STATISTIC(NumIndirectGlobalVars,
"Number of indirect global objects");
70 struct alignas(8) AlignedMap {
71 AlignedMap() =
default;
72 AlignedMap(
const AlignedMap &Arg) =
default;
73 GlobalInfoMapType Map;
77 struct AlignedMapPointerTraits {
78 static inline void *getAsVoidPointer(AlignedMap *
P) {
return P; }
79 static inline AlignedMap *getFromVoidPointer(
void *
P) {
80 return (AlignedMap *)
P;
82 static constexpr int NumLowBitsAvailable = 3;
83 static_assert(
alignof(AlignedMap) >= (1 << NumLowBitsAvailable),
84 "AlignedMap insufficiently aligned to have enough low bits.");
92 enum { MayReadAnyGlobal = 4 };
96 "ModRef and the MayReadAnyGlobal flag bits overlap.");
98 AlignedMapPointerTraits::NumLowBitsAvailable) == 0,
99 "Insufficient low bits to store our flag and ModRef info.");
104 delete Info.getPointer();
110 : Info(nullptr, Arg.Info.getInt()) {
111 if (
const auto *ArgPtr = Arg.Info.
getPointer())
112 Info.setPointer(
new AlignedMap(*ArgPtr));
115 : Info(Arg.Info.
getPointer(), Arg.Info.getInt()) {
116 Arg.Info.setPointerAndInt(
nullptr, 0);
119 delete Info.getPointer();
120 Info.setPointerAndInt(
nullptr, RHS.Info.getInt());
121 if (
const auto *RHSPtr = RHS.Info.getPointer())
122 Info.setPointer(
new AlignedMap(*RHSPtr));
126 delete Info.getPointer();
127 Info.setPointerAndInt(RHS.Info.getPointer(), RHS.Info.getInt());
145 Info.setInt(Info.getInt() |
static_cast<int>(NewMRI));
160 if (AlignedMap *
P = Info.getPointer()) {
161 auto I =
P->Map.find(&GV);
162 if (
I !=
P->Map.end())
163 GlobalMRI |=
I->second;
177 for (
const auto &
G :
P->Map)
182 AlignedMap *
P = Info.getPointer();
184 P =
new AlignedMap();
187 auto &GlobalMRI =
P->Map[&GV];
194 if (AlignedMap *
P = Info.getPointer())
207void GlobalsAAResult::DeletionCallbackHandle::deleted() {
210 GAR->FunctionInfos.erase(
F);
213 if (GAR->NonAddressTakenGlobals.erase(GV)) {
216 if (GAR->IndirectGlobals.erase(GV)) {
218 for (
auto I = GAR->AllocsForIndirectGlobals.begin(),
219 E = GAR->AllocsForIndirectGlobals.end();
222 GAR->AllocsForIndirectGlobals.erase(
I);
227 for (
auto &FIPair : GAR->FunctionInfos)
228 FIPair.second.eraseModRefInfoForGlobal(*GV);
233 GAR->AllocsForIndirectGlobals.erase(V);
237 GAR->Handles.erase(I);
251GlobalsAAResult::getFunctionInfo(
const Function *
F) {
252 auto I = FunctionInfos.find(
F);
253 if (
I != FunctionInfos.end())
262void GlobalsAAResult::AnalyzeGlobals(
Module &M) {
265 if (
F.hasLocalLinkage()) {
266 if (!AnalyzeUsesOfPointer(&
F)) {
268 NonAddressTakenGlobals.insert(&
F);
270 Handles.emplace_front(*
this, &
F);
271 Handles.front().I = Handles.begin();
272 ++NumNonAddrTakenFunctions;
274 UnknownFunctionsWithLocalLinkage =
true;
277 SmallPtrSet<Function *, 16> Readers, Writers;
278 for (GlobalVariable &GV :
M.globals())
279 if (GV.hasLocalLinkage()) {
280 if (!AnalyzeUsesOfPointer(&GV, &Readers,
281 GV.isConstant() ?
nullptr : &Writers)) {
283 NonAddressTakenGlobals.insert(&GV);
284 Handles.emplace_front(*
this, &GV);
285 Handles.front().I = Handles.begin();
287 for (Function *Reader : Readers) {
288 if (TrackedFunctions.
insert(Reader).second) {
289 Handles.emplace_front(*
this, Reader);
290 Handles.front().I = Handles.begin();
295 if (!GV.isConstant())
296 for (Function *Writer : Writers) {
297 if (TrackedFunctions.
insert(Writer).second) {
298 Handles.emplace_front(*
this, Writer);
299 Handles.front().I = Handles.begin();
303 ++NumNonAddrTakenGlobalVars;
306 if (GV.getValueType()->isPointerTy() &&
307 AnalyzeIndirectGlobalMemory(&GV))
308 ++NumIndirectGlobalVars;
321bool GlobalsAAResult::AnalyzeUsesOfPointer(
Value *V,
322 SmallPtrSetImpl<Function *> *Readers,
323 SmallPtrSetImpl<Function *> *Writers,
324 GlobalValue *OkayStoreDest) {
325 if (!
V->getType()->isPointerTy())
328 for (Use &U :
V->uses()) {
332 Readers->
insert(LI->getParent()->getParent());
334 if (V ==
SI->getOperand(1)) {
336 Writers->
insert(
SI->getParent()->getParent());
337 }
else if (
SI->getOperand(1) != OkayStoreDest) {
341 if (AnalyzeUsesOfPointer(
I, Readers, Writers))
345 if (AnalyzeUsesOfPointer(
I, Readers, Writers, OkayStoreDest))
349 if (
II->getIntrinsicID() == Intrinsic::threadlocal_address &&
350 V ==
II->getArgOperand(0)) {
351 if (AnalyzeUsesOfPointer(
II, Readers, Writers))
373 if (!
F || !
F->isDeclaration())
414bool GlobalsAAResult::AnalyzeIndirectGlobalMemory(GlobalVariable *GV) {
417 std::vector<Value *> AllocRelatedValues;
426 for (User *U : GV->
users()) {
431 if (AnalyzeUsesOfPointer(LI))
436 if (
SI->getOperand(0) == GV)
451 if (AnalyzeUsesOfPointer(Ptr,
nullptr,
nullptr,
456 AllocRelatedValues.push_back(Ptr);
465 while (!AllocRelatedValues.empty()) {
466 AllocsForIndirectGlobals[AllocRelatedValues.back()] = GV;
467 Handles.emplace_front(*
this, AllocRelatedValues.back());
468 Handles.front().I = Handles.begin();
469 AllocRelatedValues.pop_back();
471 IndirectGlobals.
insert(GV);
472 Handles.emplace_front(*
this, GV);
473 Handles.front().I = Handles.begin();
477void GlobalsAAResult::CollectSCCMembership(CallGraph &CG) {
481 for (scc_iterator<CallGraph *>
I =
scc_begin(&CG); !
I.isAtEnd(); ++
I) {
482 const std::vector<CallGraphNode *> &
SCC = *
I;
483 assert(!
SCC.empty() &&
"SCC with no functions?");
485 for (
auto *CGN : SCC)
486 if (Function *
F = CGN->getFunction())
487 FunctionToSCCMap[
F] = SCCID;
496void GlobalsAAResult::AnalyzeCallGraph(CallGraph &CG,
Module &M) {
499 for (scc_iterator<CallGraph *>
I =
scc_begin(&CG); !
I.isAtEnd(); ++
I) {
500 const std::vector<CallGraphNode *> &
SCC = *
I;
501 assert(!
SCC.empty() &&
"SCC with no functions?");
505 if (!
F || !
F->isDefinitionExact()) {
509 for (
auto *Node : SCC)
510 FunctionInfos.erase(
Node->getFunction());
515 Handles.emplace_front(*
this,
F);
516 Handles.front().I = Handles.begin();
517 bool KnowNothing =
false;
526 auto MaySyncOrCallIntoModule = [](
const Function &
F) {
527 return !
F.isDeclaration() || !
F.hasNoSync() ||
528 !
F.hasFnAttribute(Attribute::NoCallback);
533 for (
unsigned i = 0, e =
SCC.size(); i != e && !KnowNothing; ++i) {
539 if (
F->isDeclaration() ||
F->hasOptNone()) {
541 if (
F->doesNotAccessMemory()) {
543 }
else if (
F->onlyReadsMemory()) {
545 if (!
F->onlyAccessesArgMemory() && MaySyncOrCallIntoModule(*
F))
548 FI.setMayReadAnyGlobal();
551 if (!
F->onlyAccessesArgMemory())
552 FI.setMayReadAnyGlobal();
553 if (MaySyncOrCallIntoModule(*
F)) {
562 CI !=
E && !KnowNothing; ++CI)
563 if (Function *Callee = CI->second->getFunction()) {
566 FI.addFunctionInfo(*CalleeFI);
570 CallGraphNode *CalleeNode = CG[
Callee];
582 for (
auto *Node : SCC)
583 FunctionInfos.erase(
Node->getFunction());
588 for (
auto *Node : SCC) {
595 if (
Node->getFunction()->hasOptNone())
609 if (
I.mayReadFromMemory())
611 if (
I.mayWriteToMemory())
617 ++NumReadMemFunctions;
626 for (
unsigned i = 1, e =
SCC.size(); i != e; ++i)
627 FunctionInfos[
SCC[i]->getFunction()] = CachedFI;
676 for (
const Value *
Op : PN->incoming_values()) {
685 }
while (!Inputs.
empty());
716bool GlobalsAAResult::isNonEscapingGlobalNoAlias(
const GlobalValue *GV,
718 const Instruction *CtxI) {
728 if (!
V->getType()->isPointerTy())
731 SmallPtrSet<const Value *, 8> Visited;
732 SmallVector<const Value *, 8> Inputs;
749 if (GVar && InputGVar &&
750 !GVar->isDeclaration() && !InputGVar->isDeclaration() &&
751 !GVar->isInterposable() && !InputGVar->isInterposable()) {
752 Type *GVType = GVar->getInitializer()->getType();
753 Type *InputGVType = InputGVar->getInitializer()->getType();
755 (DL.getTypeAllocSize(GVType) > 0) &&
756 (DL.getTypeAllocSize(InputGVType) > 0))
808 for (
const Value *
Op : PN->incoming_values()) {
820 }
while (!Inputs.
empty());
827 ModuleAnalysisManager::Invalidator &) {
831 return !PAC.preservedWhenStateless();
853 if (GV1 && !NonAddressTakenGlobals.count(GV1))
855 if (GV2 && !NonAddressTakenGlobals.count(GV2))
860 if (GV1 && GV2 && GV1 != GV2)
867 if ((GV1 || GV2) && GV1 != GV2)
872 if ((GV1 || GV2) && GV1 != GV2) {
874 const Value *UV = GV1 ? UV2 : UV1;
875 if (isNonEscapingGlobalNoAlias(GV, UV, CtxI))
889 if (IndirectGlobals.count(GV))
893 if (IndirectGlobals.count(GV))
899 GV1 = AllocsForIndirectGlobals.lookup(UV1);
901 GV2 = AllocsForIndirectGlobals.lookup(UV2);
906 if (GV1 && GV2 && GV1 != GV2)
913 if ((GV1 || GV2) && GV1 != GV2)
922 if (
Call->doesNotAccessMemory())
929 for (
const auto &
A :
Call->args()) {
941 return ConservativeResult;
944 return ConservativeResult;
964 if (NonAddressTakenGlobals.count(GV))
966 Known = FI->getModRefInfoForGlobal(*GV) |
967 getModRefInfoForArgument(
Call, GV, AAQI);
972GlobalsAAResult::GlobalsAAResult(
977GlobalsAAResult::GlobalsAAResult(GlobalsAAResult &&Arg)
979 NonAddressTakenGlobals(
std::
move(Arg.NonAddressTakenGlobals)),
980 IndirectGlobals(
std::
move(Arg.IndirectGlobals)),
981 AllocsForIndirectGlobals(
std::
move(Arg.AllocsForIndirectGlobals)),
982 FunctionInfos(
std::
move(Arg.FunctionInfos)),
983 Handles(
std::
move(Arg.Handles)) {
985 for (
auto &
H : Handles) {
996 GlobalsAAResult Result(M.getDataLayout(), GetTLI);
999 Result.CollectSCCMembership(CG);
1002 Result.AnalyzeGlobals(M);
1005 Result.AnalyzeCallGraph(CG, M);
1026 G->NonAddressTakenGlobals.clear();
1027 G->UnknownFunctionsWithLocalLinkage =
false;
1028 G->IndirectGlobals.clear();
1029 G->AllocsForIndirectGlobals.clear();
1030 G->FunctionInfos.clear();
1031 G->FunctionToSCCMap.clear();
1033 G->CollectSCCMembership(CG);
1034 G->AnalyzeGlobals(M);
1035 G->AnalyzeCallGraph(CG, M);
1042 "Globals Alias Analysis",
false,
true)
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
Expand Atomic instructions
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
This file provides interfaces used to build and manipulate a call graph, which is a very useful tool ...
This file contains the declarations for the subclasses of Constant, which represent the different fla...
static cl::opt< bool > EnableUnsafeGlobalsModRefAliasResults("enable-unsafe-globalsmodref-alias-results", cl::init(false), cl::Hidden)
static bool isNonEscapingGlobalNoAliasWithLoad(const GlobalValue *GV, const Value *V, int &Depth, const DataLayout &DL)
This is the interface for a simple mod/ref and alias analysis over globals.
Value * getPointer(Value *Ptr)
Module.h This file contains the declarations for the Module class.
This header defines various interfaces for pass management in LLVM.
Machine Check Debug Module
uint64_t IntrinsicInst * II
FunctionAnalysisManager FAM
#define INITIALIZE_PASS_DEPENDENCY(depName)
#define INITIALIZE_PASS_END(passName, arg, name, cfg, analysis)
#define INITIALIZE_PASS_BEGIN(passName, arg, name, cfg, analysis)
This builds on the llvm/ADT/GraphTraits.h file to find the strongly connected components (SCCs) of a ...
This file defines the SmallPtrSet class.
This file defines the 'Statistic' class, which is designed to be an easy way to expose various metric...
#define STATISTIC(VARNAME, DESC)
The mod/ref information collected for a particular function.
FunctionInfo & operator=(FunctionInfo &&RHS)
void eraseModRefInfoForGlobal(const GlobalValue &GV)
Clear a global's ModRef info.
void setMayReadAnyGlobal()
Sets this function as potentially reading from any global.
void addModRefInfo(ModRefInfo NewMRI)
Adds new ModRefInfo for this function to its state.
void addFunctionInfo(const FunctionInfo &FI)
Add mod/ref info from another function into ours, saturating towards ModRef.
ModRefInfo getModRefInfo() const
Returns the ModRefInfo info for this function.
FunctionInfo()=default
Checks to document the invariants of the bit packing here.
FunctionInfo & operator=(const FunctionInfo &RHS)
void addModRefInfoForGlobal(const GlobalValue &GV, ModRefInfo NewMRI)
ModRefInfo globalClearMayReadAnyGlobal(int I) const
This method clears MayReadAnyGlobal bit added by GlobalsAAResult to return the corresponding ModRefIn...
bool mayReadAnyGlobal() const
Returns whether this function may read any global variable, and we don't know which global.
FunctionInfo(FunctionInfo &&Arg)
FunctionInfo(const FunctionInfo &Arg)
ModRefInfo getModRefInfoForGlobal(const GlobalValue &GV) const
Returns the ModRefInfo info for this function w.r.t.
This class stores info we want to provide to or retain within an alias query.
The possible results of an alias query.
@ MayAlias
The two locations may or may not alias.
@ NoAlias
The two locations do not alias at all.
PassT::Result * getCachedResult(IRUnitT &IR) const
Get the cached result of an analysis pass for a given IR unit.
PassT::Result & getResult(IRUnitT &IR, ExtraArgTs... ExtraArgs)
Get the result of an analysis pass for a given IR unit.
Represent the analysis usage information of a pass.
AnalysisUsage & addRequired()
void setPreservesAll()
Set by analyses that do not transform their input at all.
Base class for all callable instructions (InvokeInst and CallInst) Holds everything related to callin...
bool doesNotCapture(unsigned OpNo) const
Determine whether this data operand is not captured.
Function * getCalledFunction() const
Returns the function called, or null if this is an indirect function invocation or the function signa...
bool hasFnAttr(Attribute::AttrKind Kind) const
Determine whether this call has the given attribute.
unsigned getArgOperandNo(const Use *U) const
Given a use for a arg operand, get the arg operand number that corresponds to it.
bool isArgOperand(const Use *U) const
bool isDataOperand(const Use *U) const
An analysis pass to compute the CallGraph for a Module.
std::vector< CallRecord >::iterator iterator
The ModulePass which wraps up a CallGraph and the logic to build it.
The basic data container for the call graph of a Module of IR.
A parsed version of the target data layout string in and methods for querying it.
bool hasLocalLinkage() const
const Constant * getInitializer() const
getInitializer - Return the initializer for this global variable.
An alias analysis result set for globals.
LLVM_ABI ~GlobalsAAResult()
LLVM_ABI ModRefInfo getModRefInfo(const CallBase *Call, const MemoryLocation &Loc, AAQueryInfo &AAQI)
LLVM_ABI bool invalidate(Module &M, const PreservedAnalyses &PA, ModuleAnalysisManager::Invalidator &)
static LLVM_ABI GlobalsAAResult analyzeModule(Module &M, std::function< const TargetLibraryInfo &(Function &F)> GetTLI, CallGraph &CG)
LLVM_ABI MemoryEffects getMemoryEffects(const Function *F)
getMemoryEffects - Return the behavior of the specified function if called from the specified call si...
LLVM_ABI AliasResult alias(const MemoryLocation &LocA, const MemoryLocation &LocB, AAQueryInfo &AAQI, const Instruction *CtxI)
alias - If one of the pointers is to a global that we are tracking, and the other is some random poin...
Legacy wrapper pass to provide the GlobalsAAResult object.
void getAnalysisUsage(AnalysisUsage &AU) const override
getAnalysisUsage - This function should be overriden by passes that need analysis information to do t...
bool runOnModule(Module &M) override
runOnModule - Virtual method overriden by subclasses to process the module being operated on.
bool doFinalization(Module &M) override
doFinalization - Virtual method overriden by subclasses to do any necessary clean up after all passes...
Analysis pass providing a never-invalidated alias analysis result.
LLVM_ABI GlobalsAAResult run(Module &M, ModuleAnalysisManager &AM)
LLVM_ABI const Function * getFunction() const
Return the function this instruction belongs to.
An instruction for reading from memory.
static MemoryEffectsBase unknown()
Representation for a specific memory location.
static MemoryLocation getBeforeOrAfter(const Value *Ptr, const AAMDNodes &AATags=AAMDNodes())
Return a location that may access any location before or after Ptr, while remaining within the underl...
const Value * Ptr
The address of the start of the location.
ModulePass class - This class is used to implement unstructured interprocedural optimizations and ana...
A Module instance is used to store all the information related to an LLVM module.
unsigned getOpcode() const
Return the opcode for this Instruction or ConstantExpr.
AnalysisType & getAnalysis() const
getAnalysis<AnalysisType>() - This function is used by subclasses to get to the analysis information ...
PointerIntPair - This class implements a pair of a pointer and small integer.
void setPointerAndInt(PointerTy PtrVal, IntType IntVal) &
PointerTy getPointer() const
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.
PreservedAnalysisChecker getChecker() const
Build a checker for this PreservedAnalyses and the specified analysis type.
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.
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 TargetLibraryInfo.
Provides information about what library functions are available for the current target.
bool isSized(SmallPtrSetImpl< Type * > *Visited=nullptr) const
Return true if it makes sense to take the size of this type.
Value * getValPtr() const
LLVM Value Representation.
iterator_range< user_iterator > users()
LLVM_ABI const Value * stripPointerCastsForAliasAnalysis() const
Strip off pointer casts, all-zero GEPs, single-argument phi nodes and invariant group info.
const ParentTy * getParent() const
@ C
The default llvm calling convention, compatible with C.
initializer< Ty > init(const Ty &Val)
@ User
could "use" a pointer
NodeAddr< NodeBase * > Node
LLVM_ABI iterator begin() const
This is an optimization pass for GlobalISel generic memory operations.
FunctionAddr VTableAddr Value
bool all_of(R &&range, UnaryPredicate P)
Provide wrappers to std::all_of which take ranges instead of having to pass begin/end explicitly.
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
scc_iterator< T > scc_begin(const T &G)
Construct the begin iterator for a deduced graph type T.
InnerAnalysisManagerProxy< FunctionAnalysisManager, Module > FunctionAnalysisManagerModuleProxy
Provide the FunctionAnalysisManager to Module proxy.
LLVM_ABI bool isNoAliasCall(const Value *V)
Return true if this pointer is returned by a noalias function.
MemoryEffectsBase< IRMemLocation > MemoryEffects
Summary of how a function affects memory in the program.
LLVM_ABI ModulePass * createGlobalsAAWrapperPass()
bool isModSet(const ModRefInfo MRI)
LLVM_ABI bool NullPointerIsDefined(const Function *F, unsigned AS=0)
Check whether null pointer dereferencing is considered undefined behavior for a given function or an ...
bool isModOrRefSet(const ModRefInfo MRI)
bool isa(const From &Val)
isa<X> - Return true if the parameter to the template is an instance of one of the template type argu...
ModRefInfo
Flags indicating whether a memory access modifies or references memory.
@ Ref
The access may reference the value stored in memory.
@ ModRef
The access may reference and may modify the value stored in memory.
@ Mod
The access may modify the value stored in memory.
@ NoModRef
The access neither references nor modifies the value stored in memory.
DWARFExpression::Operation Op
LLVM_ABI Value * getFreedOperand(const CallBase *CB, const TargetLibraryInfo *TLI)
If this if a call to a free function, return the freed operand.
bool isModAndRefSet(const ModRefInfo MRI)
OutputIt move(R &&Range, OutputIt Out)
Provide wrappers to std::move which take ranges instead of having to pass begin/end explicitly.
bool is_contained(R &&Range, const E &Element)
Returns true if Element is found in Range.
AnalysisManager< Function > FunctionAnalysisManager
Convenience typedef for the Function analysis manager.
LLVM_ABI const Value * getUnderlyingObject(const Value *V, unsigned MaxLookup=MaxLookupSearchDepth)
This method strips off any GEP address adjustments, pointer casts or llvm.threadlocal....
LLVM_ABI void getUnderlyingObjects(const Value *V, SmallVectorImpl< const Value * > &Objects, const LoopInfo *LI=nullptr, unsigned MaxLookup=MaxLookupSearchDepth)
This method is similar to getUnderlyingObject except that it can look through phi and select instruct...
LLVM_ABI bool isIdentifiedObject(const Value *V)
Return true if this pointer refers to a distinct and identifiable object.
AnalysisManager< Module > ModuleAnalysisManager
Convenience typedef for the Module analysis manager.
Implement std::hash so that hash_code can be used in STL containers.
A special type used by analysis passes to provide an address that identifies that particular analysis...
LLVM_ABI PreservedAnalyses run(Module &M, ModuleAnalysisManager &AM)