diff options
Diffstat (limited to 'llvm/lib/Analysis/AliasAnalysis.cpp')
| -rw-r--r-- | llvm/lib/Analysis/AliasAnalysis.cpp | 100 |
1 files changed, 81 insertions, 19 deletions
diff --git a/llvm/lib/Analysis/AliasAnalysis.cpp b/llvm/lib/Analysis/AliasAnalysis.cpp index fec2415a0e45..fae7a84332fd 100644 --- a/llvm/lib/Analysis/AliasAnalysis.cpp +++ b/llvm/lib/Analysis/AliasAnalysis.cpp @@ -24,6 +24,7 @@ //===----------------------------------------------------------------------===// #include "llvm/Analysis/AliasAnalysis.h" +#include "llvm/ADT/Statistic.h" #include "llvm/Analysis/BasicAliasAnalysis.h" #include "llvm/Analysis/CFLAndersAliasAnalysis.h" #include "llvm/Analysis/CFLSteensAliasAnalysis.h" @@ -54,12 +55,17 @@ #include <functional> #include <iterator> +#define DEBUG_TYPE "aa" + using namespace llvm; +STATISTIC(NumNoAlias, "Number of NoAlias results"); +STATISTIC(NumMayAlias, "Number of MayAlias results"); +STATISTIC(NumMustAlias, "Number of MustAlias results"); + /// 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-basic-aa", cl::Hidden, - cl::init(false)); +cl::opt<bool> DisableBasicAA("disable-basic-aa", cl::Hidden, cl::init(false)); AAResults::AAResults(AAResults &&Arg) : TLI(Arg.TLI), AAs(std::move(Arg.AAs)), AADeps(std::move(Arg.AADeps)) { @@ -110,12 +116,25 @@ AliasResult AAResults::alias(const MemoryLocation &LocA, AliasResult AAResults::alias(const MemoryLocation &LocA, const MemoryLocation &LocB, AAQueryInfo &AAQI) { + AliasResult Result = MayAlias; + + Depth++; for (const auto &AA : AAs) { - auto Result = AA->alias(LocA, LocB, AAQI); + Result = AA->alias(LocA, LocB, AAQI); if (Result != MayAlias) - return Result; + break; + } + Depth--; + + if (Depth == 0) { + if (Result == NoAlias) + ++NumNoAlias; + else if (Result == MustAlias) + ++NumMustAlias; + else + ++NumMayAlias; } - return MayAlias; + return Result; } bool AAResults::pointsToConstantMemory(const MemoryLocation &Loc, @@ -215,7 +234,7 @@ ModRefInfo AAResults::getModRefInfo(const CallBase *Call, unsigned ArgIdx = std::distance(Call->arg_begin(), AI); MemoryLocation ArgLoc = MemoryLocation::getForArgument(Call, ArgIdx, TLI); - AliasResult ArgAlias = alias(ArgLoc, Loc); + AliasResult ArgAlias = alias(ArgLoc, Loc, AAQI); if (ArgAlias != NoAlias) { ModRefInfo ArgMask = getArgModRefInfo(Call, ArgIdx); AllArgsMask = unionModRef(AllArgsMask, ArgMask); @@ -235,7 +254,7 @@ ModRefInfo AAResults::getModRefInfo(const CallBase *Call, // If Loc is a constant memory location, the call definitely could not // modify the memory location. - if (isModSet(Result) && pointsToConstantMemory(Loc, /*OrLocal*/ false)) + if (isModSet(Result) && pointsToConstantMemory(Loc, AAQI, /*OrLocal*/ false)) Result = clearMod(Result); return Result; @@ -312,7 +331,7 @@ ModRefInfo AAResults::getModRefInfo(const CallBase *Call1, // ModRefC1 indicates what Call1 might do to Call2ArgLoc, and we use // above ArgMask to update dependence info. - ModRefInfo ModRefC1 = getModRefInfo(Call1, Call2ArgLoc); + ModRefInfo ModRefC1 = getModRefInfo(Call1, Call2ArgLoc, AAQI); ArgMask = intersectModRef(ArgMask, ModRefC1); // Conservatively clear IsMustAlias unless only MustAlias is found. @@ -353,7 +372,7 @@ ModRefInfo AAResults::getModRefInfo(const CallBase *Call1, // might Mod Call1ArgLoc, then we care about either a Mod or a Ref by // Call2. If Call1 might Ref, then we care only about a Mod by Call2. ModRefInfo ArgModRefC1 = getArgModRefInfo(Call1, Call1ArgIdx); - ModRefInfo ModRefC2 = getModRefInfo(Call2, Call1ArgLoc); + ModRefInfo ModRefC2 = getModRefInfo(Call2, Call1ArgLoc, AAQI); if ((isModSet(ArgModRefC1) && isModOrRefSet(ModRefC2)) || (isRefSet(ArgModRefC1) && isModSet(ModRefC2))) R = intersectModRef(unionModRef(R, ArgModRefC1), Result); @@ -628,6 +647,43 @@ ModRefInfo AAResults::getModRefInfo(const AtomicRMWInst *RMW, return ModRefInfo::ModRef; } +ModRefInfo AAResults::getModRefInfo(const Instruction *I, + const Optional<MemoryLocation> &OptLoc, + AAQueryInfo &AAQIP) { + if (OptLoc == None) { + if (const auto *Call = dyn_cast<CallBase>(I)) { + return createModRefInfo(getModRefBehavior(Call)); + } + } + + const MemoryLocation &Loc = OptLoc.getValueOr(MemoryLocation()); + + switch (I->getOpcode()) { + case Instruction::VAArg: + return getModRefInfo((const VAArgInst *)I, Loc, AAQIP); + case Instruction::Load: + return getModRefInfo((const LoadInst *)I, Loc, AAQIP); + case Instruction::Store: + return getModRefInfo((const StoreInst *)I, Loc, AAQIP); + case Instruction::Fence: + return getModRefInfo((const FenceInst *)I, Loc, AAQIP); + case Instruction::AtomicCmpXchg: + return getModRefInfo((const AtomicCmpXchgInst *)I, Loc, AAQIP); + case Instruction::AtomicRMW: + return getModRefInfo((const AtomicRMWInst *)I, Loc, AAQIP); + case Instruction::Call: + return getModRefInfo((const CallInst *)I, Loc, AAQIP); + case Instruction::Invoke: + return getModRefInfo((const InvokeInst *)I, Loc, AAQIP); + case Instruction::CatchPad: + return getModRefInfo((const CatchPadInst *)I, Loc, AAQIP); + case Instruction::CatchRet: + return getModRefInfo((const CatchReturnInst *)I, Loc, AAQIP); + default: + return ModRefInfo::NoModRef; + } +} + /// Return information about whether a particular call site modifies /// or reads the specified memory location \p MemLoc before instruction \p I /// in a BasicBlock. @@ -641,8 +697,7 @@ ModRefInfo AAResults::callCapturesBefore(const Instruction *I, if (!DT) return ModRefInfo::ModRef; - const Value *Object = - GetUnderlyingObject(MemLoc.Ptr, I->getModule()->getDataLayout()); + const Value *Object = getUnderlyingObject(MemLoc.Ptr); if (!isIdentifiedObject(Object) || isa<GlobalValue>(Object) || isa<Constant>(Object)) return ModRefInfo::ModRef; @@ -670,7 +725,7 @@ ModRefInfo AAResults::callCapturesBefore(const Instruction *I, !Call->isByValArgument(ArgNo))) continue; - AliasResult AR = alias(MemoryLocation(*CI), MemoryLocation(Object)); + AliasResult AR = alias(*CI, Object); // If this is a no-capture pointer argument, see if we can tell that it // 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 @@ -828,8 +883,8 @@ bool AAResultsWrapperPass::runOnFunction(Function &F) { void AAResultsWrapperPass::getAnalysisUsage(AnalysisUsage &AU) const { AU.setPreservesAll(); - AU.addRequired<BasicAAWrapperPass>(); - AU.addRequired<TargetLibraryInfoWrapperPass>(); + AU.addRequiredTransitive<BasicAAWrapperPass>(); + AU.addRequiredTransitive<TargetLibraryInfoWrapperPass>(); // 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 @@ -845,6 +900,13 @@ void AAResultsWrapperPass::getAnalysisUsage(AnalysisUsage &AU) const { AU.addUsedIfAvailable<ExternalAAWrapperPass>(); } +AAManager::Result AAManager::run(Function &F, FunctionAnalysisManager &AM) { + Result R(AM.getResult<TargetLibraryAnalysis>(F)); + for (auto &Getter : ResultGetters) + (*Getter)(F, AM, R); + return R; +} + AAResults llvm::createLegacyPMAAResults(Pass &P, Function &F, BasicAAResult &BAR) { AAResults AAR(P.getAnalysis<TargetLibraryInfoWrapperPass>().getTLI(F)); @@ -881,9 +943,9 @@ bool llvm::isNoAliasCall(const Value *V) { return false; } -bool llvm::isNoAliasArgument(const Value *V) { +static bool isNoAliasOrByValArgument(const Value *V) { if (const Argument *A = dyn_cast<Argument>(V)) - return A->hasNoAliasAttr(); + return A->hasNoAliasAttr() || A->hasByValAttr(); return false; } @@ -894,13 +956,13 @@ bool llvm::isIdentifiedObject(const Value *V) { return true; if (isNoAliasCall(V)) return true; - if (const Argument *A = dyn_cast<Argument>(V)) - return A->hasNoAliasAttr() || A->hasByValAttr(); + if (isNoAliasOrByValArgument(V)) + return true; return false; } bool llvm::isIdentifiedFunctionLocal(const Value *V) { - return isa<AllocaInst>(V) || isNoAliasCall(V) || isNoAliasArgument(V); + return isa<AllocaInst>(V) || isNoAliasCall(V) || isNoAliasOrByValArgument(V); } void llvm::getAAResultsAnalysisUsage(AnalysisUsage &AU) { |
