diff options
Diffstat (limited to 'include/llvm/Analysis/AliasAnalysis.h')
-rw-r--r-- | include/llvm/Analysis/AliasAnalysis.h | 262 |
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 |