aboutsummaryrefslogtreecommitdiff
path: root/llvm/lib/Analysis/GlobalsModRef.cpp
diff options
context:
space:
mode:
authorDimitry Andric <dim@FreeBSD.org>2023-02-11 12:38:04 +0000
committerDimitry Andric <dim@FreeBSD.org>2023-02-11 12:38:11 +0000
commite3b557809604d036af6e00c60f012c2025b59a5e (patch)
tree8a11ba2269a3b669601e2fd41145b174008f4da8 /llvm/lib/Analysis/GlobalsModRef.cpp
parent08e8dd7b9db7bb4a9de26d44c1cbfd24e869c014 (diff)
Diffstat (limited to 'llvm/lib/Analysis/GlobalsModRef.cpp')
-rw-r--r--llvm/lib/Analysis/GlobalsModRef.cpp93
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(