Index: include/polly/ScopInfo.h =================================================================== --- include/polly/ScopInfo.h +++ include/polly/ScopInfo.h @@ -30,6 +30,7 @@ #include "llvm/ADT/StringMap.h" #include "llvm/ADT/StringRef.h" #include "llvm/ADT/iterator_range.h" +#include "llvm/Analysis/CGSCCPassManager.h" #include "llvm/Analysis/RegionPass.h" #include "llvm/Analysis/ScalarEvolutionExpressions.h" #include "llvm/IR/DebugLoc.h" @@ -3166,6 +3167,8 @@ ScopInfoPrinterPass(raw_ostream &OS) : Stream(OS) {} PreservedAnalyses run(Function &, FunctionAnalysisManager &); + PreservedAnalyses run(LazyCallGraph::SCC &, CGSCCAnalysisManager &, + LazyCallGraph &, CGSCCUpdateResult &); raw_ostream &Stream; }; Index: include/polly/ScopPass.h =================================================================== --- include/polly/ScopPass.h +++ include/polly/ScopPass.h @@ -20,6 +20,7 @@ #include "polly/ScopInfo.h" #include "llvm/ADT/PriorityWorklist.h" +#include "llvm/Analysis/CGSCCPassManager.h" #include "llvm/Analysis/RegionPass.h" #include "llvm/IR/PassManager.h" @@ -47,6 +48,8 @@ using polly::ScopStandardAnalysisResults; using polly::SPMUpdater; +/// Implementation of ScopAnalysisManagerFunctionProxy +/// @{ template <> class InnerAnalysisManagerProxy::Result { public: @@ -77,6 +80,14 @@ ScopInfo *SI; }; +template <> +InnerAnalysisManagerProxy::Result +InnerAnalysisManagerProxy::run( + Function &F, FunctionAnalysisManager &AM); + +extern template class InnerAnalysisManagerProxy; +/// @} + // A partial specialization of the require analysis template pass to handle // extra parameters template @@ -92,11 +103,6 @@ } }; -template <> -InnerAnalysisManagerProxy::Result -InnerAnalysisManagerProxy::run( - Function &F, FunctionAnalysisManager &FAM); - template <> PreservedAnalyses PassManager; -extern template class InnerAnalysisManagerProxy; extern template class OuterAnalysisManagerProxy; } // namespace llvm @@ -113,10 +118,12 @@ template class OwningInnerAnalysisManagerProxy - : public InnerAnalysisManagerProxy { + : public InnerAnalysisManagerProxy { public: OwningInnerAnalysisManagerProxy() - : InnerAnalysisManagerProxy(InnerAM) {} + : InnerAnalysisManagerProxy( + InnerAM) {} using Result = typename InnerAnalysisManagerProxy::Result; Result run(IRUnitT &IR, AnalysisManager &AM, @@ -130,15 +137,19 @@ AnalysisManagerT InnerAM; }; +/// @name OwningScopAnalysisManagerFunctionProxy +/// @{ +using OwningScopAnalysisManagerFunctionProxy = + OwningInnerAnalysisManagerProxy; + template <> OwningInnerAnalysisManagerProxy::Result OwningInnerAnalysisManagerProxy::run( Function &F, FunctionAnalysisManager &FAM); extern template class OwningInnerAnalysisManagerProxy; +/// @} -using OwningScopAnalysisManagerFunctionProxy = - OwningInnerAnalysisManagerProxy; using ScopPassManager = PassManager; @@ -199,54 +210,55 @@ bool InvalidateCurrentScop; SmallPriorityWorklist &Worklist; ScopAnalysisManager &SAM; - template friend class FunctionToScopPassAdaptor; + template friend class CGSCCToScopPassAdaptor; }; template -class FunctionToScopPassAdaptor - : public PassInfoMixin> { +class CGSCCToScopPassAdaptor + : public PassInfoMixin> { public: - explicit FunctionToScopPassAdaptor(ScopPassT Pass) : Pass(std::move(Pass)) {} + explicit CGSCCToScopPassAdaptor(ScopPassT Pass) : Pass(std::move(Pass)) {} - PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM) { + PreservedAnalyses run(LazyCallGraph::SCC &SCC, CGSCCAnalysisManager &CGAM, + LazyCallGraph &CG, CGSCCUpdateResult &) { PreservedAnalyses PA = PreservedAnalyses::all(); - auto &SD = AM.getResult(F); - auto &SI = AM.getResult(F); - if (SI.empty()) - return PA; - - SmallPriorityWorklist Worklist; - for (auto &S : SI) - if (S.second) - Worklist.insert(S.first); - - ScopStandardAnalysisResults AR = {AM.getResult(F), - AM.getResult(F), - AM.getResult(F), - AM.getResult(F), - AM.getResult(F)}; - - ScopAnalysisManager &SAM = - AM.getResult(F).getManager(); - - SPMUpdater Updater{Worklist, SAM}; - - while (!Worklist.empty()) { - Region *R = Worklist.pop_back_val(); - if (!SD.isMaxRegionInScop(*R)) - continue; - Scop *scop = SI.getScop(R); - if (!scop) - continue; - Updater.CurrentScop = scop; - Updater.InvalidateCurrentScop = false; - PreservedAnalyses PassPA = Pass.run(*scop, SAM, AR, Updater); - - SAM.invalidate(*scop, PassPA); - PA.intersect(std::move(PassPA)); - if (Updater.invalidateCurrentScop()) - SI.recompute(); - }; + for (auto &SCCNode : SCC) { + auto &F = SCCNode.getFunction(); + auto &AM = CGAM.getResult(SCC, CG) + .getManager(); + auto &SAM = + AM.getResult(F).getManager(); + auto &SI = AM.getResult(F); + if (SI.empty()) + return PA; + + SmallPriorityWorklist Worklist; + for (auto &S : SI) + if (S.second) + Worklist.insert(S.first); + + ScopStandardAnalysisResults AR = { + AM.getResult(F), SI, + AM.getResult(F), + AM.getResult(F), AM.getResult(F)}; + + SPMUpdater Updater{Worklist, SAM}; + + while (!Worklist.empty()) { + Region *R = Worklist.pop_back_val(); + Scop *scop = SI.getScop(R); + if (!scop) + continue; + Updater.CurrentScop = scop; + Updater.InvalidateCurrentScop = false; + PreservedAnalyses PassPA = Pass.run(*scop, SAM, AR, Updater); + + SAM.invalidate(*scop, PassPA); + PA.intersect(std::move(PassPA)); + if (Updater.invalidateCurrentScop()) + SI.recompute(); + } + } PA.preserveSet>(); PA.preserve(); @@ -261,12 +273,11 @@ private: ScopPassT Pass; -}; // namespace polly +}; template -FunctionToScopPassAdaptor -createFunctionToScopPassAdaptor(ScopPassT Pass) { - return FunctionToScopPassAdaptor(std::move(Pass)); +CGSCCToScopPassAdaptor createCGSCCToScopPassAdaptor(ScopPassT Pass) { + return CGSCCToScopPassAdaptor(std::move(Pass)); } } // namespace polly Index: lib/Analysis/ScopInfo.cpp =================================================================== --- lib/Analysis/ScopInfo.cpp +++ lib/Analysis/ScopInfo.cpp @@ -5142,6 +5142,19 @@ return PreservedAnalyses::all(); } +PreservedAnalyses ScopInfoPrinterPass::run(LazyCallGraph::SCC &SCC, + CGSCCAnalysisManager &CGAM, + LazyCallGraph &CG, + CGSCCUpdateResult &) { + for (auto &SCCNode : SCC) { + Function &F = SCCNode.getFunction(); + auto &FAM = + CGAM.getResult(SCC, CG).getManager(); + run(F, FAM); + } + return PreservedAnalyses::all(); +} + void ScopInfoWrapperPass::getAnalysisUsage(AnalysisUsage &AU) const { AU.addRequired(); AU.addRequired(); Index: lib/Analysis/ScopPass.cpp =================================================================== --- lib/Analysis/ScopPass.cpp +++ lib/Analysis/ScopPass.cpp @@ -60,7 +60,13 @@ namespace polly { template class OwningInnerAnalysisManagerProxy; +template <> +OwningScopAnalysisManagerFunctionProxy::Result +OwningScopAnalysisManagerFunctionProxy::run(Function &F, + FunctionAnalysisManager &AM) { + return Result(InnerAM, AM.getResult(F)); } +} // namespace polly namespace llvm { @@ -153,16 +159,7 @@ template <> ScopAnalysisManagerFunctionProxy::Result ScopAnalysisManagerFunctionProxy::run(Function &F, - FunctionAnalysisManager &FAM) { - return Result(*InnerAM, FAM.getResult(F)); + FunctionAnalysisManager &AM) { + return Result(*InnerAM, AM.getResult(F)); } } // namespace llvm - -namespace polly { -template <> -OwningScopAnalysisManagerFunctionProxy::Result -OwningScopAnalysisManagerFunctionProxy::run(Function &F, - FunctionAnalysisManager &FAM) { - return Result(InnerAM, FAM.getResult(F)); -} -} // namespace polly Index: lib/Support/PollyPasses.def =================================================================== --- lib/Support/PollyPasses.def +++ lib/Support/PollyPasses.def @@ -13,6 +13,12 @@ FUNCTION_PASS("print", ScopInfoPrinterPass(errs())) #undef FUNCTION_PASS +#ifndef CGSCC_PASS +#define CGSCC_PASS(NAME, CREATE_PASS) +#endif +CGSCC_PASS("print", ScopInfoPrinterPass(errs())) +#undef CGSCC_PASS + #ifndef SCOP_ANALYSIS #define SCOP_ANALYSIS(NAME, CREATE_PASS) #endif Index: lib/Support/RegisterPasses.cpp =================================================================== --- lib/Support/RegisterPasses.cpp +++ lib/Support/RegisterPasses.cpp @@ -19,7 +19,6 @@ // enables additional polyhedral optimizations. //===----------------------------------------------------------------------===// -#include "polly/RegisterPasses.h" #include "polly/Canonicalization.h" #include "polly/CodeGen/CodeGeneration.h" #include "polly/CodeGen/CodegenCleanup.h" @@ -34,6 +33,7 @@ #include "polly/LinkAllPasses.h" #include "polly/Options.h" #include "polly/PolyhedralInfo.h" +#include "polly/RegisterPasses.h" #include "polly/ScopDetection.h" #include "polly/ScopInfo.h" #include "polly/Simplify.h" @@ -454,7 +454,7 @@ PM.add(createCodegenCleanupPass()); } -static void buildDefaultPollyPipeline(FunctionPassManager &PM, +static void buildDefaultPollyPipeline(CGSCCPassManager &PM, PassBuilder::OptimizationLevel Level) { if (!polly::shouldEnablePolly()) return; @@ -506,16 +506,20 @@ llvm_unreachable("Hybrid Target with GPU support is not implemented"); #endif - PM.addPass(CodePreparationPass()); - PM.addPass(createFunctionToScopPassAdaptor(std::move(SPM))); - PM.addPass(PB.buildFunctionSimplificationPipeline( + FunctionPassManager FPM; + + FPM.addPass(CodePreparationPass()); + FPM.addPass(PB.buildFunctionSimplificationPipeline( Level, PassBuilder::ThinLTOPhase::None)); // Cleanup assert(!DumpAfter && "This option is not implemented"); assert(DumpAfterFile.empty() && "This option is not implemented"); if (CFGPrinter) - PM.addPass(llvm::CFGPrinterPass()); + FPM.addPass(llvm::CFGPrinterPass()); + + PM.addPass(CGSCCToScopPassAdaptor(std::move(SPM))); + PM.addPass(createCGSCCToFunctionPassAdaptor(std::move(FPM))); } /// Register Polly to be available as an optimizer @@ -567,17 +571,18 @@ llvm::PassManagerBuilder::EP_VectorizerStart, registerPollyScalarOptimizerLatePasses); -static OwningScopAnalysisManagerFunctionProxy -createScopAnalyses(FunctionAnalysisManager &FAM) { - OwningScopAnalysisManagerFunctionProxy Proxy; +static void registerScopAnalyses(FunctionAnalysisManager &AM) { + AM.registerPass([&AM] { + OwningScopAnalysisManagerFunctionProxy Proxy; #define SCOP_ANALYSIS(NAME, CREATE_PASS) \ Proxy.getManager().registerPass([] { return CREATE_PASS; }); #include "PollyPasses.def" - Proxy.getManager().registerPass( - [&FAM] { return FunctionAnalysisManagerScopProxy(FAM); }); - return Proxy; + Proxy.getManager().registerPass( + [&AM] { return FunctionAnalysisManagerScopProxy(AM); }); + return Proxy; + }); } static void registerFunctionAnalyses(FunctionAnalysisManager &FAM) { @@ -585,8 +590,19 @@ FAM.registerPass([] { return CREATE_PASS; }); #include "PollyPasses.def" +} - FAM.registerPass([&FAM] { return createScopAnalyses(FAM); }); +static bool +parseCGSCCPipeline(StringRef Name, CGSCCPassManager &PM, + ArrayRef Pipeline) { +#define CGSCC_PASS(NAME, CREATE_PASS) \ + if (Name == NAME) { \ + PM.addPass(CREATE_PASS); \ + return true; \ + } + +#include "PollyPasses.def" + return false; } static bool @@ -630,7 +646,7 @@ return false; } -static bool parseScopPipeline(StringRef Name, FunctionPassManager &FPM, +static bool parseScopPipeline(StringRef Name, CGSCCPassManager &PM, ArrayRef Pipeline) { if (Name != "scop") return false; @@ -639,7 +655,7 @@ for (const auto &E : Pipeline) if (!parseScopPass(E.Name, SPM)) return false; - FPM.addPass(createFunctionToScopPassAdaptor(std::move(SPM))); + PM.addPass(createCGSCCToScopPassAdaptor(std::move(SPM))); } return true; } @@ -670,7 +686,7 @@ if (!isScopPassName(FirstName)) return false; - FunctionPassManager FPM(DebugLogging); + CGSCCPassManager PM(DebugLogging); ScopPassManager SPM(DebugLogging); for (auto &Element : Pipeline) { @@ -682,10 +698,11 @@ return false; } - FPM.addPass(createFunctionToScopPassAdaptor(std::move(SPM))); - if (VerifyEachPass) - FPM.addPass(VerifierPass()); - MPM.addPass(createModuleToFunctionPassAdaptor(std::move(FPM))); + PM.addPass(createCGSCCToScopPassAdaptor(std::move(SPM))); + // FIXME: When VerifyEachPass is enabled, we are supposed to add a + // VerifierPass to the pipeline here. However, there is no CGSCC-level + // verifier pass. + MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(PM))); if (VerifyEachPass) MPM.addPass(VerifierPass()); @@ -694,12 +711,13 @@ void RegisterPollyPasses(PassBuilder &PB) { PB.registerAnalysisRegistrationCallback(registerFunctionAnalyses); + PB.registerAnalysisRegistrationCallback(registerScopAnalyses); PB.registerPipelineParsingCallback(parseFunctionPipeline); PB.registerPipelineParsingCallback(parseScopPipeline); PB.registerParseTopLevelPipelineCallback(parseTopLevelPipeline); if (PassPosition == POSITION_BEFORE_VECTORIZER) - PB.registerVectorizerStartEPCallback(buildDefaultPollyPipeline); + PB.registerCGSCCOptimizerLateEPCallback(buildDefaultPollyPipeline); // FIXME else Error? } } // namespace polly Index: unittests/ScopPassManager/PassManagerTest.cpp =================================================================== --- unittests/ScopPassManager/PassManagerTest.cpp +++ unittests/ScopPassManager/PassManagerTest.cpp @@ -58,9 +58,9 @@ } TEST_F(ScopPassRegistry, PrinIslAstInfo) { - FunctionPassManager FPM; + CGSCCPassManager PM; ScopPassManager SPM; // SPM.addPass(IslAstPrinterPass(errs())); - FPM.addPass(createFunctionToScopPassAdaptor(std::move(SPM))); + PM.addPass(createCGSCCToScopPassAdaptor(std::move(SPM))); } } // namespace