[llvm] r273961 - [PM] Improve the debugging and logging facilities of the CGSCC bits of

Sean Silva via llvm-commits llvm-commits at lists.llvm.org
Wed Jul 6 12:26:03 PDT 2016


On Wed, Jul 6, 2016 at 11:44 AM, Chandler Carruth via llvm-commits <
llvm-commits at lists.llvm.org> wrote:

> On Tue, Jul 5, 2016 at 5:19 PM Davide Italiano via llvm-commits <
> llvm-commits at lists.llvm.org> wrote:
>
>> On Mon, Jun 27, 2016 at 4:26 PM, Chandler Carruth via llvm-commits
>> <llvm-commits at lists.llvm.org> wrote:
>> > Author: chandlerc
>> > Date: Mon Jun 27 18:26:08 2016
>> > New Revision: 273961
>> >
>> > URL: http://llvm.org/viewvc/llvm-project?rev=273961&view=rev
>> > Log:
>> > [PM] Improve the debugging and logging facilities of the CGSCC bits of
>> > the new pass manager.
>> >
>> > This adds operator<< overloads for the various bits of the
>> > LazyCallGraph, dump methods for use from the debugger, and debug logging
>> > using them to the CGSCC pass manager.
>> >
>> > Having this was essential for debugging the call graph update patch, and
>> > I've extracted what I could from that patch here to minimize the delta.
>> >
>> > Modified:
>> >     llvm/trunk/include/llvm/Analysis/CGSCCPassManager.h
>> >     llvm/trunk/include/llvm/Analysis/LazyCallGraph.h
>> >     llvm/trunk/lib/Analysis/LazyCallGraph.cpp
>> >     llvm/trunk/lib/Passes/PassBuilder.cppHi Hi
>> >     llvm/trunk/test/Other/new-pass-manager.ll
>> >
>>
>> Hi Chandler, this breaks the build with GCC6. Can you please take a look?
>>
>
> Yikes, just back from the holiday weekend and looking at this. Is there a
> build bot with this configuration? I'm worried I may not get it on my first
> shot...
>

In case it helps, http://gcc.godbolt.org/ has GCC6 available.

-- Sean Silva


