Index: llvm/include/llvm/Analysis/AliasAnalysis.h =================================================================== --- llvm/include/llvm/Analysis/AliasAnalysis.h +++ llvm/include/llvm/Analysis/AliasAnalysis.h @@ -940,6 +940,14 @@ ImmutablePass *createExternalAAWrapperPass( std::function Callback); +/// A wrapper pass that lets TargetTransformInfo inject its own target-specific +/// alias analysis. +/// +/// When this pass is enabled, creation of the AA chain invokes +/// TargetTransformInfo::getAAResultProvider(). If the result is not null, we +/// use the provider to add an AA result to the chain. +ImmutablePass *createTargetSpecificAAWrapperPass(); + /// 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. Index: llvm/include/llvm/Analysis/TargetTransformInfo.h =================================================================== --- llvm/include/llvm/Analysis/TargetTransformInfo.h +++ llvm/include/llvm/Analysis/TargetTransformInfo.h @@ -33,6 +33,7 @@ namespace llvm { +class AAResults; class Function; class GlobalValue; class Loop; @@ -618,6 +619,40 @@ bool areInlineCompatible(const Function *Caller, const Function *Callee) const; + /// AAResultProvider is a proxy class that lets you implement target-specific + /// alias analyses: + /// + /// class MyTargetAAresult : public AAResultBase { ... }; + /// + /// class MyTargetAAResultProvider : public AAResultProvider { + /// MyTargetAAResult Result; + /// public: + /// void addAAResult(AAResults &AAR) override { + /// // AAR only keeps a reference to Result; we have to keep it alive. + /// AAR.addResult(Result); + /// } + /// }; + /// + /// std::unique_ptr + /// MyTargetTTI::getAAResultProvider(const Function *) { + /// return make_unique(); + /// } + /// + /// (Essentially, AAResultProvider is a closure object that stores an object + /// derived from AAResultBase. We don't use std::function because it's + /// natural for these objects to be move-only and/or contain non-copyable + /// members, and std::functions must be copyable.) + class AAResultProvider { + public: + virtual ~AAResultProvider() {} + virtual void addAAResult(AAResults &AAR) = 0; + }; + + /// \returns nullptr or an AAResultProvider which the alias analysis machinery + /// can use to inject a target-specific alias analysis into the AA chain. + std::unique_ptr + getAAResultProvider(const Function *F) const; + /// @} private: @@ -746,6 +781,8 @@ Type *ExpectedType) = 0; virtual bool areInlineCompatible(const Function *Caller, const Function *Callee) const = 0; + virtual std::unique_ptr + getAAResultProvider(const Function *F) = 0; }; template @@ -991,6 +1028,10 @@ const Function *Callee) const override { return Impl.areInlineCompatible(Caller, Callee); } + std::unique_ptr + getAAResultProvider(const Function *F) override { + return Impl.getAAResultProvider(F); + } }; template Index: llvm/include/llvm/Analysis/TargetTransformInfoImpl.h =================================================================== --- llvm/include/llvm/Analysis/TargetTransformInfoImpl.h +++ llvm/include/llvm/Analysis/TargetTransformInfoImpl.h @@ -393,6 +393,11 @@ (Caller->getFnAttribute("target-features") == Callee->getFnAttribute("target-features")); } + + std::unique_ptr + getAAResultProvider(const Function *F) const { + return nullptr; + } }; /// \brief CRTP base class for use as a mix-in that aids implementing Index: llvm/include/llvm/InitializePasses.h =================================================================== --- llvm/include/llvm/InitializePasses.h +++ llvm/include/llvm/InitializePasses.h @@ -333,6 +333,7 @@ void initializeTailDuplicatePassPass(PassRegistry&); void initializeTargetLibraryInfoWrapperPassPass(PassRegistry &); void initializeTargetPassConfigPass(PassRegistry&); +void initializeTargetSpecificAAWrapperPassPass(PassRegistry &); void initializeTargetTransformInfoWrapperPassPass(PassRegistry &); void initializeThreadSanitizerPass(PassRegistry&); void initializeTwoAddressInstructionPassPass(PassRegistry&); Index: llvm/lib/Analysis/AliasAnalysis.cpp =================================================================== --- llvm/lib/Analysis/AliasAnalysis.cpp +++ llvm/lib/Analysis/AliasAnalysis.cpp @@ -35,6 +35,7 @@ #include "llvm/Analysis/ScalarEvolutionAliasAnalysis.h" #include "llvm/Analysis/ScopedNoAliasAA.h" #include "llvm/Analysis/TargetLibraryInfo.h" +#include "llvm/Analysis/TargetTransformInfo.h" #include "llvm/Analysis/TypeBasedAliasAnalysis.h" #include "llvm/Analysis/ValueTracking.h" #include "llvm/IR/BasicBlock.h" @@ -547,6 +548,48 @@ return new ExternalAAWrapperPass(std::move(Callback)); } +namespace { +/// Wrapper pass for target-specific alias analyses. Stores the TTI's +/// AAResultProvider, which owns the AAResult. +class TargetSpecificAAWrapperPass : public ImmutablePass { + std::unique_ptr Provider; + +public: + static char ID; + + TargetSpecificAAWrapperPass() : ImmutablePass(ID) { + initializeTargetSpecificAAWrapperPassPass(*PassRegistry::getPassRegistry()); + } + + void getAnalysisUsage(AnalysisUsage &AU) const override { + AU.setPreservesAll(); + AU.addRequired(); + } + + void reset() { Provider.reset(); } + + void addAAResult(const Function &F, AAResults &AAR) { + assert(!Provider && "Provider should have been cleared first."); + // Try to get an AAResultProvider for this function from our TTI. + if ((Provider = getAnalysis() + .getTTI(F) + .getAAResultProvider(&F))) + Provider->addAAResult(AAR); + } +}; +} // anonymous namespace + +char TargetSpecificAAWrapperPass::ID = 0; +INITIALIZE_PASS_BEGIN(TargetSpecificAAWrapperPass, "target-specific-aa", + "Target-specific Alias Analysis", false, true) +INITIALIZE_PASS_DEPENDENCY(TargetTransformInfoWrapperPass) +INITIALIZE_PASS_END(TargetSpecificAAWrapperPass, "target-specific-aa", + "Target-specific Alias Analysis", false, true) + +ImmutablePass *llvm::createTargetSpecificAAWrapperPass() { + return new TargetSpecificAAWrapperPass(); +} + AAResultsWrapperPass::AAResultsWrapperPass() : FunctionPass(ID) { initializeAAResultsWrapperPassPass(*PassRegistry::getPassRegistry()); } @@ -563,6 +606,7 @@ INITIALIZE_PASS_DEPENDENCY(ObjCARCAAWrapperPass) INITIALIZE_PASS_DEPENDENCY(SCEVAAWrapperPass) INITIALIZE_PASS_DEPENDENCY(ScopedNoAliasAAWrapperPass) +INITIALIZE_PASS_DEPENDENCY(TargetSpecificAAWrapperPass) INITIALIZE_PASS_DEPENDENCY(TypeBasedAAWrapperPass) INITIALIZE_PASS_END(AAResultsWrapperPass, "aa", "Function Alias Analysis Results", false, true) @@ -580,6 +624,11 @@ /// adding a new alias analysis to LLVM will require adding support for it to /// this list. bool AAResultsWrapperPass::runOnFunction(Function &F) { + // First, clear the target-specific AA's AAResultProvider, which may have a + // reference to AAR. + if (auto *WrapperPass = getAnalysisIfAvailable()) + WrapperPass->reset(); + // 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 @@ -612,6 +661,8 @@ AAR->addAAResult(WrapperPass->getResult()); if (auto *WrapperPass = getAnalysisIfAvailable()) AAR->addAAResult(WrapperPass->getResult()); + if (auto *WrapperPass = getAnalysisIfAvailable()) + WrapperPass->addAAResult(F, *AAR); // If available, run an external AA providing callback over the results as // well. Index: llvm/lib/Analysis/TargetTransformInfo.cpp =================================================================== --- llvm/lib/Analysis/TargetTransformInfo.cpp +++ llvm/lib/Analysis/TargetTransformInfo.cpp @@ -423,6 +423,11 @@ return TTIImpl->areInlineCompatible(Caller, Callee); } +std::unique_ptr +TargetTransformInfo::getAAResultProvider(const Function *F) const { + return TTIImpl->getAAResultProvider(F); +} + TargetTransformInfo::Concept::~Concept() {} TargetIRAnalysis::TargetIRAnalysis() : TTICallback(&getDefaultTTI) {} Index: llvm/lib/CodeGen/TargetPassConfig.cpp =================================================================== --- llvm/lib/CodeGen/TargetPassConfig.cpp +++ llvm/lib/CodeGen/TargetPassConfig.cpp @@ -428,6 +428,8 @@ /// Add common target configurable passes that perform LLVM IR to IR transforms /// following machine independent optimization. void TargetPassConfig::addIRPasses() { + addPass(createTargetSpecificAAWrapperPass()); + switch (UseCFLAA) { case CFLAAType::Steensgaard: addPass(createCFLSteensAAWrapperPass()); Index: llvm/lib/Target/NVPTX/CMakeLists.txt =================================================================== --- llvm/lib/Target/NVPTX/CMakeLists.txt +++ llvm/lib/Target/NVPTX/CMakeLists.txt @@ -9,6 +9,7 @@ add_public_tablegen_target(NVPTXCommonTableGen) set(NVPTXCodeGen_sources + NVPTXAliasAnalysis.cpp NVPTXAllocaHoisting.cpp NVPTXAsmPrinter.cpp NVPTXAssignValidGlobalNames.cpp Index: llvm/lib/Transforms/IPO/PassManagerBuilder.cpp =================================================================== --- llvm/lib/Transforms/IPO/PassManagerBuilder.cpp +++ llvm/lib/Transforms/IPO/PassManagerBuilder.cpp @@ -198,6 +198,7 @@ void PassManagerBuilder::addInitialAliasAnalysisPasses( legacy::PassManagerBase &PM) const { + PM.add(createTargetSpecificAAWrapperPass()); switch (UseCFLAA) { case CFLAAType::Steensgaard: PM.add(createCFLSteensAAWrapperPass());