summaryrefslogtreecommitdiffstats
path: root/llvm/lib/Analysis
diff options
context:
space:
mode:
Diffstat (limited to 'llvm/lib/Analysis')
-rw-r--r--llvm/lib/Analysis/AliasAnalysis.cpp441
-rw-r--r--llvm/lib/Analysis/AliasAnalysisCounter.cpp165
-rw-r--r--llvm/lib/Analysis/AliasAnalysisEvaluator.cpp6
-rw-r--r--llvm/lib/Analysis/AliasSetTracker.cpp7
-rw-r--r--llvm/lib/Analysis/Analysis.cpp18
-rw-r--r--llvm/lib/Analysis/BasicAliasAnalysis.cpp276
-rw-r--r--llvm/lib/Analysis/CFLAliasAnalysis.cpp107
-rw-r--r--llvm/lib/Analysis/CMakeLists.txt2
-rw-r--r--llvm/lib/Analysis/DependenceAnalysis.cpp6
-rw-r--r--llvm/lib/Analysis/GlobalsModRef.cpp170
-rw-r--r--llvm/lib/Analysis/Lint.cpp6
-rw-r--r--llvm/lib/Analysis/LoopAccessAnalysis.cpp6
-rw-r--r--llvm/lib/Analysis/MemDepPrinter.cpp2
-rw-r--r--llvm/lib/Analysis/MemoryDependenceAnalysis.cpp6
-rw-r--r--llvm/lib/Analysis/NoAliasAnalysis.cpp92
-rw-r--r--llvm/lib/Analysis/ObjCARCAliasAnalysis.cpp112
-rw-r--r--llvm/lib/Analysis/ScalarEvolutionAliasAnalysis.cpp135
-rw-r--r--llvm/lib/Analysis/ScopedNoAliasAA.cpp150
-rw-r--r--llvm/lib/Analysis/TypeBasedAliasAnalysis.cpp322
19 files changed, 946 insertions, 1083 deletions
diff --git a/llvm/lib/Analysis/AliasAnalysis.cpp b/llvm/lib/Analysis/AliasAnalysis.cpp
index 4d4a30290f4..26ab74bbb4e 100644
--- a/llvm/lib/Analysis/AliasAnalysis.cpp
+++ b/llvm/lib/Analysis/AliasAnalysis.cpp
@@ -25,9 +25,16 @@
//===----------------------------------------------------------------------===//
#include "llvm/Analysis/AliasAnalysis.h"
+#include "llvm/Analysis/BasicAliasAnalysis.h"
#include "llvm/Analysis/CFG.h"
+#include "llvm/Analysis/CFLAliasAnalysis.h"
#include "llvm/Analysis/CaptureTracking.h"
+#include "llvm/Analysis/GlobalsModRef.h"
+#include "llvm/Analysis/ObjCARCAliasAnalysis.h"
+#include "llvm/Analysis/ScalarEvolutionAliasAnalysis.h"
+#include "llvm/Analysis/ScopedNoAliasAA.h"
#include "llvm/Analysis/TargetLibraryInfo.h"
+#include "llvm/Analysis/TypeBasedAliasAnalysis.h"
#include "llvm/Analysis/ValueTracking.h"
#include "llvm/IR/BasicBlock.h"
#include "llvm/IR/DataLayout.h"
@@ -40,34 +47,72 @@
#include "llvm/Pass.h"
using namespace llvm;
-// Register the AliasAnalysis interface, providing a nice name to refer to.
-INITIALIZE_ANALYSIS_GROUP(AliasAnalysis, "Alias Analysis", NoAA)
-char AliasAnalysis::ID = 0;
+/// Allow disabling BasicAA from the AA results. This is particularly useful
+/// when testing to isolate a single AA implementation.
+static cl::opt<bool> DisableBasicAA("disable-basicaa", cl::Hidden,
+ cl::init(false));
+
+AAResults::AAResults(AAResults &&Arg) : AAs(std::move(Arg.AAs)) {
+ for (auto &AA : AAs)
+ AA->setAAResults(this);
+}
+
+AAResults &AAResults::operator=(AAResults &&Arg) {
+ AAs = std::move(Arg.AAs);
+ for (auto &AA : AAs)
+ AA->setAAResults(this);
+ return *this;
+}
+
+AAResults::~AAResults() {
+// FIXME; It would be nice to at least clear out the pointers back to this
+// aggregation here, but we end up with non-nesting lifetimes in the legacy
+// pass manager that prevent this from working. In the legacy pass manager
+// we'll end up with dangling references here in some cases.
+#if 0
+ for (auto &AA : AAs)
+ AA->setAAResults(nullptr);
+#endif
+}
//===----------------------------------------------------------------------===//
// Default chaining methods
//===----------------------------------------------------------------------===//
-AliasResult AliasAnalysis::alias(const MemoryLocation &LocA,
- const MemoryLocation &LocB) {
- assert(AA && "AA didn't call InitializeAliasAnalysis in its run method!");
- return AA->alias(LocA, LocB);
+AliasResult AAResults::alias(const MemoryLocation &LocA,
+ const MemoryLocation &LocB) {
+ for (const auto &AA : AAs) {
+ auto Result = AA->alias(LocA, LocB);
+ if (Result != MayAlias)
+ return Result;
+ }
+ return MayAlias;
}
-bool AliasAnalysis::pointsToConstantMemory(const MemoryLocation &Loc,
- bool OrLocal) {
- assert(AA && "AA didn't call InitializeAliasAnalysis in its run method!");
- return AA->pointsToConstantMemory(Loc, OrLocal);
+bool AAResults::pointsToConstantMemory(const MemoryLocation &Loc,
+ bool OrLocal) {
+ for (const auto &AA : AAs)
+ if (AA->pointsToConstantMemory(Loc, OrLocal))
+ return true;
+
+ return false;
}
-ModRefInfo AliasAnalysis::getArgModRefInfo(ImmutableCallSite CS,
- unsigned ArgIdx) {
- assert(AA && "AA didn't call InitializeAliasAnalysis in its run method!");
- return AA->getArgModRefInfo(CS, ArgIdx);
+ModRefInfo AAResults::getArgModRefInfo(ImmutableCallSite CS, unsigned ArgIdx) {
+ ModRefInfo Result = MRI_ModRef;
+
+ for (const auto &AA : AAs) {
+ Result = ModRefInfo(Result & AA->getArgModRefInfo(CS, ArgIdx));
+
+ // Early-exit the moment we reach the bottom of the lattice.
+ if (Result == MRI_NoModRef)
+ return Result;
+ }
+
+ return Result;
}
-ModRefInfo AliasAnalysis::getModRefInfo(Instruction *I,
- ImmutableCallSite Call) {
+ModRefInfo AAResults::getModRefInfo(Instruction *I, ImmutableCallSite Call) {
// We may have two calls
if (auto CS = ImmutableCallSite(I)) {
// Check if the two calls modify the same memory
@@ -84,177 +129,70 @@ ModRefInfo AliasAnalysis::getModRefInfo(Instruction *I,
return MRI_NoModRef;
}
-ModRefInfo AliasAnalysis::getModRefInfo(ImmutableCallSite CS,
- const MemoryLocation &Loc) {
- assert(AA && "AA didn't call InitializeAliasAnalysis in its run method!");
+ModRefInfo AAResults::getModRefInfo(ImmutableCallSite CS,
+ const MemoryLocation &Loc) {
+ ModRefInfo Result = MRI_ModRef;
- auto MRB = getModRefBehavior(CS);
- if (MRB == FMRB_DoesNotAccessMemory)
- return MRI_NoModRef;
+ for (const auto &AA : AAs) {
+ Result = ModRefInfo(Result & AA->getModRefInfo(CS, Loc));
- ModRefInfo Mask = MRI_ModRef;
- if (onlyReadsMemory(MRB))
- Mask = MRI_Ref;
-
- if (onlyAccessesArgPointees(MRB)) {
- bool doesAlias = false;
- ModRefInfo AllArgsMask = MRI_NoModRef;
- if (doesAccessArgPointees(MRB)) {
- for (ImmutableCallSite::arg_iterator AI = CS.arg_begin(), AE = CS.arg_end();
- AI != AE; ++AI) {
- const Value *Arg = *AI;
- if (!Arg->getType()->isPointerTy())
- continue;
- unsigned ArgIdx = std::distance(CS.arg_begin(), AI);
- MemoryLocation ArgLoc =
- MemoryLocation::getForArgument(CS, ArgIdx, *TLI);
- if (!isNoAlias(ArgLoc, Loc)) {
- ModRefInfo ArgMask = getArgModRefInfo(CS, ArgIdx);
- doesAlias = true;
- AllArgsMask = ModRefInfo(AllArgsMask | ArgMask);
- }
- }
- }
- if (!doesAlias)
- return MRI_NoModRef;
- Mask = ModRefInfo(Mask & AllArgsMask);
+ // Early-exit the moment we reach the bottom of the lattice.
+ if (Result == MRI_NoModRef)
+ return Result;
}
- // If Loc is a constant memory location, the call definitely could not
- // modify the memory location.
- if ((Mask & MRI_Mod) && pointsToConstantMemory(Loc))
- Mask = ModRefInfo(Mask & ~MRI_Mod);
-
- // If this is the end of the chain, don't forward.
- if (!AA) return Mask;
-
- // Otherwise, fall back to the next AA in the chain. But we can merge
- // in any mask we've managed to compute.
- return ModRefInfo(AA->getModRefInfo(CS, Loc) & Mask);
+ return Result;
}
-ModRefInfo AliasAnalysis::getModRefInfo(ImmutableCallSite CS1,
- ImmutableCallSite CS2) {
- assert(AA && "AA didn't call InitializeAliasAnalysis in its run method!");
+ModRefInfo AAResults::getModRefInfo(ImmutableCallSite CS1,
+ ImmutableCallSite CS2) {
+ ModRefInfo Result = MRI_ModRef;
- // If CS1 or CS2 are readnone, they don't interact.
- auto CS1B = getModRefBehavior(CS1);
- if (CS1B == FMRB_DoesNotAccessMemory)
- return MRI_NoModRef;
+ for (const auto &AA : AAs) {
+ Result = ModRefInfo(Result & AA->getModRefInfo(CS1, CS2));
- auto CS2B = getModRefBehavior(CS2);
- if (CS2B == FMRB_DoesNotAccessMemory)
- return MRI_NoModRef;
-
- // If they both only read from memory, there is no dependence.
- if (onlyReadsMemory(CS1B) && onlyReadsMemory(CS2B))
- return MRI_NoModRef;
-
- ModRefInfo Mask = MRI_ModRef;
-
- // If CS1 only reads memory, the only dependence on CS2 can be
- // from CS1 reading memory written by CS2.
- if (onlyReadsMemory(CS1B))
- Mask = ModRefInfo(Mask & MRI_Ref);
-
- // If CS2 only access memory through arguments, accumulate the mod/ref
- // information from CS1's references to the memory referenced by
- // CS2's arguments.
- if (onlyAccessesArgPointees(CS2B)) {
- ModRefInfo R = MRI_NoModRef;
- if (doesAccessArgPointees(CS2B)) {
- for (ImmutableCallSite::arg_iterator
- I = CS2.arg_begin(), E = CS2.arg_end(); I != E; ++I) {
- const Value *Arg = *I;
- if (!Arg->getType()->isPointerTy())
- continue;
- unsigned CS2ArgIdx = std::distance(CS2.arg_begin(), I);
- auto CS2ArgLoc = MemoryLocation::getForArgument(CS2, CS2ArgIdx, *TLI);
-
- // ArgMask indicates what CS2 might do to CS2ArgLoc, and the dependence of
- // CS1 on that location is the inverse.
- ModRefInfo ArgMask = getArgModRefInfo(CS2, CS2ArgIdx);
- if (ArgMask == MRI_Mod)
- ArgMask = MRI_ModRef;
- else if (ArgMask == MRI_Ref)
- ArgMask = MRI_Mod;
-
- R = ModRefInfo((R | (getModRefInfo(CS1, CS2ArgLoc) & ArgMask)) & Mask);
- if (R == Mask)
- break;
- }
- }
- return R;
+ // Early-exit the moment we reach the bottom of the lattice.
+ if (Result == MRI_NoModRef)
+ return Result;
}
- // If CS1 only accesses memory through arguments, check if CS2 references
- // any of the memory referenced by CS1's arguments. If not, return NoModRef.
- if (onlyAccessesArgPointees(CS1B)) {
- ModRefInfo R = MRI_NoModRef;
- if (doesAccessArgPointees(CS1B)) {
- for (ImmutableCallSite::arg_iterator
- I = CS1.arg_begin(), E = CS1.arg_end(); I != E; ++I) {
- const Value *Arg = *I;
- if (!Arg->getType()->isPointerTy())
- continue;
- unsigned CS1ArgIdx = std::distance(CS1.arg_begin(), I);
- auto CS1ArgLoc = MemoryLocation::getForArgument(CS1, CS1ArgIdx, *TLI);
-
- // ArgMask indicates what CS1 might do to CS1ArgLoc; if CS1 might Mod
- // CS1ArgLoc, then we care about either a Mod or a Ref by CS2. If CS1
- // might Ref, then we care only about a Mod by CS2.
- ModRefInfo ArgMask = getArgModRefInfo(CS1, CS1ArgIdx);
- ModRefInfo ArgR = getModRefInfo(CS2, CS1ArgLoc);
- if (((ArgMask & MRI_Mod) != MRI_NoModRef &&
- (ArgR & MRI_ModRef) != MRI_NoModRef) ||
- ((ArgMask & MRI_Ref) != MRI_NoModRef &&
- (ArgR & MRI_Mod) != MRI_NoModRef))
- R = ModRefInfo((R | ArgMask) & Mask);
-
- if (R == Mask)
- break;
- }
- }
- return R;
- }
+ return Result;
+}
- // If this is the end of the chain, don't forward.
- if (!AA) return Mask;
+FunctionModRefBehavior AAResults::getModRefBehavior(ImmutableCallSite CS) {
+ FunctionModRefBehavior Result = FMRB_UnknownModRefBehavior;
- // Otherwise, fall back to the next AA in the chain. But we can merge
- // in any mask we've managed to compute.
- return ModRefInfo(AA->getModRefInfo(CS1, CS2) & Mask);
-}
+ for (const auto &AA : AAs) {
+ Result = FunctionModRefBehavior(Result & AA->getModRefBehavior(CS));
-FunctionModRefBehavior AliasAnalysis::getModRefBehavior(ImmutableCallSite CS) {
- assert(AA && "AA didn't call InitializeAliasAnalysis in its run method!");
+ // Early-exit the moment we reach the bottom of the lattice.
+ if (Result == FMRB_DoesNotAccessMemory)
+ return Result;
+ }
- auto Min = FMRB_UnknownModRefBehavior;
+ return Result;
+}
- // Call back into the alias analysis with the other form of getModRefBehavior
- // to see if it can give a better response.
- if (const Function *F = CS.getCalledFunction())
- Min = getModRefBehavior(F);
+FunctionModRefBehavior AAResults::getModRefBehavior(const Function *F) {
+ FunctionModRefBehavior Result = FMRB_UnknownModRefBehavior;
- // If this is the end of the chain, don't forward.
- if (!AA) return Min;
+ for (const auto &AA : AAs) {
+ Result = FunctionModRefBehavior(Result & AA->getModRefBehavior(F));
- // Otherwise, fall back to the next AA in the chain. But we can merge
- // in any result we've managed to compute.
- return FunctionModRefBehavior(AA->getModRefBehavior(CS) & Min);
-}
+ // Early-exit the moment we reach the bottom of the lattice.
+ if (Result == FMRB_DoesNotAccessMemory)
+ return Result;
+ }
-FunctionModRefBehavior AliasAnalysis::getModRefBehavior(const Function *F) {
- assert(AA && "AA didn't call InitializeAliasAnalysis in its run method!");
- return AA->getModRefBehavior(F);
+ return Result;
}
//===----------------------------------------------------------------------===//
-// AliasAnalysis non-virtual helper method implementation
+// Helper method implementation
//===----------------------------------------------------------------------===//
-ModRefInfo AliasAnalysis::getModRefInfo(const LoadInst *L,
- const MemoryLocation &Loc) {
+ModRefInfo AAResults::getModRefInfo(const LoadInst *L,
+ const MemoryLocation &Loc) {
// Be conservative in the face of volatile/atomic.
if (!L->isUnordered())
return MRI_ModRef;
@@ -268,8 +206,8 @@ ModRefInfo AliasAnalysis::getModRefInfo(const LoadInst *L,
return MRI_Ref;
}
-ModRefInfo AliasAnalysis::getModRefInfo(const StoreInst *S,
- const MemoryLocation &Loc) {
+ModRefInfo AAResults::getModRefInfo(const StoreInst *S,
+ const MemoryLocation &Loc) {
// Be conservative in the face of volatile/atomic.
if (!S->isUnordered())
return MRI_ModRef;
@@ -290,8 +228,8 @@ ModRefInfo AliasAnalysis::getModRefInfo(const StoreInst *S,
return MRI_Mod;
}
-ModRefInfo AliasAnalysis::getModRefInfo(const VAArgInst *V,
- const MemoryLocation &Loc) {
+ModRefInfo AAResults::getModRefInfo(const VAArgInst *V,
+ const MemoryLocation &Loc) {
if (Loc.Ptr) {
// If the va_arg address cannot alias the pointer in question, then the
@@ -309,8 +247,8 @@ ModRefInfo AliasAnalysis::getModRefInfo(const VAArgInst *V,
return MRI_ModRef;
}
-ModRefInfo AliasAnalysis::getModRefInfo(const AtomicCmpXchgInst *CX,
- const MemoryLocation &Loc) {
+ModRefInfo AAResults::getModRefInfo(const AtomicCmpXchgInst *CX,
+ const MemoryLocation &Loc) {
// Acquire/Release cmpxchg has properties that matter for arbitrary addresses.
if (CX->getSuccessOrdering() > Monotonic)
return MRI_ModRef;
@@ -322,8 +260,8 @@ ModRefInfo AliasAnalysis::getModRefInfo(const AtomicCmpXchgInst *CX,
return MRI_ModRef;
}
-ModRefInfo AliasAnalysis::getModRefInfo(const AtomicRMWInst *RMW,
- const MemoryLocation &Loc) {
+ModRefInfo AAResults::getModRefInfo(const AtomicRMWInst *RMW,
+ const MemoryLocation &Loc) {
// Acquire/Release atomicrmw has properties that matter for arbitrary addresses.
if (RMW->getOrdering() > Monotonic)
return MRI_ModRef;
@@ -343,14 +281,15 @@ ModRefInfo AliasAnalysis::getModRefInfo(const AtomicRMWInst *RMW,
/// BasicAA isn't willing to spend linear time determining whether an alloca
/// was captured before or after this particular call, while we are. However,
/// with a smarter AA in place, this test is just wasting compile time.
-ModRefInfo AliasAnalysis::callCapturesBefore(const Instruction *I,
- const MemoryLocation &MemLoc,
- DominatorTree *DT,
- OrderedBasicBlock *OBB) {
+ModRefInfo AAResults::callCapturesBefore(const Instruction *I,
+ const MemoryLocation &MemLoc,
+ DominatorTree *DT,
+ OrderedBasicBlock *OBB) {
if (!DT)
return MRI_ModRef;
- const Value *Object = GetUnderlyingObject(MemLoc.Ptr, *DL);
+ const Value *Object =
+ GetUnderlyingObject(MemLoc.Ptr, I->getModule()->getDataLayout());
if (!isIdentifiedObject(Object) || isa<GlobalValue>(Object) ||
isa<Constant>(Object))
return MRI_ModRef;
@@ -393,34 +332,11 @@ ModRefInfo AliasAnalysis::callCapturesBefore(const Instruction *I,
return R;
}
-// AliasAnalysis destructor: DO NOT move this to the header file for
-// AliasAnalysis or else clients of the AliasAnalysis class may not depend on
-// the AliasAnalysis.o file in the current .a file, causing alias analysis
-// support to not be included in the tool correctly!
-//
-AliasAnalysis::~AliasAnalysis() {}
-
-/// InitializeAliasAnalysis - Subclasses must call this method to initialize the
-/// AliasAnalysis interface before any other methods are called.
-///
-void AliasAnalysis::InitializeAliasAnalysis(Pass *P, const DataLayout *NewDL) {
- DL = NewDL;
- auto *TLIP = P->getAnalysisIfAvailable<TargetLibraryInfoWrapperPass>();
- TLI = TLIP ? &TLIP->getTLI() : nullptr;
- AA = &P->getAnalysis<AliasAnalysis>();
-}
-
-// getAnalysisUsage - All alias analysis implementations should invoke this
-// directly (using AliasAnalysis::getAnalysisUsage(AU)).
-void AliasAnalysis::getAnalysisUsage(AnalysisUsage &AU) const {
- AU.addRequired<AliasAnalysis>(); // All AA's chain
-}
-
/// canBasicBlockModify - Return true if it is possible for execution of the
/// specified basic block to modify the location Loc.
///
-bool AliasAnalysis::canBasicBlockModify(const BasicBlock &BB,
- const MemoryLocation &Loc) {
+bool AAResults::canBasicBlockModify(const BasicBlock &BB,
+ const MemoryLocation &Loc) {
return canInstructionRangeModRef(BB.front(), BB.back(), Loc, MRI_Mod);
}
@@ -429,10 +345,10 @@ bool AliasAnalysis::canBasicBlockModify(const BasicBlock &BB,
/// mode) the location Loc. The instructions to consider are all
/// of the instructions in the range of [I1,I2] INCLUSIVE.
/// I1 and I2 must be in the same basic block.
-bool AliasAnalysis::canInstructionRangeModRef(const Instruction &I1,
- const Instruction &I2,
- const MemoryLocation &Loc,
- const ModRefInfo Mode) {
+bool AAResults::canInstructionRangeModRef(const Instruction &I1,
+ const Instruction &I2,
+ const MemoryLocation &Loc,
+ const ModRefInfo Mode) {
assert(I1.getParent() == I2.getParent() &&
"Instructions not in same basic block!");
BasicBlock::const_iterator I = &I1;
@@ -445,6 +361,117 @@ bool AliasAnalysis::canInstructionRangeModRef(const Instruction &I1,
return false;
}
+// Provide a definition for the root virtual destructor.
+AAResults::Concept::~Concept() {}
+
+AAResultsWrapperPass::AAResultsWrapperPass() : FunctionPass(ID) {
+ initializeAAResultsWrapperPassPass(*PassRegistry::getPassRegistry());
+}
+
+char AAResultsWrapperPass::ID = 0;
+
+INITIALIZE_PASS_BEGIN(AAResultsWrapperPass, "aa",
+ "Function Alias Analysis Results", false, true)
+INITIALIZE_PASS_DEPENDENCY(BasicAAWrapperPass)
+INITIALIZE_PASS_DEPENDENCY(CFLAAWrapperPass)
+INITIALIZE_PASS_DEPENDENCY(GlobalsAAWrapperPass)
+INITIALIZE_PASS_DEPENDENCY(ObjCARCAAWrapperPass)
+INITIALIZE_PASS_DEPENDENCY(SCEVAAWrapperPass)
+INITIALIZE_PASS_DEPENDENCY(ScopedNoAliasAAWrapperPass)
+INITIALIZE_PASS_DEPENDENCY(TypeBasedAAWrapperPass)
+INITIALIZE_PASS_END(AAResultsWrapperPass, "aa",
+ "Function Alias Analysis Results", false, true)
+
+FunctionPass *llvm::createAAResultsWrapperPass() {
+ return new AAResultsWrapperPass();
+}
+
+/// Run the wrapper pass to rebuild an aggregation over known AA passes.
+///
+/// This is the legacy pass manager's interface to the new-style AA results
+/// aggregation object. Because this is somewhat shoe-horned into the legacy
+/// pass manager, we hard code all the specific alias analyses available into
+/// it. While the particular set enabled is configured via commandline flags,
+/// adding a new alias analysis to LLVM will require adding support for it to
+/// this list.
+bool AAResultsWrapperPass::runOnFunction(Function &F) {
+ // NB! This *must* be reset before adding new AA results to the new
+ // AAResults object because in the legacy pass manager, each instance
+ // of these will refer to the *same* immutable analyses, registering and
+ // unregistering themselves with them. We need to carefully tear down the
+ // previous object first, in this case replacing it with an empty one, before
+ // registering new results.
+ AAR.reset(new AAResults());
+
+ // BasicAA is always available for function analyses. Also, we add it first
+ // so that it can trump TBAA results when it proves MustAlias.
+ // FIXME: TBAA should have an explicit mode to support this and then we
+ // should reconsider the ordering here.
+ if (!DisableBasicAA)
+ AAR->addAAResult(getAnalysis<BasicAAWrapperPass>().getResult());
+
+ // Populate the results with the currently available AAs.
+ if (auto *WrapperPass = getAnalysisIfAvailable<ScopedNoAliasAAWrapperPass>())
+ AAR->addAAResult(WrapperPass->getResult());
+ if (auto *WrapperPass = getAnalysisIfAvailable<TypeBasedAAWrapperPass>())
+ AAR->addAAResult(WrapperPass->getResult());
+ if (auto *WrapperPass =
+ getAnalysisIfAvailable<objcarc::ObjCARCAAWrapperPass>())
+ AAR->addAAResult(WrapperPass->getResult());
+ if (auto *WrapperPass = getAnalysisIfAvailable<GlobalsAAWrapperPass>())
+ AAR->addAAResult(WrapperPass->getResult());
+ if (auto *WrapperPass = getAnalysisIfAvailable<SCEVAAWrapperPass>())
+ AAR->addAAResult(WrapperPass->getResult());
+ if (auto *WrapperPass = getAnalysisIfAvailable<CFLAAWrapperPass>())
+ AAR->addAAResult(WrapperPass->getResult());
+
+ // Analyses don't mutate the IR, so return false.
+ return false;
+}
+
+void AAResultsWrapperPass::getAnalysisUsage(AnalysisUsage &AU) const {
+ AU.setPreservesAll();
+ AU.addRequired<BasicAAWrapperPass>();
+
+ // We also need to mark all the alias analysis passes we will potentially
+ // probe in runOnFunction as used here to ensure the legacy pass manager
+ // preserves them. This hard coding of lists of alias analyses is specific to
+ // the legacy pass manager.
+ AU.addUsedIfAvailable<ScopedNoAliasAAWrapperPass>();
+ AU.addUsedIfAvailable<TypeBasedAAWrapperPass>();
+ AU.addUsedIfAvailable<objcarc::ObjCARCAAWrapperPass>();
+ AU.addUsedIfAvailable<GlobalsAAWrapperPass>();
+ AU.addUsedIfAvailable<SCEVAAWrapperPass>();
+ AU.addUsedIfAvailable<CFLAAWrapperPass>();
+}
+
+AAResults llvm::createLegacyPMAAResults(Pass &P, Function &F,
+ BasicAAResult &BAR) {
+ AAResults AAR;
+
+ // Add in our explicitly constructed BasicAA results.
+ if (!DisableBasicAA)
+ AAR.addAAResult(BAR);
+
+ // Populate the results with the other currently available AAs.
+ if (auto *WrapperPass =
+ P.getAnalysisIfAvailable<ScopedNoAliasAAWrapperPass>())
+ AAR.addAAResult(WrapperPass->getResult());
+ if (auto *WrapperPass = P.getAnalysisIfAvailable<TypeBasedAAWrapperPass>())
+ AAR.addAAResult(WrapperPass->getResult());
+ if (auto *WrapperPass =
+ P.getAnalysisIfAvailable<objcarc::ObjCARCAAWrapperPass>())
+ AAR.addAAResult(WrapperPass->getResult());
+ if (auto *WrapperPass = P.getAnalysisIfAvailable<GlobalsAAWrapperPass>())
+ AAR.addAAResult(WrapperPass->getResult());
+ if (auto *WrapperPass = P.getAnalysisIfAvailable<SCEVAAWrapperPass>())
+ AAR.addAAResult(WrapperPass->getResult());
+ if (auto *WrapperPass = P.getAnalysisIfAvailable<CFLAAWrapperPass>())
+ AAR.addAAResult(WrapperPass->getResult());
+
+ return AAR;
+}
+
/// isNoAliasCall - Return true if this pointer is returned by a noalias
/// function.
bool llvm::isNoAliasCall(const Value *V) {
diff --git a/llvm/lib/Analysis/AliasAnalysisCounter.cpp b/llvm/lib/Analysis/AliasAnalysisCounter.cpp
deleted file mode 100644
index e369c31d237..00000000000
--- a/llvm/lib/Analysis/AliasAnalysisCounter.cpp
+++ /dev/null
@@ -1,165 +0,0 @@
-//===- AliasAnalysisCounter.cpp - Alias Analysis Query Counter ------------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This file implements a pass which can be used to count how many alias queries
-// are being made and how the alias analysis implementation being used responds.
-//
-//===----------------------------------------------------------------------===//
-
-#include "llvm/Analysis/AliasAnalysisCounter.h"
-#include "llvm/Analysis/AliasAnalysis.h"
-#include "llvm/IR/Module.h"
-#include "llvm/Pass.h"
-#include "llvm/Support/CommandLine.h"
-#include "llvm/Support/Debug.h"
-#include "llvm/Support/ErrorHandling.h"
-#include "llvm/Support/raw_ostream.h"
-using namespace llvm;
-
-static cl::opt<bool> PrintAll("count-aa-print-all-queries", cl::ReallyHidden,
- cl::init(true));
-static cl::opt<bool> PrintAllFailures("count-aa-print-all-failed-queries",
- cl::ReallyHidden);
-
-char AliasAnalysisCounter::ID = 0;
-INITIALIZE_AG_PASS(AliasAnalysisCounter, AliasAnalysis, "count-aa",
- "Count Alias Analysis Query Responses", false, true, false)
-
-ModulePass *llvm::createAliasAnalysisCounterPass() {
- return new AliasAnalysisCounter();
-}
-
-AliasAnalysisCounter::AliasAnalysisCounter() : ModulePass(ID) {
- initializeAliasAnalysisCounterPass(*PassRegistry::getPassRegistry());
- No = May = Partial = Must = 0;
- NoMR = JustRef = JustMod = MR = 0;
-}
-
-static void printLine(const char *Desc, unsigned Val, unsigned Sum) {
- errs() << " " << Val << " " << Desc << " responses (" << Val * 100 / Sum
- << "%)\n";
-}
-
-AliasAnalysisCounter::~AliasAnalysisCounter() {
- unsigned AASum = No + May + Partial + Must;
- unsigned MRSum = NoMR + JustRef + JustMod + MR;
- if (AASum + MRSum) { // Print a report if any counted queries occurred...
- errs() << "\n===== Alias Analysis Counter Report =====\n"
- << " Analysis counted:\n"
- << " " << AASum << " Total Alias Queries Performed\n";
- if (AASum) {
- printLine("no alias", No, AASum);
- printLine("may alias", May, AASum);
- printLine("partial alias", Partial, AASum);
- printLine("must alias", Must, AASum);
- errs() << " Alias Analysis Counter Summary: " << No * 100 / AASum << "%/"
- << May * 100 / AASum << "%/" << Partial * 100 / AASum << "%/"
- << Must * 100 / AASum << "%\n\n";
- }
-
- errs() << " " << MRSum << " Total MRI_Mod/MRI_Ref Queries Performed\n";
- if (MRSum) {
- printLine("no mod/ref", NoMR, MRSum);
- printLine("ref", JustRef, MRSum);
- printLine("mod", JustMod, MRSum);
- printLine("mod/ref", MR, MRSum);
- errs() << " MRI_Mod/MRI_Ref Analysis Counter Summary: "
- << NoMR * 100 / MRSum << "%/" << JustRef * 100 / MRSum << "%/"
- << JustMod * 100 / MRSum << "%/" << MR * 100 / MRSum << "%\n\n";
- }
- }
-}
-
-bool AliasAnalysisCounter::runOnModule(Module &M) {
- this->M = &M;
- InitializeAliasAnalysis(this, &M.getDataLayout());
- return false;
-}
-
-void AliasAnalysisCounter::getAnalysisUsage(AnalysisUsage &AU) const {
- AliasAnalysis::getAnalysisUsage(AU);
- AU.addRequired<AliasAnalysis>();
- AU.setPreservesAll();
-}
-
-void *AliasAnalysisCounter::getAdjustedAnalysisPointer(AnalysisID PI) {
- if (PI == &AliasAnalysis::ID)
- return (AliasAnalysis *)this;
- return this;
-}
-
-AliasResult AliasAnalysisCounter::alias(const MemoryLocation &LocA,
- const MemoryLocation &LocB) {
- AliasResult R = getAnalysis<AliasAnalysis>().alias(LocA, LocB);
-
- const char *AliasString = nullptr;
- switch (R) {
- case NoAlias:
- No++;
- AliasString = "No alias";
- break;
- case MayAlias:
- May++;
- AliasString = "May alias";
- break;
- case PartialAlias:
- Partial++;
- AliasString = "Partial alias";
- break;
- case MustAlias:
- Must++;
- AliasString = "Must alias";
- break;
- }
-
- if (PrintAll || (PrintAllFailures && R == MayAlias)) {
- errs() << AliasString << ":\t";
- errs() << "[" << LocA.Size << "B] ";
- LocA.Ptr->printAsOperand(errs(), true, M);
- errs() << ", ";
- errs() << "[" << LocB.Size << "B] ";
- LocB.Ptr->printAsOperand(errs(), true, M);
- errs() << "\n";
- }
-
- return R;
-}
-
-ModRefInfo AliasAnalysisCounter::getModRefInfo(ImmutableCallSite CS,
- const MemoryLocation &Loc) {
- ModRefInfo R = getAnalysis<AliasAnalysis>().getModRefInfo(CS, Loc);
-
- const char *MRString = nullptr;
- switch (R) {
- case MRI_NoModRef:
- NoMR++;
- MRString = "MRI_NoModRef";
- break;
- case MRI_Ref:
- JustRef++;
- MRString = "JustRef";
- break;
- case MRI_Mod:
- JustMod++;
- MRString = "JustMod";
- break;
- case MRI_ModRef:
- MR++;
- MRString = "MRI_ModRef";
- break;
- }
-
- if (PrintAll || (PrintAllFailures && R == MRI_ModRef)) {
- errs() << MRString << ": Ptr: ";
- errs() << "[" << Loc.Size << "B] ";
- Loc.Ptr->printAsOperand(errs(), true, M);
- errs() << "\t<->" << *CS.getInstruction() << '\n';
- }
- return R;
-}
diff --git a/llvm/lib/Analysis/AliasAnalysisEvaluator.cpp b/llvm/lib/Analysis/AliasAnalysisEvaluator.cpp
index 4540823dbed..20b123c2e16 100644
--- a/llvm/lib/Analysis/AliasAnalysisEvaluator.cpp
+++ b/llvm/lib/Analysis/AliasAnalysisEvaluator.cpp
@@ -59,7 +59,7 @@ namespace {
}
void getAnalysisUsage(AnalysisUsage &AU) const override {
- AU.addRequired<AliasAnalysis>();
+ AU.addRequired<AAResultsWrapperPass>();
AU.setPreservesAll();
}
@@ -83,7 +83,7 @@ namespace {
char AAEval::ID = 0;
INITIALIZE_PASS_BEGIN(AAEval, "aa-eval",
"Exhaustive Alias Analysis Precision Evaluator", false, true)
-INITIALIZE_AG_DEPENDENCY(AliasAnalysis)
+INITIALIZE_PASS_DEPENDENCY(AAResultsWrapperPass)
INITIALIZE_PASS_END(AAEval, "aa-eval",
"Exhaustive Alias Analysis Precision Evaluator", false, true)
@@ -142,7 +142,7 @@ static inline bool isInterestingPointer(Value *V) {
bool AAEval::runOnFunction(Function &F) {
const DataLayout &DL = F.getParent()->getDataLayout();
- AliasAnalysis &AA = getAnalysis<AliasAnalysis>();
+ AliasAnalysis &AA = getAnalysis<AAResultsWrapperPass>().getAAResults();
SetVector<Value *> Pointers;
SetVector<CallSite> CallSites;
diff --git a/llvm/lib/Analysis/AliasSetTracker.cpp b/llvm/lib/Analysis/AliasSetTracker.cpp
index f9d3126833b..6cc2a030982 100644
--- a/llvm/lib/Analysis/AliasSetTracker.cpp
+++ b/llvm/lib/Analysis/AliasSetTracker.cpp
@@ -649,11 +649,12 @@ namespace {
void getAnalysisUsage(AnalysisUsage &AU) const override {
AU.setPreservesAll();
- AU.addRequired<AliasAnalysis>();
+ AU.addRequired<AAResultsWrapperPass>();
}
bool runOnFunction(Function &F) override {
- Tracker = new AliasSetTracker(getAnalysis<AliasAnalysis>());
+ auto &AAWP = getAnalysis<AAResultsWrapperPass>();
+ Tracker = new AliasSetTracker(AAWP.getAAResults());
for (inst_iterator I = inst_begin(F), E = inst_end(F); I != E; ++I)
Tracker->add(&*I);
@@ -667,6 +668,6 @@ namespace {
char AliasSetPrinter::ID = 0;
INITIALIZE_PASS_BEGIN(AliasSetPrinter, "print-alias-sets",
"Alias Set Printer", false, true)
-INITIALIZE_AG_DEPENDENCY(AliasAnalysis)
+INITIALIZE_PASS_DEPENDENCY(AAResultsWrapperPass)
INITIALIZE_PASS_END(AliasSetPrinter, "print-alias-sets",
"Alias Set Printer", false, true)
diff --git a/llvm/lib/Analysis/Analysis.cpp b/llvm/lib/Analysis/Analysis.cpp
index d338710f7bf..9c1ac000be2 100644
--- a/llvm/lib/Analysis/Analysis.cpp
+++ b/llvm/lib/Analysis/Analysis.cpp
@@ -20,12 +20,9 @@ using namespace llvm;
/// initializeAnalysis - Initialize all passes linked into the Analysis library.
void llvm::initializeAnalysis(PassRegistry &Registry) {
- initializeAliasAnalysisAnalysisGroup(Registry);
- initializeAliasAnalysisCounterPass(Registry);
initializeAAEvalPass(Registry);
initializeAliasSetPrinterPass(Registry);
- initializeNoAAPass(Registry);
- initializeBasicAliasAnalysisPass(Registry);
+ initializeBasicAAWrapperPassPass(Registry);
initializeBlockFrequencyInfoWrapperPassPass(Registry);
initializeBranchProbabilityInfoWrapperPassPass(Registry);
initializeCallGraphWrapperPassPass(Registry);
@@ -36,7 +33,7 @@ void llvm::initializeAnalysis(PassRegistry &Registry) {
initializeCFGPrinterPass(Registry);
initializeCFGOnlyViewerPass(Registry);
initializeCFGOnlyPrinterPass(Registry);
- initializeCFLAliasAnalysisPass(Registry);
+ initializeCFLAAWrapperPassPass(Registry);
initializeDependenceAnalysisPass(Registry);
initializeDelinearizationPass(Registry);
initializeDemandedBitsPass(Registry);
@@ -50,7 +47,8 @@ void llvm::initializeAnalysis(PassRegistry &Registry) {
initializePostDomPrinterPass(Registry);
initializePostDomOnlyViewerPass(Registry);
initializePostDomOnlyPrinterPass(Registry);
- initializeGlobalsModRefPass(Registry);
+ initializeAAResultsWrapperPassPass(Registry);
+ initializeGlobalsAAWrapperPassPass(Registry);
initializeIVUsersPass(Registry);
initializeInstCountPass(Registry);
initializeIntervalPartitionPass(Registry);
@@ -61,18 +59,18 @@ void llvm::initializeAnalysis(PassRegistry &Registry) {
initializeMemDerefPrinterPass(Registry);
initializeMemoryDependenceAnalysisPass(Registry);
initializeModuleDebugInfoPrinterPass(Registry);
- initializeObjCARCAliasAnalysisPass(Registry);
+ initializeObjCARCAAWrapperPassPass(Registry);
initializePostDominatorTreePass(Registry);
initializeRegionInfoPassPass(Registry);
initializeRegionViewerPass(Registry);
initializeRegionPrinterPass(Registry);
initializeRegionOnlyViewerPass(Registry);
initializeRegionOnlyPrinterPass(Registry);
+ initializeSCEVAAWrapperPassPass(Registry);
initializeScalarEvolutionWrapperPassPass(Registry);
- initializeScalarEvolutionAliasAnalysisPass(Registry);
initializeTargetTransformInfoWrapperPassPass(Registry);
- initializeTypeBasedAliasAnalysisPass(Registry);
- initializeScopedNoAliasAAPass(Registry);
+ initializeTypeBasedAAWrapperPassPass(Registry);
+ initializeScopedNoAliasAAWrapperPassPass(Registry);
}
void LLVMInitializeAnalysis(LLVMPassRegistryRef R) {
diff --git a/llvm/lib/Analysis/BasicAliasAnalysis.cpp b/llvm/lib/Analysis/BasicAliasAnalysis.cpp
index a6a25f9326a..04e6d98b5fb 100644
--- a/llvm/lib/Analysis/BasicAliasAnalysis.cpp
+++ b/llvm/lib/Analysis/BasicAliasAnalysis.cpp
@@ -23,6 +23,7 @@
#include "llvm/Analysis/LoopInfo.h"
#include "llvm/Analysis/MemoryBuiltins.h"
#include "llvm/Analysis/ValueTracking.h"
+#include "llvm/Analysis/AssumptionCache.h"
#include "llvm/IR/Constants.h"
#include "llvm/IR/DataLayout.h"
#include "llvm/IR/DerivedTypes.h"
@@ -177,7 +178,7 @@ static bool isObjectSize(const Value *V, uint64_t Size, const DataLayout &DL,
///
/// Note that this looks through extends, so the high bits may not be
/// represented in the result.
-/*static*/ const Value *BasicAliasAnalysis::GetLinearExpression(
+/*static*/ const Value *BasicAAResult::GetLinearExpression(
const Value *V, APInt &Scale, APInt &Offset, unsigned &ZExtBits,
unsigned &SExtBits, const DataLayout &DL, unsigned Depth,
AssumptionCache *AC, DominatorTree *DT, bool &NSW, bool &NUW) {
@@ -331,7 +332,7 @@ static bool isObjectSize(const Value *V, uint64_t Size, const DataLayout &DL,
/// GetUnderlyingObject and DecomposeGEPExpression must use the same search
/// depth (MaxLookupSearchDepth). When DataLayout not is around, it just looks
/// through pointer casts.
-/*static*/ const Value *BasicAliasAnalysis::DecomposeGEPExpression(
+/*static*/ const Value *BasicAAResult::DecomposeGEPExpression(
const Value *V, int64_t &BaseOffs,
SmallVectorImpl<VariableGEPIndex> &VarIndices, bool &MaxLookupReached,
const DataLayout &DL, AssumptionCache *AC, DominatorTree *DT) {
@@ -466,40 +467,21 @@ static bool isObjectSize(const Value *V, uint64_t Size, const DataLayout &DL,
return V;
}
-//===----------------------------------------------------------------------===//
-// BasicAliasAnalysis Pass
-//===----------------------------------------------------------------------===//
-
-// Register the pass...
-char BasicAliasAnalysis::ID = 0;
-INITIALIZE_AG_PASS_BEGIN(BasicAliasAnalysis, AliasAnalysis, "basicaa",
- "Basic Alias Analysis (stateless AA impl)", false,
- true, false)
-INITIALIZE_PASS_DEPENDENCY(AssumptionCacheTracker)
-INITIALIZE_PASS_DEPENDENCY(TargetLibraryInfoWrapperPass)
-INITIALIZE_AG_PASS_END(BasicAliasAnalysis, AliasAnalysis, "basicaa",
- "Basic Alias Analysis (stateless AA impl)", false, true,
- false)
-
-ImmutablePass *llvm::createBasicAliasAnalysisPass() {
- return new BasicAliasAnalysis();
-}
-
/// Returns whether the given pointer value points to memory that is local to
/// the function, with global constants being considered local to all
/// functions.
-bool BasicAliasAnalysis::pointsToConstantMemory(const MemoryLocation &Loc,
- bool OrLocal) {
+bool BasicAAResult::pointsToConstantMemory(const MemoryLocation &Loc,
+ bool OrLocal) {
assert(Visited.empty() && "Visited must be cleared after use!");
unsigned MaxLookup = 8;
SmallVector<const Value *, 16> Worklist;
Worklist.push_back(Loc.Ptr);
do {
- const Value *V = GetUnderlyingObject(Worklist.pop_back_val(), *DL);
+ const Value *V = GetUnderlyingObject(Worklist.pop_back_val(), DL);
if (!Visited.insert(V).second) {
Visited.clear();
- return AliasAnalysis::pointsToConstantMemory(Loc, OrLocal);
+ return AAResultBase::pointsToConstantMemory(Loc, OrLocal);
}
// An alloca instruction defines local memory.
@@ -513,7 +495,7 @@ bool BasicAliasAnalysis::pointsToConstantMemory(const MemoryLocation &Loc,
// others. GV may even be a declaration, not a definition.
if (!GV->isConstant()) {
Visited.clear();
- return AliasAnalysis::pointsToConstantMemory(Loc, OrLocal);
+ return AAResultBase::pointsToConstantMemory(Loc, OrLocal);
}
continue;
}
@@ -531,7 +513,7 @@ bool BasicAliasAnalysis::pointsToConstantMemory(const MemoryLocation &Loc,
// Don't bother inspecting phi nodes with many operands.
if (PN->getNumIncomingValues() > MaxLookup) {
Visited.clear();
- return AliasAnalysis::pointsToConstantMemory(Loc, OrLocal);
+ return AAResultBase::pointsToConstantMemory(Loc, OrLocal);
}
for (Value *IncValue : PN->incoming_values())
Worklist.push_back(IncValue);
@@ -540,7 +522,7 @@ bool BasicAliasAnalysis::pointsToConstantMemory(const MemoryLocation &Loc,
// Otherwise be conservative.
Visited.clear();
- return AliasAnalysis::pointsToConstantMemory(Loc, OrLocal);
+ return AAResultBase::pointsToConstantMemory(Loc, OrLocal);
} while (!Worklist.empty() && --MaxLookup);
@@ -566,8 +548,7 @@ static bool isMemsetPattern16(const Function *MS,
}
/// Returns the behavior when calling the given call site.
-FunctionModRefBehavior
-BasicAliasAnalysis::getModRefBehavior(ImmutableCallSite CS) {
+FunctionModRefBehavior BasicAAResult::getModRefBehavior(ImmutableCallSite CS) {
if (CS.doesNotAccessMemory())
// Can't do better than this.
return FMRB_DoesNotAccessMemory;
@@ -582,14 +563,13 @@ BasicAliasAnalysis::getModRefBehavior(ImmutableCallSite CS) {
if (CS.onlyAccessesArgMemory())
Min = FunctionModRefBehavior(Min & FMRB_OnlyAccessesArgumentPointees);
- // The AliasAnalysis base class has some smarts, lets use them.
- return FunctionModRefBehavior(AliasAnalysis::getModRefBehavior(CS) & Min);
+ // The AAResultBase base class has some smarts, lets use them.
+ return FunctionModRefBehavior(AAResultBase::getModRefBehavior(CS) & Min);
}
/// Returns the behavior when calling the given function. For use when the call
/// site is not known.
-FunctionModRefBehavior
-BasicAliasAnalysis::getModRefBehavior(const Function *F) {
+FunctionModRefBehavior BasicAAResult::getModRefBehavior(const Function *F) {
// If the function declares it doesn't access memory, we can't do better.
if (F->doesNotAccessMemory())
return FMRB_DoesNotAccessMemory;
@@ -603,17 +583,15 @@ BasicAliasAnalysis::getModRefBehavior(const Function *F) {
if (F->onlyAccessesArgMemory())
Min = FunctionModRefBehavior(Min & FMRB_OnlyAccessesArgumentPointees);
- const TargetLibraryInfo &TLI =
- getAnalysis<TargetLibraryInfoWrapperPass>().getTLI();
if (isMemsetPattern16(F, TLI))
Min = FMRB_OnlyAccessesArgumentPointees;
// Otherwise be conservative.
- return FunctionModRefBehavior(AliasAnalysis::getModRefBehavior(F) & Min);
+ return FunctionModRefBehavior(AAResultBase::getModRefBehavior(F) & Min);
}
-ModRefInfo BasicAliasAnalysis::getArgModRefInfo(ImmutableCallSite CS,
- unsigned ArgIdx) {
+ModRefInfo BasicAAResult::getArgModRefInfo(ImmutableCallSite CS,
+ unsigned ArgIdx) {
if (const IntrinsicInst *II = dyn_cast<IntrinsicInst>(CS.getInstruction()))
switch (II->getIntrinsicID()) {
default:
@@ -631,14 +609,14 @@ ModRefInfo BasicAliasAnalysis::getArgModRefInfo(ImmutableCallSite CS,
// LoopIdiomRecognizer likes to turn loops into calls to memset_pattern16
// whenever possible.
if (CS.getCalledFunction() &&
- isMemsetPattern16(CS.getCalledFunction(), *TLI)) {
+ isMemsetPattern16(CS.getCalledFunction(), TLI)) {
assert((ArgIdx == 0 || ArgIdx == 1) &&
"Invalid argument index for memset_pattern16");
return ArgIdx ? MRI_Ref : MRI_Mod;
}
// FIXME: Handle memset_pattern4 and memset_pattern8 also.
- return AliasAnalysis::getArgModRefInfo(CS, ArgIdx);
+ return AAResultBase::getArgModRefInfo(CS, ArgIdx);
}
static bool isAssumeIntrinsic(ImmutableCallSite CS) {
@@ -649,23 +627,18 @@ static bool isAssumeIntrinsic(ImmutableCallSite CS) {
return false;
}
-bool BasicAliasAnalysis::doInitialization(Module &M) {
- InitializeAliasAnalysis(this, &M.getDataLayout());
- return true;
-}
-
/// Checks to see if the specified callsite can clobber the specified memory
/// object.
///
/// Since we only look at local properties of this function, we really can't
/// say much about this query. We do, however, use simple "address taken"
/// analysis on local objects.
-ModRefInfo BasicAliasAnalysis::getModRefInfo(ImmutableCallSite CS,
- const MemoryLocation &Loc) {
+ModRefInfo BasicAAResult::getModRefInfo(ImmutableCallSite CS,
+ const MemoryLocation &Loc) {
assert(notDifferentParent(CS.getInstruction(), Loc.Ptr) &&
"AliasAnalysis query involving multiple functions!");
- const Value *Object = GetUnderlyingObject(Loc.Ptr, *DL);
+ const Value *Object = GetUnderlyingObject(Loc.Ptr, DL);
// If this is a tail call and Loc.Ptr points to a stack location, we know that
// the tail call cannot access or modify the local stack.
@@ -697,7 +670,9 @@ ModRefInfo BasicAliasAnalysis::getModRefInfo(ImmutableCallSite CS,
// is impossible to alias the pointer we're checking. If not, we have to
// assume that the call could touch the pointer, even though it doesn't
// escape.
- if (!isNoAlias(MemoryLocation(*CI), MemoryLocation(Object))) {
+ AliasResult AR =
+ getBestAAResults().alias(MemoryLocation(*CI), MemoryLocation(Object));
+ if (AR) {
PassedAsArg = true;
break;
}
@@ -713,20 +688,20 @@ ModRefInfo BasicAliasAnalysis::getModRefInfo(ImmutableCallSite CS,
if (isAssumeIntrinsic(CS))
return MRI_NoModRef;
- // The AliasAnalysis base class has some smarts, lets use them.
- return AliasAnalysis::getModRefInfo(CS, Loc);
+ // The AAResultBase base class has some smarts, lets use them.
+ return AAResultBase::getModRefInfo(CS, Loc);
}
-ModRefInfo BasicAliasAnalysis::getModRefInfo(ImmutableCallSite CS1,
- ImmutableCallSite CS2) {
+ModRefInfo BasicAAResult::getModRefInfo(ImmutableCallSite CS1,
+ ImmutableCallSite CS2) {
// While the assume intrinsic is marked as arbitrarily writing so that
// proper control dependencies will be maintained, it never aliases any
// particular memory location.
if (isAssumeIntrinsic(CS1) || isAssumeIntrinsic(CS2))
return MRI_NoModRef;
- // The AliasAnalysis base class has some smarts, lets use them.
- return AliasAnalysis::getModRefInfo(CS1, CS2);
+ // The AAResultBase base class has some smarts, lets use them.
+ return AAResultBase::getModRefInfo(CS1, CS2);
}
/// Provide ad-hoc rules to disambiguate accesses through two GEP operators,
@@ -829,34 +804,15 @@ static AliasResult aliasSameBasePointerGEPs(const GEPOperator *GEP1,
/// We know that V1 is a GEP, but we don't know anything about V2.
/// UnderlyingV1 is GetUnderlyingObject(GEP1, DL), UnderlyingV2 is the same for
/// V2.
-AliasResult BasicAliasAnalysis::aliasGEP(
- const GEPOperator *GEP1, uint64_t V1Size, const AAMDNodes &V1AAInfo,
- const Value *V2, uint64_t V2Size, const AAMDNodes &V2AAInfo,
- const Value *UnderlyingV1, const Value *UnderlyingV2) {
+AliasResult BasicAAResult::aliasGEP(const GEPOperator *GEP1, uint64_t V1Size,
+ const AAMDNodes &V1AAInfo, const Value *V2,
+ uint64_t V2Size, const AAMDNodes &V2AAInfo,
+ const Value *UnderlyingV1,
+ const Value *UnderlyingV2) {
int64_t GEP1BaseOffset;
bool GEP1MaxLookupReached;
SmallVector<VariableGEPIndex, 4> GEP1VariableIndices;
- // We have to get two AssumptionCaches here because GEP1 and V2 may be from
- // different functions.
- // FIXME: This really doesn't make any sense. We get a dominator tree below
- // that can only refer to a single function. But this function (aliasGEP) is
- // a method on an immutable pass that can be called when there *isn't*
- // a single function. The old pass management layer makes this "work", but
- // this isn't really a clean solution.
- AssumptionCacheTracker &ACT = getAnalysis<AssumptionCacheTracker>();
- AssumptionCache *AC1 = nullptr, *AC2 = nullptr;
- if (auto *GEP1I = dyn_cast<Instruction>(GEP1))
- AC1 = &ACT.getAssumptionCache(
- const_cast<Function &>(*GEP1I->getParent()->getParent()));
- if (auto *I2 = dyn_cast<Instruction>(V2))
- AC2 = &ACT.getAssumptionCache(
- const_cast<Function &>(*I2->getParent()->getParent()));
-
- DominatorTreeWrapperPass *DTWP =
- getAnalysisIfAvailable<DominatorTreeWrapperPass>();
- DominatorTree *DT = DTWP ? &DTWP->getDomTree() : nullptr;
-
// If we have two gep instructions with must-alias or not-alias'ing base
// pointers, figure out if the indexes to the GEP tell us anything about the
// derived pointer.
@@ -880,15 +836,15 @@ AliasResult BasicAliasAnalysis::aliasGEP(
SmallVector<VariableGEPIndex, 4> GEP2VariableIndices;
const Value *GEP2BasePtr =
DecomposeGEPExpression(GEP2, GEP2BaseOffset, GEP2VariableIndices,
- GEP2MaxLookupReached, *DL, AC2, DT);
+ GEP2MaxLookupReached, DL, &AC, DT);
const Value *GEP1BasePtr =
DecomposeGEPExpression(GEP1, GEP1BaseOffset, GEP1VariableIndices,
- GEP1MaxLookupReached, *DL, AC1, DT);
+ GEP1MaxLookupReached, DL, &AC, DT);
// DecomposeGEPExpression and GetUnderlyingObject should return the
// same result except when DecomposeGEPExpression has no DataLayout.
+ // FIXME: They always have a DataLayout so this should become an
+ // assert.
if (GEP1BasePtr != UnderlyingV1 || GEP2BasePtr != UnderlyingV2) {
- assert(!DL &&
- "DecomposeGEPExpression and GetUnderlyingObject disagree!");
return MayAlias;
}
// If the max search depth is reached the result is undefined
@@ -913,27 +869,27 @@ AliasResult BasicAliasAnalysis::aliasGEP(
// about the relation of the resulting pointer.
const Value *GEP1BasePtr =
DecomposeGEPExpression(GEP1, GEP1BaseOffset, GEP1VariableIndices,
- GEP1MaxLookupReached, *DL, AC1, DT);
+ GEP1MaxLookupReached, DL, &AC, DT);
int64_t GEP2BaseOffset;
bool GEP2MaxLookupReached;
SmallVector<VariableGEPIndex, 4> GEP2VariableIndices;
const Value *GEP2BasePtr =
DecomposeGEPExpression(GEP2, GEP2BaseOffset, GEP2VariableIndices,
- GEP2MaxLookupReached, *DL, AC2, DT);
+ GEP2MaxLookupReached, DL, &AC, DT);
// DecomposeGEPExpression and GetUnderlyingObject should return the
// same result except when DecomposeGEPExpression has no DataLayout.
+ // FIXME: They always have a DataLayout so this should become an assert.
if (GEP1BasePtr != UnderlyingV1 || GEP2BasePtr != UnderlyingV2) {
- assert(!DL && "DecomposeGEPExpression and GetUnderlyingObject disagree!");
return MayAlias;
}
// If we know the two GEPs are based off of the exact same pointer (and not
// just the same underlying object), see if that tells us anything about
// the resulting pointers.
- if (DL && GEP1->getPointerOperand() == GEP2->getPointerOperand()) {
- AliasResult R = aliasSameBasePointerGEPs(GEP1, V1Size, GEP2, V2Size, *DL);
+ if (GEP1->getPointerOperand() == GEP2->getPointerOperand()) {
+ AliasResult R = aliasSameBasePointerGEPs(GEP1, V1Size, GEP2, V2Size, DL);
// If we couldn't find anything interesting, don't abandon just yet.
if (R != MayAlias)
return R;
@@ -970,12 +926,12 @@ AliasResult BasicAliasAnalysis::aliasGEP(
const Value *GEP1BasePtr =
DecomposeGEPExpression(GEP1, GEP1BaseOffset, GEP1VariableIndices,
- GEP1MaxLookupReached, *DL, AC1, DT);
+ GEP1MaxLookupReached, DL, &AC, DT);
// DecomposeGEPExpression and GetUnderlyingObject should return the
// same result except when DecomposeGEPExpression has no DataLayout.
+ // FIXME: They always have a DataLayout so this should become an assert.
if (GEP1BasePtr != UnderlyingV1) {
- assert(!DL && "DecomposeGEPExpression and GetUnderlyingObject disagree!");
return MayAlias;
}
// If the max search depth is reached the result is undefined
@@ -1039,8 +995,8 @@ AliasResult BasicAliasAnalysis::aliasGEP(
const Value *V = GEP1VariableIndices[i].V;
bool SignKnownZero, SignKnownOne;
- ComputeSignBit(const_cast<Value *>(V), SignKnownZero, SignKnownOne, *DL,
- 0, AC1, nullptr, DT);
+ ComputeSignBit(const_cast<Value *>(V), SignKnownZero, SignKnownOne, DL,
+ 0, &AC, nullptr, DT);
// Zero-extension widens the variable, and so forces the sign
// bit to zero.
@@ -1075,7 +1031,7 @@ AliasResult BasicAliasAnalysis::aliasGEP(
return NoAlias;
if (constantOffsetHeuristic(GEP1VariableIndices, V1Size, V2Size,
- GEP1BaseOffset, DL, AC1, DT))
+ GEP1BaseOffset, &AC, DT))
return NoAlias;
}
@@ -1103,11 +1059,10 @@ static AliasResult MergeAliasResults(AliasResult A, AliasResult B) {
/// Provides a bunch of ad-hoc rules to disambiguate a Select instruction
/// against another.
-AliasResult BasicAliasAnalysis::aliasSelect(const SelectInst *SI,
- uint64_t SISize,
- const AAMDNodes &SIAAInfo,
- const Value *V2, uint64_t V2Size,
- const AAMDNodes &V2AAInfo) {
+AliasResult BasicAAResult::aliasSelect(const SelectInst *SI, uint64_t SISize,
+ const AAMDNodes &SIAAInfo,
+ const Value *V2, uint64_t V2Size,
+ const AAMDNodes &V2AAInfo) {
// If the values are Selects with the same condition, we can do a more precise
// check: just check for aliases between the values on corresponding arms.
if (const SelectInst *SI2 = dyn_cast<SelectInst>(V2))
@@ -1136,10 +1091,10 @@ AliasResult BasicAliasAnalysis::aliasSelect(const SelectInst *SI,
/// Provide a bunch of ad-hoc rules to disambiguate a PHI instruction against
/// another.
-AliasResult BasicAliasAnalysis::aliasPHI(const PHINode *PN, uint64_t PNSize,
- const AAMDNodes &PNAAInfo,
- const Value *V2, uint64_t V2Size,
- const AAMDNodes &V2AAInfo) {
+AliasResult BasicAAResult::aliasPHI(const PHINode *PN, uint64_t PNSize,
+ const AAMDNodes &PNAAInfo, const Value *V2,
+ uint64_t V2Size,
+ const AAMDNodes &V2AAInfo) {
// Track phi nodes we have visited. We use this information when we determine
// value equivalence.
VisitedPhiBBs.insert(PN->getParent());
@@ -1242,10 +1197,9 @@ AliasResult BasicAliasAnalysis::aliasPHI(const PHINode *PN, uint64_t PNSize,
/// Provideis a bunch of ad-hoc rules to disambiguate in common cases, such as
/// array references.
-AliasResult BasicAliasAnalysis::aliasCheck(const Value *V1, uint64_t V1Size,
- AAMDNodes V1AAInfo, const Value *V2,
- uint64_t V2Size,
- AAMDNodes V2AAInfo) {
+AliasResult BasicAAResult::aliasCheck(const Value *V1, uint64_t V1Size,
+ AAMDNodes V1AAInfo, const Value *V2,
+ uint64_t V2Size, AAMDNodes V2AAInfo) {
// If either of the memory references is empty, it doesn't matter what the
// pointer values are.
if (V1Size == 0 || V2Size == 0)
@@ -1273,8 +1227,8 @@ AliasResult BasicAliasAnalysis::aliasCheck(const Value *V1, uint64_t V1Size,
return NoAlias; // Scalars cannot alias each other
// Figure out what objects these things are pointing to if we can.
- const Value *O1 = GetUnderlyingObject(V1, *DL, MaxLookupSearchDepth);
- const Value *O2 = GetUnderlyingObject(V2, *DL, MaxLookupSearchDepth);
+ const Value *O1 = GetUnderlyingObject(V1, DL, MaxLookupSearchDepth);
+ const Value *O2 = GetUnderlyingObject(V2, DL, MaxLookupSearchDepth);
// Null values in the default address space don't point to any object, so they
// don't alias any other pointer.
@@ -1323,12 +1277,11 @@ AliasResult BasicAliasAnalysis::aliasCheck(const Value *V1, uint64_t V1Size,
// If the size of one access is larger than the entire object on the other
// side, then we know such behavior is undefined and can assume no alias.
- if (DL)
- if ((V1Size != MemoryLocation::UnknownSize &&
- isObjectSmallerThan(O2, V1Size, *DL, *TLI)) ||
- (V2Size != MemoryLocation::UnknownSize &&
- isObjectSmallerThan(O1, V2Size, *DL, *TLI)))
- return NoAlias;
+ if ((V1Size != MemoryLocation::UnknownSize &&
+ isObjectSmallerThan(O2, V1Size, DL, TLI)) ||
+ (V2Size != MemoryLocation::UnknownSize &&
+ isObjectSmallerThan(O1, V2Size, DL, TLI)))
+ return NoAlias;
// Check the cache before climbing up use-def chains. This also terminates
// otherwise infinitely recursive queries.
@@ -1382,16 +1335,17 @@ AliasResult BasicAliasAnalysis::aliasCheck(const Value *V1, uint64_t V1Size,
// If both pointers are pointing into the same object and one of them
// accesses is accessing the entire object, then the accesses must
// overlap in some way.
- if (DL && O1 == O2)
+ if (O1 == O2)
if ((V1Size != MemoryLocation::UnknownSize &&
- isObjectSize(O1, V1Size, *DL, *TLI)) ||
+ isObjectSize(O1, V1Size, DL, TLI)) ||
(V2Size != MemoryLocation::UnknownSize &&
- isObjectSize(O2, V2Size, *DL, *TLI)))
+ isObjectSize(O2, V2Size, DL, TLI)))
return AliasCache[Locs] = PartialAlias;
- AliasResult Result =
- AliasAnalysis::alias(MemoryLocation(V1, V1Size, V1AAInfo),
- MemoryLocation(V2, V2Size, V2AAInfo));
+ // Recurse back into the best AA results we have, potentially with refined
+ // memory locations. We have already ensured that BasicAA has a MayAlias
+ // cache result for these, so any recursion back into BasicAA won't loop.
+ AliasResult Result = getBestAAResults().alias(Locs.first, Locs.second);
return AliasCache[Locs] = Result;
}
@@ -1402,8 +1356,8 @@ AliasResult BasicAliasAnalysis::aliasCheck(const Value *V1, uint64_t V1Size,
/// visited phi nodes an making sure that the phis cannot reach the value. We
/// have to do this because we are looking through phi nodes (That is we say
/// noalias(V, phi(VA, VB)) if noalias(V, VA) and noalias(V, VB).
-bool BasicAliasAnalysis::isValueEqualInPotentialCycles(const Value *V,
- const Value *V2) {
+bool BasicAAResult::isValueEqualInPotentialCycles(const Value *V,
+ const Value *V2) {
if (V != V2)
return false;
@@ -1417,13 +1371,6 @@ bool BasicAliasAnalysis::isValueEqualInPotentialCycles(const Value *V,
if (VisitedPhiBBs.size() > MaxNumPhiBBsValueReachabilityCheck)
return false;
- // Use dominance or loop info if available.
- DominatorTreeWrapperPass *DTWP =
- getAnalysisIfAvailable<DominatorTreeWrapperPass>();
- DominatorTree *DT = DTWP ? &DTWP->getDomTree() : nullptr;
- auto *LIWP = getAnalysisIfAvailable<LoopInfoWrapperPass>();
- LoopInfo *LI = LIWP ? &LIWP->getLoopInfo() : nullptr;
-
// Make sure that the visited phis cannot reach the Value. This ensures that
// the Values cannot come from different iterations of a potential cycle the
// phi nodes could be involved in.
@@ -1438,7 +1385,7 @@ bool BasicAliasAnalysis::isValueEqualInPotentialCycles(const Value *V,
///
/// Dest and Src are the variable indices from two decomposed GetElementPtr
/// instructions GEP1 and GEP2 which have common base pointers.
-void BasicAliasAnalysis::GetIndexDifference(
+void BasicAAResult::GetIndexDifference(
SmallVectorImpl<VariableGEPIndex> &Dest,
const SmallVectorImpl<VariableGEPIndex> &Src) {
if (Src.empty())
@@ -1474,12 +1421,12 @@ void BasicAliasAnalysis::GetIndexDifference(
}
}
-bool BasicAliasAnalysis::constantOffsetHeuristic(
+bool BasicAAResult::constantOffsetHeuristic(
const SmallVectorImpl<VariableGEPIndex> &VarIndices, uint64_t V1Size,
- uint64_t V2Size, int64_t BaseOffset, const DataLayout *DL,
- AssumptionCache *AC, DominatorTree *DT) {
+ uint64_t V2Size, int64_t BaseOffset, AssumptionCache *AC,
+ DominatorTree *DT) {
if (VarIndices.size() != 2 || V1Size == MemoryLocation::UnknownSize ||
- V2Size == MemoryLocation::UnknownSize || !DL)
+ V2Size == MemoryLocation::UnknownSize)
return false;
const VariableGEPIndex &Var0 = VarIndices[0], &Var1 = VarIndices[1];
@@ -1499,10 +1446,10 @@ bool BasicAliasAnalysis::constantOffsetHeuristic(
bool NSW = true, NUW = true;
unsigned V0ZExtBits = 0, V0SExtBits = 0, V1ZExtBits = 0, V1SExtBits = 0;
const Value *V0 = GetLinearExpression(Var0.V, V0Scale, V0Offset, V0ZExtBits,
- V0SExtBits, *DL, 0, AC, DT, NSW, NUW);
+ V0SExtBits, DL, 0, AC, DT, NSW, NUW);
NSW = true, NUW = true;
const Value *V1 = GetLinearExpression(Var1.V, V1Scale, V1Offset, V1ZExtBits,
- V1SExtBits, *DL, 0, AC, DT, NSW, NUW);
+ V1SExtBits, DL, 0, AC, DT, NSW, NUW);
if (V0Scale != V1Scale || V0ZExtBits != V1ZExtBits ||
V0SExtBits != V1SExtBits || !isValueEqualInPotentialCycles(V0, V1))
@@ -1527,3 +1474,58 @@ bool BasicAliasAnalysis::constantOffsetHeuristic(
return V1Size + std::abs(BaseOffset) <= MinDiffBytes &&
V2Size + std::abs(BaseOffset) <= MinDiffBytes;
}
+
+//===----------------------------------------------------------------------===//
+// BasicAliasAnalysis Pass
+//===----------------------------------------------------------------------===//
+
+char BasicAA::PassID;
+
+BasicAAResult BasicAA::run(Function &F, AnalysisManager<Function> *AM) {
+ return BasicAAResult(F.getParent()->getDataLayout(),
+ AM->getResult<TargetLibraryAnalysis>(F),
+ AM->getResult<AssumptionAnalysis>(F),
+ AM->getCachedResult<DominatorTreeAnalysis>(F),
+ AM->getCachedResult<LoopAnalysis>(F));
+}
+
+char BasicAAWrapperPass::ID = 0;
+void BasicAAWrapperPass::anchor() {}
+
+INITIALIZE_PASS_BEGIN(BasicAAWrapperPass, "basicaa",
+ "Basic Alias Analysis (stateless AA impl)", true, true)
+INITIALIZE_PASS_DEPENDENCY(AssumptionCacheTracker)
+INITIALIZE_PASS_DEPENDENCY(TargetLibraryInfoWrapperPass)
+INITIALIZE_PASS_END(BasicAAWrapperPass, "basicaa",
+ "Basic Alias Analysis (stateless AA impl)", true, true)
+
+FunctionPass *llvm::createBasicAAWrapperPass() {
+ return new BasicAAWrapperPass();
+}
+
+bool BasicAAWrapperPass::runOnFunction(Function &F) {
+ auto &ACT = getAnalysis<AssumptionCacheTracker>();
+ auto &TLIWP = getAnalysis<TargetLibraryInfoWrapperPass>();
+ auto *DTWP = getAnalysisIfAvailable<DominatorTreeWrapperPass>();
+ auto *LIWP = getAnalysisIfAvailable<LoopInfoWrapperPass>();
+
+ Result.reset(new BasicAAResult(F.getParent()->getDataLayout(), TLIWP.getTLI(),
+ ACT.getAssumptionCache(F),
+ DTWP ? &DTWP->getDomTree() : nullptr,
+ LIWP ? &LIWP->getLoopInfo() : nullptr));
+
+ return false;
+}
+
+void BasicAAWrapperPass::getAnalysisUsage(AnalysisUsage &AU) const {
+ AU.setPreservesAll();
+ AU.addRequired<AssumptionCacheTracker>();
+ AU.addRequired<TargetLibraryInfoWrapperPass>();
+}
+
+BasicAAResult llvm::createLegacyPMBasicAAResult(Pass &P, Function &F) {
+ return BasicAAResult(
+ F.getParent()->getDataLayout(),
+ P.getAnalysis<TargetLibraryInfoWrapperPass>().getTLI(),
+ P.getAnalysis<AssumptionCacheTracker>().getAssumptionCache(F));
+}
diff --git a/llvm/lib/Analysis/CFLAliasAnalysis.cpp b/llvm/lib/Analysis/CFLAliasAnalysis.cpp
index 729f7e412a8..4843ed6587a 100644
--- a/llvm/lib/Analysis/CFLAliasAnalysis.cpp
+++ b/llvm/lib/Analysis/CFLAliasAnalysis.cpp
@@ -33,7 +33,7 @@
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/None.h"
#include "llvm/ADT/Optional.h"
-#include "llvm/Analysis/AliasAnalysis.h"
+#include "llvm/Analysis/TargetLibraryInfo.h"
#include "llvm/IR/Constants.h"
#include "llvm/IR/Function.h"
#include "llvm/IR/InstVisitor.h"
@@ -53,18 +53,11 @@ using namespace llvm;
#define DEBUG_TYPE "cfl-aa"
-// -- Setting up/registering CFLAA pass -- //
-char CFLAliasAnalysis::ID = 0;
-
-INITIALIZE_AG_PASS(CFLAliasAnalysis, AliasAnalysis, "cfl-aa",
- "CFL-Based AA implementation", false, true, false)
-
-ImmutablePass *llvm::createCFLAliasAnalysisPass() {
- return new CFLAliasAnalysis();
-}
+CFLAAResult::CFLAAResult(const TargetLibraryInfo &TLI) : AAResultBase(TLI) {}
+CFLAAResult::CFLAAResult(CFLAAResult &&Arg) : AAResultBase(std::move(Arg)) {}
// \brief Information we have about a function and would like to keep around
-struct CFLAliasAnalysis::FunctionInfo {
+struct CFLAAResult::FunctionInfo {
StratifiedSets<Value *> Sets;
// Lots of functions have < 4 returns. Adjust as necessary.
SmallVector<Value *, 4> ReturnedValues;
@@ -73,22 +66,6 @@ struct CFLAliasAnalysis::FunctionInfo {
: Sets(std::move(S)), ReturnedValues(std::move(RV)) {}
};
-CFLAliasAnalysis::CFLAliasAnalysis() : ImmutablePass(ID) {
- initializeCFLAliasAnalysisPass(*PassRegistry::getPassRegistry());
-}
-
-CFLAliasAnalysis::~CFLAliasAnalysis() {}
-
-void CFLAliasAnalysis::getAnalysisUsage(AnalysisUsage &AU) const {
- AliasAnalysis::getAnalysisUsage(AU);
-}
-
-void *CFLAliasAnalysis::getAdjustedAnalysisPointer(const void *ID) {
- if (ID == &AliasAnalysis::ID)
- return (AliasAnalysis *)this;
- return this;
-}
-
// Try to go from a Value* to a Function*. Never returns nullptr.
static Optional<Function *> parentFunctionOfValue(Value *);
@@ -177,11 +154,11 @@ struct Edge {
// \brief Gets the edges our graph should have, based on an Instruction*
class GetEdgesVisitor : public InstVisitor<GetEdgesVisitor, void> {
- CFLAliasAnalysis &AA;
+ CFLAAResult &AA;
SmallVectorImpl<Edge> &Output;
public:
- GetEdgesVisitor(CFLAliasAnalysis &AA, SmallVectorImpl<Edge> &Output)
+ GetEdgesVisitor(CFLAAResult &AA, SmallVectorImpl<Edge> &Output)
: AA(AA), Output(Output) {}
void visitInstruction(Instruction &) {
@@ -669,12 +646,10 @@ static Optional<StratifiedAttr> valueToAttrIndex(Value *Val);
static EdgeType flipWeight(EdgeType);
// Gets edges of the given Instruction*, writing them to the SmallVector*.
-static void argsToEdges(CFLAliasAnalysis &, Instruction *,
- SmallVectorImpl<Edge> &);
+static void argsToEdges(CFLAAResult &, Instruction *, SmallVectorImpl<Edge> &);
// Gets edges of the given ConstantExpr*, writing them to the SmallVector*.
-static void argsToEdges(CFLAliasAnalysis &, ConstantExpr *,
- SmallVectorImpl<Edge> &);
+static void argsToEdges(CFLAAResult &, ConstantExpr *, SmallVectorImpl<Edge> &);
// Gets the "Level" that one should travel in StratifiedSets
// given an EdgeType.
@@ -682,13 +657,13 @@ static Level directionOfEdgeType(EdgeType);
// Builds the graph needed for constructing the StratifiedSets for the
// given function
-static void buildGraphFrom(CFLAliasAnalysis &, Function *,
+static void buildGraphFrom(CFLAAResult &, Function *,
SmallVectorImpl<Value *> &, NodeMapT &, GraphT &);
// Gets the edges of a ConstantExpr as if it was an Instruction. This
// function also acts on any nested ConstantExprs, adding the edges
// of those to the given SmallVector as well.
-static void constexprToEdges(CFLAliasAnalysis &, ConstantExpr &,
+static void constexprToEdges(CFLAAResult &, ConstantExpr &,
SmallVectorImpl<Edge> &);
// Given an Instruction, this will add it to the graph, along with any
@@ -697,7 +672,7 @@ static void constexprToEdges(CFLAliasAnalysis &, ConstantExpr &,
// %0 = load i16* getelementptr ([1 x i16]* @a, 0, 0), align 2
// addInstructionToGraph would add both the `load` and `getelementptr`
// instructions to the graph appropriately.
-static void addInstructionToGraph(CFLAliasAnalysis &, Instruction &,
+static void addInstructionToGraph(CFLAAResult &, Instruction &,
SmallVectorImpl<Value *> &, NodeMapT &,
GraphT &);
@@ -777,7 +752,7 @@ static EdgeType flipWeight(EdgeType Initial) {
llvm_unreachable("Incomplete coverage of EdgeType enum");
}
-static void argsToEdges(CFLAliasAnalysis &Analysis, Instruction *Inst,
+static void argsToEdges(CFLAAResult &Analysis, Instruction *Inst,
SmallVectorImpl<Edge> &Output) {
assert(hasUsefulEdges(Inst) &&
"Expected instructions to have 'useful' edges");
@@ -785,7 +760,7 @@ static void argsToEdges(CFLAliasAnalysis &Analysis, Instruction *Inst,
v.visit(Inst);
}
-static void argsToEdges(CFLAliasAnalysis &Analysis, ConstantExpr *CE,
+static void argsToEdges(CFLAAResult &Analysis, ConstantExpr *CE,
SmallVectorImpl<Edge> &Output) {
assert(hasUsefulEdges(CE) && "Expected constant expr to have 'useful' edges");
GetEdgesVisitor v(Analysis, Output);
@@ -804,7 +779,7 @@ static Level directionOfEdgeType(EdgeType Weight) {
llvm_unreachable("Incomplete switch coverage");
}
-static void constexprToEdges(CFLAliasAnalysis &Analysis,
+static void constexprToEdges(CFLAAResult &Analysis,
ConstantExpr &CExprToCollapse,
SmallVectorImpl<Edge> &Results) {
SmallVector<ConstantExpr *, 4> Worklist;
@@ -834,7 +809,7 @@ static void constexprToEdges(CFLAliasAnalysis &Analysis,
}
}
-static void addInstructionToGraph(CFLAliasAnalysis &Analysis, Instruction &Inst,
+static void addInstructionToGraph(CFLAAResult &Analysis, Instruction &Inst,
SmallVectorImpl<Value *> &ReturnedValues,
NodeMapT &Map, GraphT &Graph) {
const auto findOrInsertNode = [&Map, &Graph](Value *Val) {
@@ -897,7 +872,7 @@ static void addInstructionToGraph(CFLAliasAnalysis &Analysis, Instruction &Inst,
// buy us much that we don't already have. I'd like to add interprocedural
// analysis prior to this however, in case that somehow requires the graph
// produced by this for efficient execution
-static void buildGraphFrom(CFLAliasAnalysis &Analysis, Function *Fn,
+static void buildGraphFrom(CFLAAResult &Analysis, Function *Fn,
SmallVectorImpl<Value *> &ReturnedValues,
NodeMapT &Map, GraphT &Graph) {
for (auto &Bb : Fn->getBasicBlockList())
@@ -928,7 +903,7 @@ static bool canSkipAddingToSets(Value *Val) {
}
// Builds the graph + StratifiedSets for a function.
-CFLAliasAnalysis::FunctionInfo CFLAliasAnalysis::buildSetsFrom(Function *Fn) {
+CFLAAResult::FunctionInfo CFLAAResult::buildSetsFrom(Function *Fn) {
NodeMapT Map;
GraphT Graph;
SmallVector<Value *, 4> ReturnedValues;
@@ -1014,7 +989,7 @@ CFLAliasAnalysis::FunctionInfo CFLAliasAnalysis::buildSetsFrom(Function *Fn) {
return FunctionInfo(Builder.build(), std::move(ReturnedValues));
}
-void CFLAliasAnalysis::scan(Function *Fn) {
+void CFLAAResult::scan(Function *Fn) {
auto InsertPair = Cache.insert(std::make_pair(Fn, Optional<FunctionInfo>()));
(void)InsertPair;
assert(InsertPair.second &&
@@ -1025,12 +1000,12 @@ void CFLAliasAnalysis::scan(Function *Fn) {
Handles.push_front(FunctionHandle(Fn, this));
}
-void CFLAliasAnalysis::evict(Function *Fn) { Cache.erase(Fn); }
+void CFLAAResult::evict(Function *Fn) { Cache.erase(Fn); }
/// \brief Ensures that the given function is available in the cache.
/// Returns the appropriate entry from the cache.
-const Optional<CFLAliasAnalysis::FunctionInfo> &
-CFLAliasAnalysis::ensureCached(Function *Fn) {
+const Optional<CFLAAResult::FunctionInfo> &
+CFLAAResult::ensureCached(Function *Fn) {
auto Iter = Cache.find(Fn);
if (Iter == Cache.end()) {
scan(Fn);
@@ -1041,8 +1016,8 @@ CFLAliasAnalysis::ensureCached(Function *Fn) {
return Iter->second;
}
-AliasResult CFLAliasAnalysis::query(const MemoryLocation &LocA,
- const MemoryLocation &LocB) {
+AliasResult CFLAAResult::query(const MemoryLocation &LocA,
+ const MemoryLocation &LocB) {
auto *ValA = const_cast<Value *>(LocA.Ptr);
auto *ValB = const_cast<Value *>(LocB.Ptr);
@@ -1108,7 +1083,37 @@ AliasResult CFLAliasAnalysis::query(const MemoryLocation &LocA,
return NoAlias;
}
-bool CFLAliasAnalysis::doInitialization(Module &M) {
- InitializeAliasAnalysis(this, &M.getDataLayout());
- return true;
+CFLAAResult CFLAA::run(Function &F, AnalysisManager<Function> *AM) {
+ return CFLAAResult(AM->getResult<TargetLibraryAnalysis>(F));
+}
+
+char CFLAA::PassID;
+
+char CFLAAWrapperPass::ID = 0;
+INITIALIZE_PASS_BEGIN(CFLAAWrapperPass, "cfl-aa", "CFL-Based Alias Analysis",
+ false, true)
+INITIALIZE_PASS_DEPENDENCY(TargetLibraryInfoWrapperPass)
+INITIALIZE_PASS_END(CFLAAWrapperPass, "cfl-aa", "CFL-Based Alias Analysis",
+ false, true)
+
+ImmutablePass *llvm::createCFLAAWrapperPass() { return new CFLAAWrapperPass(); }
+
+CFLAAWrapperPass::CFLAAWrapperPass() : ImmutablePass(ID) {
+ initializeCFLAAWrapperPassPass(*PassRegistry::getPassRegistry());
+}
+
+bool CFLAAWrapperPass::doInitialization(Module &M) {
+ Result.reset(
+ new CFLAAResult(getAnalysis<TargetLibraryInfoWrapperPass>().getTLI()));
+ return false;
+}
+
+bool CFLAAWrapperPass::doFinalization(Module &M) {
+ Result.reset();
+ return false;
+}
+
+void CFLAAWrapperPass::getAnalysisUsage(AnalysisUsage &AU) const {
+ AU.setPreservesAll();
+ AU.addRequired<TargetLibraryInfoWrapperPass>();
}
diff --git a/llvm/lib/Analysis/CMakeLists.txt b/llvm/lib/Analysis/CMakeLists.txt
index 3750dc5b26f..cb5cd07493b 100644
--- a/llvm/lib/Analysis/CMakeLists.txt
+++ b/llvm/lib/Analysis/CMakeLists.txt
@@ -1,6 +1,5 @@
add_llvm_library(LLVMAnalysis
AliasAnalysis.cpp
- AliasAnalysisCounter.cpp
AliasAnalysisEvaluator.cpp
AliasSetTracker.cpp
Analysis.cpp
@@ -48,7 +47,6 @@ add_llvm_library(LLVMAnalysis
MemoryDependenceAnalysis.cpp
MemoryLocation.cpp
ModuleDebugInfoPrinter.cpp
- NoAliasAnalysis.cpp
ObjCARCAliasAnalysis.cpp
ObjCARCAnalysisUtils.cpp
ObjCARCInstKind.cpp
diff --git a/llvm/lib/Analysis/DependenceAnalysis.cpp b/llvm/lib/Analysis/DependenceAnalysis.cpp
index 5add828770f..a296ce0dbdf 100644
--- a/llvm/lib/Analysis/DependenceAnalysis.cpp
+++ b/llvm/lib/Analysis/DependenceAnalysis.cpp
@@ -118,7 +118,7 @@ INITIALIZE_PASS_BEGIN(DependenceAnalysis, "da",
"Dependence Analysis", true, true)
INITIALIZE_PASS_DEPENDENCY(LoopInfoWrapperPass)
INITIALIZE_PASS_DEPENDENCY(ScalarEvolutionWrapperPass)
-INITIALIZE_AG_DEPENDENCY(AliasAnalysis)
+INITIALIZE_PASS_DEPENDENCY(AAResultsWrapperPass)
INITIALIZE_PASS_END(DependenceAnalysis, "da",
"Dependence Analysis", true, true)
@@ -132,7 +132,7 @@ FunctionPass *llvm::createDependenceAnalysisPass() {
bool DependenceAnalysis::runOnFunction(Function &F) {
this->F = &F;
- AA = &getAnalysis<AliasAnalysis>();
+ AA = &getAnalysis<AAResultsWrapperPass>().getAAResults();
SE = &getAnalysis<ScalarEvolutionWrapperPass>().getSE();
LI = &getAnalysis<LoopInfoWrapperPass>().getLoopInfo();
return false;
@@ -145,7 +145,7 @@ void DependenceAnalysis::releaseMemory() {
void DependenceAnalysis::getAnalysisUsage(AnalysisUsage &AU) const {
AU.setPreservesAll();
- AU.addRequiredTransitive<AliasAnalysis>();
+ AU.addRequiredTransitive<AAResultsWrapperPass>();
AU.addRequiredTransitive<ScalarEvolutionWrapperPass>();
AU.addRequiredTransitive<LoopInfoWrapperPass>();
}
diff --git a/llvm/lib/Analysis/GlobalsModRef.cpp b/llvm/lib/Analysis/GlobalsModRef.cpp
index 5482a13d1e7..6981244f77a 100644
--- a/llvm/lib/Analysis/GlobalsModRef.cpp
+++ b/llvm/lib/Analysis/GlobalsModRef.cpp
@@ -19,6 +19,7 @@
#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/ADT/Statistic.h"
#include "llvm/Analysis/MemoryBuiltins.h"
+#include "llvm/Analysis/TargetLibraryInfo.h"
#include "llvm/Analysis/ValueTracking.h"
#include "llvm/IR/DerivedTypes.h"
#include "llvm/IR/InstIterator.h"
@@ -58,7 +59,7 @@ static cl::opt<bool> EnableUnsafeGlobalsModRefAliasResults(
/// general and as pertains to specific globals. We only have this detailed
/// information when we know *something* useful about the behavior. If we
/// saturate to fully general mod/ref, we remove the info for the function.
-class GlobalsModRef::FunctionInfo {
+class GlobalsAAResult::FunctionInfo {
typedef SmallDenseMap<const GlobalValue *, ModRefInfo, 16> GlobalInfoMapType;
/// Build a wrapper struct that has 8-byte alignment. All heap allocations
@@ -191,56 +192,41 @@ private:
PointerIntPair<AlignedMap *, 3, unsigned, AlignedMapPointerTraits> Info;
};
-void GlobalsModRef::DeletionCallbackHandle::deleted() {
+void GlobalsAAResult::DeletionCallbackHandle::deleted() {
Value *V = getValPtr();
if (auto *F = dyn_cast<Function>(V))
- GMR.FunctionInfos.erase(F);
+ GAR.FunctionInfos.erase(F);
if (GlobalValue *GV = dyn_cast<GlobalValue>(V)) {
- if (GMR.NonAddressTakenGlobals.erase(GV)) {
+ if (GAR.NonAddressTakenGlobals.erase(GV)) {
// This global might be an indirect global. If so, remove it and
// remove any AllocRelatedValues for it.
- if (GMR.IndirectGlobals.erase(GV)) {
+ if (GAR.IndirectGlobals.erase(GV)) {
// Remove any entries in AllocsForIndirectGlobals for this global.
- for (auto I = GMR.AllocsForIndirectGlobals.begin(),
- E = GMR.AllocsForIndirectGlobals.end();
+ for (auto I = GAR.AllocsForIndirectGlobals.begin(),
+ E = GAR.AllocsForIndirectGlobals.end();
I != E; ++I)
if (I->second == GV)
- GMR.AllocsForIndirectGlobals.erase(I);
+ GAR.AllocsForIndirectGlobals.erase(I);
}
// Scan the function info we have collected and remove this global
// from all of them.
- for (auto &FIPair : GMR.FunctionInfos)
+ for (auto &FIPair : GAR.FunctionInfos)
FIPair.second.eraseModRefInfoForGlobal(*GV);
}
}
// If this is an allocation related to an indirect global, remove it.
- GMR.AllocsForIndirectGlobals.erase(V);
+ GAR.AllocsForIndirectGlobals.erase(V);
// And clear out the handle.
setValPtr(nullptr);
- GMR.Handles.erase(I);
+ GAR.Handles.erase(I);
// This object is now destroyed!
}
-char GlobalsModRef::ID = 0;
-INITIALIZE_AG_PASS_BEGIN(GlobalsModRef, AliasAnalysis, "globalsmodref-aa",
- "Simple mod/ref analysis for globals", false, true,
- false)
-INITIALIZE_PASS_DEPENDENCY(CallGraphWrapperPass)
-INITIALIZE_AG_PASS_END(GlobalsModRef, AliasAnalysis, "globalsmodref-aa",
- "Simple mod/ref analysis for globals", false, true,
- false)
-
-Pass *llvm::createGlobalsModRefPass() { return new GlobalsModRef(); }
-
-GlobalsModRef::GlobalsModRef() : ModulePass(ID) {
- initializeGlobalsModRefPass(*PassRegistry::getPassRegistry());
-}
-
-FunctionModRefBehavior GlobalsModRef::getModRefBehavior(const Function *F) {
+FunctionModRefBehavior GlobalsAAResult::getModRefBehavior(const Function *F) {
FunctionModRefBehavior Min = FMRB_UnknownModRefBehavior;
if (FunctionInfo *FI = getFunctionInfo(F)) {
@@ -250,10 +236,11 @@ FunctionModRefBehavior GlobalsModRef::getModRefBehavior(const Function *F) {
Min = FMRB_OnlyReadsMemory;
}
- return FunctionModRefBehavior(AliasAnalysis::getModRefBehavior(F) & Min);
+ return FunctionModRefBehavior(AAResultBase::getModRefBehavior(F) & Min);
}
-FunctionModRefBehavior GlobalsModRef::getModRefBehavior(ImmutableCallSite CS) {
+FunctionModRefBehavior
+GlobalsAAResult::getModRefBehavior(ImmutableCallSite CS) {
FunctionModRefBehavior Min = FMRB_UnknownModRefBehavior;
if (const Function *F = CS.getCalledFunction())
@@ -264,12 +251,13 @@ FunctionModRefBehavior GlobalsModRef::getModRefBehavior(ImmutableCallSite CS) {
Min = FMRB_OnlyReadsMemory;
}
- return FunctionModRefBehavior(AliasAnalysis::getModRefBehavior(CS) & Min);
+ return FunctionModRefBehavior(AAResultBase::getModRefBehavior(CS) & Min);
}
/// Returns the function info for the function, or null if we don't have
/// anything useful to say about it.
-GlobalsModRef::FunctionInfo *GlobalsModRef::getFunctionInfo(const Function *F) {
+GlobalsAAResult::FunctionInfo *
+GlobalsAAResult::getFunctionInfo(const Function *F) {
auto I = FunctionInfos.find(F);
if (I != FunctionInfos.end())
return &I->second;
@@ -280,7 +268,7 @@ GlobalsModRef::FunctionInfo *GlobalsModRef::getFunctionInfo(const Function *F) {
/// GlobalValue's in the program. If none of them have their "address taken"
/// (really, their address passed to something nontrivial), record this fact,
/// and record the functions that they are used directly in.
-void GlobalsModRef::AnalyzeGlobals(Module &M) {
+void GlobalsAAResult::AnalyzeGlobals(Module &M) {
SmallPtrSet<Function *, 64> TrackedFunctions;
for (Function &F : M)
if (F.hasLocalLinkage())
@@ -337,10 +325,10 @@ void GlobalsModRef::AnalyzeGlobals(Module &M) {
/// write to the value.
///
/// If OkayStoreDest is non-null, stores into this global are allowed.
-bool GlobalsModRef::AnalyzeUsesOfPointer(Value *V,
- SmallPtrSetImpl<Function *> *Readers,
- SmallPtrSetImpl<Function *> *Writers,
- GlobalValue *OkayStoreDest) {
+bool GlobalsAAResult::AnalyzeUsesOfPointer(Value *V,
+ SmallPtrSetImpl<Function *> *Readers,
+ SmallPtrSetImpl<Function *> *Writers,
+ GlobalValue *OkayStoreDest) {
if (!V->getType()->isPointerTy())
return true;
@@ -367,7 +355,7 @@ bool GlobalsModRef::AnalyzeUsesOfPointer(Value *V,
// passing into the function.
if (!CS.isCallee(&U)) {
// Detect calls to free.
- if (isFreeCall(I, TLI)) {
+ if (isFreeCall(I, &TLI)) {
if (Writers)
Writers->insert(CS->getParent()->getParent());
} else {
@@ -392,7 +380,7 @@ bool GlobalsModRef::AnalyzeUsesOfPointer(Value *V,
/// Further, all loads out of GV must directly use the memory, not store the
/// pointer somewhere. If this is true, we consider the memory pointed to by
/// GV to be owned by GV and can disambiguate other pointers from it.
-bool GlobalsModRef::AnalyzeIndirectGlobalMemory(GlobalValue *GV) {
+bool GlobalsAAResult::AnalyzeIndirectGlobalMemory(GlobalValue *GV) {
// Keep track of values related to the allocation of the memory, f.e. the
// value produced by the malloc call and any casts.
std::vector<Value *> AllocRelatedValues;
@@ -420,7 +408,7 @@ bool GlobalsModRef::AnalyzeIndirectGlobalMemory(GlobalValue *GV) {
Value *Ptr = GetUnderlyingObject(SI->getOperand(0),
GV->getParent()->getDataLayout());
- if (!isAllocLikeFn(Ptr, TLI))
+ if (!isAllocLikeFn(Ptr, &TLI))
return false; // Too hard to analyze.
// Analyze all uses of the allocation. If any of them are used in a
@@ -455,7 +443,7 @@ bool GlobalsModRef::AnalyzeIndirectGlobalMemory(GlobalValue *GV) {
/// immediately stored to and read from. Propagate this information up the call
/// graph to all callers and compute the mod/ref info for all memory for each
/// function.
-void GlobalsModRef::AnalyzeCallGraph(CallGraph &CG, Module &M) {
+void GlobalsAAResult::AnalyzeCallGraph(CallGraph &CG, Module &M) {
// We do a bottom-up SCC traversal of the call graph. In other words, we
// visit all callees before callers (leaf-first).
for (scc_iterator<CallGraph *> I = scc_begin(&CG); !I.isAtEnd(); ++I) {
@@ -538,7 +526,7 @@ void GlobalsModRef::AnalyzeCallGraph(CallGraph &CG, Module &M) {
// We handle calls specially because the graph-relevant aspects are
// handled above.
if (auto CS = CallSite(&I)) {
- if (isAllocationFn(&I, TLI) || isFreeCall(&I, TLI)) {
+ if (isAllocationFn(&I, &TLI) || isFreeCall(&I, &TLI)) {
// FIXME: It is completely unclear why this is necessary and not
// handled by the above graph code.
FI.addModRefInfo(MRI_ModRef);
@@ -546,7 +534,7 @@ void GlobalsModRef::AnalyzeCallGraph(CallGraph &CG, Module &M) {
// The callgraph doesn't include intrinsic calls.
if (Callee->isIntrinsic()) {
FunctionModRefBehavior Behaviour =
- AliasAnalysis::getModRefBehavior(Callee);
+ AAResultBase::getModRefBehavior(Callee);
FI.addModRefInfo(ModRefInfo(Behaviour & MRI_ModRef));
}
}
@@ -599,8 +587,8 @@ void GlobalsModRef::AnalyzeCallGraph(CallGraph &CG, Module &M) {
// variables in this way to either not trust AA results while the escape is
// active, or to be forced to operate as a module pass that cannot co-exist
// with an alias analysis such as GMR.
-bool GlobalsModRef::isNonEscapingGlobalNoAlias(const GlobalValue *GV,
- const Value *V) {
+bool GlobalsAAResult::isNonEscapingGlobalNoAlias(const GlobalValue *GV,
+ const Value *V) {
// In order to know that the underlying object cannot alias the
// non-addr-taken global, we must know that it would have to be an escape.
// Thus if the underlying object is a function argument, a load from
@@ -631,8 +619,8 @@ bool GlobalsModRef::isNonEscapingGlobalNoAlias(const GlobalValue *GV,
Type *GVType = GVar->getInitializer()->getType();
Type *InputGVType = InputGVar->getInitializer()->getType();
if (GVType->isSized() && InputGVType->isSized() &&
- (DL->getTypeAllocSize(GVType) > 0) &&
- (DL->getTypeAllocSize(InputGVType) > 0))
+ (DL.getTypeAllocSize(GVType) > 0) &&
+ (DL.getTypeAllocSize(InputGVType) > 0))
continue;
}
@@ -651,7 +639,7 @@ bool GlobalsModRef::isNonEscapingGlobalNoAlias(const GlobalValue *GV,
if (auto *LI = dyn_cast<LoadInst>(Input)) {
// A pointer loaded from a global would have been captured, and we know
// that the global is non-escaping, so no alias.
- if (isa<GlobalValue>(GetUnderlyingObject(LI->getPointerOperand(), *DL)))
+ if (isa<GlobalValue>(GetUnderlyingObject(LI->getPointerOperand(), DL)))
continue;
// Otherwise, a load could come from anywhere, so bail.
@@ -665,8 +653,8 @@ bool GlobalsModRef::isNonEscapingGlobalNoAlias(const GlobalValue *GV,
if (++Depth > 4)
return false;
if (auto *SI = dyn_cast<SelectInst>(Input)) {
- const Value *LHS = GetUnderlyingObject(SI->getTrueValue(), *DL);
- const Value *RHS = GetUnderlyingObject(SI->getFalseValue(), *DL);
+ const Value *LHS = GetUnderlyingObject(SI->getTrueValue(), DL);
+ const Value *RHS = GetUnderlyingObject(SI->getFalseValue(), DL);
if (Visited.insert(LHS).second)
Inputs.push_back(LHS);
if (Visited.insert(RHS).second)
@@ -675,7 +663,7 @@ bool GlobalsModRef::isNonEscapingGlobalNoAlias(const GlobalValue *GV,
}
if (auto *PN = dyn_cast<PHINode>(Input)) {
for (const Value *Op : PN->incoming_values()) {
- Op = GetUnderlyingObject(Op, *DL);
+ Op = GetUnderlyingObject(Op, DL);
if (Visited.insert(Op).second)
Inputs.push_back(Op);
}
@@ -684,7 +672,7 @@ bool GlobalsModRef::isNonEscapingGlobalNoAlias(const GlobalValue *GV,
// FIXME: It would be good to handle other obvious no-alias cases here, but
// it isn't clear how to do so reasonbly without building a small version
- // of BasicAA into this code. We could recurse into AliasAnalysis::alias
+ // of BasicAA into this code. We could recurse into AAResultBase::alias
// here but that seems likely to go poorly as we're inside the
// implementation of such a query. Until then, just conservatievly retun
// false.
@@ -698,11 +686,11 @@ bool GlobalsModRef::isNonEscapingGlobalNoAlias(const GlobalValue *GV,
/// alias - If one of the pointers is to a global that we are tracking, and the
/// other is some random pointer, we know there cannot be an alias, because the
/// address of the global isn't taken.
-AliasResult GlobalsModRef::alias(const MemoryLocation &LocA,
- const MemoryLocation &LocB) {
+AliasResult GlobalsAAResult::alias(const MemoryLocation &LocA,
+ const MemoryLocation &LocB) {
// Get the base object these pointers point to.
- const Value *UV1 = GetUnderlyingObject(LocA.Ptr, *DL);
- const Value *UV2 = GetUnderlyingObject(LocB.Ptr, *DL);
+ const Value *UV1 = GetUnderlyingObject(LocA.Ptr, DL);
+ const Value *UV2 = GetUnderlyingObject(LocB.Ptr, DL);
// If either of the underlying values is a global, they may be non-addr-taken
// globals, which we can answer queries about.
@@ -774,16 +762,15 @@ AliasResult GlobalsModRef::alias(const MemoryLocation &LocA,
if ((GV1 || GV2) && GV1 != GV2)
return NoAlias;
- return AliasAnalysis::alias(LocA, LocB);
+ return AAResultBase::alias(LocA, LocB);
}
-ModRefInfo GlobalsModRef::getModRefInfo(ImmutableCallSite CS,
- const MemoryLocation &Loc) {
+ModRefInfo GlobalsAAResult::getModRefInfo(ImmutableCallSite CS,
+ const MemoryLocation &Loc) {
unsigned Known = MRI_ModRef;
// If we are asking for mod/ref info of a direct call with a pointer to a
// global we are tracking, return information if we have it.
- const DataLayout &DL = CS.getCaller()->getParent()->getDataLayout();
if (const GlobalValue *GV =
dyn_cast<GlobalValue>(GetUnderlyingObject(Loc.Ptr, DL)))
if (GV->hasLocalLinkage())
@@ -794,5 +781,68 @@ ModRefInfo GlobalsModRef::getModRefInfo(ImmutableCallSite CS,
if (Known == MRI_NoModRef)
return MRI_NoModRef; // No need to query other mod/ref analyses
- return ModRefInfo(Known & AliasAnalysis::getModRefInfo(CS, Loc));
+ return ModRefInfo(Known & AAResultBase::getModRefInfo(CS, Loc));
+}
+
+GlobalsAAResult::GlobalsAAResult(const DataLayout &DL,
+ const TargetLibraryInfo &TLI)
+ : AAResultBase(TLI), DL(DL) {}
+
+GlobalsAAResult::GlobalsAAResult(GlobalsAAResult &&Arg)
+ : AAResultBase(std::move(Arg)), DL(Arg.DL) {}
+
+/*static*/ GlobalsAAResult
+GlobalsAAResult::analyzeModule(Module &M, const TargetLibraryInfo &TLI,
+ CallGraph &CG) {
+ GlobalsAAResult Result(M.getDataLayout(), TLI);
+
+ // Find non-addr taken globals.
+ Result.AnalyzeGlobals(M);
+
+ // Propagate on CG.
+ Result.AnalyzeCallGraph(CG, M);
+
+ return Result;
+}
+
+GlobalsAAResult GlobalsAA::run(Module &M, AnalysisManager<Module> *AM) {
+ return GlobalsAAResult::analyzeModule(M,
+ AM->getResult<TargetLibraryAnalysis>(M),
+ AM->getResult<CallGraphAnalysis>(M));
+}
+
+char GlobalsAA::PassID;
+
+char GlobalsAAWrapperPass::ID = 0;
+INITIALIZE_PASS_BEGIN(GlobalsAAWrapperPass, "globals-aa",
+ "Globals Alias Analysis", false, true)
+INITIALIZE_PASS_DEPENDENCY(CallGraphWrapperPass)
+INITIALIZE_PASS_DEPENDENCY(TargetLibraryInfoWrapperPass)
+INITIALIZE_PASS_END(GlobalsAAWrapperPass, "globals-aa",
+ "Globals Alias Analysis", false, true)
+
+ModulePass *llvm::createGlobalsAAWrapperPass() {
+ return new GlobalsAAWrapperPass();
+}
+
+GlobalsAAWrapperPass::GlobalsAAWrapperPass() : ModulePass(ID) {
+ initializeGlobalsAAWrapperPassPass(*PassRegistry::getPassRegistry());
+}
+
+bool GlobalsAAWrapperPass::runOnModule(Module &M) {
+ Result.reset(new GlobalsAAResult(GlobalsAAResult::analyzeModule(
+ M, getAnalysis<TargetLibraryInfoWrapperPass>().getTLI(),
+ getAnalysis<CallGraphWrapperPass>().getCallGraph())));
+ return false;
+}
+
+bool GlobalsAAWrapperPass::doFinalization(Module &M) {
+ Result.reset();
+ return false;
+}
+
+void GlobalsAAWrapperPass::getAnalysisUsage(AnalysisUsage &AU) const {
+ AU.setPreservesAll();
+ AU.addRequired<CallGraphWrapperPass>();
+ AU.addRequired<TargetLibraryInfoWrapperPass>();
}
diff --git a/llvm/lib/Analysis/Lint.cpp b/llvm/lib/Analysis/Lint.cpp
index ca277f56a25..0f5599e8204 100644
--- a/llvm/lib/Analysis/Lint.cpp
+++ b/llvm/lib/Analysis/Lint.cpp
@@ -123,7 +123,7 @@ namespace {
void getAnalysisUsage(AnalysisUsage &AU) const override {
AU.setPreservesAll();
- AU.addRequired<AliasAnalysis>();
+ AU.addRequired<AAResultsWrapperPass>();
AU.addRequired<AssumptionCacheTracker>();
AU.addRequired<TargetLibraryInfoWrapperPass>();
AU.addRequired<DominatorTreeWrapperPass>();
@@ -167,7 +167,7 @@ INITIALIZE_PASS_BEGIN(Lint, "lint", "Statically lint-checks LLVM IR",
INITIALIZE_PASS_DEPENDENCY(AssumptionCacheTracker)
INITIALIZE_PASS_DEPENDENCY(TargetLibraryInfoWrapperPass)
INITIALIZE_PASS_DEPENDENCY(DominatorTreeWrapperPass)
-INITIALIZE_AG_DEPENDENCY(AliasAnalysis)
+INITIALIZE_PASS_DEPENDENCY(AAResultsWrapperPass)
INITIALIZE_PASS_END(Lint, "lint", "Statically lint-checks LLVM IR",
false, true)
@@ -181,7 +181,7 @@ INITIALIZE_PASS_END(Lint, "lint", "Statically lint-checks LLVM IR",
bool Lint::runOnFunction(Function &F) {
Mod = F.getParent();
DL = &F.getParent()->getDataLayout();
- AA = &getAnalysis<AliasAnalysis>();
+ AA = &getAnalysis<AAResultsWrapperPass>().getAAResults();
AC = &getAnalysis<AssumptionCacheTracker>().getAssumptionCache(F);
DT = &getAnalysis<DominatorTreeWrapperPass>().getDomTree();
TLI = &getAnalysis<TargetLibraryInfoWrapperPass>().getTLI();
diff --git a/llvm/lib/Analysis/LoopAccessAnalysis.cpp b/llvm/lib/Analysis/LoopAccessAnalysis.cpp
index 87dd8d47a65..14c3c57e4c9 100644
--- a/llvm/lib/Analysis/LoopAccessAnalysis.cpp
+++ b/llvm/lib/Analysis/LoopAccessAnalysis.cpp
@@ -1802,7 +1802,7 @@ bool LoopAccessAnalysis::runOnFunction(Function &F) {
SE = &getAnalysis<ScalarEvolutionWrapperPass>().getSE();
auto *TLIP = getAnalysisIfAvailable<TargetLibraryInfoWrapperPass>();
TLI = TLIP ? &TLIP->getTLI() : nullptr;
- AA = &getAnalysis<AliasAnalysis>();
+ AA = &getAnalysis<AAResultsWrapperPass>().getAAResults();
DT = &getAnalysis<DominatorTreeWrapperPass>().getDomTree();
LI = &getAnalysis<LoopInfoWrapperPass>().getLoopInfo();
@@ -1811,7 +1811,7 @@ bool LoopAccessAnalysis::runOnFunction(Function &F) {
void LoopAccessAnalysis::getAnalysisUsage(AnalysisUsage &AU) const {
AU.addRequired<ScalarEvolutionWrapperPass>();
- AU.addRequired<AliasAnalysis>();
+ AU.addRequired<AAResultsWrapperPass>();
AU.addRequired<DominatorTreeWrapperPass>();
AU.addRequired<LoopInfoWrapperPass>();
@@ -1823,7 +1823,7 @@ static const char laa_name[] = "Loop Access Analysis";
#define LAA_NAME "loop-accesses"
INITIALIZE_PASS_BEGIN(LoopAccessAnalysis, LAA_NAME, laa_name, false, true)
-INITIALIZE_AG_DEPENDENCY(AliasAnalysis)
+INITIALIZE_PASS_DEPENDENCY(AAResultsWrapperPass)
INITIALIZE_PASS_DEPENDENCY(ScalarEvolutionWrapperPass)
INITIALIZE_PASS_DEPENDENCY(DominatorTreeWrapperPass)
INITIALIZE_PASS_DEPENDENCY(LoopInfoWrapperPass)
diff --git a/llvm/lib/Analysis/MemDepPrinter.cpp b/llvm/lib/Analysis/MemDepPrinter.cpp
index 4d7c9b040b5..078cefe5180 100644
--- a/llvm/lib/Analysis/MemDepPrinter.cpp
+++ b/llvm/lib/Analysis/MemDepPrinter.cpp
@@ -49,7 +49,7 @@ namespace {
void print(raw_ostream &OS, const Module * = nullptr) const override;
void getAnalysisUsage(AnalysisUsage &AU) const override {
- AU.addRequiredTransitive<AliasAnalysis>();
+ AU.addRequiredTransitive<AAResultsWrapperPass>();
AU.addRequiredTransitive<MemoryDependenceAnalysis>();
AU.setPreservesAll();
}
diff --git a/llvm/lib/Analysis/MemoryDependenceAnalysis.cpp b/llvm/lib/Analysis/MemoryDependenceAnalysis.cpp
index decba79b5c7..07fd9cfbfc1 100644
--- a/llvm/lib/Analysis/MemoryDependenceAnalysis.cpp
+++ b/llvm/lib/Analysis/MemoryDependenceAnalysis.cpp
@@ -65,8 +65,8 @@ char MemoryDependenceAnalysis::ID = 0;
// Register this pass...
INITIALIZE_PASS_BEGIN(MemoryDependenceAnalysis, "memdep",
"Memory Dependence Analysis", false, true)
-INITIALIZE_AG_DEPENDENCY(AliasAnalysis)
INITIALIZE_PASS_DEPENDENCY(AssumptionCacheTracker)
+INITIALIZE_PASS_DEPENDENCY(AAResultsWrapperPass)
INITIALIZE_PASS_DEPENDENCY(TargetLibraryInfoWrapperPass)
INITIALIZE_PASS_END(MemoryDependenceAnalysis, "memdep",
"Memory Dependence Analysis", false, true)
@@ -94,12 +94,12 @@ void MemoryDependenceAnalysis::releaseMemory() {
void MemoryDependenceAnalysis::getAnalysisUsage(AnalysisUsage &AU) const {
AU.setPreservesAll();
AU.addRequired<AssumptionCacheTracker>();
- AU.addRequiredTransitive<AliasAnalysis>();
+ AU.addRequiredTransitive<AAResultsWrapperPass>();
AU.addRequiredTransitive<TargetLibraryInfoWrapperPass>();
}
bool MemoryDependenceAnalysis::runOnFunction(Function &F) {
- AA = &getAnalysis<AliasAnalysis>();
+ AA = &getAnalysis<AAResultsWrapperPass>().getAAResults();
AC = &getAnalysis<AssumptionCacheTracker>().getAssumptionCache(F);
DominatorTreeWrapperPass *DTWP =
getAnalysisIfAvailable<DominatorTreeWrapperPass>();
diff --git a/llvm/lib/Analysis/NoAliasAnalysis.cpp b/llvm/lib/Analysis/NoAliasAnalysis.cpp
deleted file mode 100644
index aa78ceab89c..00000000000
--- a/llvm/lib/Analysis/NoAliasAnalysis.cpp
+++ /dev/null
@@ -1,92 +0,0 @@
-//===- NoAliasAnalysis.cpp - Minimal Alias Analysis Impl ------------------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This file defines the default implementation of the Alias Analysis interface
-// that simply returns "I don't know" for all queries.
-//
-//===----------------------------------------------------------------------===//
-
-#include "llvm/Analysis/Passes.h"
-#include "llvm/Analysis/AliasAnalysis.h"
-#include "llvm/IR/DataLayout.h"
-#include "llvm/IR/LLVMContext.h"
-#include "llvm/IR/Module.h"
-#include "llvm/Pass.h"
-using namespace llvm;
-
-namespace {
- /// NoAA - This class implements the -no-aa pass, which always returns "I
- /// don't know" for alias queries. NoAA is unlike other alias analysis
- /// implementations, in that it does not chain to a previous analysis. As
- /// such it doesn't follow many of the rules that other alias analyses must.
- ///
- struct NoAA : public ImmutablePass, public AliasAnalysis {
- static char ID; // Class identification, replacement for typeinfo
- NoAA() : ImmutablePass(ID) {
- initializeNoAAPass(*PassRegistry::getPassRegistry());
- }
-
- void getAnalysisUsage(AnalysisUsage &AU) const override {}
-
- bool doInitialization(Module &M) override {
- // Note: NoAA does not call InitializeAliasAnalysis because it's
- // special and does not support chaining.
- DL = &M.getDataLayout();
- return true;
- }
-
- AliasResult alias(const MemoryLocation &LocA,
- const MemoryLocation &LocB) override {
- return MayAlias;
- }
-
- FunctionModRefBehavior getModRefBehavior(ImmutableCallSite CS) override {
- return FMRB_UnknownModRefBehavior;
- }
- FunctionModRefBehavior getModRefBehavior(const Function *F) override {
- return FMRB_UnknownModRefBehavior;
- }
-
- bool pointsToConstantMemory(const MemoryLocation &Loc,
- bool OrLocal) override {
- return false;
- }
- ModRefInfo getArgModRefInfo(ImmutableCallSite CS,
- unsigned ArgIdx) override {
- return MRI_ModRef;
- }
-
- ModRefInfo getModRefInfo(ImmutableCallSite CS,
- const MemoryLocation &Loc) override {
- return MRI_ModRef;
- }
- ModRefInfo getModRefInfo(ImmutableCallSite CS1,
- ImmutableCallSite CS2) override {
- return MRI_ModRef;
- }
-
- /// getAdjustedAnalysisPointer - This method is used when a pass implements
- /// an analysis interface through multiple inheritance. If needed, it
- /// should override this to adjust the this pointer as needed for the
- /// specified pass info.
- void *getAdjustedAnalysisPointer(const void *ID) override {
- if (ID == &AliasAnalysis::ID)
- return (AliasAnalysis*)this;
- return this;
- }
- };
-} // End of anonymous namespace
-
-// Register this pass...
-char NoAA::ID = 0;
-INITIALIZE_AG_PASS(NoAA, AliasAnalysis, "no-aa",
- "No Alias Analysis (always returns 'may' alias)",
- true, true, true)
-
-ImmutablePass *llvm::createNoAAPass() { return new NoAA(); }
diff --git a/llvm/lib/Analysis/ObjCARCAliasAnalysis.cpp b/llvm/lib/Analysis/ObjCARCAliasAnalysis.cpp
index 29b74119028..25f660ffe22 100644
--- a/llvm/lib/Analysis/ObjCARCAliasAnalysis.cpp
+++ b/llvm/lib/Analysis/ObjCARCAliasAnalysis.cpp
@@ -18,6 +18,9 @@
/// used. Naive LLVM IR transformations which would otherwise be
/// behavior-preserving may break these assumptions.
///
+/// TODO: Theoretically we could check for dependencies between objc_* calls
+/// and FMRB_OnlyAccessesArgumentPointees calls or other well-behaved calls.
+///
//===----------------------------------------------------------------------===//
#include "llvm/Analysis/ObjCARCAliasAnalysis.h"
@@ -34,46 +37,27 @@
using namespace llvm;
using namespace llvm::objcarc;
-// Register this pass...
-char ObjCARCAliasAnalysis::ID = 0;
-INITIALIZE_AG_PASS(ObjCARCAliasAnalysis, AliasAnalysis, "objc-arc-aa",
- "ObjC-ARC-Based Alias Analysis", false, true, false)
-
-ImmutablePass *llvm::createObjCARCAliasAnalysisPass() {
- return new ObjCARCAliasAnalysis();
-}
-
-bool ObjCARCAliasAnalysis::doInitialization(Module &M) {
- InitializeAliasAnalysis(this, &M.getDataLayout());
- return true;
-}
-
-void ObjCARCAliasAnalysis::getAnalysisUsage(AnalysisUsage &AU) const {
- AU.setPreservesAll();
- AliasAnalysis::getAnalysisUsage(AU);
-}
-
-AliasResult ObjCARCAliasAnalysis::alias(const MemoryLocation &LocA,
- const MemoryLocation &LocB) {
+AliasResult ObjCARCAAResult::alias(const MemoryLocation &LocA,
+ const MemoryLocation &LocB) {
if (!EnableARCOpts)
- return AliasAnalysis::alias(LocA, LocB);
+ return AAResultBase::alias(LocA, LocB);
// First, strip off no-ops, including ObjC-specific no-ops, and try making a
// precise alias query.
const Value *SA = GetRCIdentityRoot(LocA.Ptr);
const Value *SB = GetRCIdentityRoot(LocB.Ptr);
AliasResult Result =
- AliasAnalysis::alias(MemoryLocation(SA, LocA.Size, LocA.AATags),
- MemoryLocation(SB, LocB.Size, LocB.AATags));
+ AAResultBase::alias(MemoryLocation(SA, LocA.Size, LocA.AATags),
+ MemoryLocation(SB, LocB.Size, LocB.AATags));
if (Result != MayAlias)
return Result;
// If that failed, climb to the underlying object, including climbing through
// ObjC-specific no-ops, and try making an imprecise alias query.
- const Value *UA = GetUnderlyingObjCPtr(SA, *DL);
- const Value *UB = GetUnderlyingObjCPtr(SB, *DL);
+ const Value *UA = GetUnderlyingObjCPtr(SA, DL);
+ const Value *UB = GetUnderlyingObjCPtr(SB, DL);
if (UA != SA || UB != SB) {
- Result = AliasAnalysis::alias(MemoryLocation(UA), MemoryLocation(UB));
+ Result = AAResultBase::alias(MemoryLocation(UA), MemoryLocation(UB));
// We can't use MustAlias or PartialAlias results here because
// GetUnderlyingObjCPtr may return an offsetted pointer value.
if (Result == NoAlias)
@@ -85,39 +69,32 @@ AliasResult ObjCARCAliasAnalysis::alias(const MemoryLocation &LocA,
return MayAlias;
}
-bool ObjCARCAliasAnalysis::pointsToConstantMemory(const MemoryLocation &Loc,
- bool OrLocal) {
+bool ObjCARCAAResult::pointsToConstantMemory(const MemoryLocation &Loc,
+ bool OrLocal) {
if (!EnableARCOpts)
- return AliasAnalysis::pointsToConstantMemory(Loc, OrLocal);
+ return AAResultBase::pointsToConstantMemory(Loc, OrLocal);
// First, strip off no-ops, including ObjC-specific no-ops, and try making
// a precise alias query.
const Value *S = GetRCIdentityRoot(Loc.Ptr);
- if (AliasAnalysis::pointsToConstantMemory(
+ if (AAResultBase::pointsToConstantMemory(
MemoryLocation(S, Loc.Size, Loc.AATags), OrLocal))
return true;
// If that failed, climb to the underlying object, including climbing through
// ObjC-specific no-ops, and try making an imprecise alias query.
- const Value *U = GetUnderlyingObjCPtr(S, *DL);
+ const Value *U = GetUnderlyingObjCPtr(S, DL);
if (U != S)
- return AliasAnalysis::pointsToConstantMemory(MemoryLocation(U), OrLocal);
+ return AAResultBase::pointsToConstantMemory(MemoryLocation(U), OrLocal);
// If that failed, fail. We don't need to chain here, since that's covered
// by the earlier precise query.
return false;
}
-FunctionModRefBehavior
-ObjCARCAliasAnalysis::getModRefBehavior(ImmutableCallSite CS) {
- // We have nothing to do. Just chain to the next AliasAnalysis.
- return AliasAnalysis::getModRefBehavior(CS);
-}
-
-FunctionModRefBehavior
-ObjCARCAliasAnalysis::getModRefBehavior(const Function *F) {
+FunctionModRefBehavior ObjCARCAAResult::getModRefBehavior(const Function *F) {
if (!EnableARCOpts)
- return AliasAnalysis::getModRefBehavior(F);
+ return AAResultBase::getModRefBehavior(F);
switch (GetFunctionClass(F)) {
case ARCInstKind::NoopCast:
@@ -126,13 +103,13 @@ ObjCARCAliasAnalysis::getModRefBehavior(const Function *F) {
break;
}
- return AliasAnalysis::getModRefBehavior(F);
+ return AAResultBase::getModRefBehavior(F);
}
-ModRefInfo ObjCARCAliasAnalysis::getModRefInfo(ImmutableCallSite CS,
- const MemoryLocation &Loc) {
+ModRefInfo ObjCARCAAResult::getModRefInfo(ImmutableCallSite CS,
+ const MemoryLocation &Loc) {
if (!EnableARCOpts)
- return AliasAnalysis::getModRefInfo(CS, Loc);
+ return AAResultBase::getModRefInfo(CS, Loc);
switch (GetBasicARCInstKind(CS.getInstruction())) {
case ARCInstKind::Retain:
@@ -151,12 +128,43 @@ ModRefInfo ObjCARCAliasAnalysis::getModRefInfo(ImmutableCallSite CS,
break;
}
- return AliasAnalysis::getModRefInfo(CS, Loc);
+ return AAResultBase::getModRefInfo(CS, Loc);
+}
+
+ObjCARCAAResult ObjCARCAA::run(Function &F, AnalysisManager<Function> *AM) {
+ return ObjCARCAAResult(F.getParent()->getDataLayout(),
+ AM->getResult<TargetLibraryAnalysis>(F));
}
-ModRefInfo ObjCARCAliasAnalysis::getModRefInfo(ImmutableCallSite CS1,
- ImmutableCallSite CS2) {
- // TODO: Theoretically we could check for dependencies between objc_* calls
- // and FMRB_OnlyAccessesArgumentPointees calls or other well-behaved calls.
- return AliasAnalysis::getModRefInfo(CS1, CS2);
+char ObjCARCAA::PassID;
+
+char ObjCARCAAWrapperPass::ID = 0;
+INITIALIZE_PASS_BEGIN(ObjCARCAAWrapperPass, "objc-arc-aa",
+ "ObjC-ARC-Based Alias Analysis", false, true)
+INITIALIZE_PASS_DEPENDENCY(TargetLibraryInfoWrapperPass)
+INITIALIZE_PASS_END(ObjCARCAAWrapperPass, "objc-arc-aa",
+ "ObjC-ARC-Based Alias Analysis", false, true)
+
+ImmutablePass *llvm::createObjCARCAAWrapperPass() {
+ return new ObjCARCAAWrapperPass();
+}
+
+ObjCARCAAWrapperPass::ObjCARCAAWrapperPass() : ImmutablePass(ID) {
+ initializeObjCARCAAWrapperPassPass(*PassRegistry::getPassRegistry());
+}
+
+bool ObjCARCAAWrapperPass::doInitialization(Module &M) {
+ Result.reset(new ObjCARCAAResult(
+ M.getDataLayout(), getAnalysis<TargetLibraryInfoWrapperPass>().getTLI()));
+ return false;
+}
+
+bool ObjCARCAAWrapperPass::doFinalization(Module &M) {
+ Result.reset();
+ return false;
+}
+
+void ObjCARCAAWrapperPass::getAnalysisUsage(AnalysisUsage &AU) const {
+ AU.setPreservesAll();
+ AU.addRequired<TargetLibraryInfoWrapperPass>();
}
diff --git a/llvm/lib/Analysis/ScalarEvolutionAliasAnalysis.cpp b/llvm/lib/Analysis/ScalarEvolutionAliasAnalysis.cpp
index 6fcf27ea4ab..2e50c80c4e7 100644
--- a/llvm/lib/Analysis/ScalarEvolutionAliasAnalysis.cpp
+++ b/llvm/lib/Analysis/ScalarEvolutionAliasAnalysis.cpp
@@ -20,66 +20,20 @@
//===----------------------------------------------------------------------===//
#include "llvm/Analysis/ScalarEvolutionAliasAnalysis.h"
+#include "llvm/Analysis/TargetLibraryInfo.h"
using namespace llvm;
-// Register this pass...
-char ScalarEvolutionAliasAnalysis::ID = 0;
-INITIALIZE_AG_PASS_BEGIN(ScalarEvolutionAliasAnalysis, AliasAnalysis, "scev-aa",
- "ScalarEvolution-based Alias Analysis", false, true,
- false)
-INITIALIZE_PASS_DEPENDENCY(ScalarEvolutionWrapperPass)
-INITIALIZE_AG_PASS_END(ScalarEvolutionAliasAnalysis, AliasAnalysis, "scev-aa",
- "ScalarEvolution-based Alias Analysis", false, true,
- false)
-
-FunctionPass *llvm::createScalarEvolutionAliasAnalysisPass() {
- return new ScalarEvolutionAliasAnalysis();
-}
-
-void ScalarEvolutionAliasAnalysis::getAnalysisUsage(AnalysisUsage &AU) const {
- AU.addRequiredTransitive<ScalarEvolutionWrapperPass>();
- AU.setPreservesAll();
- AliasAnalysis::getAnalysisUsage(AU);
-}
-
-bool ScalarEvolutionAliasAnalysis::runOnFunction(Function &F) {
- InitializeAliasAnalysis(this, &F.getParent()->getDataLayout());
- SE = &getAnalysis<ScalarEvolutionWrapperPass>().getSE();
- return false;
-}
-
-/// Given an expression, try to find a base value.
-///
-/// Returns null if none was found.
-Value *ScalarEvolutionAliasAnalysis::GetBaseValue(const SCEV *S) {
- if (const SCEVAddRecExpr *AR = dyn_cast<SCEVAddRecExpr>(S)) {
- // In an addrec, assume that the base will be in the start, rather
- // than the step.
- return GetBaseValue(AR->getStart());
- } else if (const SCEVAddExpr *A = dyn_cast<SCEVAddExpr>(S)) {
- // If there's a pointer operand, it'll be sorted at the end of the list.
- const SCEV *Last = A->getOperand(A->getNumOperands() - 1);
- if (Last->getType()->isPointerTy())
- return GetBaseValue(Last);
- } else if (const SCEVUnknown *U = dyn_cast<SCEVUnknown>(S)) {
- // This is a leaf node.
- return U->getValue();
- }
- // No Identified object found.
- return nullptr;
-}
-
-AliasResult ScalarEvolutionAliasAnalysis::alias(const MemoryLocation &LocA,
- const MemoryLocation &LocB) {
+AliasResult SCEVAAResult::alias(const MemoryLocation &LocA,
+ const MemoryLocation &LocB) {
// If either of the memory references is empty, it doesn't matter what the
// pointer values are. This allows the code below to ignore this special
// case.
if (LocA.Size == 0 || LocB.Size == 0)
return NoAlias;
- // This is ScalarEvolutionAliasAnalysis. Get the SCEVs!
- const SCEV *AS = SE->getSCEV(const_cast<Value *>(LocA.Ptr));
- const SCEV *BS = SE->getSCEV(const_cast<Value *>(LocB.Ptr));
+ // This is SCEVAAResult. Get the SCEVs!
+ const SCEV *AS = SE.getSCEV(const_cast<Value *>(LocA.Ptr));
+ const SCEV *BS = SE.getSCEV(const_cast<Value *>(LocB.Ptr));
// If they evaluate to the same expression, it's a MustAlias.
if (AS == BS)
@@ -87,20 +41,20 @@ AliasResult ScalarEvolutionAliasAnalysis::alias(const MemoryLocation &LocA,
// If something is known about the difference between the two addresses,
// see if it's enough to prove a NoAlias.
- if (SE->getEffectiveSCEVType(AS->getType()) ==
- SE->getEffectiveSCEVType(BS->getType())) {
- unsigned BitWidth = SE->getTypeSizeInBits(AS->getType());
+ if (SE.getEffectiveSCEVType(AS->getType()) ==
+ SE.getEffectiveSCEVType(BS->getType())) {
+ unsigned BitWidth = SE.getTypeSizeInBits(AS->getType());
APInt ASizeInt(BitWidth, LocA.Size);
APInt BSizeInt(BitWidth, LocB.Size);
// Compute the difference between the two pointers.
- const SCEV *BA = SE->getMinusSCEV(BS, AS);
+ const SCEV *BA = SE.getMinusSCEV(BS, AS);
// Test whether the difference is known to be great enough that memory of
// the given sizes don't overlap. This assumes that ASizeInt and BSizeInt
// are non-zero, which is special-cased above.
- if (ASizeInt.ule(SE->getUnsignedRange(BA).getUnsignedMin()) &&
- (-BSizeInt).uge(SE->getUnsignedRange(BA).getUnsignedMax()))
+ if (ASizeInt.ule(SE.getUnsignedRange(BA).getUnsignedMin()) &&
+ (-BSizeInt).uge(SE.getUnsignedRange(BA).getUnsignedMax()))
return NoAlias;
// Folding the subtraction while preserving range information can be tricky
@@ -108,13 +62,13 @@ AliasResult ScalarEvolutionAliasAnalysis::alias(const MemoryLocation &LocA,
// and try again to see if things fold better that way.
// Compute the difference between the two pointers.
- const SCEV *AB = SE->getMinusSCEV(AS, BS);
+ const SCEV *AB = SE.getMinusSCEV(AS, BS);
// Test whether the difference is known to be great enough that memory of
// the given sizes don't overlap. This assumes that ASizeInt and BSizeInt
// are non-zero, which is special-cased above.
- if (BSizeInt.ule(SE->getUnsignedRange(AB).getUnsignedMin()) &&
- (-ASizeInt).uge(SE->getUnsignedRange(AB).getUnsignedMax()))
+ if (BSizeInt.ule(SE.getUnsignedRange(AB).getUnsignedMin()) &&
+ (-ASizeInt).uge(SE.getUnsignedRange(AB).getUnsignedMax()))
return NoAlias;
}
@@ -133,5 +87,62 @@ AliasResult ScalarEvolutionAliasAnalysis::alias(const MemoryLocation &LocA,
return NoAlias;
// Forward the query to the next analysis.
- return AliasAnalysis::alias(LocA, LocB);
+ return AAResultBase::alias(LocA, LocB);
+}
+
+/// Given an expression, try to find a base value.
+///
+/// Returns null if none was found.
+Value *SCEVAAResult::GetBaseValue(const SCEV *S) {
+ if (const SCEVAddRecExpr *AR = dyn_cast<SCEVAddRecExpr>(S)) {
+ // In an addrec, assume that the base will be in the start, rather
+ // than the step.
+ return GetBaseValue(AR->getStart());
+ } else if (const SCEVAddExpr *A = dyn_cast<SCEVAddExpr>(S)) {
+ // If there's a pointer operand, it'll be sorted at the end of the list.
+ const SCEV *Last = A->getOperand(A->getNumOperands() - 1);
+ if (Last->getType()->isPointerTy())
+ return GetBaseValue(Last);
+ } else if (const SCEVUnknown *U = dyn_cast<SCEVUnknown>(S)) {
+ // This is a leaf node.
+ return U->getValue();
+ }
+ // No Identified object found.
+ return nullptr;
+}
+
+SCEVAAResult SCEVAA::run(Function &F, AnalysisManager<Function> *AM) {
+ return SCEVAAResult(AM->getResult<TargetLibraryAnalysis>(F),
+ AM->getResult<ScalarEvolutionAnalysis>(F));
+}
+
+char SCEVAA::PassID;
+
+char SCEVAAWrapperPass::ID = 0;
+INITIALIZE_PASS_BEGIN(SCEVAAWrapperPass, "scev-aa",
+ "ScalarEvolution-based Alias Analysis", false, true)
+INITIALIZE_PASS_DEPENDENCY(ScalarEvolutionWrapperPass)
+INITIALIZE_PASS_DEPENDENCY(TargetLibraryInfoWrapperPass)
+INITIALIZE_PASS_END(SCEVAAWrapperPass, "scev-aa",
+ "ScalarEvolution-based Alias Analysis", false, true)
+
+FunctionPass *llvm::createSCEVAAWrapperPass() {
+ return new SCEVAAWrapperPass();
+}
+
+SCEVAAWrapperPass::SCEVAAWrapperPass() : FunctionPass(ID) {
+ initializeSCEVAAWrapperPassPass(*PassRegistry::getPassRegistry());
+}
+
+bool SCEVAAWrapperPass::runOnFunction(Function &F) {
+ Result.reset(
+ new SCEVAAResult(getAnalysis<TargetLibraryInfoWrapperPass>().getTLI(),
+ getAnalysis<ScalarEvolutionWrapperPass>().getSE()));
+ return false;
+}
+
+void SCEVAAWrapperPass::getAnalysisUsage(AnalysisUsage &AU) const {
+ AU.setPreservesAll();
+ AU.addRequired<ScalarEvolutionWrapperPass>();
+ AU.addRequired<TargetLibraryInfoWrapperPass>();
}
diff --git a/llvm/lib/Analysis/ScopedNoAliasAA.cpp b/llvm/lib/Analysis/ScopedNoAliasAA.cpp
index 2ff9c0c31f5..7d70f4c77b2 100644
--- a/llvm/lib/Analysis/ScopedNoAliasAA.cpp
+++ b/llvm/lib/Analysis/ScopedNoAliasAA.cpp
@@ -34,7 +34,7 @@
#include "llvm/Analysis/ScopedNoAliasAA.h"
#include "llvm/ADT/SmallPtrSet.h"
-#include "llvm/Analysis/AliasAnalysis.h"
+#include "llvm/Analysis/TargetLibraryInfo.h"
#include "llvm/IR/Constants.h"
#include "llvm/IR/LLVMContext.h"
#include "llvm/IR/Metadata.h"
@@ -72,26 +72,62 @@ public:
};
} // End of anonymous namespace
-// Register this pass...
-char ScopedNoAliasAA::ID = 0;
-INITIALIZE_AG_PASS(ScopedNoAliasAA, AliasAnalysis, "scoped-noalias",
- "Scoped NoAlias Alias Analysis", false, true, false)
+AliasResult ScopedNoAliasAAResult::alias(const MemoryLocation &LocA,
+ const MemoryLocation &LocB) {
+ if (!EnableScopedNoAlias)
+ return AAResultBase::alias(LocA, LocB);
+
+ // Get the attached MDNodes.
+ const MDNode *AScopes = LocA.AATags.Scope, *BScopes = LocB.AATags.Scope;
+
+ const MDNode *ANoAlias = LocA.AATags.NoAlias, *BNoAlias = LocB.AATags.NoAlias;
+
+ if (!mayAliasInScopes(AScopes, BNoAlias))
+ return NoAlias;
+
+ if (!mayAliasInScopes(BScopes, ANoAlias))
+ return NoAlias;
-ImmutablePass *llvm::createScopedNoAliasAAPass() {
- return new ScopedNoAliasAA();
+ // If they may alias, chain to the next AliasAnalysis.
+ return AAResultBase::alias(LocA, LocB);
}
-bool ScopedNoAliasAA::doInitialization(Module &M) {
- InitializeAliasAnalysis(this, &M.getDataLayout());
- return true;
+ModRefInfo ScopedNoAliasAAResult::getModRefInfo(ImmutableCallSite CS,
+ const MemoryLocation &Loc) {
+ if (!EnableScopedNoAlias)
+ return AAResultBase::getModRefInfo(CS, Loc);
+
+ if (!mayAliasInScopes(Loc.AATags.Scope, CS.getInstruction()->getMetadata(
+ LLVMContext::MD_noalias)))
+ return MRI_NoModRef;
+
+ if (!mayAliasInScopes(
+ CS.getInstruction()->getMetadata(LLVMContext::MD_alias_scope),
+ Loc.AATags.NoAlias))
+ return MRI_NoModRef;
+
+ return AAResultBase::getModRefInfo(CS, Loc);
}
-void ScopedNoAliasAA::getAnalysisUsage(AnalysisUsage &AU) const {
- AU.setPreservesAll();
- AliasAnalysis::getAnalysisUsage(AU);
+ModRefInfo ScopedNoAliasAAResult::getModRefInfo(ImmutableCallSite CS1,
+ ImmutableCallSite CS2) {
+ if (!EnableScopedNoAlias)
+ return AAResultBase::getModRefInfo(CS1, CS2);
+
+ if (!mayAliasInScopes(
+ CS1.getInstruction()->getMetadata(LLVMContext::MD_alias_scope),
+ CS2.getInstruction()->getMetadata(LLVMContext::MD_noalias)))
+ return MRI_NoModRef;
+
+ if (!mayAliasInScopes(
+ CS2.getInstruction()->getMetadata(LLVMContext::MD_alias_scope),
+ CS1.getInstruction()->getMetadata(LLVMContext::MD_noalias)))
+ return MRI_NoModRef;
+
+ return AAResultBase::getModRefInfo(CS1, CS2);
}
-void ScopedNoAliasAA::collectMDInDomain(
+void ScopedNoAliasAAResult::collectMDInDomain(
const MDNode *List, const MDNode *Domain,
SmallPtrSetImpl<const MDNode *> &Nodes) const {
for (unsigned i = 0, ie = List->getNumOperands(); i != ie; ++i)
@@ -100,8 +136,8 @@ void ScopedNoAliasAA::collectMDInDomain(
Nodes.insert(MD);
}
-bool ScopedNoAliasAA::mayAliasInScopes(const MDNode *Scopes,
- const MDNode *NoAlias) const {
+bool ScopedNoAliasAAResult::mayAliasInScopes(const MDNode *Scopes,
+ const MDNode *NoAlias) const {
if (!Scopes || !NoAlias)
return true;
@@ -136,72 +172,40 @@ bool ScopedNoAliasAA::mayAliasInScopes(const MDNode *Scopes,
return true;
}
-AliasResult ScopedNoAliasAA::alias(const MemoryLocation &LocA,
- const MemoryLocation &LocB) {
- if (!EnableScopedNoAlias)
- return AliasAnalysis::alias(LocA, LocB);
-
- // Get the attached MDNodes.
- const MDNode *AScopes = LocA.AATags.Scope, *BScopes = LocB.AATags.Scope;
-
- const MDNode *ANoAlias = LocA.AATags.NoAlias, *BNoAlias = LocB.AATags.NoAlias;
+ScopedNoAliasAAResult ScopedNoAliasAA::run(Function &F,
+ AnalysisManager<Function> *AM) {
+ return ScopedNoAliasAAResult(AM->getResult<TargetLibraryAnalysis>(F));
+}
- if (!mayAliasInScopes(AScopes, BNoAlias))
- return NoAlias;
+char ScopedNoAliasAA::PassID;
- if (!mayAliasInScopes(BScopes, ANoAlias))
- return NoAlias;
+char ScopedNoAliasAAWrapperPass::ID = 0;
+INITIALIZE_PASS_BEGIN(ScopedNoAliasAAWrapperPass, "scoped-noalias",
+ "Scoped NoAlias Alias Analysis", false, true)
+INITIALIZE_PASS_DEPENDENCY(TargetLibraryInfoWrapperPass)
+INITIALIZE_PASS_END(ScopedNoAliasAAWrapperPass, "scoped-noalias",
+ "Scoped NoAlias Alias Analysis", false, true)
- // If they may alias, chain to the next AliasAnalysis.
- return AliasAnalysis::alias(LocA, LocB);
-}
-
-bool ScopedNoAliasAA::pointsToConstantMemory(const MemoryLocation &Loc,
- bool OrLocal) {
- return AliasAnalysis::pointsToConstantMemory(Loc, OrLocal);
+ImmutablePass *llvm::createScopedNoAliasAAWrapperPass() {
+ return new ScopedNoAliasAAWrapperPass();
}
-FunctionModRefBehavior
-ScopedNoAliasAA::getModRefBehavior(ImmutableCallSite CS) {
- return AliasAnalysis::getModRefBehavior(CS);
+ScopedNoAliasAAWrapperPass::ScopedNoAliasAAWrapperPass() : ImmutablePass(ID) {
+ initializeScopedNoAliasAAWrapperPassPass(*PassRegistry::getPassRegistry());
}
-FunctionModRefBehavior ScopedNoAliasAA::getModRefBehavior(const Function *F) {
- return AliasAnalysis::getModRefBehavior(F);
+bool ScopedNoAliasAAWrapperPass::doInitialization(Module &M) {
+ Result.reset(new ScopedNoAliasAAResult(
+ getAnalysis<TargetLibraryInfoWrapperPass>().getTLI()));
+ return false;
}
-ModRefInfo ScopedNoAliasAA::getModRefInfo(ImmutableCallSite CS,
- const MemoryLocation &Loc) {
- if (!EnableScopedNoAlias)
- return AliasAnalysis::getModRefInfo(CS, Loc);
-
- if (!mayAliasInScopes(Loc.AATags.Scope, CS.getInstruction()->getMetadata(
- LLVMContext::MD_noalias)))
- return MRI_NoModRef;
-
- if (!mayAliasInScopes(
- CS.getInstruction()->getMetadata(LLVMContext::MD_alias_scope),
- Loc.AATags.NoAlias))
- return MRI_NoModRef;
-
- return AliasAnalysis::getModRefInfo(CS, Loc);
+bool ScopedNoAliasAAWrapperPass::doFinalization(Module &M) {
+ Result.reset();
+ return false;
}
-ModRefInfo ScopedNoAliasAA::getModRefInfo(ImmutableCallSite CS1,
- ImmutableCallSite CS2) {
- if (!EnableScopedNoAlias)
- return AliasAnalysis::getModRefInfo(CS1, CS2);
-
- if (!mayAliasInScopes(
- CS1.getInstruction()->getMetadata(LLVMContext::MD_alias_scope),
- CS2.getInstruction()->getMetadata(LLVMContext::MD_noalias)))
- return MRI_NoModRef;
-
- if (!mayAliasInScopes(
- CS2.getInstruction()->getMetadata(LLVMContext::MD_alias_scope),
- CS1.getInstruction()->getMetadata(LLVMContext::MD_noalias)))
- return MRI_NoModRef;
-
- return AliasAnalysis::getModRefInfo(CS1, CS2);
+void ScopedNoAliasAAWrapperPass::getAnalysisUsage(AnalysisUsage &AU) const {
+ AU.setPreservesAll();
+ AU.addRequired<TargetLibraryInfoWrapperPass>();
}
-
diff --git a/llvm/lib/Analysis/TypeBasedAliasAnalysis.cpp b/llvm/lib/Analysis/TypeBasedAliasAnalysis.cpp
index ebef8e1b3af..805f3efb081 100644
--- a/llvm/lib/Analysis/TypeBasedAliasAnalysis.cpp
+++ b/llvm/lib/Analysis/TypeBasedAliasAnalysis.cpp
@@ -122,6 +122,7 @@
//===----------------------------------------------------------------------===//
#include "llvm/Analysis/TypeBasedAliasAnalysis.h"
+#include "llvm/Analysis/TargetLibraryInfo.h"
#include "llvm/ADT/SetVector.h"
#include "llvm/IR/Constants.h"
#include "llvm/IR/LLVMContext.h"
@@ -269,25 +270,6 @@ public:
};
}
-// Register this pass...
-char TypeBasedAliasAnalysis::ID = 0;
-INITIALIZE_AG_PASS(TypeBasedAliasAnalysis, AliasAnalysis, "tbaa",
- "Type-Based Alias Analysis", false, true, false)
-
-ImmutablePass *llvm::createTypeBasedAliasAnalysisPass() {
- return new TypeBasedAliasAnalysis();
-}
-
-bool TypeBasedAliasAnalysis::doInitialization(Module &M) {
- InitializeAliasAnalysis(this, &M.getDataLayout());
- return true;
-}
-
-void TypeBasedAliasAnalysis::getAnalysisUsage(AnalysisUsage &AU) const {
- AU.setPreservesAll();
- AliasAnalysis::getAnalysisUsage(AU);
-}
-
/// Check the first operand of the tbaa tag node, if it is a MDNode, we treat
/// it as struct-path aware TBAA format, otherwise, we treat it as scalar TBAA
/// format.
@@ -297,145 +279,36 @@ static bool isStructPathTBAA(const MDNode *MD) {
return isa<MDNode>(MD->getOperand(0)) && MD->getNumOperands() >= 3;
}
-/// Aliases - Test whether the type represented by A may alias the
-/// type represented by B.
-bool TypeBasedAliasAnalysis::Aliases(const MDNode *A, const MDNode *B) const {
- // Make sure that both MDNodes are struct-path aware.
- if (isStructPathTBAA(A) && isStructPathTBAA(B))
- return PathAliases(A, B);
-
- // Keep track of the root node for A and B.
- TBAANode RootA, RootB;
-
- // Climb the tree from A to see if we reach B.
- for (TBAANode T(A);;) {
- if (T.getNode() == B)
- // B is an ancestor of A.
- return true;
-
- RootA = T;
- T = T.getParent();
- if (!T.getNode())
- break;
- }
-
- // Climb the tree from B to see if we reach A.
- for (TBAANode T(B);;) {
- if (T.getNode() == A)
- // A is an ancestor of B.
- return true;
-
- RootB = T;
- T = T.getParent();
- if (!T.getNode())
- break;
- }
-
- // Neither node is an ancestor of the other.
-
- // If they have different roots, they're part of different potentially
- // unrelated type systems, so we must be conservative.
- if (RootA.getNode() != RootB.getNode())
- return true;
-
- // If they have the same root, then we've proved there's no alias.
- return false;
-}
-
-/// Test whether the struct-path tag represented by A may alias the
-/// struct-path tag represented by B.
-bool TypeBasedAliasAnalysis::PathAliases(const MDNode *A,
- const MDNode *B) const {
- // Verify that both input nodes are struct-path aware.
- assert(isStructPathTBAA(A) && "MDNode A is not struct-path aware.");
- assert(isStructPathTBAA(B) && "MDNode B is not struct-path aware.");
-
- // Keep track of the root node for A and B.
- TBAAStructTypeNode RootA, RootB;
- TBAAStructTagNode TagA(A), TagB(B);
-
- // TODO: We need to check if AccessType of TagA encloses AccessType of
- // TagB to support aggregate AccessType. If yes, return true.
-
- // Start from the base type of A, follow the edge with the correct offset in
- // the type DAG and adjust the offset until we reach the base type of B or
- // until we reach the Root node.
- // Compare the adjusted offset once we have the same base.
-
- // Climb the type DAG from base type of A to see if we reach base type of B.
- const MDNode *BaseA = TagA.getBaseType();
- const MDNode *BaseB = TagB.getBaseType();
- uint64_t OffsetA = TagA.getOffset(), OffsetB = TagB.getOffset();
- for (TBAAStructTypeNode T(BaseA);;) {
- if (T.getNode() == BaseB)
- // Base type of A encloses base type of B, check if the offsets match.
- return OffsetA == OffsetB;
-
- RootA = T;
- // Follow the edge with the correct offset, OffsetA will be adjusted to
- // be relative to the field type.
- T = T.getParent(OffsetA);
- if (!T.getNode())
- break;
- }
-
- // Reset OffsetA and climb the type DAG from base type of B to see if we reach
- // base type of A.
- OffsetA = TagA.getOffset();
- for (TBAAStructTypeNode T(BaseB);;) {
- if (T.getNode() == BaseA)
- // Base type of B encloses base type of A, check if the offsets match.
- return OffsetA == OffsetB;
-
- RootB = T;
- // Follow the edge with the correct offset, OffsetB will be adjusted to
- // be relative to the field type.
- T = T.getParent(OffsetB);
- if (!T.getNode())
- break;
- }
-
- // Neither node is an ancestor of the other.
-
- // If they have different roots, they're part of different potentially
- // unrelated type systems, so we must be conservative.
- if (RootA.getNode() != RootB.getNode())
- return true;
-
- // If they have the same root, then we've proved there's no alias.
- return false;
-}
-
-AliasResult TypeBasedAliasAnalysis::alias(const MemoryLocation &LocA,
- const MemoryLocation &LocB) {
+AliasResult TypeBasedAAResult::alias(const MemoryLocation &LocA,
+ const MemoryLocation &LocB) {
if (!EnableTBAA)
- return AliasAnalysis::alias(LocA, LocB);
+ return AAResultBase::alias(LocA, LocB);
// Get the attached MDNodes. If either value lacks a tbaa MDNode, we must
// be conservative.
const MDNode *AM = LocA.AATags.TBAA;
if (!AM)
- return AliasAnalysis::alias(LocA, LocB);
+ return AAResultBase::alias(LocA, LocB);
const MDNode *BM = LocB.AATags.TBAA;
if (!BM)
- return AliasAnalysis::alias(LocA, LocB);
+ return AAResultBase::alias(LocA, LocB);
// If they may alias, chain to the next AliasAnalysis.
if (Aliases(AM, BM))
- return AliasAnalysis::alias(LocA, LocB);
+ return AAResultBase::alias(LocA, LocB);
// Otherwise return a definitive result.
return NoAlias;
}
-bool TypeBasedAliasAnalysis::pointsToConstantMemory(const MemoryLocation &Loc,
- bool OrLocal) {
+bool TypeBasedAAResult::pointsToConstantMemory(const MemoryLocation &Loc,
+ bool OrLocal) {
if (!EnableTBAA)
- return AliasAnalysis::pointsToConstantMemory(Loc, OrLocal);
+ return AAResultBase::pointsToConstantMemory(Loc, OrLocal);
const MDNode *M = Loc.AATags.TBAA;
if (!M)
- return AliasAnalysis::pointsToConstantMemory(Loc, OrLocal);
+ return AAResultBase::pointsToConstantMemory(Loc, OrLocal);
// If this is an "immutable" type, we can assume the pointer is pointing
// to constant memory.
@@ -443,13 +316,13 @@ bool TypeBasedAliasAnalysis::pointsToConstantMemory(const MemoryLocation &Loc,
(isStructPathTBAA(M) && TBAAStructTagNode(M).TypeIsImmutable()))
return true;
- return AliasAnalysis::pointsToConstantMemory(Loc, OrLocal);
+ return AAResultBase::pointsToConstantMemory(Loc, OrLocal);
}
FunctionModRefBehavior
-TypeBasedAliasAnalysis::getModRefBehavior(ImmutableCallSite CS) {
+TypeBasedAAResult::getModRefBehavior(ImmutableCallSite CS) {
if (!EnableTBAA)
- return AliasAnalysis::getModRefBehavior(CS);
+ return AAResultBase::getModRefBehavior(CS);
FunctionModRefBehavior Min = FMRB_UnknownModRefBehavior;
@@ -460,19 +333,18 @@ TypeBasedAliasAnalysis::getModRefBehavior(ImmutableCallSite CS) {
(isStructPathTBAA(M) && TBAAStructTagNode(M).TypeIsImmutable()))
Min = FMRB_OnlyReadsMemory;
- return FunctionModRefBehavior(AliasAnalysis::getModRefBehavior(CS) & Min);
+ return FunctionModRefBehavior(AAResultBase::getModRefBehavior(CS) & Min);
}
-FunctionModRefBehavior
-TypeBasedAliasAnalysis::getModRefBehavior(const Function *F) {
+FunctionModRefBehavior TypeBasedAAResult::getModRefBehavior(const Function *F) {
// Functions don't have metadata. Just chain to the next implementation.
- return AliasAnalysis::getModRefBehavior(F);
+ return AAResultBase::getModRefBehavior(F);
}
-ModRefInfo TypeBasedAliasAnalysis::getModRefInfo(ImmutableCallSite CS,
- const MemoryLocation &Loc) {
+ModRefInfo TypeBasedAAResult::getModRefInfo(ImmutableCallSite CS,
+ const MemoryLocation &Loc) {
if (!EnableTBAA)
- return AliasAnalysis::getModRefInfo(CS, Loc);
+ return AAResultBase::getModRefInfo(CS, Loc);
if (const MDNode *L = Loc.AATags.TBAA)
if (const MDNode *M =
@@ -480,13 +352,13 @@ ModRefInfo TypeBasedAliasAnalysis::getModRefInfo(ImmutableCallSite CS,
if (!Aliases(L, M))
return MRI_NoModRef;
- return AliasAnalysis::getModRefInfo(CS, Loc);
+ return AAResultBase::getModRefInfo(CS, Loc);
}
-ModRefInfo TypeBasedAliasAnalysis::getModRefInfo(ImmutableCallSite CS1,
- ImmutableCallSite CS2) {
+ModRefInfo TypeBasedAAResult::getModRefInfo(ImmutableCallSite CS1,
+ ImmutableCallSite CS2) {
if (!EnableTBAA)
- return AliasAnalysis::getModRefInfo(CS1, CS2);
+ return AAResultBase::getModRefInfo(CS1, CS2);
if (const MDNode *M1 =
CS1.getInstruction()->getMetadata(LLVMContext::MD_tbaa))
@@ -495,7 +367,7 @@ ModRefInfo TypeBasedAliasAnalysis::getModRefInfo(ImmutableCallSite CS1,
if (!Aliases(M1, M2))
return MRI_NoModRef;
- return AliasAnalysis::getModRefInfo(CS1, CS2);
+ return AAResultBase::getModRefInfo(CS1, CS2);
}
bool MDNode::isTBAAVtableAccess() const {
@@ -604,3 +476,147 @@ void Instruction::getAAMetadata(AAMDNodes &N, bool Merge) const {
N.NoAlias = getMetadata(LLVMContext::MD_noalias);
}
+/// Aliases - Test whether the type represented by A may alias the
+/// type represented by B.
+bool TypeBasedAAResult::Aliases(const MDNode *A, const MDNode *B) const {
+ // Make sure that both MDNodes are struct-path aware.
+ if (isStructPathTBAA(A) && isStructPathTBAA(B))
+ return PathAliases(A, B);
+
+ // Keep track of the root node for A and B.
+ TBAANode RootA, RootB;
+
+ // Climb the tree from A to see if we reach B.
+ for (TBAANode T(A);;) {
+ if (T.getNode() == B)
+ // B is an ancestor of A.
+ return true;
+
+ RootA = T;
+ T = T.getParent();
+ if (!T.getNode())
+ break;
+ }
+
+ // Climb the tree from B to see if we reach A.
+ for (TBAANode T(B);;) {
+ if (T.getNode() == A)
+ // A is an ancestor of B.
+ return true;
+
+ RootB = T;
+ T = T.getParent();
+ if (!T.getNode())
+ break;
+ }
+
+ // Neither node is an ancestor of the other.
+
+ // If they have different roots, they're part of different potentially
+ // unrelated type systems, so we must be conservative.
+ if (RootA.getNode() != RootB.getNode())
+ return true;
+
+ // If they have the same root, then we've proved there's no alias.
+ return false;
+}
+
+/// Test whether the struct-path tag represented by A may alias the
+/// struct-path tag represented by B.
+bool TypeBasedAAResult::PathAliases(const MDNode *A, const MDNode *B) const {
+ // Verify that both input nodes are struct-path aware.
+ assert(isStructPathTBAA(A) && "MDNode A is not struct-path aware.");
+ assert(isStructPathTBAA(B) && "MDNode B is not struct-path aware.");
+
+ // Keep track of the root node for A and B.
+ TBAAStructTypeNode RootA, RootB;
+ TBAAStructTagNode TagA(A), TagB(B);
+
+ // TODO: We need to check if AccessType of TagA encloses AccessType of
+ // TagB to support aggregate AccessType. If yes, return true.
+
+ // Start from the base type of A, follow the edge with the correct offset in
+ // the type DAG and adjust the offset until we reach the base type of B or
+ // until we reach the Root node.
+ // Compare the adjusted offset once we have the same base.
+
+ // Climb the type DAG from base type of A to see if we reach base type of B.
+ const MDNode *BaseA = TagA.getBaseType();
+ const MDNode *BaseB = TagB.getBaseType();
+ uint64_t OffsetA = TagA.getOffset(), OffsetB = TagB.getOffset();
+ for (TBAAStructTypeNode T(BaseA);;) {
+ if (T.getNode() == BaseB)
+ // Base type of A encloses base type of B, check if the offsets match.
+ return OffsetA == OffsetB;
+
+ RootA = T;
+ // Follow the edge with the correct offset, OffsetA will be adjusted to
+ // be relative to the field type.
+ T = T.getParent(OffsetA);
+ if (!T.getNode())
+ break;
+ }
+
+ // Reset OffsetA and climb the type DAG from base type of B to see if we reach
+ // base type of A.
+ OffsetA = TagA.getOffset();
+ for (TBAAStructTypeNode T(BaseB);;) {
+ if (T.getNode() == BaseA)
+ // Base type of B encloses base type of A, check if the offsets match.
+ return OffsetA == OffsetB;
+
+ RootB = T;
+ // Follow the edge with the correct offset, OffsetB will be adjusted to
+ // be relative to the field type.
+ T = T.getParent(OffsetB);
+ if (!T.getNode())
+ break;
+ }
+
+ // Neither node is an ancestor of the other.
+
+ // If they have different roots, they're part of different potentially
+ // unrelated type systems, so we must be conservative.
+ if (RootA.getNode() != RootB.getNode())
+ return true;
+
+ // If they have the same root, then we've proved there's no alias.
+ return false;
+}
+
+TypeBasedAAResult TypeBasedAA::run(Function &F, AnalysisManager<Function> *AM) {
+ return TypeBasedAAResult(AM->getResult<TargetLibraryAnalysis>(F));
+}
+
+char TypeBasedAA::PassID;
+
+char TypeBasedAAWrapperPass::ID = 0;
+INITIALIZE_PASS_BEGIN(TypeBasedAAWrapperPass, "tbaa",
+ "Type-Based Alias Analysis", false, true)
+INITIALIZE_PASS_DEPENDENCY(TargetLibraryInfoWrapperPass)
+INITIALIZE_PASS_END(TypeBasedAAWrapperPass, "tbaa", "Type-Based Alias Analysis",
+ false, true)
+
+ImmutablePass *llvm::createTypeBasedAAWrapperPass() {
+ return new TypeBasedAAWrapperPass();
+}
+
+TypeBasedAAWrapperPass::TypeBasedAAWrapperPass() : ImmutablePass(ID) {
+ initializeTypeBasedAAWrapperPassPass(*PassRegistry::getPassRegistry());
+}
+
+bool TypeBasedAAWrapperPass::doInitialization(Module &M) {
+ Result.reset(new TypeBasedAAResult(
+ getAnalysis<TargetLibraryInfoWrapperPass>().getTLI()));
+ return false;
+}
+
+bool TypeBasedAAWrapperPass::doFinalization(Module &M) {
+ Result.reset();
+ return false;
+}
+
+void TypeBasedAAWrapperPass::getAnalysisUsage(AnalysisUsage &AU) const {
+ AU.setPreservesAll();
+ AU.addRequired<TargetLibraryInfoWrapperPass>();
+}
OpenPOWER on IntegriCloud