diff options
Diffstat (limited to 'llvm')
| -rw-r--r-- | llvm/include/llvm/IR/PassManager.h | 28 | ||||
| -rw-r--r-- | llvm/lib/Passes/PassBuilder.cpp | 59 | ||||
| -rw-r--r-- | llvm/test/Other/new-pass-manager.ll | 108 |
3 files changed, 188 insertions, 7 deletions
diff --git a/llvm/include/llvm/IR/PassManager.h b/llvm/include/llvm/IR/PassManager.h index 402d04a54a4..7a6364063bd 100644 --- a/llvm/include/llvm/IR/PassManager.h +++ b/llvm/include/llvm/IR/PassManager.h @@ -987,6 +987,34 @@ struct InvalidateAllAnalysesPass : PassInfoMixin<InvalidateAllAnalysesPass> { } }; +/// A utility pass template that simply runs another pass multiple times. +/// +/// This can be useful when debugging or testing passes. It also serves as an +/// example of how to extend the pass manager in ways beyond composition. +template <typename PassT> +class RepeatingPassWrapper : public PassInfoMixin<RepeatingPassWrapper<PassT>> { +public: + RepeatingPassWrapper(int Count, PassT P) : Count(Count), P(std::move(P)) {} + + template <typename IRUnitT, typename... Ts> + PreservedAnalyses run(IRUnitT &Arg, AnalysisManager<IRUnitT> &AM, + Ts... Args) { + auto PA = PreservedAnalyses::all(); + for (int i = 0; i < Count; ++i) + PA.intersect(P.run(Arg, AM, Args...)); + return PA; + } + +private: + const int Count; + PassT P; +}; + +template <typename PassT> +RepeatingPassWrapper<PassT> createRepeatingPassWrapper(int Count, PassT P) { + return RepeatingPassWrapper<PassT>(Count, std::move(P)); +} + } #endif diff --git a/llvm/lib/Passes/PassBuilder.cpp b/llvm/lib/Passes/PassBuilder.cpp index 4dae8748ffd..6369b55e4b6 100644 --- a/llvm/lib/Passes/PassBuilder.cpp +++ b/llvm/lib/Passes/PassBuilder.cpp @@ -274,6 +274,15 @@ void PassBuilder::addLTODefaultPipeline(ModulePassManager &MPM, MPM.addPass(createModuleToFunctionPassAdaptor(std::move(LateFPM))); } +static Optional<int> parseRepeatPassName(StringRef Name) { + if (!Name.consume_front("repeat<") || !Name.consume_back(">")) + return None; + int Count; + if (Name.getAsInteger(0, Count) || Count <= 0) + return None; + return Count; +} + static bool isModulePassName(StringRef Name) { // Manually handle aliases for pre-configured pipeline fragments. if (Name.startswith("default") || Name.startswith("lto")) @@ -287,6 +296,10 @@ static bool isModulePassName(StringRef Name) { if (Name == "function") return true; + // Explicitly handle custom-parsed pass names. + if (parseRepeatPassName(Name)) + return true; + #define MODULE_PASS(NAME, CREATE_PASS) \ if (Name == NAME) \ return true; @@ -305,6 +318,10 @@ static bool isCGSCCPassName(StringRef Name) { if (Name == "function") return true; + // Explicitly handle custom-parsed pass names. + if (parseRepeatPassName(Name)) + return true; + #define CGSCC_PASS(NAME, CREATE_PASS) \ if (Name == NAME) \ return true; @@ -323,6 +340,10 @@ static bool isFunctionPassName(StringRef Name) { if (Name == "loop") return true; + // Explicitly handle custom-parsed pass names. + if (parseRepeatPassName(Name)) + return true; + #define FUNCTION_PASS(NAME, CREATE_PASS) \ if (Name == NAME) \ return true; @@ -339,6 +360,10 @@ static bool isLoopPassName(StringRef Name) { if (Name == "loop") return true; + // Explicitly handle custom-parsed pass names. + if (parseRepeatPassName(Name)) + return true; + #define LOOP_PASS(NAME, CREATE_PASS) \ if (Name == NAME) \ return true; @@ -440,6 +465,14 @@ bool PassBuilder::parseModulePass(ModulePassManager &MPM, MPM.addPass(createModuleToFunctionPassAdaptor(std::move(FPM))); return true; } + if (auto Count = parseRepeatPassName(Name)) { + ModulePassManager NestedMPM(DebugLogging); + if (!parseModulePassPipeline(NestedMPM, InnerPipeline, VerifyEachPass, + DebugLogging)) + return false; + MPM.addPass(createRepeatingPassWrapper(*Count, std::move(NestedMPM))); + return true; + } // Normal passes can't have pipelines. return false; } @@ -519,6 +552,14 @@ bool PassBuilder::parseCGSCCPass(CGSCCPassManager &CGPM, createCGSCCToFunctionPassAdaptor(std::move(FPM), DebugLogging)); return true; } + if (auto Count = parseRepeatPassName(Name)) { + CGSCCPassManager NestedCGPM(DebugLogging); + if (!parseCGSCCPassPipeline(NestedCGPM, InnerPipeline, VerifyEachPass, + DebugLogging)) + return false; + CGPM.addPass(createRepeatingPassWrapper(*Count, std::move(NestedCGPM))); + return true; + } // Normal passes can't have pipelines. return false; } @@ -571,6 +612,14 @@ bool PassBuilder::parseFunctionPass(FunctionPassManager &FPM, FPM.addPass(createFunctionToLoopPassAdaptor(std::move(LPM))); return true; } + if (auto Count = parseRepeatPassName(Name)) { + FunctionPassManager NestedFPM(DebugLogging); + if (!parseFunctionPassPipeline(NestedFPM, InnerPipeline, VerifyEachPass, + DebugLogging)) + return false; + FPM.addPass(createRepeatingPassWrapper(*Count, std::move(NestedFPM))); + return true; + } // Normal passes can't have pipelines. return false; } @@ -599,7 +648,7 @@ bool PassBuilder::parseFunctionPass(FunctionPassManager &FPM, bool PassBuilder::parseLoopPass(LoopPassManager &FPM, const PipelineElement &E, bool VerifyEachPass, bool DebugLogging) { - auto &Name = E.Name; + StringRef Name = E.Name; auto &InnerPipeline = E.InnerPipeline; // First handle complex passes like the pass managers which carry pipelines. @@ -613,6 +662,14 @@ bool PassBuilder::parseLoopPass(LoopPassManager &FPM, const PipelineElement &E, FPM.addPass(std::move(NestedLPM)); return true; } + if (auto Count = parseRepeatPassName(Name)) { + LoopPassManager NestedLPM(DebugLogging); + if (!parseLoopPassPipeline(NestedLPM, InnerPipeline, VerifyEachPass, + DebugLogging)) + return false; + FPM.addPass(createRepeatingPassWrapper(*Count, std::move(NestedLPM))); + return true; + } // Normal passes can't have pipelines. return false; } diff --git a/llvm/test/Other/new-pass-manager.ll b/llvm/test/Other/new-pass-manager.ll index cbb45928429..13197a19409 100644 --- a/llvm/test/Other/new-pass-manager.ll +++ b/llvm/test/Other/new-pass-manager.ll @@ -48,7 +48,7 @@ ; CHECK-MODULE-PRINT: Running pass: VerifierPass ; CHECK-MODULE-PRINT: Running pass: PrintModulePass ; CHECK-MODULE-PRINT: ModuleID -; CHECK-MODULE-PRINT: define void @foo() +; CHECK-MODULE-PRINT: define void @foo(i1 %x) ; CHECK-MODULE-PRINT: Running pass: VerifierPass ; CHECK-MODULE-PRINT: Finished llvm::Module pass manager run @@ -57,7 +57,7 @@ ; CHECK-MODULE-VERIFY: Starting llvm::Module pass manager run ; CHECK-MODULE-VERIFY: Running pass: PrintModulePass ; CHECK-MODULE-VERIFY: ModuleID -; CHECK-MODULE-VERIFY: define void @foo() +; CHECK-MODULE-VERIFY: define void @foo(i1 %x) ; CHECK-MODULE-VERIFY: Running pass: VerifierPass ; CHECK-MODULE-VERIFY: Finished llvm::Module pass manager run @@ -70,7 +70,7 @@ ; CHECK-FUNCTION-PRINT: Starting llvm::Function pass manager run ; CHECK-FUNCTION-PRINT: Running pass: PrintFunctionPass ; CHECK-FUNCTION-PRINT-NOT: ModuleID -; CHECK-FUNCTION-PRINT: define void @foo() +; CHECK-FUNCTION-PRINT: define void @foo(i1 %x) ; CHECK-FUNCTION-PRINT: Finished llvm::Function pass manager run ; CHECK-FUNCTION-PRINT: Running pass: VerifierPass ; CHECK-FUNCTION-PRINT: Finished llvm::Module pass manager run @@ -81,14 +81,19 @@ ; CHECK-FUNCTION-VERIFY: Starting llvm::Function pass manager run ; CHECK-FUNCTION-VERIFY: Running pass: PrintFunctionPass ; CHECK-FUNCTION-VERIFY-NOT: ModuleID -; CHECK-FUNCTION-VERIFY: define void @foo() +; CHECK-FUNCTION-VERIFY: define void @foo(i1 %x) ; CHECK-FUNCTION-VERIFY: Running pass: VerifierPass ; CHECK-FUNCTION-VERIFY: Finished llvm::Function pass manager run ; CHECK-FUNCTION-VERIFY: Finished llvm::Module pass manager run ; RUN: opt -S -o - -passes='no-op-module,no-op-module' %s \ ; RUN: | FileCheck %s --check-prefix=CHECK-NOOP -; CHECK-NOOP: define void @foo() { +; CHECK-NOOP: define void @foo(i1 %x) { +; CHECK-NOOP: entry: +; CHECK-NOOP: br i1 %x, label %loop, label %exit +; CHECK-NOOP: loop: +; CHECK-NOOP: br label %loop +; CHECK-NOOP: exit: ; CHECK-NOOP: ret void ; CHECK-NOOP: } @@ -363,7 +368,98 @@ ; CHECK-LTO-O2: Running pass: InstCombinePass ; CHECK-LTO-O2: Running pass: SimplifyCFGPass -define void @foo() { +; RUN: opt -disable-output -disable-verify -debug-pass-manager \ +; RUN: -passes='repeat<3>(no-op-module)' %s 2>&1 \ +; RUN: | FileCheck %s --check-prefix=CHECK-REPEAT-MODULE-PASS +; CHECK-REPEAT-MODULE-PASS: Starting llvm::Module pass manager run +; CHECK-REPEAT-MODULE-PASS-NEXT: Running pass: RepeatingPassWrapper +; CHECK-REPEAT-MODULE-PASS-NEXT: Starting llvm::Module pass manager run +; CHECK-REPEAT-MODULE-PASS-NEXT: Running pass: NoOpModulePass +; CHECK-REPEAT-MODULE-PASS-NEXT: Finished llvm::Module pass manager run +; CHECK-REPEAT-MODULE-PASS-NEXT: Starting llvm::Module pass manager run +; CHECK-REPEAT-MODULE-PASS-NEXT: Running pass: NoOpModulePass +; CHECK-REPEAT-MODULE-PASS-NEXT: Finished llvm::Module pass manager run +; CHECK-REPEAT-MODULE-PASS-NEXT: Starting llvm::Module pass manager run +; CHECK-REPEAT-MODULE-PASS-NEXT: Running pass: NoOpModulePass +; CHECK-REPEAT-MODULE-PASS-NEXT: Finished llvm::Module pass manager run +; CHECK-REPEAT-MODULE-PASS-NEXT: Finished llvm::Module pass manager run + +; RUN: opt -disable-output -disable-verify -debug-pass-manager \ +; RUN: -passes='cgscc(repeat<3>(no-op-cgscc))' %s 2>&1 \ +; RUN: | FileCheck %s --check-prefix=CHECK-REPEAT-CGSCC-PASS +; CHECK-REPEAT-CGSCC-PASS: Starting llvm::Module pass manager run +; CHECK-REPEAT-CGSCC-PASS-NEXT: Running pass: ModuleToPostOrderCGSCCPassAdaptor +; CHECK-REPEAT-CGSCC-PASS-NEXT: Running analysis: InnerAnalysisManagerProxy<{{.*}}> +; CHECK-REPEAT-CGSCC-PASS-NEXT: Running analysis: LazyCallGraphAnalysis +; CHECK-REPEAT-CGSCC-PASS-NEXT: Running an SCC pass across the RefSCC: [(foo)] +; CHECK-REPEAT-CGSCC-PASS-NEXT: Starting llvm::LazyCallGraph::SCC pass manager run +; CHECK-REPEAT-CGSCC-PASS-NEXT: Running pass: RepeatingPassWrapper +; CHECK-REPEAT-CGSCC-PASS-NEXT: Starting llvm::LazyCallGraph::SCC pass manager run +; CHECK-REPEAT-CGSCC-PASS-NEXT: Running pass: NoOpCGSCCPass +; CHECK-REPEAT-CGSCC-PASS-NEXT: Finished llvm::LazyCallGraph::SCC pass manager run +; CHECK-REPEAT-CGSCC-PASS-NEXT: Starting llvm::LazyCallGraph::SCC pass manager run +; CHECK-REPEAT-CGSCC-PASS-NEXT: Running pass: NoOpCGSCCPass +; CHECK-REPEAT-CGSCC-PASS-NEXT: Finished llvm::LazyCallGraph::SCC pass manager run +; CHECK-REPEAT-CGSCC-PASS-NEXT: Starting llvm::LazyCallGraph::SCC pass manager run +; CHECK-REPEAT-CGSCC-PASS-NEXT: Running pass: NoOpCGSCCPass +; CHECK-REPEAT-CGSCC-PASS-NEXT: Finished llvm::LazyCallGraph::SCC pass manager run +; CHECK-REPEAT-CGSCC-PASS-NEXT: Finished llvm::LazyCallGraph::SCC pass manager run +; CHECK-REPEAT-CGSCC-PASS-NEXT: Finished llvm::Module pass manager run + +; RUN: opt -disable-output -disable-verify -debug-pass-manager \ +; RUN: -passes='function(repeat<3>(no-op-function))' %s 2>&1 \ +; RUN: | FileCheck %s --check-prefix=CHECK-REPEAT-FUNCTION-PASS +; CHECK-REPEAT-FUNCTION-PASS: Starting llvm::Module pass manager run +; CHECK-REPEAT-FUNCTION-PASS-NEXT: Running pass: ModuleToFunctionPassAdaptor +; CHECK-REPEAT-FUNCTION-PASS-NEXT: Running analysis: InnerAnalysisManagerProxy<{{.*}}> +; CHECK-REPEAT-FUNCTION-PASS-NEXT: Starting llvm::Function pass manager run +; CHECK-REPEAT-FUNCTION-PASS-NEXT: Running pass: RepeatingPassWrapper +; CHECK-REPEAT-FUNCTION-PASS-NEXT: Starting llvm::Function pass manager run +; CHECK-REPEAT-FUNCTION-PASS-NEXT: Running pass: NoOpFunctionPass +; CHECK-REPEAT-FUNCTION-PASS-NEXT: Finished llvm::Function pass manager run +; CHECK-REPEAT-FUNCTION-PASS-NEXT: Starting llvm::Function pass manager run +; CHECK-REPEAT-FUNCTION-PASS-NEXT: Running pass: NoOpFunctionPass +; CHECK-REPEAT-FUNCTION-PASS-NEXT: Finished llvm::Function pass manager run +; CHECK-REPEAT-FUNCTION-PASS-NEXT: Starting llvm::Function pass manager run +; CHECK-REPEAT-FUNCTION-PASS-NEXT: Running pass: NoOpFunctionPass +; CHECK-REPEAT-FUNCTION-PASS-NEXT: Finished llvm::Function pass manager run +; CHECK-REPEAT-FUNCTION-PASS-NEXT: Finished llvm::Function pass manager run +; CHECK-REPEAT-FUNCTION-PASS-NEXT: Finished llvm::Module pass manager run + +; RUN: opt -disable-output -disable-verify -debug-pass-manager \ +; RUN: -passes='loop(repeat<3>(no-op-loop))' %s 2>&1 \ +; RUN: | FileCheck %s --check-prefix=CHECK-REPEAT-LOOP-PASS +; CHECK-REPEAT-LOOP-PASS: Starting llvm::Module pass manager run +; CHECK-REPEAT-LOOP-PASS-NEXT: Running pass: ModuleToFunctionPassAdaptor +; CHECK-REPEAT-LOOP-PASS-NEXT: Running analysis: InnerAnalysisManagerProxy<{{.*}}> +; CHECK-REPEAT-LOOP-PASS-NEXT: Starting llvm::Function pass manager run +; CHECK-REPEAT-LOOP-PASS-NEXT: Running pass: FunctionToLoopPassAdaptor +; CHECK-REPEAT-LOOP-PASS-NEXT: Running analysis: InnerAnalysisManagerProxy<{{.*}}> +; CHECK-REPEAT-LOOP-PASS-NEXT: Running analysis: LoopAnalysis +; CHECK-REPEAT-LOOP-PASS-NEXT: Running analysis: DominatorTreeAnalysis +; CHECK-REPEAT-LOOP-PASS-NEXT: Starting llvm::Loop pass manager run +; CHECK-REPEAT-LOOP-PASS-NEXT: Running pass: RepeatingPassWrapper +; CHECK-REPEAT-LOOP-PASS-NEXT: Starting llvm::Loop pass manager run +; CHECK-REPEAT-LOOP-PASS-NEXT: Running pass: NoOpLoopPass +; CHECK-REPEAT-LOOP-PASS-NEXT: Finished llvm::Loop pass manager run +; CHECK-REPEAT-LOOP-PASS-NEXT: Starting llvm::Loop pass manager run +; CHECK-REPEAT-LOOP-PASS-NEXT: Running pass: NoOpLoopPass +; CHECK-REPEAT-LOOP-PASS-NEXT: Finished llvm::Loop pass manager run +; CHECK-REPEAT-LOOP-PASS-NEXT: Starting llvm::Loop pass manager run +; CHECK-REPEAT-LOOP-PASS-NEXT: Running pass: NoOpLoopPass +; CHECK-REPEAT-LOOP-PASS-NEXT: Finished llvm::Loop pass manager run +; CHECK-REPEAT-LOOP-PASS-NEXT: Finished llvm::Loop pass manager run +; CHECK-REPEAT-LOOP-PASS-NEXT: Finished llvm::Function pass manager run +; CHECK-REPEAT-LOOP-PASS-NEXT: Finished llvm::Module pass manager run + +define void @foo(i1 %x) { +entry: + br i1 %x, label %loop, label %exit + +loop: + br label %loop + +exit: ret void } |

