[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 23:53:14 PDT 2016


That sounds fine. My main concern was avoiding the overloaded "wrapper".

I don't particularly like the new name though, but it's livable. This is a
textbook example of a decorator and "decorator" exactly conveys what it is.

-- Sean Silva

On Wed, Aug 3, 2016 at 7:26 PM, Chandler Carruth <chandlerc at gmail.com>
wrote:

> Yea, I completely agree that Wrapper is a bad suffix. Thanks for catching
> it, I just hadn't gone down that thought process. However, I'm not terribly
> fond of just using Decorator here because I feel like it isn't conveying
> much of anything. With the actual place we used "wrapper pass" in the old
> pass manager it has a reasonably specific meaning, and this doesn't.
> Ultimately, I think the suffix isn't helping at all and what is needed is a
> better name. =]
>
> After some bikeshedding on IRC, I'm going with RepeatedPass<...> as it is
> a template to create a repeated pass. =] Happy to keep tweaking this if
> this name presents more problems.
>
> On Wed, Aug 3, 2016 at 1:20 PM Sean Silva via llvm-commits <
> llvm-commits at lists.llvm.org> wrote:
>
>> 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
>>>
>>
>> _______________________________________________
>> 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/8f54271f/attachment.html>


More information about the llvm-commits mailing list