diff options
author | Dimitry Andric <dim@FreeBSD.org> | 2023-02-11 12:38:04 +0000 |
---|---|---|
committer | Dimitry Andric <dim@FreeBSD.org> | 2023-02-11 12:38:11 +0000 |
commit | e3b557809604d036af6e00c60f012c2025b59a5e (patch) | |
tree | 8a11ba2269a3b669601e2fd41145b174008f4da8 /llvm/lib/Analysis/GlobalsModRef.cpp | |
parent | 08e8dd7b9db7bb4a9de26d44c1cbfd24e869c014 (diff) |
Diffstat (limited to 'llvm/lib/Analysis/GlobalsModRef.cpp')
-rw-r--r-- | llvm/lib/Analysis/GlobalsModRef.cpp | 93 |
1 files changed, 45 insertions, 48 deletions
diff --git a/llvm/lib/Analysis/GlobalsModRef.cpp b/llvm/lib/Analysis/GlobalsModRef.cpp index e6ef1c78a628..c218b3d511e2 100644 --- a/llvm/lib/Analysis/GlobalsModRef.cpp +++ b/llvm/lib/Analysis/GlobalsModRef.cpp @@ -23,7 +23,6 @@ #include "llvm/Analysis/ValueTracking.h" #include "llvm/IR/InstIterator.h" #include "llvm/IR/Instructions.h" -#include "llvm/IR/IntrinsicInst.h" #include "llvm/IR/Module.h" #include "llvm/IR/PassManager.h" #include "llvm/InitializePasses.h" @@ -87,17 +86,14 @@ class GlobalsAAResult::FunctionInfo { /// The bit that flags that this function may read any global. This is /// chosen to mix together with ModRefInfo bits. /// FIXME: This assumes ModRefInfo lattice will remain 4 bits! - /// It overlaps with ModRefInfo::Must bit! /// FunctionInfo.getModRefInfo() masks out everything except ModRef so - /// this remains correct, but the Must info is lost. + /// this remains correct. enum { MayReadAnyGlobal = 4 }; /// Checks to document the invariants of the bit packing here. - static_assert((MayReadAnyGlobal & static_cast<int>(ModRefInfo::MustModRef)) == - 0, + static_assert((MayReadAnyGlobal & static_cast<int>(ModRefInfo::ModRef)) == 0, "ModRef and the MayReadAnyGlobal flag bits overlap."); - static_assert(((MayReadAnyGlobal | - static_cast<int>(ModRefInfo::MustModRef)) >> + static_assert(((MayReadAnyGlobal | static_cast<int>(ModRefInfo::ModRef)) >> AlignedMapPointerTraits::NumLowBitsAvailable) == 0, "Insufficient low bits to store our flag and ModRef info."); @@ -133,11 +129,9 @@ public: } /// This method clears MayReadAnyGlobal bit added by GlobalsAAResult to return - /// the corresponding ModRefInfo. It must align in functionality with - /// clearMust(). + /// the corresponding ModRefInfo. ModRefInfo globalClearMayReadAnyGlobal(int I) const { - return ModRefInfo((I & static_cast<int>(ModRefInfo::ModRef)) | - static_cast<int>(ModRefInfo::NoModRef)); + return ModRefInfo(I & static_cast<int>(ModRefInfo::ModRef)); } /// Returns the \c ModRefInfo info for this function. @@ -147,7 +141,7 @@ public: /// Adds new \c ModRefInfo for this function to its state. void addModRefInfo(ModRefInfo NewMRI) { - Info.setInt(Info.getInt() | static_cast<int>(setMust(NewMRI))); + Info.setInt(Info.getInt() | static_cast<int>(NewMRI)); } /// Returns whether this function may read any global variable, and we don't @@ -165,7 +159,7 @@ public: if (AlignedMap *P = Info.getPointer()) { auto I = P->Map.find(&GV); if (I != P->Map.end()) - GlobalMRI = unionModRef(GlobalMRI, I->second); + GlobalMRI |= I->second; } return GlobalMRI; } @@ -190,7 +184,7 @@ public: Info.setPointer(P); } auto &GlobalMRI = P->Map[&GV]; - GlobalMRI = unionModRef(GlobalMRI, NewMRI); + GlobalMRI |= NewMRI; } /// Clear a global's ModRef info. Should be used when a global is being @@ -243,17 +237,11 @@ void GlobalsAAResult::DeletionCallbackHandle::deleted() { // This object is now destroyed! } -FunctionModRefBehavior GlobalsAAResult::getModRefBehavior(const Function *F) { - FunctionModRefBehavior Min = FMRB_UnknownModRefBehavior; +MemoryEffects GlobalsAAResult::getMemoryEffects(const Function *F) { + if (FunctionInfo *FI = getFunctionInfo(F)) + return MemoryEffects(FI->getModRefInfo()); - if (FunctionInfo *FI = getFunctionInfo(F)) { - if (!isModOrRefSet(FI->getModRefInfo())) - Min = FMRB_DoesNotAccessMemory; - else if (!isModSet(FI->getModRefInfo())) - Min = FMRB_OnlyReadsMemory; - } - - return FunctionModRefBehavior(AAResultBase::getModRefBehavior(F) & Min); + return AAResultBase::getMemoryEffects(F); } /// Returns the function info for the function, or null if we don't have @@ -365,7 +353,31 @@ bool GlobalsAAResult::AnalyzeUsesOfPointer(Value *V, if (Writers) Writers->insert(Call->getParent()->getParent()); } else { - return true; // Argument of an unknown call. + // In general, we return true for unknown calls, but there are + // some simple checks that we can do for functions that + // will never call back into the module. + auto *F = Call->getCalledFunction(); + // TODO: we should be able to remove isDeclaration() check + // and let the function body analysis check for captures, + // and collect the mod-ref effects. This information will + // be later propagated via the call graph. + if (!F || !F->isDeclaration()) + return true; + // Note that the NoCallback check here is a little bit too + // conservative. If there are no captures of the global + // in the module, then this call may not be a capture even + // if it does not have NoCallback. + if (!Call->hasFnAttr(Attribute::NoCallback) || + !Call->isArgOperand(&U) || + !Call->doesNotCapture(Call->getArgOperandNo(&U))) + return true; + + // Conservatively, assume the call reads and writes the global. + // We could use memory attributes to make it more precise. + if (Readers) + Readers->insert(Call->getParent()->getParent()); + if (Writers) + Writers->insert(Call->getParent()->getParent()); } } } else if (ICmpInst *ICI = dyn_cast<ICmpInst>(I)) { @@ -580,21 +592,8 @@ void GlobalsAAResult::AnalyzeCallGraph(CallGraph &CG, Module &M) { // We handle calls specially because the graph-relevant aspects are // handled above. - if (auto *Call = dyn_cast<CallBase>(&I)) { - if (Function *Callee = Call->getCalledFunction()) { - // The callgraph doesn't include intrinsic calls. - if (Callee->isIntrinsic()) { - if (isa<DbgInfoIntrinsic>(Call)) - // Don't let dbg intrinsics affect alias info. - continue; - - FunctionModRefBehavior Behaviour = - AAResultBase::getModRefBehavior(Callee); - FI.addModRefInfo(createModRefInfo(Behaviour)); - } - } + if (isa<CallBase>(&I)) continue; - } // All non-call instructions we use the primary predicates for whether // they read or write memory. @@ -816,7 +815,7 @@ bool GlobalsAAResult::invalidate(Module &, const PreservedAnalyses &PA, /// address of the global isn't taken. AliasResult GlobalsAAResult::alias(const MemoryLocation &LocA, const MemoryLocation &LocB, - AAQueryInfo &AAQI) { + AAQueryInfo &AAQI, const Instruction *) { // Get the base object these pointers point to. const Value *UV1 = getUnderlyingObject(LocA.Ptr->stripPointerCastsForAliasAnalysis()); @@ -893,7 +892,7 @@ AliasResult GlobalsAAResult::alias(const MemoryLocation &LocA, if ((GV1 || GV2) && GV1 != GV2) return AliasResult::NoAlias; - return AAResultBase::alias(LocA, LocB, AAQI); + return AAResultBase::alias(LocA, LocB, AAQI, nullptr); } ModRefInfo GlobalsAAResult::getModRefInfoForArgument(const CallBase *Call, @@ -915,8 +914,8 @@ ModRefInfo GlobalsAAResult::getModRefInfoForArgument(const CallBase *Call, // Try ::alias to see if all objects are known not to alias GV. !all_of(Objects, [&](const Value *V) { return this->alias(MemoryLocation::getBeforeOrAfter(V), - MemoryLocation::getBeforeOrAfter(GV), - AAQI) == AliasResult::NoAlias; + MemoryLocation::getBeforeOrAfter(GV), AAQI, + nullptr) == AliasResult::NoAlias; })) return ConservativeResult; @@ -943,12 +942,10 @@ ModRefInfo GlobalsAAResult::getModRefInfo(const CallBase *Call, if (const Function *F = Call->getCalledFunction()) if (NonAddressTakenGlobals.count(GV)) if (const FunctionInfo *FI = getFunctionInfo(F)) - Known = unionModRef(FI->getModRefInfoForGlobal(*GV), - getModRefInfoForArgument(Call, GV, AAQI)); + Known = FI->getModRefInfoForGlobal(*GV) | + getModRefInfoForArgument(Call, GV, AAQI); - if (!isModOrRefSet(Known)) - return ModRefInfo::NoModRef; // No need to query other mod/ref analyses - return intersectModRef(Known, AAResultBase::getModRefInfo(Call, Loc, AAQI)); + return Known; } GlobalsAAResult::GlobalsAAResult( |