summaryrefslogtreecommitdiff
path: root/include/llvm/Analysis/AliasAnalysis.h
diff options
context:
space:
mode:
Diffstat (limited to 'include/llvm/Analysis/AliasAnalysis.h')
-rw-r--r--include/llvm/Analysis/AliasAnalysis.h262
1 files changed, 74 insertions, 188 deletions
diff --git a/include/llvm/Analysis/AliasAnalysis.h b/include/llvm/Analysis/AliasAnalysis.h
index 5cc840a64a627..d6308b7073a09 100644
--- a/include/llvm/Analysis/AliasAnalysis.h
+++ b/include/llvm/Analysis/AliasAnalysis.h
@@ -38,11 +38,11 @@
#ifndef LLVM_ANALYSIS_ALIASANALYSIS_H
#define LLVM_ANALYSIS_ALIASANALYSIS_H
-#include "llvm/ADT/DenseMap.h"
#include "llvm/IR/CallSite.h"
#include "llvm/IR/Metadata.h"
#include "llvm/IR/PassManager.h"
#include "llvm/Analysis/MemoryLocation.h"
+#include "llvm/Analysis/TargetLibraryInfo.h"
namespace llvm {
class BasicAAResult;
@@ -50,7 +50,6 @@ class LoadInst;
class StoreInst;
class VAArgInst;
class DataLayout;
-class TargetLibraryInfo;
class Pass;
class AnalysisUsage;
class MemTransferInst;
@@ -141,7 +140,7 @@ enum FunctionModRefBehavior {
/// non-volatile loads and stores from objects pointed to by its
/// pointer-typed arguments, with arbitrary offsets.
///
- /// This property corresponds to the IntrReadWriteArgMem LLVM intrinsic flag.
+ /// This property corresponds to the IntrArgMemOnly LLVM intrinsic flag.
FMRB_OnlyAccessesArgumentPointees = FMRL_ArgumentPointees | MRI_ModRef,
/// This function does not perform any non-local stores or volatile loads,
@@ -152,6 +151,13 @@ enum FunctionModRefBehavior {
/// This property corresponds to the IntrReadMem LLVM intrinsic flag.
FMRB_OnlyReadsMemory = FMRL_Anywhere | MRI_Ref,
+ // This function does not read from memory anywhere, but may write to any
+ // memory location.
+ //
+ // This property corresponds to the LLVM IR 'writeonly' attribute.
+ // This property corresponds to the IntrWriteMem LLVM intrinsic flag.
+ FMRB_DoesNotReadMemory = FMRL_Anywhere | MRI_Mod,
+
/// This indicates that the function could not be classified into one of the
/// behaviors above.
FMRB_UnknownModRefBehavior = FMRL_Anywhere | MRI_ModRef
@@ -161,9 +167,8 @@ class AAResults {
public:
// Make these results default constructable and movable. We have to spell
// these out because MSVC won't synthesize them.
- AAResults() {}
+ AAResults(const TargetLibraryInfo &TLI) : TLI(TLI) {}
AAResults(AAResults &&Arg);
- AAResults &operator=(AAResults &&Arg);
~AAResults();
/// Register a specific AA result.
@@ -314,6 +319,12 @@ public:
return !(MRB & MRI_Mod);
}
+ /// Checks if functions with the specified behavior are known to only write
+ /// memory (or not access memory at all).
+ static bool doesNotReadMemory(FunctionModRefBehavior MRB) {
+ return !(MRB & MRI_Ref);
+ }
+
/// Checks if functions with the specified behavior are known to read and
/// write at most from objects pointed to by their pointer-typed arguments
/// (with arbitrary offsets).
@@ -450,11 +461,11 @@ public:
ModRefInfo getModRefInfo(const Instruction *I) {
if (auto CS = ImmutableCallSite(I)) {
auto MRB = getModRefBehavior(CS);
- if (MRB & MRI_ModRef)
+ if ((MRB & MRI_ModRef) == MRI_ModRef)
return MRI_ModRef;
- else if (MRB & MRI_Ref)
+ if (MRB & MRI_Ref)
return MRI_Ref;
- else if (MRB & MRI_Mod)
+ if (MRB & MRI_Mod)
return MRI_Mod;
return MRI_NoModRef;
}
@@ -557,6 +568,8 @@ private:
template <typename T> friend class AAResultBase;
+ const TargetLibraryInfo &TLI;
+
std::vector<std::unique_ptr<Concept>> AAs;
};
@@ -753,20 +766,23 @@ protected:
}
};
- const TargetLibraryInfo &TLI;
-
- explicit AAResultBase(const TargetLibraryInfo &TLI) : TLI(TLI) {}
+ explicit AAResultBase() {}
// Provide all the copy and move constructors so that derived types aren't
// constrained.
- AAResultBase(const AAResultBase &Arg) : TLI(Arg.TLI) {}
- AAResultBase(AAResultBase &&Arg) : TLI(Arg.TLI) {}
+ AAResultBase(const AAResultBase &Arg) {}
+ AAResultBase(AAResultBase &&Arg) {}
/// Get a proxy for the best AA result set to query at this time.
///
/// When this result is part of a larger aggregation, this will proxy to that
/// aggregation. When this result is used in isolation, it will just delegate
/// back to the derived class's implementation.
+ ///
+ /// Note that callers of this need to take considerable care to not cause
+ /// performance problems when they use this routine, in the case of a large
+ /// number of alias analyses being aggregated, it can be expensive to walk
+ /// back across the chain.
AAResultsProxy getBestAAResults() { return AAResultsProxy(AAR, derived()); }
public:
@@ -783,13 +799,6 @@ public:
}
FunctionModRefBehavior getModRefBehavior(ImmutableCallSite CS) {
- if (!CS.hasOperandBundles())
- // If CS has operand bundles then aliasing attributes from the function it
- // calls do not directly apply to the CallSite. This can be made more
- // precise in the future.
- if (const Function *F = CS.getCalledFunction())
- return getBestAAResults().getModRefBehavior(F);
-
return FMRB_UnknownModRefBehavior;
}
@@ -797,170 +806,24 @@ public:
return FMRB_UnknownModRefBehavior;
}
- ModRefInfo getModRefInfo(ImmutableCallSite CS, const MemoryLocation &Loc);
-
- ModRefInfo getModRefInfo(ImmutableCallSite CS1, ImmutableCallSite CS2);
-};
-
-/// Synthesize \c ModRefInfo for a call site and memory location by examining
-/// the general behavior of the call site and any specific information for its
-/// arguments.
-///
-/// This essentially, delegates across the alias analysis interface to collect
-/// information which may be enough to (conservatively) fulfill the query.
-template <typename DerivedT>
-ModRefInfo AAResultBase<DerivedT>::getModRefInfo(ImmutableCallSite CS,
- const MemoryLocation &Loc) {
- auto MRB = getBestAAResults().getModRefBehavior(CS);
- if (MRB == FMRB_DoesNotAccessMemory)
- return MRI_NoModRef;
-
- ModRefInfo Mask = MRI_ModRef;
- if (AAResults::onlyReadsMemory(MRB))
- Mask = MRI_Ref;
-
- if (AAResults::onlyAccessesArgPointees(MRB)) {
- bool DoesAlias = false;
- ModRefInfo AllArgsMask = MRI_NoModRef;
- if (AAResults::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);
- AliasResult ArgAlias = getBestAAResults().alias(ArgLoc, Loc);
- if (ArgAlias != NoAlias) {
- ModRefInfo ArgMask = getBestAAResults().getArgModRefInfo(CS, ArgIdx);
- DoesAlias = true;
- AllArgsMask = ModRefInfo(AllArgsMask | ArgMask);
- }
- }
- }
- if (!DoesAlias)
- return MRI_NoModRef;
- Mask = ModRefInfo(Mask & AllArgsMask);
- }
-
- // If Loc is a constant memory location, the call definitely could not
- // modify the memory location.
- if ((Mask & MRI_Mod) &&
- getBestAAResults().pointsToConstantMemory(Loc, /*OrLocal*/ false))
- Mask = ModRefInfo(Mask & ~MRI_Mod);
-
- return Mask;
-}
-
-/// Synthesize \c ModRefInfo for two call sites by examining the general
-/// behavior of the call site and any specific information for its arguments.
-///
-/// This essentially, delegates across the alias analysis interface to collect
-/// information which may be enough to (conservatively) fulfill the query.
-template <typename DerivedT>
-ModRefInfo AAResultBase<DerivedT>::getModRefInfo(ImmutableCallSite CS1,
- ImmutableCallSite CS2) {
- // If CS1 or CS2 are readnone, they don't interact.
- auto CS1B = getBestAAResults().getModRefBehavior(CS1);
- if (CS1B == FMRB_DoesNotAccessMemory)
- return MRI_NoModRef;
-
- auto CS2B = getBestAAResults().getModRefBehavior(CS2);
- if (CS2B == FMRB_DoesNotAccessMemory)
- return MRI_NoModRef;
-
- // If they both only read from memory, there is no dependence.
- if (AAResults::onlyReadsMemory(CS1B) && AAResults::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 (AAResults::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 (AAResults::onlyAccessesArgPointees(CS2B)) {
- ModRefInfo R = MRI_NoModRef;
- if (AAResults::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 =
- getBestAAResults().getArgModRefInfo(CS2, CS2ArgIdx);
- if (ArgMask == MRI_Mod)
- ArgMask = MRI_ModRef;
- else if (ArgMask == MRI_Ref)
- ArgMask = MRI_Mod;
-
- ArgMask = ModRefInfo(ArgMask &
- getBestAAResults().getModRefInfo(CS1, CS2ArgLoc));
-
- R = ModRefInfo((R | ArgMask) & Mask);
- if (R == Mask)
- break;
- }
- }
- return R;
+ ModRefInfo getModRefInfo(ImmutableCallSite CS, const MemoryLocation &Loc) {
+ return MRI_ModRef;
}
- // 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 (AAResults::onlyAccessesArgPointees(CS1B)) {
- ModRefInfo R = MRI_NoModRef;
- if (AAResults::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 = getBestAAResults().getArgModRefInfo(CS1, CS1ArgIdx);
- ModRefInfo ArgR = getBestAAResults().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;
+ ModRefInfo getModRefInfo(ImmutableCallSite CS1, ImmutableCallSite CS2) {
+ return MRI_ModRef;
}
+};
- return Mask;
-}
-/// isNoAliasCall - Return true if this pointer is returned by a noalias
-/// function.
+/// Return true if this pointer is returned by a noalias function.
bool isNoAliasCall(const Value *V);
-/// isNoAliasArgument - Return true if this is an argument with the noalias
-/// attribute.
+/// Return true if this is an argument with the noalias attribute.
bool isNoAliasArgument(const Value *V);
-/// isIdentifiedObject - Return true if this pointer refers to a distinct and
-/// identifiable object. This returns true for:
+/// Return true if this pointer refers to a distinct and identifiable object.
+/// This returns true for:
/// Global Variables and Functions (but not Global Aliases)
/// Allocas
/// ByVal and NoAlias Arguments
@@ -968,8 +831,8 @@ bool isNoAliasArgument(const Value *V);
///
bool isIdentifiedObject(const Value *V);
-/// isIdentifiedFunctionLocal - Return true if V is umabigously identified
-/// at the function-level. Different IdentifiedFunctionLocals can't alias.
+/// Return true if V is umabigously identified at the function-level.
+/// Different IdentifiedFunctionLocals can't alias.
/// Further, an IdentifiedFunctionLocal can not alias with any function
/// arguments other than itself, which is not necessarily true for
/// IdentifiedObjects.
@@ -987,42 +850,48 @@ bool isIdentifiedFunctionLocal(const Value *V);
/// This manager effectively wraps the AnalysisManager for registering alias
/// analyses. When you register your alias analysis with this manager, it will
/// ensure the analysis itself is registered with its AnalysisManager.
-class AAManager {
+class AAManager : public AnalysisInfoMixin<AAManager> {
public:
typedef AAResults Result;
// This type hase value semantics. We have to spell these out because MSVC
// won't synthesize them.
AAManager() {}
- AAManager(AAManager &&Arg)
- : FunctionResultGetters(std::move(Arg.FunctionResultGetters)) {}
- AAManager(const AAManager &Arg)
- : FunctionResultGetters(Arg.FunctionResultGetters) {}
+ AAManager(AAManager &&Arg) : ResultGetters(std::move(Arg.ResultGetters)) {}
+ AAManager(const AAManager &Arg) : ResultGetters(Arg.ResultGetters) {}
AAManager &operator=(AAManager &&RHS) {
- FunctionResultGetters = std::move(RHS.FunctionResultGetters);
+ ResultGetters = std::move(RHS.ResultGetters);
return *this;
}
AAManager &operator=(const AAManager &RHS) {
- FunctionResultGetters = RHS.FunctionResultGetters;
+ ResultGetters = RHS.ResultGetters;
return *this;
}
/// Register a specific AA result.
template <typename AnalysisT> void registerFunctionAnalysis() {
- FunctionResultGetters.push_back(&getFunctionAAResultImpl<AnalysisT>);
+ ResultGetters.push_back(&getFunctionAAResultImpl<AnalysisT>);
+ }
+
+ /// Register a specific AA result.
+ template <typename AnalysisT> void registerModuleAnalysis() {
+ ResultGetters.push_back(&getModuleAAResultImpl<AnalysisT>);
}
Result run(Function &F, AnalysisManager<Function> &AM) {
- Result R;
- for (auto &Getter : FunctionResultGetters)
+ Result R(AM.getResult<TargetLibraryAnalysis>(F));
+ for (auto &Getter : ResultGetters)
(*Getter)(F, AM, R);
return R;
}
private:
+ friend AnalysisInfoMixin<AAManager>;
+ static char PassID;
+
SmallVector<void (*)(Function &F, AnalysisManager<Function> &AM,
AAResults &AAResults),
- 4> FunctionResultGetters;
+ 4> ResultGetters;
template <typename AnalysisT>
static void getFunctionAAResultImpl(Function &F,
@@ -1030,6 +899,15 @@ private:
AAResults &AAResults) {
AAResults.addAAResult(AM.template getResult<AnalysisT>(F));
}
+
+ template <typename AnalysisT>
+ static void getModuleAAResultImpl(Function &F, AnalysisManager<Function> &AM,
+ AAResults &AAResults) {
+ auto &MAM =
+ AM.getResult<ModuleAnalysisManagerFunctionProxy>(F).getManager();
+ if (auto *R = MAM.template getCachedResult<AnalysisT>(*F.getParent()))
+ AAResults.addAAResult(*R);
+ }
};
/// A wrapper pass to provide the legacy pass manager access to a suitably
@@ -1065,8 +943,16 @@ ImmutablePass *createExternalAAWrapperPass(
/// A helper for the legacy pass manager to create a \c AAResults
/// object populated to the best of our ability for a particular function when
/// inside of a \c ModulePass or a \c CallGraphSCCPass.
+///
+/// If a \c ModulePass or a \c CallGraphSCCPass calls \p
+/// createLegacyPMAAResults, it also needs to call \p addUsedAAAnalyses in \p
+/// getAnalysisUsage.
AAResults createLegacyPMAAResults(Pass &P, Function &F, BasicAAResult &BAR);
+/// A helper for the legacy pass manager to populate \p AU to add uses to make
+/// sure the analyses required by \p createLegacyPMAAResults are available.
+void getAAResultsAnalysisUsage(AnalysisUsage &AU);
+
} // End llvm namespace
#endif