diff --git a/llvm/include/llvm/Analysis/AliasAnalysis.h b/llvm/include/llvm/Analysis/AliasAnalysis.h index b3b44a50ca827..d23b81854c9ea 100644 --- a/llvm/include/llvm/Analysis/AliasAnalysis.h +++ b/llvm/include/llvm/Analysis/AliasAnalysis.h @@ -1013,6 +1013,18 @@ struct ExternalAAWrapperPass : ImmutablePass { explicit ExternalAAWrapperPass(CallbackT CB); + /// Returns whether this external AA should run before Basic AA. + /// + /// By default, external AA passes are run after Basic AA. If this returns + /// true, the external AA will be run before Basic AA during alias analysis. + /// + /// For some targets, we prefer to run the external AA early to improve + /// compile time as it has more target-specific information. This is + /// particularly useful when the external AA can provide more precise results + /// than Basic AA so that Basic AA does not need to spend time recomputing + /// them. + virtual bool runEarly() { return false; } + void getAnalysisUsage(AnalysisUsage &AU) const override { AU.setPreservesAll(); } diff --git a/llvm/include/llvm/Target/TargetMachine.h b/llvm/include/llvm/Target/TargetMachine.h index 566e7dba6792b..906926729ed74 100644 --- a/llvm/include/llvm/Target/TargetMachine.h +++ b/llvm/include/llvm/Target/TargetMachine.h @@ -396,6 +396,11 @@ class TargetMachine { // TODO: Populate all pass names by using PassRegistry.def. virtual void registerPassBuilderCallbacks(PassBuilder &) {} + /// Allow the target to register early alias analyses (AA before BasicAA) with + /// the AAManager for use with the new pass manager. Only affects the + /// "default" AAManager. + virtual void registerEarlyDefaultAliasAnalyses(AAManager &) {} + /// Allow the target to register alias analyses with the AAManager for use /// with the new pass manager. Only affects the "default" AAManager. virtual void registerDefaultAliasAnalyses(AAManager &) {} diff --git a/llvm/lib/Analysis/AliasAnalysis.cpp b/llvm/lib/Analysis/AliasAnalysis.cpp index efabf69b06047..8afb176bc392f 100644 --- a/llvm/lib/Analysis/AliasAnalysis.cpp +++ b/llvm/lib/Analysis/AliasAnalysis.cpp @@ -736,28 +736,49 @@ bool AAResultsWrapperPass::runOnFunction(Function &F) { AAR.reset( new AAResults(getAnalysis().getTLI(F))); + // Add any target-specific alias analyses that should be run early. + auto *ExtWrapperPass = getAnalysisIfAvailable(); + if (ExtWrapperPass && ExtWrapperPass->runEarly() && ExtWrapperPass->CB) { + LLVM_DEBUG(dbgs() << "AAResults register Early ExternalAA: " + << ExtWrapperPass->getPassName() << "\n"); + ExtWrapperPass->CB(*this, F, *AAR); + } + // 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) + if (!DisableBasicAA) { + LLVM_DEBUG(dbgs() << "AAResults register BasicAA\n"); AAR->addAAResult(getAnalysis().getResult()); + } // Populate the results with the currently available AAs. - if (auto *WrapperPass = getAnalysisIfAvailable()) + if (auto *WrapperPass = + getAnalysisIfAvailable()) { + LLVM_DEBUG(dbgs() << "AAResults register ScopedNoAliasAA\n"); AAR->addAAResult(WrapperPass->getResult()); - if (auto *WrapperPass = getAnalysisIfAvailable()) + } + if (auto *WrapperPass = getAnalysisIfAvailable()) { + LLVM_DEBUG(dbgs() << "AAResults register TypeBasedAA\n"); AAR->addAAResult(WrapperPass->getResult()); - if (auto *WrapperPass = getAnalysisIfAvailable()) + } + if (auto *WrapperPass = getAnalysisIfAvailable()) { + LLVM_DEBUG(dbgs() << "AAResults register GlobalsAA\n"); AAR->addAAResult(WrapperPass->getResult()); - if (auto *WrapperPass = getAnalysisIfAvailable()) + } + if (auto *WrapperPass = getAnalysisIfAvailable()) { + LLVM_DEBUG(dbgs() << "AAResults register SCEVAA\n"); AAR->addAAResult(WrapperPass->getResult()); + } // If available, run an external AA providing callback over the results as // well. - if (auto *WrapperPass = getAnalysisIfAvailable()) - if (WrapperPass->CB) - WrapperPass->CB(*this, F, *AAR); + if (ExtWrapperPass && !ExtWrapperPass->runEarly() && ExtWrapperPass->CB) { + LLVM_DEBUG(dbgs() << "AAResults register Late ExternalAA: " + << ExtWrapperPass->getPassName() << "\n"); + ExtWrapperPass->CB(*this, F, *AAR); + } // Analyses don't mutate the IR, so return false. return false; diff --git a/llvm/lib/Passes/PassBuilderPipelines.cpp b/llvm/lib/Passes/PassBuilderPipelines.cpp index f172271be09ab..5a85b308925a6 100644 --- a/llvm/lib/Passes/PassBuilderPipelines.cpp +++ b/llvm/lib/Passes/PassBuilderPipelines.cpp @@ -2320,6 +2320,10 @@ AAManager PassBuilder::buildDefaultAAPipeline() { // The order in which these are registered determines their priority when // being queried. + // Add any target-specific alias analyses that should be run early. + if (TM) + TM->registerEarlyDefaultAliasAnalyses(AA); + // First we register the basic alias analysis that provides the majority of // per-function local AA logic. This is a stateless, on-demand local set of // AA techniques. diff --git a/llvm/lib/Target/NVPTX/NVPTXAliasAnalysis.h b/llvm/lib/Target/NVPTX/NVPTXAliasAnalysis.h index a82c3aaa72423..430fcd741c1b6 100644 --- a/llvm/lib/Target/NVPTX/NVPTXAliasAnalysis.h +++ b/llvm/lib/Target/NVPTX/NVPTXAliasAnalysis.h @@ -85,16 +85,23 @@ class NVPTXAAWrapperPass : public ImmutablePass { // Wrapper around ExternalAAWrapperPass so that the default // constructor gets the callback. +// Note that NVPTXAA will run before BasicAA for compile time considerations. class NVPTXExternalAAWrapper : public ExternalAAWrapperPass { public: static char ID; + bool runEarly() override { return true; } + NVPTXExternalAAWrapper() : ExternalAAWrapperPass([](Pass &P, Function &, AAResults &AAR) { if (auto *WrapperPass = P.getAnalysisIfAvailable()) AAR.addAAResult(WrapperPass->getResult()); }) {} + + StringRef getPassName() const override { + return "NVPTX Address space based Alias Analysis Wrapper"; + } }; ImmutablePass *createNVPTXAAWrapperPass(); diff --git a/llvm/lib/Target/NVPTX/NVPTXTargetMachine.cpp b/llvm/lib/Target/NVPTX/NVPTXTargetMachine.cpp index f78d4585bbe98..fe95f3b9e89b4 100644 --- a/llvm/lib/Target/NVPTX/NVPTXTargetMachine.cpp +++ b/llvm/lib/Target/NVPTX/NVPTXTargetMachine.cpp @@ -232,7 +232,7 @@ MachineFunctionInfo *NVPTXTargetMachine::createMachineFunctionInfo( F, STI); } -void NVPTXTargetMachine::registerDefaultAliasAnalyses(AAManager &AAM) { +void NVPTXTargetMachine::registerEarlyDefaultAliasAnalyses(AAManager &AAM) { AAM.registerFunctionAnalysis(); } @@ -347,10 +347,7 @@ void NVPTXPassConfig::addIRPasses() { disablePass(&RemoveLoadsIntoFakeUsesID); addPass(createNVPTXAAWrapperPass()); - addPass(createExternalAAWrapperPass([](Pass &P, Function &, AAResults &AAR) { - if (auto *WrapperPass = P.getAnalysisIfAvailable()) - AAR.addAAResult(WrapperPass->getResult()); - })); + addPass(createNVPTXExternalAAWrapperPass()); // NVVMReflectPass is added in addEarlyAsPossiblePasses, so hopefully running // it here does nothing. But since we need it for correctness when lowering diff --git a/llvm/lib/Target/NVPTX/NVPTXTargetMachine.h b/llvm/lib/Target/NVPTX/NVPTXTargetMachine.h index 34d841cd28404..118a01a0352f5 100644 --- a/llvm/lib/Target/NVPTX/NVPTXTargetMachine.h +++ b/llvm/lib/Target/NVPTX/NVPTXTargetMachine.h @@ -64,7 +64,7 @@ class NVPTXTargetMachine : public CodeGenTargetMachineImpl { createMachineFunctionInfo(BumpPtrAllocator &Allocator, const Function &F, const TargetSubtargetInfo *STI) const override; - void registerDefaultAliasAnalyses(AAManager &AAM) override; + void registerEarlyDefaultAliasAnalyses(AAManager &AAM) override; void registerPassBuilderCallbacks(PassBuilder &PB) override; diff --git a/llvm/test/Analysis/NVPTXAA/NVPTXAA_before_BasicAA.ll b/llvm/test/Analysis/NVPTXAA/NVPTXAA_before_BasicAA.ll new file mode 100644 index 0000000000000..0d16b344e9f66 --- /dev/null +++ b/llvm/test/Analysis/NVPTXAA/NVPTXAA_before_BasicAA.ll @@ -0,0 +1,17 @@ +; REQUIRES: asserts +; RUN: opt -aa-pipeline=default -passes='require' -debug-pass-manager -disable-output -S < %s 2>&1 | FileCheck %s +; RUN: llc --debug-only='aa' -o /dev/null %s 2>&1 | FileCheck %s -check-prefix=LEGACY + +; In default AA pipeline, NVPTXAA should run before BasicAA to reduce compile time for NVPTX backend +target triple = "nvptx64-nvidia-cuda" + +; CHECK: Running analysis: NVPTXAA on foo +; CHECK-NEXT: Running analysis: BasicAA on foo + +; LEGACY: AAResults register Early ExternalAA: NVPTX Address space based Alias Analysis Wrapper +; LEGACY-NEXT: AAResults register BasicAA +define void @foo(){ +entry: + ret void +} +