[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