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

Chandler Carruth via llvm-commits llvm-commits at lists.llvm.org
Wed Aug 3 19:26:30 PDT 2016


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/20160804/36652f84/attachment-0001.html>


More information about the llvm-commits mailing list