123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026 |
- //==- AliasAnalysis.cpp - Generic Alias Analysis Interface Implementation --==//
- //
- // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
- // See https://llvm.org/LICENSE.txt for license information.
- // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
- //
- //===----------------------------------------------------------------------===//
- //
- // This file implements the generic AliasAnalysis interface which is used as the
- // common interface used by all clients and implementations of alias analysis.
- //
- // This file also implements the default version of the AliasAnalysis interface
- // that is to be used when no other implementation is specified. This does some
- // simple tests that detect obvious cases: two different global pointers cannot
- // alias, a global cannot alias a malloc, two different mallocs cannot alias,
- // etc.
- //
- // This alias analysis implementation really isn't very good for anything, but
- // it is very fast, and makes a nice clean default implementation. Because it
- // handles lots of little corner cases, other, more complex, alias analysis
- // implementations may choose to rely on this pass to resolve these simple and
- // easy cases.
- //
- //===----------------------------------------------------------------------===//
- #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"
- #include "llvm/Analysis/CaptureTracking.h"
- #include "llvm/Analysis/GlobalsModRef.h"
- #include "llvm/Analysis/MemoryLocation.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/Argument.h"
- #include "llvm/IR/Attributes.h"
- #include "llvm/IR/BasicBlock.h"
- #include "llvm/IR/Instruction.h"
- #include "llvm/IR/Instructions.h"
- #include "llvm/IR/Module.h"
- #include "llvm/IR/Type.h"
- #include "llvm/IR/Value.h"
- #include "llvm/InitializePasses.h"
- #include "llvm/Pass.h"
- #include "llvm/Support/AtomicOrdering.h"
- #include "llvm/Support/Casting.h"
- #include "llvm/Support/CommandLine.h"
- #include <algorithm>
- #include <cassert>
- #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");
- namespace llvm {
- /// Allow disabling BasicAA from the AA results. This is particularly useful
- /// when testing to isolate a single AA implementation.
- cl::opt<bool> DisableBasicAA("disable-basic-aa", cl::Hidden, cl::init(false));
- } // namespace llvm
- #ifndef NDEBUG
- /// Print a trace of alias analysis queries and their results.
- static cl::opt<bool> EnableAATrace("aa-trace", cl::Hidden, cl::init(false));
- #else
- static const bool EnableAATrace = false;
- #endif
- AAResults::AAResults(AAResults &&Arg)
- : TLI(Arg.TLI), AAs(std::move(Arg.AAs)), AADeps(std::move(Arg.AADeps)) {
- for (auto &AA : AAs)
- AA->setAAResults(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
- }
- bool AAResults::invalidate(Function &F, const PreservedAnalyses &PA,
- FunctionAnalysisManager::Invalidator &Inv) {
- // AAResults preserves the AAManager by default, due to the stateless nature
- // of AliasAnalysis. There is no need to check whether it has been preserved
- // explicitly. Check if any module dependency was invalidated and caused the
- // AAManager to be invalidated. Invalidate ourselves in that case.
- auto PAC = PA.getChecker<AAManager>();
- if (!PAC.preservedWhenStateless())
- return true;
- // Check if any of the function dependencies were invalidated, and invalidate
- // ourselves in that case.
- for (AnalysisKey *ID : AADeps)
- if (Inv.invalidate(ID, F, PA))
- return true;
- // Everything we depend on is still fine, so are we. Nothing to invalidate.
- return false;
- }
- //===----------------------------------------------------------------------===//
- // Default chaining methods
- //===----------------------------------------------------------------------===//
- AliasResult AAResults::alias(const MemoryLocation &LocA,
- const MemoryLocation &LocB) {
- SimpleAAQueryInfo AAQIP;
- return alias(LocA, LocB, AAQIP);
- }
- AliasResult AAResults::alias(const MemoryLocation &LocA,
- const MemoryLocation &LocB, AAQueryInfo &AAQI) {
- AliasResult Result = AliasResult::MayAlias;
- if (EnableAATrace) {
- for (unsigned I = 0; I < AAQI.Depth; ++I)
- dbgs() << " ";
- dbgs() << "Start " << *LocA.Ptr << " @ " << LocA.Size << ", "
- << *LocB.Ptr << " @ " << LocB.Size << "\n";
- }
- AAQI.Depth++;
- for (const auto &AA : AAs) {
- Result = AA->alias(LocA, LocB, AAQI);
- if (Result != AliasResult::MayAlias)
- break;
- }
- AAQI.Depth--;
- if (EnableAATrace) {
- for (unsigned I = 0; I < AAQI.Depth; ++I)
- dbgs() << " ";
- dbgs() << "End " << *LocA.Ptr << " @ " << LocA.Size << ", "
- << *LocB.Ptr << " @ " << LocB.Size << " = " << Result << "\n";
- }
- if (AAQI.Depth == 0) {
- if (Result == AliasResult::NoAlias)
- ++NumNoAlias;
- else if (Result == AliasResult::MustAlias)
- ++NumMustAlias;
- else
- ++NumMayAlias;
- }
- return Result;
- }
- bool AAResults::pointsToConstantMemory(const MemoryLocation &Loc,
- bool OrLocal) {
- SimpleAAQueryInfo AAQIP;
- return pointsToConstantMemory(Loc, AAQIP, OrLocal);
- }
- bool AAResults::pointsToConstantMemory(const MemoryLocation &Loc,
- AAQueryInfo &AAQI, bool OrLocal) {
- for (const auto &AA : AAs)
- if (AA->pointsToConstantMemory(Loc, AAQI, OrLocal))
- return true;
- return false;
- }
- ModRefInfo AAResults::getArgModRefInfo(const CallBase *Call, unsigned ArgIdx) {
- ModRefInfo Result = ModRefInfo::ModRef;
- for (const auto &AA : AAs) {
- Result = intersectModRef(Result, AA->getArgModRefInfo(Call, ArgIdx));
- // Early-exit the moment we reach the bottom of the lattice.
- if (isNoModRef(Result))
- return ModRefInfo::NoModRef;
- }
- return Result;
- }
- ModRefInfo AAResults::getModRefInfo(Instruction *I, const CallBase *Call2) {
- SimpleAAQueryInfo AAQIP;
- return getModRefInfo(I, Call2, AAQIP);
- }
- ModRefInfo AAResults::getModRefInfo(Instruction *I, const CallBase *Call2,
- AAQueryInfo &AAQI) {
- // We may have two calls.
- if (const auto *Call1 = dyn_cast<CallBase>(I)) {
- // Check if the two calls modify the same memory.
- return getModRefInfo(Call1, Call2, AAQI);
- }
- // If this is a fence, just return ModRef.
- if (I->isFenceLike())
- return ModRefInfo::ModRef;
- // Otherwise, check if the call modifies or references the
- // location this memory access defines. The best we can say
- // is that if the call references what this instruction
- // defines, it must be clobbered by this location.
- const MemoryLocation DefLoc = MemoryLocation::get(I);
- ModRefInfo MR = getModRefInfo(Call2, DefLoc, AAQI);
- if (isModOrRefSet(MR))
- return setModAndRef(MR);
- return ModRefInfo::NoModRef;
- }
- ModRefInfo AAResults::getModRefInfo(const CallBase *Call,
- const MemoryLocation &Loc) {
- SimpleAAQueryInfo AAQIP;
- return getModRefInfo(Call, Loc, AAQIP);
- }
- ModRefInfo AAResults::getModRefInfo(const CallBase *Call,
- const MemoryLocation &Loc,
- AAQueryInfo &AAQI) {
- ModRefInfo Result = ModRefInfo::ModRef;
- for (const auto &AA : AAs) {
- Result = intersectModRef(Result, AA->getModRefInfo(Call, Loc, AAQI));
- // Early-exit the moment we reach the bottom of the lattice.
- if (isNoModRef(Result))
- return ModRefInfo::NoModRef;
- }
- // Try to refine the mod-ref info further using other API entry points to the
- // aggregate set of AA results.
- auto MRB = getModRefBehavior(Call);
- if (onlyAccessesInaccessibleMem(MRB))
- return ModRefInfo::NoModRef;
- if (onlyReadsMemory(MRB))
- Result = clearMod(Result);
- else if (onlyWritesMemory(MRB))
- Result = clearRef(Result);
- if (onlyAccessesArgPointees(MRB) || onlyAccessesInaccessibleOrArgMem(MRB)) {
- bool IsMustAlias = true;
- ModRefInfo AllArgsMask = ModRefInfo::NoModRef;
- if (doesAccessArgPointees(MRB)) {
- for (const auto &I : llvm::enumerate(Call->args())) {
- const Value *Arg = I.value();
- if (!Arg->getType()->isPointerTy())
- continue;
- unsigned ArgIdx = I.index();
- MemoryLocation ArgLoc =
- MemoryLocation::getForArgument(Call, ArgIdx, TLI);
- AliasResult ArgAlias = alias(ArgLoc, Loc, AAQI);
- if (ArgAlias != AliasResult::NoAlias) {
- ModRefInfo ArgMask = getArgModRefInfo(Call, ArgIdx);
- AllArgsMask = unionModRef(AllArgsMask, ArgMask);
- }
- // Conservatively clear IsMustAlias unless only MustAlias is found.
- IsMustAlias &= (ArgAlias == AliasResult::MustAlias);
- }
- }
- // Return NoModRef if no alias found with any argument.
- if (isNoModRef(AllArgsMask))
- return ModRefInfo::NoModRef;
- // Logical & between other AA analyses and argument analysis.
- Result = intersectModRef(Result, AllArgsMask);
- // If only MustAlias found above, set Must bit.
- Result = IsMustAlias ? setMust(Result) : clearMust(Result);
- }
- // If Loc is a constant memory location, the call definitely could not
- // modify the memory location.
- if (isModSet(Result) && pointsToConstantMemory(Loc, AAQI, /*OrLocal*/ false))
- Result = clearMod(Result);
- return Result;
- }
- ModRefInfo AAResults::getModRefInfo(const CallBase *Call1,
- const CallBase *Call2) {
- SimpleAAQueryInfo AAQIP;
- return getModRefInfo(Call1, Call2, AAQIP);
- }
- ModRefInfo AAResults::getModRefInfo(const CallBase *Call1,
- const CallBase *Call2, AAQueryInfo &AAQI) {
- ModRefInfo Result = ModRefInfo::ModRef;
- for (const auto &AA : AAs) {
- Result = intersectModRef(Result, AA->getModRefInfo(Call1, Call2, AAQI));
- // Early-exit the moment we reach the bottom of the lattice.
- if (isNoModRef(Result))
- return ModRefInfo::NoModRef;
- }
- // Try to refine the mod-ref info further using other API entry points to the
- // aggregate set of AA results.
- // If Call1 or Call2 are readnone, they don't interact.
- auto Call1B = getModRefBehavior(Call1);
- if (Call1B == FMRB_DoesNotAccessMemory)
- return ModRefInfo::NoModRef;
- auto Call2B = getModRefBehavior(Call2);
- if (Call2B == FMRB_DoesNotAccessMemory)
- return ModRefInfo::NoModRef;
- // If they both only read from memory, there is no dependence.
- if (onlyReadsMemory(Call1B) && onlyReadsMemory(Call2B))
- return ModRefInfo::NoModRef;
- // If Call1 only reads memory, the only dependence on Call2 can be
- // from Call1 reading memory written by Call2.
- if (onlyReadsMemory(Call1B))
- Result = clearMod(Result);
- else if (onlyWritesMemory(Call1B))
- Result = clearRef(Result);
- // If Call2 only access memory through arguments, accumulate the mod/ref
- // information from Call1's references to the memory referenced by
- // Call2's arguments.
- if (onlyAccessesArgPointees(Call2B)) {
- if (!doesAccessArgPointees(Call2B))
- return ModRefInfo::NoModRef;
- ModRefInfo R = ModRefInfo::NoModRef;
- bool IsMustAlias = true;
- for (auto I = Call2->arg_begin(), E = Call2->arg_end(); I != E; ++I) {
- const Value *Arg = *I;
- if (!Arg->getType()->isPointerTy())
- continue;
- unsigned Call2ArgIdx = std::distance(Call2->arg_begin(), I);
- auto Call2ArgLoc =
- MemoryLocation::getForArgument(Call2, Call2ArgIdx, TLI);
- // ArgModRefC2 indicates what Call2 might do to Call2ArgLoc, and the
- // dependence of Call1 on that location is the inverse:
- // - If Call2 modifies location, dependence exists if Call1 reads or
- // writes.
- // - If Call2 only reads location, dependence exists if Call1 writes.
- ModRefInfo ArgModRefC2 = getArgModRefInfo(Call2, Call2ArgIdx);
- ModRefInfo ArgMask = ModRefInfo::NoModRef;
- if (isModSet(ArgModRefC2))
- ArgMask = ModRefInfo::ModRef;
- else if (isRefSet(ArgModRefC2))
- ArgMask = ModRefInfo::Mod;
- // ModRefC1 indicates what Call1 might do to Call2ArgLoc, and we use
- // above ArgMask to update dependence info.
- ModRefInfo ModRefC1 = getModRefInfo(Call1, Call2ArgLoc, AAQI);
- ArgMask = intersectModRef(ArgMask, ModRefC1);
- // Conservatively clear IsMustAlias unless only MustAlias is found.
- IsMustAlias &= isMustSet(ModRefC1);
- R = intersectModRef(unionModRef(R, ArgMask), Result);
- if (R == Result) {
- // On early exit, not all args were checked, cannot set Must.
- if (I + 1 != E)
- IsMustAlias = false;
- break;
- }
- }
- if (isNoModRef(R))
- return ModRefInfo::NoModRef;
- // If MustAlias found above, set Must bit.
- return IsMustAlias ? setMust(R) : clearMust(R);
- }
- // If Call1 only accesses memory through arguments, check if Call2 references
- // any of the memory referenced by Call1's arguments. If not, return NoModRef.
- if (onlyAccessesArgPointees(Call1B)) {
- if (!doesAccessArgPointees(Call1B))
- return ModRefInfo::NoModRef;
- ModRefInfo R = ModRefInfo::NoModRef;
- bool IsMustAlias = true;
- for (auto I = Call1->arg_begin(), E = Call1->arg_end(); I != E; ++I) {
- const Value *Arg = *I;
- if (!Arg->getType()->isPointerTy())
- continue;
- unsigned Call1ArgIdx = std::distance(Call1->arg_begin(), I);
- auto Call1ArgLoc =
- MemoryLocation::getForArgument(Call1, Call1ArgIdx, TLI);
- // ArgModRefC1 indicates what Call1 might do to Call1ArgLoc; if 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, AAQI);
- if ((isModSet(ArgModRefC1) && isModOrRefSet(ModRefC2)) ||
- (isRefSet(ArgModRefC1) && isModSet(ModRefC2)))
- R = intersectModRef(unionModRef(R, ArgModRefC1), Result);
- // Conservatively clear IsMustAlias unless only MustAlias is found.
- IsMustAlias &= isMustSet(ModRefC2);
- if (R == Result) {
- // On early exit, not all args were checked, cannot set Must.
- if (I + 1 != E)
- IsMustAlias = false;
- break;
- }
- }
- if (isNoModRef(R))
- return ModRefInfo::NoModRef;
- // If MustAlias found above, set Must bit.
- return IsMustAlias ? setMust(R) : clearMust(R);
- }
- return Result;
- }
- FunctionModRefBehavior AAResults::getModRefBehavior(const CallBase *Call) {
- FunctionModRefBehavior Result = FMRB_UnknownModRefBehavior;
- for (const auto &AA : AAs) {
- Result = FunctionModRefBehavior(Result & AA->getModRefBehavior(Call));
- // Early-exit the moment we reach the bottom of the lattice.
- if (Result == FMRB_DoesNotAccessMemory)
- return Result;
- }
- return Result;
- }
- FunctionModRefBehavior AAResults::getModRefBehavior(const Function *F) {
- FunctionModRefBehavior Result = FMRB_UnknownModRefBehavior;
- for (const auto &AA : AAs) {
- Result = FunctionModRefBehavior(Result & AA->getModRefBehavior(F));
- // Early-exit the moment we reach the bottom of the lattice.
- if (Result == FMRB_DoesNotAccessMemory)
- return Result;
- }
- return Result;
- }
- raw_ostream &llvm::operator<<(raw_ostream &OS, AliasResult AR) {
- switch (AR) {
- case AliasResult::NoAlias:
- OS << "NoAlias";
- break;
- case AliasResult::MustAlias:
- OS << "MustAlias";
- break;
- case AliasResult::MayAlias:
- OS << "MayAlias";
- break;
- case AliasResult::PartialAlias:
- OS << "PartialAlias";
- if (AR.hasOffset())
- OS << " (off " << AR.getOffset() << ")";
- break;
- }
- return OS;
- }
- //===----------------------------------------------------------------------===//
- // Helper method implementation
- //===----------------------------------------------------------------------===//
- ModRefInfo AAResults::getModRefInfo(const LoadInst *L,
- const MemoryLocation &Loc) {
- SimpleAAQueryInfo AAQIP;
- return getModRefInfo(L, Loc, AAQIP);
- }
- ModRefInfo AAResults::getModRefInfo(const LoadInst *L,
- const MemoryLocation &Loc,
- AAQueryInfo &AAQI) {
- // Be conservative in the face of atomic.
- if (isStrongerThan(L->getOrdering(), AtomicOrdering::Unordered))
- return ModRefInfo::ModRef;
- // If the load address doesn't alias the given address, it doesn't read
- // or write the specified memory.
- if (Loc.Ptr) {
- AliasResult AR = alias(MemoryLocation::get(L), Loc, AAQI);
- if (AR == AliasResult::NoAlias)
- return ModRefInfo::NoModRef;
- if (AR == AliasResult::MustAlias)
- return ModRefInfo::MustRef;
- }
- // Otherwise, a load just reads.
- return ModRefInfo::Ref;
- }
- ModRefInfo AAResults::getModRefInfo(const StoreInst *S,
- const MemoryLocation &Loc) {
- SimpleAAQueryInfo AAQIP;
- return getModRefInfo(S, Loc, AAQIP);
- }
- ModRefInfo AAResults::getModRefInfo(const StoreInst *S,
- const MemoryLocation &Loc,
- AAQueryInfo &AAQI) {
- // Be conservative in the face of atomic.
- if (isStrongerThan(S->getOrdering(), AtomicOrdering::Unordered))
- return ModRefInfo::ModRef;
- if (Loc.Ptr) {
- AliasResult AR = alias(MemoryLocation::get(S), Loc, AAQI);
- // If the store address cannot alias the pointer in question, then the
- // specified memory cannot be modified by the store.
- if (AR == AliasResult::NoAlias)
- return ModRefInfo::NoModRef;
- // If the pointer is a pointer to constant memory, then it could not have
- // been modified by this store.
- if (pointsToConstantMemory(Loc, AAQI))
- return ModRefInfo::NoModRef;
- // If the store address aliases the pointer as must alias, set Must.
- if (AR == AliasResult::MustAlias)
- return ModRefInfo::MustMod;
- }
- // Otherwise, a store just writes.
- return ModRefInfo::Mod;
- }
- ModRefInfo AAResults::getModRefInfo(const FenceInst *S, const MemoryLocation &Loc) {
- SimpleAAQueryInfo AAQIP;
- return getModRefInfo(S, Loc, AAQIP);
- }
- ModRefInfo AAResults::getModRefInfo(const FenceInst *S,
- const MemoryLocation &Loc,
- AAQueryInfo &AAQI) {
- // If we know that the location is a constant memory location, the fence
- // cannot modify this location.
- if (Loc.Ptr && pointsToConstantMemory(Loc, AAQI))
- return ModRefInfo::Ref;
- return ModRefInfo::ModRef;
- }
- ModRefInfo AAResults::getModRefInfo(const VAArgInst *V,
- const MemoryLocation &Loc) {
- SimpleAAQueryInfo AAQIP;
- return getModRefInfo(V, Loc, AAQIP);
- }
- ModRefInfo AAResults::getModRefInfo(const VAArgInst *V,
- const MemoryLocation &Loc,
- AAQueryInfo &AAQI) {
- if (Loc.Ptr) {
- AliasResult AR = alias(MemoryLocation::get(V), Loc, AAQI);
- // If the va_arg address cannot alias the pointer in question, then the
- // specified memory cannot be accessed by the va_arg.
- if (AR == AliasResult::NoAlias)
- return ModRefInfo::NoModRef;
- // If the pointer is a pointer to constant memory, then it could not have
- // been modified by this va_arg.
- if (pointsToConstantMemory(Loc, AAQI))
- return ModRefInfo::NoModRef;
- // If the va_arg aliases the pointer as must alias, set Must.
- if (AR == AliasResult::MustAlias)
- return ModRefInfo::MustModRef;
- }
- // Otherwise, a va_arg reads and writes.
- return ModRefInfo::ModRef;
- }
- ModRefInfo AAResults::getModRefInfo(const CatchPadInst *CatchPad,
- const MemoryLocation &Loc) {
- SimpleAAQueryInfo AAQIP;
- return getModRefInfo(CatchPad, Loc, AAQIP);
- }
- ModRefInfo AAResults::getModRefInfo(const CatchPadInst *CatchPad,
- const MemoryLocation &Loc,
- AAQueryInfo &AAQI) {
- if (Loc.Ptr) {
- // If the pointer is a pointer to constant memory,
- // then it could not have been modified by this catchpad.
- if (pointsToConstantMemory(Loc, AAQI))
- return ModRefInfo::NoModRef;
- }
- // Otherwise, a catchpad reads and writes.
- return ModRefInfo::ModRef;
- }
- ModRefInfo AAResults::getModRefInfo(const CatchReturnInst *CatchRet,
- const MemoryLocation &Loc) {
- SimpleAAQueryInfo AAQIP;
- return getModRefInfo(CatchRet, Loc, AAQIP);
- }
- ModRefInfo AAResults::getModRefInfo(const CatchReturnInst *CatchRet,
- const MemoryLocation &Loc,
- AAQueryInfo &AAQI) {
- if (Loc.Ptr) {
- // If the pointer is a pointer to constant memory,
- // then it could not have been modified by this catchpad.
- if (pointsToConstantMemory(Loc, AAQI))
- return ModRefInfo::NoModRef;
- }
- // Otherwise, a catchret reads and writes.
- return ModRefInfo::ModRef;
- }
- ModRefInfo AAResults::getModRefInfo(const AtomicCmpXchgInst *CX,
- const MemoryLocation &Loc) {
- SimpleAAQueryInfo AAQIP;
- return getModRefInfo(CX, Loc, AAQIP);
- }
- ModRefInfo AAResults::getModRefInfo(const AtomicCmpXchgInst *CX,
- const MemoryLocation &Loc,
- AAQueryInfo &AAQI) {
- // Acquire/Release cmpxchg has properties that matter for arbitrary addresses.
- if (isStrongerThanMonotonic(CX->getSuccessOrdering()))
- return ModRefInfo::ModRef;
- if (Loc.Ptr) {
- AliasResult AR = alias(MemoryLocation::get(CX), Loc, AAQI);
- // If the cmpxchg address does not alias the location, it does not access
- // it.
- if (AR == AliasResult::NoAlias)
- return ModRefInfo::NoModRef;
- // If the cmpxchg address aliases the pointer as must alias, set Must.
- if (AR == AliasResult::MustAlias)
- return ModRefInfo::MustModRef;
- }
- return ModRefInfo::ModRef;
- }
- ModRefInfo AAResults::getModRefInfo(const AtomicRMWInst *RMW,
- const MemoryLocation &Loc) {
- SimpleAAQueryInfo AAQIP;
- return getModRefInfo(RMW, Loc, AAQIP);
- }
- ModRefInfo AAResults::getModRefInfo(const AtomicRMWInst *RMW,
- const MemoryLocation &Loc,
- AAQueryInfo &AAQI) {
- // Acquire/Release atomicrmw has properties that matter for arbitrary addresses.
- if (isStrongerThanMonotonic(RMW->getOrdering()))
- return ModRefInfo::ModRef;
- if (Loc.Ptr) {
- AliasResult AR = alias(MemoryLocation::get(RMW), Loc, AAQI);
- // If the atomicrmw address does not alias the location, it does not access
- // it.
- if (AR == AliasResult::NoAlias)
- return ModRefInfo::NoModRef;
- // If the atomicrmw address aliases the pointer as must alias, set Must.
- if (AR == AliasResult::MustAlias)
- return ModRefInfo::MustModRef;
- }
- 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:
- case Instruction::CallBr:
- case Instruction::Invoke:
- return getModRefInfo((const CallBase *)I, Loc, AAQIP);
- case Instruction::CatchPad:
- return getModRefInfo((const CatchPadInst *)I, Loc, AAQIP);
- case Instruction::CatchRet:
- return getModRefInfo((const CatchReturnInst *)I, Loc, AAQIP);
- default:
- assert(!I->mayReadOrWriteMemory() &&
- "Unhandled memory access instruction!");
- 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.
- /// FIXME: this is really just shoring-up a deficiency in alias analysis.
- /// 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 AAResults::callCapturesBefore(const Instruction *I,
- const MemoryLocation &MemLoc,
- DominatorTree *DT,
- AAQueryInfo &AAQI) {
- if (!DT)
- return ModRefInfo::ModRef;
- const Value *Object = getUnderlyingObject(MemLoc.Ptr);
- if (!isIdentifiedFunctionLocal(Object))
- return ModRefInfo::ModRef;
- const auto *Call = dyn_cast<CallBase>(I);
- if (!Call || Call == Object)
- return ModRefInfo::ModRef;
- if (PointerMayBeCapturedBefore(Object, /* ReturnCaptures */ true,
- /* StoreCaptures */ true, I, DT,
- /* include Object */ true))
- return ModRefInfo::ModRef;
- unsigned ArgNo = 0;
- ModRefInfo R = ModRefInfo::NoModRef;
- bool IsMustAlias = true;
- // Set flag only if no May found and all operands processed.
- for (auto CI = Call->data_operands_begin(), CE = Call->data_operands_end();
- CI != CE; ++CI, ++ArgNo) {
- // Only look at the no-capture or byval pointer arguments. If this
- // pointer were passed to arguments that were neither of these, then it
- // couldn't be no-capture.
- if (!(*CI)->getType()->isPointerTy() ||
- (!Call->doesNotCapture(ArgNo) && ArgNo < Call->arg_size() &&
- !Call->isByValArgument(ArgNo)))
- continue;
- AliasResult AR = alias(
- MemoryLocation::getBeforeOrAfter(*CI),
- MemoryLocation::getBeforeOrAfter(Object), AAQI);
- // 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
- // escape.
- if (AR != AliasResult::MustAlias)
- IsMustAlias = false;
- if (AR == AliasResult::NoAlias)
- continue;
- if (Call->doesNotAccessMemory(ArgNo))
- continue;
- if (Call->onlyReadsMemory(ArgNo)) {
- R = ModRefInfo::Ref;
- continue;
- }
- // Not returning MustModRef since we have not seen all the arguments.
- return ModRefInfo::ModRef;
- }
- return IsMustAlias ? setMust(R) : clearMust(R);
- }
- /// canBasicBlockModify - Return true if it is possible for execution of the
- /// specified basic block to modify the location Loc.
- ///
- bool AAResults::canBasicBlockModify(const BasicBlock &BB,
- const MemoryLocation &Loc) {
- return canInstructionRangeModRef(BB.front(), BB.back(), Loc, ModRefInfo::Mod);
- }
- /// canInstructionRangeModRef - Return true if it is possible for the
- /// execution of the specified instructions to mod\ref (according to the
- /// 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 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.getIterator();
- BasicBlock::const_iterator E = I2.getIterator();
- ++E; // Convert from inclusive to exclusive range.
- for (; I != E; ++I) // Check every instruction in range
- if (isModOrRefSet(intersectModRef(getModRefInfo(&*I, Loc), Mode)))
- return true;
- return false;
- }
- // Provide a definition for the root virtual destructor.
- AAResults::Concept::~Concept() = default;
- // Provide a definition for the static object used to identify passes.
- AnalysisKey AAManager::Key;
- ExternalAAWrapperPass::ExternalAAWrapperPass() : ImmutablePass(ID) {
- initializeExternalAAWrapperPassPass(*PassRegistry::getPassRegistry());
- }
- ExternalAAWrapperPass::ExternalAAWrapperPass(CallbackT CB)
- : ImmutablePass(ID), CB(std::move(CB)) {
- initializeExternalAAWrapperPassPass(*PassRegistry::getPassRegistry());
- }
- char ExternalAAWrapperPass::ID = 0;
- INITIALIZE_PASS(ExternalAAWrapperPass, "external-aa", "External Alias Analysis",
- false, true)
- ImmutablePass *
- llvm::createExternalAAWrapperPass(ExternalAAWrapperPass::CallbackT Callback) {
- return new ExternalAAWrapperPass(std::move(Callback));
- }
- 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(CFLAndersAAWrapperPass)
- INITIALIZE_PASS_DEPENDENCY(CFLSteensAAWrapperPass)
- INITIALIZE_PASS_DEPENDENCY(ExternalAAWrapperPass)
- 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(getAnalysis<TargetLibraryInfoWrapperPass>().getTLI(F)));
- // 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<CFLAndersAAWrapperPass>())
- AAR->addAAResult(WrapperPass->getResult());
- if (auto *WrapperPass = getAnalysisIfAvailable<CFLSteensAAWrapperPass>())
- AAR->addAAResult(WrapperPass->getResult());
- // If available, run an external AA providing callback over the results as
- // well.
- if (auto *WrapperPass = getAnalysisIfAvailable<ExternalAAWrapperPass>())
- if (WrapperPass->CB)
- WrapperPass->CB(*this, F, *AAR);
- // Analyses don't mutate the IR, so return false.
- return false;
- }
- void AAResultsWrapperPass::getAnalysisUsage(AnalysisUsage &AU) const {
- AU.setPreservesAll();
- 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
- // 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<CFLAndersAAWrapperPass>();
- AU.addUsedIfAvailable<CFLSteensAAWrapperPass>();
- 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));
- // 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<CFLAndersAAWrapperPass>())
- AAR.addAAResult(WrapperPass->getResult());
- if (auto *WrapperPass = P.getAnalysisIfAvailable<CFLSteensAAWrapperPass>())
- AAR.addAAResult(WrapperPass->getResult());
- if (auto *WrapperPass = P.getAnalysisIfAvailable<ExternalAAWrapperPass>())
- if (WrapperPass->CB)
- WrapperPass->CB(P, F, AAR);
- return AAR;
- }
- bool llvm::isNoAliasCall(const Value *V) {
- if (const auto *Call = dyn_cast<CallBase>(V))
- return Call->hasRetAttr(Attribute::NoAlias);
- return false;
- }
- static bool isNoAliasOrByValArgument(const Value *V) {
- if (const Argument *A = dyn_cast<Argument>(V))
- return A->hasNoAliasAttr() || A->hasByValAttr();
- return false;
- }
- bool llvm::isIdentifiedObject(const Value *V) {
- if (isa<AllocaInst>(V))
- return true;
- if (isa<GlobalValue>(V) && !isa<GlobalAlias>(V))
- return true;
- if (isNoAliasCall(V))
- return true;
- if (isNoAliasOrByValArgument(V))
- return true;
- return false;
- }
- bool llvm::isIdentifiedFunctionLocal(const Value *V) {
- return isa<AllocaInst>(V) || isNoAliasCall(V) || isNoAliasOrByValArgument(V);
- }
- bool llvm::isNotVisibleOnUnwind(const Value *Object,
- bool &RequiresNoCaptureBeforeUnwind) {
- RequiresNoCaptureBeforeUnwind = false;
- // Alloca goes out of scope on unwind.
- if (isa<AllocaInst>(Object))
- return true;
- // Byval goes out of scope on unwind.
- if (auto *A = dyn_cast<Argument>(Object))
- return A->hasByValAttr();
- // A noalias return is not accessible from any other code. If the pointer
- // does not escape prior to the unwind, then the caller cannot access the
- // memory either.
- if (isNoAliasCall(Object)) {
- RequiresNoCaptureBeforeUnwind = true;
- return true;
- }
- return false;
- }
- void llvm::getAAResultsAnalysisUsage(AnalysisUsage &AU) {
- // This function needs to be in sync with llvm::createLegacyPMAAResults -- if
- // more alias analyses are added to llvm::createLegacyPMAAResults, they need
- // to be added here also.
- AU.addRequired<TargetLibraryInfoWrapperPass>();
- AU.addUsedIfAvailable<ScopedNoAliasAAWrapperPass>();
- AU.addUsedIfAvailable<TypeBasedAAWrapperPass>();
- AU.addUsedIfAvailable<objcarc::ObjCARCAAWrapperPass>();
- AU.addUsedIfAvailable<GlobalsAAWrapperPass>();
- AU.addUsedIfAvailable<CFLAndersAAWrapperPass>();
- AU.addUsedIfAvailable<CFLSteensAAWrapperPass>();
- AU.addUsedIfAvailable<ExternalAAWrapperPass>();
- }
|