[llvm] r261203 - [PM] Port the PostOrderFunctionAttrs pass to the new pass manager and

Sean Silva via llvm-commits llvm-commits at lists.llvm.org
Thu Feb 18 17:25:58 PST 2016


On Thu, Feb 18, 2016 at 3:03 AM, Chandler Carruth via llvm-commits <
llvm-commits at lists.llvm.org> wrote:

> Author: chandlerc
> Date: Thu Feb 18 05:03:11 2016
> New Revision: 261203
>
> URL: http://llvm.org/viewvc/llvm-project?rev=261203&view=rev
> Log:
> [PM] Port the PostOrderFunctionAttrs pass to the new pass manager and
> convert one test to use this.
>
> This is a particularly significant milestone because it required
> a working per-function AA framework which can be queried over each
> function from within a CGSCC transform pass (and additionally a module
> analysis to be accessible). This is essentially *the* point of the
> entire pass manager rewrite. A CGSCC transform is able to query for
> multiple different function's analysis results. It works. The whole
> thing appears to actually work and accomplish the original goal. While
> we were able to hack function attrs and basic-aa to "work" in the old
> pass manager, this port doesn't use any of that, it directly leverages
> the new fundamental functionality.
>

Congrats!

-- Sean Silva


>
> For this to work, the CGSCC framework also has to support SCC-based
> behavior analysis, etc. The only part of the CGSCC pass infrastructure
> not sorted out at this point are the updates in the face of inlining and
> running function passes that mutate the call graph.
>
> The changes are pretty boring and boiler-plate. Most of the work was
> factored into more focused preperatory patches. But this is what wires
> it all together.
>
> Added:
>     llvm/trunk/include/llvm/Transforms/IPO/FunctionAttrs.h
> Modified:
>     llvm/trunk/include/llvm/InitializePasses.h
>     llvm/trunk/include/llvm/LinkAllPasses.h
>     llvm/trunk/include/llvm/Transforms/IPO.h
>     llvm/trunk/lib/LTO/LTOCodeGenerator.cpp
>     llvm/trunk/lib/Passes/PassBuilder.cpp
>     llvm/trunk/lib/Passes/PassRegistry.def
>     llvm/trunk/lib/Transforms/IPO/FunctionAttrs.cpp
>     llvm/trunk/lib/Transforms/IPO/IPO.cpp
>     llvm/trunk/lib/Transforms/IPO/PassManagerBuilder.cpp
>     llvm/trunk/test/Transforms/FunctionAttrs/readattrs.ll
>
> Modified: llvm/trunk/include/llvm/InitializePasses.h
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/InitializePasses.h?rev=261203&r1=261202&r2=261203&view=diff
>
> ==============================================================================
> --- llvm/trunk/include/llvm/InitializePasses.h (original)
> +++ llvm/trunk/include/llvm/InitializePasses.h Thu Feb 18 05:03:11 2016
> @@ -231,7 +231,7 @@ void initializePostDomOnlyViewerPass(Pas
>  void initializePostDomPrinterPass(PassRegistry&);
>  void initializePostDomViewerPass(PassRegistry&);
>  void initializePostDominatorTreePass(PassRegistry&);
> -void initializePostOrderFunctionAttrsPass(PassRegistry&);
> +void initializePostOrderFunctionAttrsLegacyPassPass(PassRegistry&);
>  void initializePostRASchedulerPass(PassRegistry&);
>  void initializePostMachineSchedulerPass(PassRegistry&);
>  void initializePrintFunctionPassWrapperPass(PassRegistry&);
>
> Modified: llvm/trunk/include/llvm/LinkAllPasses.h
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/LinkAllPasses.h?rev=261203&r1=261202&r2=261203&view=diff
>
> ==============================================================================
> --- llvm/trunk/include/llvm/LinkAllPasses.h (original)
> +++ llvm/trunk/include/llvm/LinkAllPasses.h Thu Feb 18 05:03:11 2016
> @@ -36,6 +36,7 @@
>  #include "llvm/IR/Function.h"
>  #include "llvm/IR/IRPrintingPasses.h"
>  #include "llvm/Transforms/IPO.h"
> +#include "llvm/Transforms/IPO/FunctionAttrs.h"
>  #include "llvm/Transforms/Instrumentation.h"
>  #include "llvm/Transforms/ObjCARC.h"
>  #include "llvm/Transforms/Scalar.h"
> @@ -159,7 +160,7 @@ namespace {
>        (void) llvm::createPostDomTree();
>        (void) llvm::createInstructionNamerPass();
>        (void) llvm::createMetaRenamerPass();
> -      (void) llvm::createPostOrderFunctionAttrsPass();
> +      (void) llvm::createPostOrderFunctionAttrsLegacyPass();
>        (void) llvm::createReversePostOrderFunctionAttrsPass();
>        (void) llvm::createMergeFunctionsPass();
>        std::string buf;
>
> Modified: llvm/trunk/include/llvm/Transforms/IPO.h
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Transforms/IPO.h?rev=261203&r1=261202&r2=261203&view=diff
>
> ==============================================================================
> --- llvm/trunk/include/llvm/Transforms/IPO.h (original)
> +++ llvm/trunk/include/llvm/Transforms/IPO.h Thu Feb 18 05:03:11 2016
> @@ -188,15 +188,6 @@ ModulePass *createBlockExtractorPass();
>  ModulePass *createStripDeadPrototypesPass();
>
>
>  //===----------------------------------------------------------------------===//
> -/// createPostOrderFunctionAttrsPass - This pass walks SCCs of the call
> graph
> -/// in post-order to deduce and propagate function attributes. It can
> discover
> -/// functions that do not access memory, or only read memory, and give
> them the
> -/// readnone/readonly attribute. It also discovers function arguments
> that are
> -/// not captured by the function and marks them with the nocapture
> attribute.
> -///
> -Pass *createPostOrderFunctionAttrsPass();
> -
>
> -//===----------------------------------------------------------------------===//
>  /// createReversePostOrderFunctionAttrsPass - This pass walks SCCs of the
> call
>  /// graph in RPO to deduce and propagate function attributes. Currently it
>  /// only handles synthesizing norecurse attributes.
>
> Added: llvm/trunk/include/llvm/Transforms/IPO/FunctionAttrs.h
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Transforms/IPO/FunctionAttrs.h?rev=261203&view=auto
>
> ==============================================================================
> --- llvm/trunk/include/llvm/Transforms/IPO/FunctionAttrs.h (added)
> +++ llvm/trunk/include/llvm/Transforms/IPO/FunctionAttrs.h Thu Feb 18
> 05:03:11 2016
> @@ -0,0 +1,45 @@
> +//===-- FunctionAttrs.h - Compute function attrs
> --------------------------===//
> +//
> +//                     The LLVM Compiler Infrastructure
> +//
> +// This file is distributed under the University of Illinois Open Source
> +// License. See LICENSE.TXT for details.
> +//
>
> +//===----------------------------------------------------------------------===//
> +/// \file
> +/// Provides passes for computing function attributes based on
> interprocedural
> +/// analyses.
>
> +//===----------------------------------------------------------------------===//
> +
> +#ifndef LLVM_TRANSFORMS_IPO_FUNCTIONATTRS_H
> +#define LLVM_TRANSFORMS_IPO_FUNCTIONATTRS_H
> +
> +#include "llvm/Analysis/LazyCallGraph.h"
> +#include "llvm/Analysis/CGSCCPassManager.h"
> +#include "llvm/IR/PassManager.h"
> +
> +namespace llvm {
> +
> +/// Computes function attributes in post-order over the call graph.
> +///
> +/// By operating in post-order, this pass computes precise attributes for
> +/// called functions prior to processsing their callers. This "bottom-up"
> +/// approach allows powerful interprocedural inference of function
> attributes
> +/// like memory access patterns, etc. It can discover functions that do
> not
> +/// access memory, or only read memory, and give them the
> readnone/readonly
> +/// attribute. It also discovers function arguments that are not captured
> by
> +/// the function and marks them with the nocapture attribute.
> +class PostOrderFunctionAttrsPass {
> +public:
> +  static StringRef name() { return "PostOrderFunctionAttrsPass"; }
> +
> +  PreservedAnalyses run(LazyCallGraph::SCC &C, CGSCCAnalysisManager *AM);
> +};
> +
> +/// Create a legacy pass manager instance of a pass to compute function
> attrs
> +/// in post-order.
> +Pass *createPostOrderFunctionAttrsLegacyPass();
> +
> +}
> +
> +#endif // LLVM_TRANSFORMS_IPO_FUNCTIONATTRS_H
>
> Modified: llvm/trunk/lib/LTO/LTOCodeGenerator.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/LTO/LTOCodeGenerator.cpp?rev=261203&r1=261202&r2=261203&view=diff
>
> ==============================================================================
> --- llvm/trunk/lib/LTO/LTOCodeGenerator.cpp (original)
> +++ llvm/trunk/lib/LTO/LTOCodeGenerator.cpp Thu Feb 18 05:03:11 2016
> @@ -93,7 +93,7 @@ void LTOCodeGenerator::initializeLTOPass
>    initializeSROALegacyPassPass(R);
>    initializeSROA_DTPass(R);
>    initializeSROA_SSAUpPass(R);
> -  initializePostOrderFunctionAttrsPass(R);
> +  initializePostOrderFunctionAttrsLegacyPassPass(R);
>    initializeReversePostOrderFunctionAttrsPass(R);
>    initializeGlobalsAAWrapperPassPass(R);
>    initializeLICMPass(R);
>
> Modified: llvm/trunk/lib/Passes/PassBuilder.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Passes/PassBuilder.cpp?rev=261203&r1=261202&r2=261203&view=diff
>
> ==============================================================================
> --- llvm/trunk/lib/Passes/PassBuilder.cpp (original)
> +++ llvm/trunk/lib/Passes/PassBuilder.cpp Thu Feb 18 05:03:11 2016
> @@ -32,6 +32,7 @@
>  #include "llvm/Support/Debug.h"
>  #include "llvm/Target/TargetMachine.h"
>  #include "llvm/Transforms/IPO/ForceFunctionAttrs.h"
> +#include "llvm/Transforms/IPO/FunctionAttrs.h"
>  #include "llvm/Transforms/IPO/InferFunctionAttrs.h"
>  #include "llvm/Transforms/IPO/StripDeadPrototypes.h"
>  #include "llvm/Transforms/InstCombine/InstCombine.h"
>
> Modified: llvm/trunk/lib/Passes/PassRegistry.def
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Passes/PassRegistry.def?rev=261203&r1=261202&r2=261203&view=diff
>
> ==============================================================================
> --- llvm/trunk/lib/Passes/PassRegistry.def (original)
> +++ llvm/trunk/lib/Passes/PassRegistry.def Thu Feb 18 05:03:11 2016
> @@ -47,6 +47,7 @@ CGSCC_ANALYSIS("no-op-cgscc", NoOpCGSCCA
>  #define CGSCC_PASS(NAME, CREATE_PASS)
>  #endif
>  CGSCC_PASS("invalidate<all>", InvalidateAllAnalysesPass())
> +CGSCC_PASS("function-attrs", PostOrderFunctionAttrsPass())
>  CGSCC_PASS("no-op-cgscc", NoOpCGSCCPass())
>  #undef CGSCC_PASS
>
>
> Modified: llvm/trunk/lib/Transforms/IPO/FunctionAttrs.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/IPO/FunctionAttrs.cpp?rev=261203&r1=261202&r2=261203&view=diff
>
> ==============================================================================
> --- llvm/trunk/lib/Transforms/IPO/FunctionAttrs.cpp (original)
> +++ llvm/trunk/lib/Transforms/IPO/FunctionAttrs.cpp Thu Feb 18 05:03:11
> 2016
> @@ -13,6 +13,7 @@
>  ///
>
>  //===----------------------------------------------------------------------===//
>
> +#include "llvm/Transforms/IPO/FunctionAttrs.h"
>  #include "llvm/Transforms/IPO.h"
>  #include "llvm/ADT/SCCIterator.h"
>  #include "llvm/ADT/SetVector.h"
> @@ -52,39 +53,6 @@ typedef SmallSetVector<Function *, 8> SC
>  }
>
>  namespace {
> -struct PostOrderFunctionAttrs : public CallGraphSCCPass {
> -  static char ID; // Pass identification, replacement for typeid
> -  PostOrderFunctionAttrs() : CallGraphSCCPass(ID) {
> -
> initializePostOrderFunctionAttrsPass(*PassRegistry::getPassRegistry());
> -  }
> -
> -  bool runOnSCC(CallGraphSCC &SCC) override;
> -
> -  void getAnalysisUsage(AnalysisUsage &AU) const override {
> -    AU.setPreservesCFG();
> -    AU.addRequired<AssumptionCacheTracker>();
> -    AU.addRequired<TargetLibraryInfoWrapperPass>();
> -    addUsedAAAnalyses(AU);
> -    CallGraphSCCPass::getAnalysisUsage(AU);
> -  }
> -
> -private:
> -  TargetLibraryInfo *TLI;
> -};
> -}
> -
> -char PostOrderFunctionAttrs::ID = 0;
> -INITIALIZE_PASS_BEGIN(PostOrderFunctionAttrs, "functionattrs",
> -                      "Deduce function attributes", false, false)
> -INITIALIZE_PASS_DEPENDENCY(AssumptionCacheTracker)
> -INITIALIZE_PASS_DEPENDENCY(CallGraphWrapperPass)
> -INITIALIZE_PASS_DEPENDENCY(TargetLibraryInfoWrapperPass)
> -INITIALIZE_PASS_END(PostOrderFunctionAttrs, "functionattrs",
> -                    "Deduce function attributes", false, false)
> -
> -Pass *llvm::createPostOrderFunctionAttrsPass() { return new
> PostOrderFunctionAttrs(); }
> -
> -namespace {
>  /// The three kinds of memory access relevant to 'readonly' and
>  /// 'readnone' attributes.
>  enum MemoryAccessKind {
> @@ -1019,7 +987,102 @@ static bool addNoRecurseAttrs(const SCCN
>    return setDoesNotRecurse(*F);
>  }
>
> -bool PostOrderFunctionAttrs::runOnSCC(CallGraphSCC &SCC) {
> +PreservedAnalyses
> +PostOrderFunctionAttrsPass::run(LazyCallGraph::SCC &C,
> CGSCCAnalysisManager *AM) {
> +  Module &M = *C.begin()->getFunction().getParent();
> +  const ModuleAnalysisManager &MAM =
> +      AM->getResult<ModuleAnalysisManagerCGSCCProxy>(C).getManager();
> +  FunctionAnalysisManager &FAM =
> +      AM->getResult<FunctionAnalysisManagerCGSCCProxy>(C).getManager();
> +
> +  // FIXME: Need some way to make it more reasonable to assume that this
> is
> +  // always cached.
> +  TargetLibraryInfo &TLI = *MAM.getCachedResult<TargetLibraryAnalysis>(M);
> +
> +  // We pass a lambda into functions to wire them up to the analysis
> manager
> +  // for getting function analyses.
> +  auto AARGetter = [&](Function &F) -> AAResults & {
> +    return FAM.getResult<AAManager>(F);
> +  };
> +
> +  // Fill SCCNodes with the elements of the SCC. Also track whether there
> are
> +  // any external or opt-none nodes that will prevent us from optimizing
> any
> +  // part of the SCC.
> +  SCCNodeSet SCCNodes;
> +  bool HasUnknownCall = false;
> +  for (LazyCallGraph::Node &N : C) {
> +    Function &F = N.getFunction();
> +    if (F.hasFnAttribute(Attribute::OptimizeNone)) {
> +      // Treat any function we're trying not to optimize as if it were an
> +      // indirect call and omit it from the node set used below.
> +      HasUnknownCall = true;
> +      continue;
> +    }
> +    // Track whether any functions in this SCC have an unknown call edge.
> +    // Note: if this is ever a performance hit, we can common it with
> +    // subsequent routines which also do scans over the instructions of
> the
> +    // function.
> +    if (!HasUnknownCall)
> +      for (Instruction &I : instructions(F))
> +        if (auto CS = CallSite(&I))
> +          if (!CS.getCalledFunction()) {
> +            HasUnknownCall = true;
> +            break;
> +          }
> +
> +    SCCNodes.insert(&F);
> +  }
> +
> +  bool Changed = false;
> +  Changed |= addReadAttrs(SCCNodes, AARGetter);
> +  Changed |= addArgumentAttrs(SCCNodes);
> +
> +  // If we have no external nodes participating in the SCC, we can deduce
> some
> +  // more precise attributes as well.
> +  if (!HasUnknownCall) {
> +    Changed |= addNoAliasAttrs(SCCNodes);
> +    Changed |= addNonNullAttrs(SCCNodes, TLI);
> +    Changed |= removeConvergentAttrs(SCCNodes);
> +    Changed |= addNoRecurseAttrs(SCCNodes);
> +  }
> +
> +  return Changed ? PreservedAnalyses::none() : PreservedAnalyses::all();
> +}
> +
> +namespace {
> +struct PostOrderFunctionAttrsLegacyPass : public CallGraphSCCPass {
> +  static char ID; // Pass identification, replacement for typeid
> +  PostOrderFunctionAttrsLegacyPass() : CallGraphSCCPass(ID) {
> +
> initializePostOrderFunctionAttrsLegacyPassPass(*PassRegistry::getPassRegistry());
> +  }
> +
> +  bool runOnSCC(CallGraphSCC &SCC) override;
> +
> +  void getAnalysisUsage(AnalysisUsage &AU) const override {
> +    AU.setPreservesCFG();
> +    AU.addRequired<AssumptionCacheTracker>();
> +    AU.addRequired<TargetLibraryInfoWrapperPass>();
> +    addUsedAAAnalyses(AU);
> +    CallGraphSCCPass::getAnalysisUsage(AU);
> +  }
> +
> +private:
> +  TargetLibraryInfo *TLI;
> +};
> +}
> +
> +char PostOrderFunctionAttrsLegacyPass::ID = 0;
> +INITIALIZE_PASS_BEGIN(PostOrderFunctionAttrsLegacyPass, "functionattrs",
> +                      "Deduce function attributes", false, false)
> +INITIALIZE_PASS_DEPENDENCY(AssumptionCacheTracker)
> +INITIALIZE_PASS_DEPENDENCY(CallGraphWrapperPass)
> +INITIALIZE_PASS_DEPENDENCY(TargetLibraryInfoWrapperPass)
> +INITIALIZE_PASS_END(PostOrderFunctionAttrsLegacyPass, "functionattrs",
> +                    "Deduce function attributes", false, false)
> +
> +Pass *llvm::createPostOrderFunctionAttrsLegacyPass() { return new
> PostOrderFunctionAttrsLegacyPass(); }
> +
> +bool PostOrderFunctionAttrsLegacyPass::runOnSCC(CallGraphSCC &SCC) {
>    TLI = &getAnalysis<TargetLibraryInfoWrapperPass>().getTLI();
>    bool Changed = false;
>
>
> Modified: llvm/trunk/lib/Transforms/IPO/IPO.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/IPO/IPO.cpp?rev=261203&r1=261202&r2=261203&view=diff
>
> ==============================================================================
> --- llvm/trunk/lib/Transforms/IPO/IPO.cpp (original)
> +++ llvm/trunk/lib/Transforms/IPO/IPO.cpp Thu Feb 18 05:03:11 2016
> @@ -18,6 +18,7 @@
>  #include "llvm/InitializePasses.h"
>  #include "llvm/IR/LegacyPassManager.h"
>  #include "llvm/Transforms/IPO.h"
> +#include "llvm/Transforms/IPO/FunctionAttrs.h"
>
>  using namespace llvm;
>
> @@ -41,7 +42,7 @@ void llvm::initializeIPO(PassRegistry &R
>    initializeLowerBitSetsPass(Registry);
>    initializeMergeFunctionsPass(Registry);
>    initializePartialInlinerPass(Registry);
> -  initializePostOrderFunctionAttrsPass(Registry);
> +  initializePostOrderFunctionAttrsLegacyPassPass(Registry);
>    initializeReversePostOrderFunctionAttrsPass(Registry);
>    initializePruneEHPass(Registry);
>    initializeStripDeadPrototypesLegacyPassPass(Registry);
> @@ -73,7 +74,7 @@ void LLVMAddDeadArgEliminationPass(LLVMP
>  }
>
>  void LLVMAddFunctionAttrsPass(LLVMPassManagerRef PM) {
> -  unwrap(PM)->add(createPostOrderFunctionAttrsPass());
> +  unwrap(PM)->add(createPostOrderFunctionAttrsLegacyPass());
>  }
>
>  void LLVMAddFunctionInliningPass(LLVMPassManagerRef PM) {
>
> Modified: llvm/trunk/lib/Transforms/IPO/PassManagerBuilder.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/IPO/PassManagerBuilder.cpp?rev=261203&r1=261202&r2=261203&view=diff
>
> ==============================================================================
> --- llvm/trunk/lib/Transforms/IPO/PassManagerBuilder.cpp (original)
> +++ llvm/trunk/lib/Transforms/IPO/PassManagerBuilder.cpp Thu Feb 18
> 05:03:11 2016
> @@ -31,6 +31,7 @@
>  #include "llvm/Target/TargetMachine.h"
>  #include "llvm/Transforms/IPO.h"
>  #include "llvm/Transforms/IPO/ForceFunctionAttrs.h"
> +#include "llvm/Transforms/IPO/FunctionAttrs.h"
>  #include "llvm/Transforms/IPO/InferFunctionAttrs.h"
>  #include "llvm/Transforms/Scalar.h"
>  #include "llvm/Transforms/Vectorize.h"
> @@ -382,7 +383,7 @@ void PassManagerBuilder::populateModuleP
>      Inliner = nullptr;
>    }
>    if (!DisableUnitAtATime)
> -    MPM.add(createPostOrderFunctionAttrsPass());
> +    MPM.add(createPostOrderFunctionAttrsLegacyPass());
>    if (OptLevel > 2)
>      MPM.add(createArgumentPromotionPass()); // Scalarize uninlined fn args
>
> @@ -577,7 +578,7 @@ void PassManagerBuilder::addLTOOptimizat
>    PM.add(createIPSCCPPass());
>
>    // Now that we internalized some globals, see if we can hack on them!
> -  PM.add(createPostOrderFunctionAttrsPass());
> +  PM.add(createPostOrderFunctionAttrsLegacyPass());
>    PM.add(createReversePostOrderFunctionAttrsPass());
>    PM.add(createGlobalOptimizerPass());
>    // Promote any localized global vars.
> @@ -627,7 +628,7 @@ void PassManagerBuilder::addLTOOptimizat
>      PM.add(createScalarReplAggregatesPass());
>
>    // Run a few AA driven optimizations here and now, to cleanup the code.
> -  PM.add(createPostOrderFunctionAttrsPass()); // Add nocapture.
> +  PM.add(createPostOrderFunctionAttrsLegacyPass()); // Add nocapture.
>    PM.add(createGlobalsAAWrapperPass()); // IP alias analysis.
>
>    PM.add(createLICMPass());                 // Hoist loop invariants.
>
> Modified: llvm/trunk/test/Transforms/FunctionAttrs/readattrs.ll
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/FunctionAttrs/readattrs.ll?rev=261203&r1=261202&r2=261203&view=diff
>
> ==============================================================================
> --- llvm/trunk/test/Transforms/FunctionAttrs/readattrs.ll (original)
> +++ llvm/trunk/test/Transforms/FunctionAttrs/readattrs.ll Thu Feb 18
> 05:03:11 2016
> @@ -1,4 +1,5 @@
>  ; RUN: opt < %s -functionattrs -S | FileCheck %s
> +; RUN: opt < %s -aa-pipeline=basic-aa
> -passes='require<targetlibinfo>,cgscc(function-attrs)' -S | FileCheck %s
>  @x = global i32 0
>
>  declare void @test1_1(i8* %x1_1, i8* readonly %y1_1, ...)
>
>
> _______________________________________________
> 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/20160218/fcec09ce/attachment.html>


More information about the llvm-commits mailing list