>
>
>>
>> Thanks!
>>
>> [756/2768] Building CXX object
>> lib/Analysis/CMakeFiles/LLVMAnalysis.dir/LazyCallGraph.cpp.o
>> ../lib/Analysis/LazyCallGraph.cpp:123:14: warning: ‘llvm::raw_ostream&
>> llvm::operator<<(llvm::raw_ostream&, const
>> llvm::LazyCallGraph::Node&)’ has not been declared within llvm
>>  raw_ostream &llvm::operator<<(raw_ostream &OS, const LazyCallGraph::Node
>> &N) {
>>               ^~~~
>> In file included from ../lib/Analysis/LazyCallGraph.cpp:10:0:
>> ../include/llvm/Analysis/LazyCallGraph.h:227:25: note: only here as a
>> friend
>>      friend raw_ostream &operator<<(raw_ostream &OS, const Node &N);
>>                          ^~~~~~~~
>> ../lib/Analysis/LazyCallGraph.cpp:184:14: warning: ‘llvm::raw_ostream&
>> llvm::operator<<(llvm::raw_ostream&, const llvm::LazyCallGraph::SCC&)’
>> has not been declared within llvm
>>  raw_ostream &llvm::operator<<(raw_ostream &OS, const LazyCallGraph::SCC
>> &C) {
>>               ^~~~
>> In file included from ../lib/Analysis/LazyCallGraph.cpp:10:0:
>> ../include/llvm/Analysis/LazyCallGraph.h:367:25: note: only here as a
>> friend
>>      friend raw_ostream &operator<<(raw_ostream &OS, const SCC &C);
>>                          ^~~~~~~~
>> ../lib/Analysis/LazyCallGraph.cpp:227:14: warning: ‘llvm::raw_ostream&
>> llvm::operator<<(llvm::raw_ostream&, const
>> llvm::LazyCallGraph::RefSCC&)’ has not been declared within llvm
>>  raw_ostream &llvm::operator<<(raw_ostream &OS,
>>               ^~~~
>> In file included from ../lib/Analysis/LazyCallGraph.cpp:10:0:
>> ../include/llvm/Analysis/LazyCallGraph.h:439:25: note: only here as a
>> friend
>>      friend raw_ostream &operator<<(raw_ostream &OS, const RefSCC &RC);
>>                          ^~~~~~~~
>>
>>
>>
>> > Modified: llvm/trunk/include/llvm/Analysis/CGSCCPassManager.h
>> > URL:
>> http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Analysis/CGSCCPassManager.h?rev=273961&r1=273960&r2=273961&view=diff
>> >
>> ==============================================================================
>> > --- llvm/trunk/include/llvm/Analysis/CGSCCPassManager.h (original)
>> > +++ llvm/trunk/include/llvm/Analysis/CGSCCPassManager.h Mon Jun 27
>> 18:26:08 2016
>> > @@ -67,19 +67,20 @@ template <typename CGSCCPassT>
>> >  class ModuleToPostOrderCGSCCPassAdaptor
>> >      : public
>> PassInfoMixin<ModuleToPostOrderCGSCCPassAdaptor<CGSCCPassT>> {
>> >  public:
>> > -  explicit ModuleToPostOrderCGSCCPassAdaptor(CGSCCPassT Pass)
>> > -      : Pass(std::move(Pass)) {}
>> > +  explicit ModuleToPostOrderCGSCCPassAdaptor(CGSCCPassT Pass, bool
>> DebugLogging = false)
>> > +      : Pass(std::move(Pass)), DebugLogging(DebugLogging) {}
>> >    // We have to explicitly define all the special member functions
>> because MSVC
>> >    // refuses to generate them.
>> >    ModuleToPostOrderCGSCCPassAdaptor(
>> >        const ModuleToPostOrderCGSCCPassAdaptor &Arg)
>> > -      : Pass(Arg.Pass) {}
>> > +      : Pass(Arg.Pass), DebugLogging(Arg.DebugLogging) {}
>> >    ModuleToPostOrderCGSCCPassAdaptor(ModuleToPostOrderCGSCCPassAdaptor
>> &&Arg)
>> > -      : Pass(std::move(Arg.Pass)) {}
>> > +      : Pass(std::move(Arg.Pass)), DebugLogging(Arg.DebugLogging) {}
>> >    friend void swap(ModuleToPostOrderCGSCCPassAdaptor &LHS,
>> >                     ModuleToPostOrderCGSCCPassAdaptor &RHS) {
>> >      using std::swap;
>> >      swap(LHS.Pass, RHS.Pass);
>> > +    swap(LHS.DebugLogging, RHS.DebugLogging);
>> >    }
>> >    ModuleToPostOrderCGSCCPassAdaptor &
>> >    operator=(ModuleToPostOrderCGSCCPassAdaptor RHS) {
>> > @@ -97,8 +98,11 @@ public:
>> >      LazyCallGraph &CG = AM.getResult<LazyCallGraphAnalysis>(M);
>> >
>> >      PreservedAnalyses PA = PreservedAnalyses::all();
>> > -    for (LazyCallGraph::RefSCC &OuterC : CG.postorder_ref_sccs())
>> > -      for (LazyCallGraph::SCC &C : OuterC) {
>> > +    for (LazyCallGraph::RefSCC &RC : CG.postorder_ref_sccs()) {
>> > +      if (DebugLogging)
>> > +        dbgs() << "Running an SCC pass across the RefSCC: " << RC <<
>> "\n";
>> > +
>> > +      for (LazyCallGraph::SCC &C : RC) {
>> >          PreservedAnalyses PassPA = Pass.run(C, CGAM);
>> >
>> >          // We know that the CGSCC pass couldn't have invalidated any
>> other
>> > @@ -115,6 +119,7 @@ public:
>> >          // analyses will eventually occur when the module pass
>> completes.
>> >          PA.intersect(std::move(PassPA));
>> >        }
>> > +    }
>> >
>> >      // By definition we preserve the proxy. This precludes *any*
>> invalidation
>> >      // of CGSCC analyses by the proxy, but that's OK because we've
>> taken
>> > @@ -126,14 +131,15 @@ public:
>> >
>> >  private:
>> >    CGSCCPassT Pass;
>> > +  bool DebugLogging;
>> >  };
>> >
>> >  /// \brief A function to deduce a function pass type and wrap it in the
>> >  /// templated adaptor.
>> >  template <typename CGSCCPassT>
>> >  ModuleToPostOrderCGSCCPassAdaptor<CGSCCPassT>
>> > -createModuleToPostOrderCGSCCPassAdaptor(CGSCCPassT Pass) {
>> > -  return
>> ModuleToPostOrderCGSCCPassAdaptor<CGSCCPassT>(std::move(Pass));
>> > +createModuleToPostOrderCGSCCPassAdaptor(CGSCCPassT Pass, bool
>> DebugLogging = false) {
>> > +  return
>> ModuleToPostOrderCGSCCPassAdaptor<CGSCCPassT>(std::move(Pass),
>> DebugLogging);
>> >  }
>> >
>> >  extern template class
>> InnerAnalysisManagerProxy<FunctionAnalysisManager,
>> > @@ -159,18 +165,19 @@ template <typename FunctionPassT>
>> >  class CGSCCToFunctionPassAdaptor
>> >      : public PassInfoMixin<CGSCCToFunctionPassAdaptor<FunctionPassT>> {
>> >  public:
>> > -  explicit CGSCCToFunctionPassAdaptor(FunctionPassT Pass)
>> > -      : Pass(std::move(Pass)) {}
>> > +  explicit CGSCCToFunctionPassAdaptor(FunctionPassT Pass, bool
>> DebugLogging = false)
>> > +      : Pass(std::move(Pass)), DebugLogging(DebugLogging) {}
>> >    // We have to explicitly define all the special member functions
>> because MSVC
>> >    // refuses to generate them.
>> >    CGSCCToFunctionPassAdaptor(const CGSCCToFunctionPassAdaptor &Arg)
>> > -      : Pass(Arg.Pass) {}
>> > +      : Pass(Arg.Pass), DebugLogging(Arg.DebugLogging) {}
>> >    CGSCCToFunctionPassAdaptor(CGSCCToFunctionPassAdaptor &&Arg)
>> > -      : Pass(std::move(Arg.Pass)) {}
>> > +      : Pass(std::move(Arg.Pass)), DebugLogging(Arg.DebugLogging) {}
>> >    friend void swap(CGSCCToFunctionPassAdaptor &LHS,
>> >                     CGSCCToFunctionPassAdaptor &RHS) {
>> >      using std::swap;
>> >      swap(LHS.Pass, RHS.Pass);
>> > +    swap(LHS.DebugLogging, RHS.DebugLogging);
>> >    }
>> >    CGSCCToFunctionPassAdaptor &operator=(CGSCCToFunctionPassAdaptor
>> RHS) {
>> >      swap(*this, RHS);
>> > @@ -183,6 +190,9 @@ public:
>> >      FunctionAnalysisManager &FAM =
>> >
>> AM.getResult<FunctionAnalysisManagerCGSCCProxy>(C).getManager();
>> >
>> > +    if (DebugLogging)
>> > +      dbgs() << "Running function passes across an SCC: " << C << "\n";
>> > +
>> >      PreservedAnalyses PA = PreservedAnalyses::all();
>> >      for (LazyCallGraph::Node &N : C) {
>> >        PreservedAnalyses PassPA = Pass.run(N.getFunction(), FAM);
>> > @@ -211,14 +221,16 @@ public:
>> >
>> >  private:
>> >    FunctionPassT Pass;
>> > +  bool DebugLogging;
>> >  };
>> >
>> >  /// \brief A function to deduce a function pass type and wrap it in the
>> >  /// templated adaptor.
>> >  template <typename FunctionPassT>
>> >  CGSCCToFunctionPassAdaptor<FunctionPassT>
>> > -createCGSCCToFunctionPassAdaptor(FunctionPassT Pass) {
>> > -  return CGSCCToFunctionPassAdaptor<FunctionPassT>(std::move(Pass));
>> > +createCGSCCToFunctionPassAdaptor(FunctionPassT Pass, bool DebugLogging
>> = false) {
>> > +  return CGSCCToFunctionPassAdaptor<FunctionPassT>(std::move(Pass),
>> > +                                                   DebugLogging);
>> >  }
>> >  }
>> >
>> >
>> > Modified: llvm/trunk/include/llvm/Analysis/LazyCallGraph.h
>> > URL:
>> http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Analysis/LazyCallGraph.h?rev=273961&r1=273960&r2=273961&view=diff
>> >
>> ==============================================================================
>> > --- llvm/trunk/include/llvm/Analysis/LazyCallGraph.h (original)
>> > +++ llvm/trunk/include/llvm/Analysis/LazyCallGraph.h Mon Jun 27
>> 18:26:08 2016
>> > @@ -48,6 +48,7 @@
>> >  #include "llvm/IR/Module.h"
>> >  #include "llvm/IR/PassManager.h"
>> >  #include "llvm/Support/Allocator.h"
>> > +#include "llvm/Support/raw_ostream.h"
>> >  #include <iterator>
>> >  #include <utility>
>> >
>> > @@ -222,6 +223,12 @@ public:
>> >      /// Internal helper to remove the edge to the given function.
>> >      void removeEdgeInternal(Function &ChildF);
>> >
>> > +    /// Print the name of this node's function.
>> > +    friend raw_ostream &operator<<(raw_ostream &OS, const Node &N);
>> > +
>> > +    /// Dump the name of this node's function to stderr.
>> > +    void dump() const;
>> > +
>> >    public:
>> >      LazyCallGraph &getGraph() const { return *G; }
>> >
>> > @@ -353,6 +360,15 @@ public:
>> >        Nodes.clear();
>> >      }
>> >
>> > +    /// Print a short descrtiption useful for debugging or logging.
>> > +    ///
>> > +    /// We print the function names in the SCC wrapped in '()'s and
>> skipping
>> > +    /// the middle functions if there are a large number.
>> > +    friend raw_ostream &operator<<(raw_ostream &OS, const SCC &C);
>> > +
>> > +    /// Dump a short description of this SCC to stderr.
>> > +    void dump() const;
>> > +
>> >  #ifndef NDEBUG
>> >      /// Verify invariants about the SCC.
>> >      ///
>> > @@ -373,25 +389,15 @@ public:
>> >
>> >      RefSCC &getOuterRefSCC() const { return *OuterRefSCC; }
>> >
>> > -    /// Short name useful for debugging or logging.
>> > +    /// Provide a short name by printing this SCC to a std::string.
>> >      ///
>> > -    /// We use the name of the first function in the SCC to name the
>> SCC for
>> > -    /// the purposes of debugging and logging.
>> > +    /// This copes with the fact that we don't have a name per-se for
>> an SCC
>> > +    /// while still making the use of this in debugging and logging
>> useful.
>> >      std::string getName() const {
>> >        std::string Name;
>> > -      int i = 0;
>> > -      for (Node &N : *this) {
>> > -        if (i > 0)
>> > -          Name += ", ";
>> > -        // Elide the inner elements if there are too many.
>> > -        if (i > 8) {
>> > -          Name += "..., ";
>> > -          Name += Nodes.back()->getFunction().getName().str();
>> > -          break;
>> > -        }
>> > -        Name += N.getFunction().getName().str();
>> > -        ++i;
>> > -      }
>> > +      raw_string_ostream OS(Name);
>> > +      OS << *this;
>> > +      OS.flush();
>> >        return Name;
>> >      }
>> >    };
>> > @@ -426,6 +432,15 @@ public:
>> >      /// formRefSCCFast on the graph itself.
>> >      RefSCC(LazyCallGraph &G);
>> >
>> > +    /// Print a short description useful for debugging or logging.
>> > +    ///
>> > +    /// We print the SCCs wrapped in '[]'s and skipping the middle
>> SCCs if
>> > +    /// there are a large number.
>> > +    friend raw_ostream &operator<<(raw_ostream &OS, const RefSCC &RC);
>> > +
>> > +    /// Dump a short description of this RefSCC to stderr.
>> > +    void dump() const;
>> > +
>> >  #ifndef NDEBUG
>> >      /// Verify invariants about the RefSCC and all its SCCs.
>> >      ///
>> > @@ -477,12 +492,16 @@ public:
>> >      /// Test if this RefSCC is a descendant of \a C.
>> >      bool isDescendantOf(const RefSCC &C) const;
>> >
>> > -    /// Short name useful for debugging or logging.
>> > +    /// Provide a short name by printing this SCC to a std::string.
>> >      ///
>> > -    /// We use the name of the first function in the SCC to name the
>> SCC for
>> > -    /// the purposes of debugging and logging.
>> > -    StringRef getName() const {
>> > -      return begin()->begin()->getFunction().getName();
>> > +    /// This copes with the fact that we don't have a name per-se for
>> an SCC
>> > +    /// while still making the use of this in debugging and logging
>> useful.
>> > +    std::string getName() const {
>> > +      std::string Name;
>> > +      raw_string_ostream OS(Name);
>> > +      OS << *this;
>> > +      OS.flush();
>> > +      return Name;
>> >      }
>> >
>> >      ///@{
>> >
>> > Modified: llvm/trunk/lib/Analysis/LazyCallGraph.cpp
>> > URL:
>> http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Analysis/LazyCallGraph.cpp?rev=273961&r1=273960&r2=273961&view=diff
>> >
>> ==============================================================================
>> > --- llvm/trunk/lib/Analysis/LazyCallGraph.cpp (original)
>> > +++ llvm/trunk/lib/Analysis/LazyCallGraph.cpp Mon Jun 27 18:26:08 2016
>> > @@ -120,6 +120,14 @@ void LazyCallGraph::Node::removeEdgeInte
>> >    EdgeIndexMap.erase(IndexMapI);
>> >  }
>> >
>> > +raw_ostream &llvm::operator<<(raw_ostream &OS, const
>> LazyCallGraph::Node &N) {
>> > +  return OS << N.F.getName();
>> > +}
>> > +
>> > +void LazyCallGraph::Node::dump() const {
>> > +  dbgs() << *this << '\n';
>> > +}
>> > +
>> >  LazyCallGraph::LazyCallGraph(Module &M) : NextDFSNumber(0) {
>> >    DEBUG(dbgs() << "Building CG for module: " << M.getModuleIdentifier()
>> >                 << "\n");
>> > @@ -173,6 +181,28 @@ LazyCallGraph &LazyCallGraph::operator=(
>> >    return *this;
>> >  }
>> >
>> > +raw_ostream &llvm::operator<<(raw_ostream &OS, const
>> LazyCallGraph::SCC &C) {
>> > +  OS << '(';
>> > +  int i = 0;
>> > +  for (LazyCallGraph::Node &N : C) {
>> > +    if (i > 0)
>> > +      OS << ", ";
>> > +    // Elide the inner elements if there are too many.
>> > +    if (i > 8) {
>> > +      OS << "..., " << *C.Nodes.back();
>> > +      break;
>> > +    }
>> > +    OS << N;
>> > +    ++i;
>> > +  }
>> > +  OS << ')';
>> > +  return OS;
>> > +}
>> > +
>> > +void LazyCallGraph::SCC::dump() const {
>> > +  dbgs() << *this << '\n';
>> > +}
>> > +
>> >  #ifndef NDEBUG
>> >  void LazyCallGraph::SCC::verify() {
>> >    assert(OuterRefSCC && "Can't have a null RefSCC!");
>> > @@ -194,6 +224,29 @@ void LazyCallGraph::SCC::verify() {
>> >
>> >  LazyCallGraph::RefSCC::RefSCC(LazyCallGraph &G) : G(&G) {}
>> >
>> > +raw_ostream &llvm::operator<<(raw_ostream &OS,
>> > +                              const LazyCallGraph::RefSCC &RC) {
>> > +  OS << '[';
>> > +  int i = 0;
>> > +  for (LazyCallGraph::SCC &C : RC) {
>> > +    if (i > 0)
>> > +      OS << ", ";
>> > +    // Elide the inner elements if there are too many.
>> > +    if (i > 4) {
>> > +      OS << "..., " << *RC.SCCs.back();
>> > +      break;
>> > +    }
>> > +    OS << C;
>> > +    ++i;
>> > +  }
>> > +  OS << ']';
>> > +  return OS;
>> > +}
>> > +
>> > +void LazyCallGraph::RefSCC::dump() const {
>> > +  dbgs() << *this << '\n';
>> > +}
>> > +
>> >  #ifndef NDEBUG
>> >  void LazyCallGraph::RefSCC::verify() {
>> >    assert(G && "Can't have a null graph!");
>> >
>> > Modified: llvm/trunk/lib/Passes/PassBuilder.cpp
>> > URL:
>> http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Passes/PassBuilder.cpp?rev=273961&r1=273960&r2=273961&view=diff
>> >
>> ==============================================================================
>> > --- llvm/trunk/lib/Passes/PassBuilder.cpp (original)
>> > +++ llvm/trunk/lib/Passes/PassBuilder.cpp Mon Jun 27 18:26:08 2016
>> > @@ -561,7 +561,8 @@ bool PassBuilder::parseCGSCCPassPipeline
>> >        PipelineText = PipelineText.substr(1);
>> >
>> >        // Add the nested pass manager with the appropriate adaptor.
>> > -
>> CGPM.addPass(createCGSCCToFunctionPassAdaptor(std::move(NestedFPM)));
>> > +      CGPM.addPass(
>> > +          createCGSCCToFunctionPassAdaptor(std::move(NestedFPM),
>> DebugLogging));
>> >      } else {
>> >        // Otherwise try to parse a pass name.
>> >        size_t End = PipelineText.find_first_of(",)");
>> > @@ -627,8 +628,8 @@ bool PassBuilder::parseModulePassPipelin
>> >        PipelineText = PipelineText.substr(1);
>> >
>> >        // Add the nested pass manager with the appropriate adaptor.
>> > -      MPM.addPass(
>> > -
>> createModuleToPostOrderCGSCCPassAdaptor(std::move(NestedCGPM)));
>> > +
>> MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(NestedCGPM),
>> > +
>> DebugLogging));
>> >      } else if (PipelineText.startswith("function(")) {
>> >        FunctionPassManager NestedFPM(DebugLogging);
>> >
>> > @@ -689,7 +690,7 @@ bool PassBuilder::parsePassPipeline(Modu
>> >                                  DebugLogging) ||
>> >          !PipelineText.empty())
>> >        return false;
>> > -
>> MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM)));
>> > +
>> MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM),
>> DebugLogging));
>> >      return true;
>> >    }
>> >
>> >
>> > 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=273961&r1=273960&r2=273961&view=diff
>> >
>> ==============================================================================
>> > --- llvm/trunk/test/Other/new-pass-manager.ll (original)
>> > +++ llvm/trunk/test/Other/new-pass-manager.ll Mon Jun 27 18:26:08 2016
>> > @@ -22,6 +22,7 @@
>> >  ; CHECK-CGSCC-PASS-NEXT: Running pass:
>> ModuleToPostOrderCGSCCPassAdaptor
>> >  ; CHECK-CGSCC-PASS-NEXT: Running analysis:
>> InnerAnalysisManagerProxy<{{.*}}>
>> >  ; CHECK-CGSCC-PASS-NEXT: Running analysis: LazyCallGraphAnalysis
>> > +; CHECK-CGSCC-PASS-NEXT: Running an SCC pass across the RefSCC: [(foo)]
>> >  ; CHECK-CGSCC-PASS-NEXT: Starting llvm::LazyCallGraph::SCC pass
>> manager run
>> >  ; CHECK-CGSCC-PASS-NEXT: Running pass: NoOpCGSCCPass
>> >  ; CHECK-CGSCC-PASS-NEXT: Finished llvm::LazyCallGraph::SCC pass
>> manager run
>> >
>> >
>> > _______________________________________________
>> > llvm-commits mailing list
>> > llvm-commits at lists.llvm.org
>> > http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-commits
>>
>> --
>> Davide
>>
>> "There are no solved problems; there are only problems that are more
>> or less solved" -- Henri Poincare
>> _______________________________________________
>> 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/20160706/72159eb9/attachment.html>


More information about the llvm-commits mailing list