[llvm] r277581 - [PM] Add a generic 'repeat N times' pass wrapper to the new pass

Sean Silva via llvm-commits llvm-commits at lists.llvm.org
Wed Aug 3 13:20:21 PDT 2016


Sorry for not mentioning this earlier, but can you please avoid using the
term "wrapper" for this? (as it may cause confusion with the "wrapper pass"
notion for analyses)

Same goes for the DevirtIteratingWrapper in https://reviews.llvm.org/D23114

These seem to essentially be decorator classes, so "decorator" is probably
a better name anyway and avoids the confusion.

-- Sean Silva


On Wed, Aug 3, 2016 at 12:44 AM, Chandler Carruth via llvm-commits <
llvm-commits at lists.llvm.org> wrote:

> Author: chandlerc
> Date: Wed Aug  3 02:44:48 2016
> New Revision: 277581
>
> URL: http://llvm.org/viewvc/llvm-project?rev=277581&view=rev
> Log:
> [PM] Add a generic 'repeat N times' pass wrapper to the new pass
> manager.
>
> While this has some utility for debugging and testing on its own, it is
> primarily intended to demonstrate the technique for adding custom
> wrappers that can provide more interesting interation behavior in
> a nice, orthogonal, and composable layer.
>
> Being able to write these kinds of very dynamic and customized controls
> for running passes was one of the motivating use cases of the new pass
> manager design, and this gives a hint at how they might look. The actual
> logic is tiny here, and most of this is just wiring in the pipeline
> parsing so that this can be widely used.
>
> I'm adding this now to show the wiring without a lot of business logic.
> This is a precursor patch for showing how a "iterate up to N times as
> long as we devirtualize a call" utility can be added as a separable and
> composable component along side the CGSCC pass management.
>
> Differential Revision: https://reviews.llvm.org/D22405
>
> Modified:
>     llvm/trunk/include/llvm/IR/PassManager.h
>     llvm/trunk/lib/Passes/PassBuilder.cpp
>     llvm/trunk/test/Other/new-pass-manager.ll
>
> Modified: llvm/trunk/include/llvm/IR/PassManager.h
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/IR/PassManager.h?rev=277581&r1=277580&r2=277581&view=diff
>
> ==============================================================================
> --- llvm/trunk/include/llvm/IR/PassManager.h (original)
> +++ llvm/trunk/include/llvm/IR/PassManager.h Wed Aug  3 02:44:48 2016
> @@ -987,6 +987,34 @@ struct InvalidateAllAnalysesPass : PassI
>    }
>  };
>
> +/// 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
>
> Modified: llvm/trunk/lib/Passes/PassBuilder.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Passes/PassBuilder.cpp?rev=277581&r1=277580&r2=277581&view=diff
>
> ==============================================================================
> --- llvm/trunk/lib/Passes/PassBuilder.cpp (original)
> +++ llvm/trunk/lib/Passes/PassBuilder.cpp Wed Aug  3 02:44:48 2016
> @@ -274,6 +274,15 @@ void PassBuilder::addLTODefaultPipeline(
>    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 N
>    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 Na
>    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
>    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 Nam
>    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(Module
>        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(CGSCCPa
>            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(Func
>        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(Func
>
>  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(LoopPass
>        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;
>    }
>
> Modified: llvm/trunk/test/Other/new-pass-manager.ll
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Other/new-pass-manager.ll?rev=277581&r1=277580&r2=277581&view=diff
>
> ==============================================================================
> --- llvm/trunk/test/Other/new-pass-manager.ll (original)
> +++ llvm/trunk/test/Other/new-pass-manager.ll Wed Aug  3 02:44:48 2016
> @@ -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
>  }
>
>
>
> _______________________________________________
> llvm-commits mailing list
> llvm-commits at lists.llvm.org
> http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-commits
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20160803/3828e0af/attachment.html>


More information about the llvm-commits mailing list