[llvm] r217334 - Add an Assumption-Tracking Pass

Hal Finkel hfinkel at anl.gov
Mon Sep 8 12:41:47 PDT 2014


----- Original Message -----
> From: "Alexey Samsonov" <vonosmas at gmail.com>
> To: "Hal Finkel" <hfinkel at anl.gov>
> Cc: "llvm-commits" <llvm-commits at cs.uiuc.edu>
> Sent: Monday, September 8, 2014 2:22:54 PM
> Subject: Re: [llvm] r217334 - Add an Assumption-Tracking Pass
> 
> 
> 
> 
> 
> On Mon, Sep 8, 2014 at 11:52 AM, Hal Finkel < hfinkel at anl.gov >
> wrote:
> 
> 
> ----- Original Message -----
> > From: "Alexey Samsonov" < vonosmas at gmail.com >
> > To: "Hal Finkel" < hfinkel at anl.gov >
> > Cc: "llvm-commits" < llvm-commits at cs.uiuc.edu >
> 
> 
> > Sent: Monday, September 8, 2014 1:27:46 PM
> > Subject: Re: [llvm] r217334 - Add an Assumption-Tracking Pass
> > 
> > 
> > 
> > 
> > On Mon, Sep 8, 2014 at 11:07 AM, Hal Finkel < hfinkel at anl.gov >
> > wrote:
> > 
> > 
> > 
> > 
> > ----- Original Message -----
> > > From: "Alexey Samsonov" < vonosmas at gmail.com >
> > > To: "Hal Finkel" < hfinkel at anl.gov >
> > > Cc: "llvm-commits" < llvm-commits at cs.uiuc.edu >
> > > Sent: Monday, September 8, 2014 12:57:52 PM
> > > Subject: Re: [llvm] r217334 - Add an Assumption-Tracking Pass
> > > 
> > > 
> > > Hi Hal,
> > > 
> > > 
> > > On Sun, Sep 7, 2014 at 5:44 AM, Hal Finkel < hfinkel at anl.gov >
> > > wrote:
> > > 
> > > 
> > > Author: hfinkel
> > > Date: Sun Sep 7 07:44:26 2014
> > > New Revision: 217334
> > > 
> > > URL: http://llvm.org/viewvc/llvm-project?rev=217334&view=rev
> > > Log:
> > > Add an Assumption-Tracking Pass
> > > 
> > > This adds an immutable pass, AssumptionTracker, which keeps a
> > > cache
> > > of
> > > @llvm.assume call instructions within a module. It uses callback
> > > value handles
> > > to keep stale functions and intrinsics out of the map, and it
> > > relies
> > > on any
> > > code that creates new @llvm.assume calls to notify it of the new
> > > instructions.
> > > The benefit is that code needing to find @llvm.assume intrinsics
> > > can
> > > do so
> > > directly, without scanning the function, thus allowing the cost
> > > of
> > > @llvm.assume
> > > handling to be negligible when none are present.
> > > 
> > > The current design is intended to be lightweight. We don't keep
> > > track
> > > of
> > > anything until we need a list of assumptions in some function.
> > > The
> > > first time
> > > this happens, we scan the function. After that, we add/remove
> > > @llvm.assume
> > > calls from the cache in response to registration calls and
> > > ValueHandle
> > > callbacks.
> > > 
> > > There are no new direct test cases for this pass, but because it
> > > calls it
> > > validation function upon module finalization, we'll pick up
> > > detectable
> > > inconsistencies from the other tests that touch @llvm.assume
> > > calls.
> > > 
> > > This pass will be used by follow-up commits that make use of
> > > @llvm.assume.
> > > 
> > > Added:
> > > llvm/trunk/include/llvm/Analysis/AssumptionTracker.h
> > > llvm/trunk/lib/Analysis/AssumptionTracker.cpp
> > > Modified:
> > > llvm/trunk/include/llvm/InitializePasses.h
> > > llvm/trunk/include/llvm/Transforms/Utils/Cloning.h
> > > llvm/trunk/include/llvm/Transforms/Utils/UnrollLoop.h
> > > llvm/trunk/lib/Analysis/CMakeLists.txt
> > > llvm/trunk/lib/Transforms/IPO/InlineAlways.cpp
> > > llvm/trunk/lib/Transforms/IPO/InlineSimple.cpp
> > > llvm/trunk/lib/Transforms/IPO/Inliner.cpp
> > > llvm/trunk/lib/Transforms/InstCombine/InstCombine.h
> > > llvm/trunk/lib/Transforms/InstCombine/InstCombineCalls.cpp
> > > llvm/trunk/lib/Transforms/InstCombine/InstructionCombining.cpp
> > > llvm/trunk/lib/Transforms/Scalar/LoopUnrollPass.cpp
> > > llvm/trunk/lib/Transforms/Scalar/LoopUnswitch.cpp
> > > llvm/trunk/lib/Transforms/Utils/InlineFunction.cpp
> > > llvm/trunk/lib/Transforms/Utils/LoopUnroll.cpp
> > > 
> > > Added: llvm/trunk/include/llvm/Analysis/AssumptionTracker.h
> > > URL:
> > > http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Analysis/AssumptionTracker.h?rev=217334&view=auto
> > > ==============================================================================
> > > --- llvm/trunk/include/llvm/Analysis/AssumptionTracker.h (added)
> > > +++ llvm/trunk/include/llvm/Analysis/AssumptionTracker.h Sun Sep
> > > 7
> > > 07:44:26 2014
> > > @@ -0,0 +1,128 @@
> > > +//===- llvm/Analysis/AssumptionTracker.h - Track @llvm.assume
> > > ---*-
> > > C++ -*-===//
> > > +//
> > > +// The LLVM Compiler Infrastructure
> > > +//
> > > +// This file is distributed under the University of Illinois
> > > Open
> > > Source
> > > +// License. See LICENSE.TXT for details.
> > > +//
> > > +//===----------------------------------------------------------------------===//
> > > +//
> > > +// This file contains a pass that keeps track of @llvm.assume
> > > intrinsics in
> > > +// the functions of a module (allowing assumptions within any
> > > function to be
> > > +// found cheaply by other parts of the optimizer).
> > > +//
> > > +//===----------------------------------------------------------------------===//
> > > +
> > > +#ifndef LLVM_ANALYSIS_ASSUMPTIONTRACKER_H
> > > +#define LLVM_ANALYSIS_ASSUMPTIONTRACKER_H
> > > +
> > > +#include "llvm/ADT/DenseMap.h"
> > > +#include "llvm/ADT/DenseSet.h"
> > > +#include "llvm/ADT/SmallSet.h"
> > > +#include "llvm/IR/Function.h"
> > > +#include "llvm/IR/Instructions.h"
> > > +#include "llvm/IR/ValueHandle.h"
> > > +#include "llvm/Pass.h"
> > > +#include <memory>
> > > +
> > > +namespace llvm {
> > > +
> > > +/// An immutable pass that tracks @llvm.assume intrinsics in a
> > > module.
> > > +class AssumptionTracker : public ImmutablePass {
> > > + /// A callback value handle applied to function objects, which
> > > we
> > > use to
> > > + /// delete our cache of intrinsics for a function when it is
> > > deleted.
> > > + class FunctionCallbackVH : public CallbackVH {
> > > + AssumptionTracker *AT;
> > > + void deleted() override;
> > > +
> > > + public:
> > > + typedef DenseMapInfo<Value *> DMI;
> > > +
> > > + FunctionCallbackVH(Value *V, AssumptionTracker *AT = nullptr)
> > > + : CallbackVH(V), AT(AT) {}
> > > + };
> > > +
> > > + /// A callback value handle applied to call instructions, which
> > > keeps
> > > + /// track of the call's parent function so that we can remove a
> > > + /// assumption intrinsic call from our cache when the
> > > instruction
> > > is
> > > + /// deleted.
> > > + class CallCallbackVH : public CallbackVH {
> > > + AssumptionTracker *AT;
> > > + void deleted() override;
> > > +
> > > + // We store the function here because we need it to lookup the
> > > set
> > > + // containing this handle when the underlying CallInst is being
> > > deleted.
> > > + Function *F;
> > > +
> > > + public:
> > > + typedef DenseMapInfo<Instruction *> DMI;
> > > +
> > > + CallCallbackVH(Instruction *I, AssumptionTracker *AT = nullptr)
> > > + : CallbackVH(I), AT(AT), F(nullptr) {
> > > + if (I != DMI::getEmptyKey() && I != DMI::getTombstoneKey())
> > > + F = I->getParent()->getParent();
> > > + }
> > > +
> > > + operator CallInst*() const {
> > > + Value *V = getValPtr();
> > > + if (V == DMI::getEmptyKey() || V == DMI::getTombstoneKey())
> > > + return static_cast<CallInst*>(V);
> > > 
> > > 
> > > 
> > > ^^ UBSan bootstrap bot reports undefined behavior here:
> > > 
> > > /home/dtoolsbot/build/sanitizer-x86_64-linux-bootstrap/build/llvm/include/llvm/Analysis/AssumptionTracker.h:69:18:
> > > runtime error: downcast of misaligned address 0xfffffffffffffffc
> > > for
> > > type 'llvm::CallInst', which requires 8 byte alignment
> > > 
> > > (full log:
> > > http://lab.llvm.org:8011/builders/sanitizer-x86_64-linux-bootstrap/builds/4491/steps/check-llvm%20ubsan/logs/stdio
> > > )
> > > 
> > > 
> > > The real problem is probably the fact that we don't enforce
> > > correct
> > > alignment on EmptyKey and TombstoneKey in DenseMap<T*, foo>, but
> > > it's not clear how to do this in the general case:
> > > correct alignment of "fake pointers" of type T* depends on the
> > > natural alignment of T, while the definition of T might not be
> > > available.
> > > 
> > > 
> > > Can you work around this problem somehow, and avoid bogus cast of
> > > fake pointer here?
> > 
> > Interesting. Would using a reinterpret_cast fix the problem?
> > 
> > 
> > 
> > reinterpret_cast<> will make the tool silent (at least, in its
> > current implementation). 5.2.10 [expr.reinterpret.cast], p. 7
> > makes me think that the result of this reinterpret_cast<> is
> > unspecified.
> 
> Sounds good. If you look in include/llvm/ADT/DenseMapInfo.h, you'll
> see that the original pointer values were formed via a
> reinterpret_cast, so I'd not be making anything depend more on
> unspecified if I make this a reinterpret_cast too.
> 
> 
> 
> I agree.

r217397, thanks!

 -Hal

> 
> 
> 
> -Hal
> 
> 
> 
> > 
> > 
> > 
> > -Hal
> > 
> > 
> > 
> > > 
> > > 
> > > 
> > > 
> > > +
> > > + return cast<CallInst>(V);
> > > + }
> > > +
> > > + CallInst *operator->() const { return
> > > cast<CallInst>(getValPtr());
> > > }
> > > + CallInst &operator*() const { return
> > > *cast<CallInst>(getValPtr());
> > > }
> > > + };
> > > +
> > > + friend FunctionCallbackVH;
> > > + friend CallCallbackVH;
> > > +
> > > + // FIXME: SmallSet might be better here, but it currently has
> > > no
> > > iterators.
> > > + typedef DenseSet<CallCallbackVH, CallCallbackVH::DMI>
> > > CallHandleSet;
> > > + typedef DenseMap<FunctionCallbackVH,
> > > std::unique_ptr<CallHandleSet>,
> > > + FunctionCallbackVH::DMI> FunctionCallsMap;
> > > + FunctionCallsMap CachedAssumeCalls;
> > > +
> > > + /// Scan the provided function for @llvm.assume intrinsic
> > > calls.
> > > Returns an
> > > + /// iterator to the set for this function in the
> > > CachedAssumeCalls
> > > map.
> > > + FunctionCallsMap::iterator scanFunction(Function *F);
> > > +
> > > +public:
> > > + /// Remove the cache of @llvm.assume intrinsics for the given
> > > function.
> > > + void forgetCachedAssumptions(Function *F);
> > > +
> > > + /// Add an @llvm.assume intrinsic to the cache for its parent
> > > function.
> > > + void registerAssumption(CallInst *CI);
> > > +
> > > + typedef CallHandleSet::iterator assumption_iterator;
> > > + typedef iterator_range<assumption_iterator> assumption_range;
> > > +
> > > + inline assumption_range assumptions(Function *F) {
> > > + FunctionCallsMap::iterator I = CachedAssumeCalls.find(F);
> > > + if (I == CachedAssumeCalls.end()) {
> > > + I = scanFunction(F);
> > > + }
> > > +
> > > + return assumption_range(I->second->begin(), I->second->end());
> > > + }
> > > +
> > > + AssumptionTracker();
> > > + ~AssumptionTracker();
> > > +
> > > + void releaseMemory() override {
> > > + CachedAssumeCalls.shrink_and_clear();
> > > + }
> > > +
> > > + void verifyAnalysis() const override;
> > > + bool doFinalization(Module &) override {
> > > + verifyAnalysis();
> > > + return false;
> > > + }
> > > +
> > > + static char ID; // Pass identification, replacement for typeid
> > > +};
> > > +
> > > +} // end namespace llvm
> > > +
> > > +#endif
> > > 
> > > Modified: llvm/trunk/include/llvm/InitializePasses.h
> > > URL:
> > > http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/InitializePasses.h?rev=217334&r1=217333&r2=217334&view=diff
> > > ==============================================================================
> > > --- llvm/trunk/include/llvm/InitializePasses.h (original)
> > > +++ llvm/trunk/include/llvm/InitializePasses.h Sun Sep 7 07:44:26
> > > 2014
> > > @@ -262,6 +262,7 @@ void initializeDataLayoutPassPass(PassRe
> > > void initializeTargetTransformInfoAnalysisGroup(PassRegistry&);
> > > void initializeNoTTIPass(PassRegistry&);
> > > void initializeTargetLibraryInfoPass(PassRegistry&);
> > > +void initializeAssumptionTrackerPass(PassRegistry &);
> > > void initializeTwoAddressInstructionPassPass(PassRegistry&);
> > > void initializeTypeBasedAliasAnalysisPass(PassRegistry&);
> > > void initializeScopedNoAliasAAPass(PassRegistry&);
> > > 
> > > Modified: llvm/trunk/include/llvm/Transforms/Utils/Cloning.h
> > > URL:
> > > http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Transforms/Utils/Cloning.h?rev=217334&r1=217333&r2=217334&view=diff
> > > ==============================================================================
> > > --- llvm/trunk/include/llvm/Transforms/Utils/Cloning.h (original)
> > > +++ llvm/trunk/include/llvm/Transforms/Utils/Cloning.h Sun Sep 7
> > > 07:44:26 2014
> > > @@ -44,6 +44,7 @@ class Loop;
> > > class LoopInfo;
> > > class AllocaInst;
> > > class AliasAnalysis;
> > > +class AssumptionTracker;
> > > 
> > > /// CloneModule - Return an exact copy of the specified module
> > > ///
> > > @@ -160,14 +161,16 @@ class InlineFunctionInfo {
> > > public:
> > > explicit InlineFunctionInfo(CallGraph *cg = nullptr,
> > > const DataLayout *DL = nullptr,
> > > - AliasAnalysis *AA = nullptr)
> > > - : CG(cg), DL(DL), AA(AA) {}
> > > + AliasAnalysis *AA = nullptr,
> > > + AssumptionTracker *AT = nullptr)
> > > + : CG(cg), DL(DL), AA(AA), AT(AT) {}
> > > 
> > > /// CG - If non-null, InlineFunction will update the callgraph to
> > > reflect the
> > > /// changes it makes.
> > > CallGraph *CG;
> > > const DataLayout *DL;
> > > AliasAnalysis *AA;
> > > + AssumptionTracker *AT;
> > > 
> > > /// StaticAllocas - InlineFunction fills this in with all static
> > > allocas that
> > > /// get copied into the caller.
> > > 
> > > Modified: llvm/trunk/include/llvm/Transforms/Utils/UnrollLoop.h
> > > URL:
> > > http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Transforms/Utils/UnrollLoop.h?rev=217334&r1=217333&r2=217334&view=diff
> > > ==============================================================================
> > > --- llvm/trunk/include/llvm/Transforms/Utils/UnrollLoop.h
> > > (original)
> > > +++ llvm/trunk/include/llvm/Transforms/Utils/UnrollLoop.h Sun Sep
> > > 7
> > > 07:44:26 2014
> > > @@ -18,6 +18,7 @@
> > > 
> > > namespace llvm {
> > > 
> > > +class AssumptionTracker;
> > > class Loop;
> > > class LoopInfo;
> > > class LPPassManager;
> > > @@ -25,7 +26,7 @@ class Pass;
> > > 
> > > bool UnrollLoop(Loop *L, unsigned Count, unsigned TripCount, bool
> > > AllowRuntime,
> > > unsigned TripMultiple, LoopInfo *LI, Pass *PP,
> > > - LPPassManager *LPM);
> > > + LPPassManager *LPM, AssumptionTracker *AT);
> > > 
> > > bool UnrollRuntimeLoopProlog(Loop *L, unsigned Count, LoopInfo
> > > *LI,
> > > LPPassManager* LPM);
> > > 
> > > Added: llvm/trunk/lib/Analysis/AssumptionTracker.cpp
> > > URL:
> > > http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Analysis/AssumptionTracker.cpp?rev=217334&view=auto
> > > ==============================================================================
> > > --- llvm/trunk/lib/Analysis/AssumptionTracker.cpp (added)
> > > +++ llvm/trunk/lib/Analysis/AssumptionTracker.cpp Sun Sep 7
> > > 07:44:26
> > > 2014
> > > @@ -0,0 +1,113 @@
> > > +//===- AssumptionTracker.cpp - Track @llvm.assume
> > > -------------------------===//
> > > +//
> > > +// The LLVM Compiler Infrastructure
> > > +//
> > > +// This file is distributed under the University of Illinois
> > > Open
> > > Source
> > > +// License. See LICENSE.TXT for details.
> > > +//
> > > +//===----------------------------------------------------------------------===//
> > > +//
> > > +// This file contains a pass that keeps track of @llvm.assume
> > > intrinsics in
> > > +// the functions of a module.
> > > +//
> > > +//===----------------------------------------------------------------------===//
> > > +
> > > +#include "llvm/Analysis/AssumptionTracker.h"
> > > +#include "llvm/IR/CallSite.h"
> > > +#include "llvm/IR/Dominators.h"
> > > +#include "llvm/IR/Function.h"
> > > +#include "llvm/IR/Instructions.h"
> > > +#include "llvm/IR/IntrinsicInst.h"
> > > +#include "llvm/IR/PatternMatch.h"
> > > +#include "llvm/Support/Debug.h"
> > > +using namespace llvm;
> > > +using namespace llvm::PatternMatch;
> > > +
> > > +void AssumptionTracker::FunctionCallbackVH::deleted() {
> > > + AT->forgetCachedAssumptions(cast<Function>(getValPtr()));
> > > + // 'this' now dangles!
> > > +}
> > > +
> > > +void AssumptionTracker::forgetCachedAssumptions(Function *F) {
> > > + CachedAssumeCalls.erase(F);
> > > +}
> > > +
> > > +void AssumptionTracker::CallCallbackVH::deleted() {
> > > + assert(F && "delete callback called on dummy handle");
> > > + FunctionCallsMap::iterator I = AT->CachedAssumeCalls.find(F);
> > > + assert(I != AT->CachedAssumeCalls.end() &&
> > > + "Function cleared from the map without removing the values?");
> > > +
> > > + I->second->erase(*this);
> > > + // 'this' now dangles!
> > > +}
> > > +
> > > +AssumptionTracker::FunctionCallsMap::iterator
> > > +AssumptionTracker::scanFunction(Function *F) {
> > > + auto IP =
> > > + CachedAssumeCalls.insert(std::make_pair(FunctionCallbackVH(F,
> > > this),
> > > + std::unique_ptr<CallHandleSet>(
> > > + new CallHandleSet())));
> > > + assert(IP.second && "Scanning function already in the map?");
> > > +
> > > + FunctionCallsMap::iterator I = IP.first;
> > > +
> > > + // Go through all instructions in all blocks, add all calls to
> > > @llvm.assume
> > > + // to our cache.
> > > + for (BasicBlock &B : *F)
> > > + for (Instruction &II : B)
> > > + if (match(cast<Value>(&II),
> > > m_Intrinsic<Intrinsic::assume>(m_Value())))
> > > + I->second->insert(CallCallbackVH(&II, this));
> > > +
> > > + return I;
> > > +}
> > > +
> > > +void AssumptionTracker::verifyAnalysis() const {
> > > +#ifndef NDEBUG
> > > + for (const auto &I : CachedAssumeCalls) {
> > > + for (const BasicBlock &B : cast<Function>(*I.first))
> > > + for (const Instruction &II : B) {
> > > + Instruction *C = const_cast<Instruction*>(&II);
> > > + if (match(C, m_Intrinsic<Intrinsic::assume>(m_Value()))) {
> > > + assert(I.second->count(CallCallbackVH(C,
> > > + const_cast<AssumptionTracker*>(this))) &&
> > > + "Assumption in scanned function not in cache");
> > > + }
> > > + }
> > > + }
> > > +#endif
> > > +}
> > > +
> > > +void AssumptionTracker::registerAssumption(CallInst *CI) {
> > > + assert(match(cast<Value>(CI),
> > > + m_Intrinsic<Intrinsic::assume>(m_Value())) &&
> > > + "Registered call does not call @llvm.assume");
> > > + assert(CI->getParent() &&
> > > + "Cannot register @llvm.assume call not in a basic block");
> > > +
> > > + Function *F = CI->getParent()->getParent();
> > > + assert(F && "Cannot register @llvm.assume call not in a
> > > function");
> > > +
> > > + FunctionCallsMap::iterator I = CachedAssumeCalls.find(F);
> > > + if (I == CachedAssumeCalls.end()) {
> > > + // If this function has not already been scanned, then don't do
> > > anything
> > > + // here. This intrinsic will be found, if it still exists, if
> > > the
> > > list of
> > > + // assumptions in this function is requested at some later
> > > point.
> > > This
> > > + // maintains the following invariant: if a function is present
> > > in
> > > the
> > > + // cache, then its list of assumption intrinsic calls is
> > > complete.
> > > + return;
> > > + }
> > > +
> > > + I->second->insert(CallCallbackVH(CI, this));
> > > +}
> > > +
> > > +AssumptionTracker::AssumptionTracker() : ImmutablePass(ID) {
> > > +
> > > initializeAssumptionTrackerPass(*PassRegistry::getPassRegistry());
> > > +}
> > > +
> > > +AssumptionTracker::~AssumptionTracker() {}
> > > +
> > > +INITIALIZE_PASS(AssumptionTracker, "assumption-tracker",
> > > "Assumption
> > > Tracker",
> > > + false, true)
> > > +char AssumptionTracker::ID = 0;
> > > +
> > > 
> > > Modified: llvm/trunk/lib/Analysis/CMakeLists.txt
> > > URL:
> > > http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Analysis/CMakeLists.txt?rev=217334&r1=217333&r2=217334&view=diff
> > > ==============================================================================
> > > --- llvm/trunk/lib/Analysis/CMakeLists.txt (original)
> > > +++ llvm/trunk/lib/Analysis/CMakeLists.txt Sun Sep 7 07:44:26
> > > 2014
> > > @@ -5,6 +5,7 @@ add_llvm_library(LLVMAnalysis
> > > AliasDebugger.cpp
> > > AliasSetTracker.cpp
> > > Analysis.cpp
> > > + AssumptionTracker.cpp
> > > BasicAliasAnalysis.cpp
> > > BlockFrequencyInfo.cpp
> > > BlockFrequencyInfoImpl.cpp
> > > 
> > > Modified: llvm/trunk/lib/Transforms/IPO/InlineAlways.cpp
> > > URL:
> > > http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/IPO/InlineAlways.cpp?rev=217334&r1=217333&r2=217334&view=diff
> > > ==============================================================================
> > > --- llvm/trunk/lib/Transforms/IPO/InlineAlways.cpp (original)
> > > +++ llvm/trunk/lib/Transforms/IPO/InlineAlways.cpp Sun Sep 7
> > > 07:44:26
> > > 2014
> > > @@ -15,6 +15,7 @@
> > > #include "llvm/Transforms/IPO.h"
> > > #include "llvm/ADT/SmallPtrSet.h"
> > > #include "llvm/Analysis/AliasAnalysis.h"
> > > +#include "llvm/Analysis/AssumptionTracker.h"
> > > #include "llvm/Analysis/CallGraph.h"
> > > #include "llvm/Analysis/InlineCost.h"
> > > #include "llvm/IR/CallSite.h"
> > > @@ -67,6 +68,7 @@ char AlwaysInliner::ID = 0;
> > > INITIALIZE_PASS_BEGIN(AlwaysInliner, "always-inline",
> > > "Inliner for always_inline functions", false, false)
> > > INITIALIZE_AG_DEPENDENCY(AliasAnalysis)
> > > +INITIALIZE_PASS_DEPENDENCY(AssumptionTracker)
> > > INITIALIZE_PASS_DEPENDENCY(CallGraphWrapperPass)
> > > INITIALIZE_PASS_DEPENDENCY(InlineCostAnalysis)
> > > INITIALIZE_PASS_END(AlwaysInliner, "always-inline",
> > > 
> > > Modified: llvm/trunk/lib/Transforms/IPO/InlineSimple.cpp
> > > URL:
> > > http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/IPO/InlineSimple.cpp?rev=217334&r1=217333&r2=217334&view=diff
> > > ==============================================================================
> > > --- llvm/trunk/lib/Transforms/IPO/InlineSimple.cpp (original)
> > > +++ llvm/trunk/lib/Transforms/IPO/InlineSimple.cpp Sun Sep 7
> > > 07:44:26
> > > 2014
> > > @@ -13,6 +13,7 @@
> > > 
> > > #include "llvm/Transforms/IPO.h"
> > > #include "llvm/Analysis/AliasAnalysis.h"
> > > +#include "llvm/Analysis/AssumptionTracker.h"
> > > #include "llvm/Analysis/CallGraph.h"
> > > #include "llvm/Analysis/InlineCost.h"
> > > #include "llvm/IR/CallSite.h"
> > > @@ -75,6 +76,7 @@ char SimpleInliner::ID = 0;
> > > INITIALIZE_PASS_BEGIN(SimpleInliner, "inline",
> > > "Function Integration/Inlining", false, false)
> > > INITIALIZE_AG_DEPENDENCY(AliasAnalysis)
> > > +INITIALIZE_PASS_DEPENDENCY(AssumptionTracker)
> > > INITIALIZE_PASS_DEPENDENCY(CallGraphWrapperPass)
> > > INITIALIZE_PASS_DEPENDENCY(InlineCostAnalysis)
> > > INITIALIZE_PASS_END(SimpleInliner, "inline",
> > > 
> > > Modified: llvm/trunk/lib/Transforms/IPO/Inliner.cpp
> > > URL:
> > > http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/IPO/Inliner.cpp?rev=217334&r1=217333&r2=217334&view=diff
> > > ==============================================================================
> > > --- llvm/trunk/lib/Transforms/IPO/Inliner.cpp (original)
> > > +++ llvm/trunk/lib/Transforms/IPO/Inliner.cpp Sun Sep 7 07:44:26
> > > 2014
> > > @@ -17,6 +17,7 @@
> > > #include "llvm/ADT/SmallPtrSet.h"
> > > #include "llvm/ADT/Statistic.h"
> > > #include "llvm/Analysis/AliasAnalysis.h"
> > > +#include "llvm/Analysis/AssumptionTracker.h"
> > > #include "llvm/Analysis/CallGraph.h"
> > > #include "llvm/Analysis/InlineCost.h"
> > > #include "llvm/IR/CallSite.h"
> > > @@ -76,6 +77,7 @@ Inliner::Inliner(char &ID, int Threshold
> > > /// always explicitly call the implementation here.
> > > void Inliner::getAnalysisUsage(AnalysisUsage &AU) const {
> > > AU.addRequired<AliasAnalysis>();
> > > + AU.addRequired<AssumptionTracker>();
> > > CallGraphSCCPass::getAnalysisUsage(AU);
> > > }
> > > 
> > > @@ -441,6 +443,7 @@ static bool InlineHistoryIncludes(Functi
> > > 
> > > bool Inliner::runOnSCC(CallGraphSCC &SCC) {
> > > CallGraph &CG =
> > > getAnalysis<CallGraphWrapperPass>().getCallGraph();
> > > + AssumptionTracker *AT = &getAnalysis<AssumptionTracker>();
> > > DataLayoutPass *DLP = getAnalysisIfAvailable<DataLayoutPass>();
> > > const DataLayout *DL = DLP ? &DLP->getDataLayout() : nullptr;
> > > const TargetLibraryInfo *TLI =
> > > getAnalysisIfAvailable<TargetLibraryInfo>();
> > > @@ -503,7 +506,7 @@ bool Inliner::runOnSCC(CallGraphSCC &SCC
> > > 
> > > 
> > > InlinedArrayAllocasTy InlinedArrayAllocas;
> > > - InlineFunctionInfo InlineInfo(&CG, DL, AA);
> > > + InlineFunctionInfo InlineInfo(&CG, DL, AA, AT);
> > > 
> > > // Now that we have all of the call sites, loop over them and
> > > inline
> > > them if
> > > // it looks profitable to do so.
> > > 
> > > Modified: llvm/trunk/lib/Transforms/InstCombine/InstCombine.h
> > > URL:
> > > http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/InstCombine/InstCombine.h?rev=217334&r1=217333&r2=217334&view=diff
> > > ==============================================================================
> > > --- llvm/trunk/lib/Transforms/InstCombine/InstCombine.h
> > > (original)
> > > +++ llvm/trunk/lib/Transforms/InstCombine/InstCombine.h Sun Sep 7
> > > 07:44:26 2014
> > > @@ -11,12 +11,14 @@
> > > #define LLVM_LIB_TRANSFORMS_INSTCOMBINE_INSTCOMBINE_H
> > > 
> > > #include "InstCombineWorklist.h"
> > > +#include "llvm/Analysis/AssumptionTracker.h"
> > > #include "llvm/Analysis/TargetFolder.h"
> > > #include "llvm/Analysis/ValueTracking.h"
> > > #include "llvm/IR/IRBuilder.h"
> > > #include "llvm/IR/InstVisitor.h"
> > > #include "llvm/IR/IntrinsicInst.h"
> > > #include "llvm/IR/Operator.h"
> > > +#include "llvm/IR/PatternMatch.h"
> > > #include "llvm/Pass.h"
> > > #include "llvm/Transforms/Utils/SimplifyLibCalls.h"
> > > 
> > > @@ -71,14 +73,20 @@ static inline Constant *SubOne(Constant
> > > class LLVM_LIBRARY_VISIBILITY InstCombineIRInserter
> > > : public IRBuilderDefaultInserter<true> {
> > > InstCombineWorklist &Worklist;
> > > + AssumptionTracker *AT;
> > > 
> > > public:
> > > - InstCombineIRInserter(InstCombineWorklist &WL) : Worklist(WL)
> > > {}
> > > + InstCombineIRInserter(InstCombineWorklist &WL,
> > > AssumptionTracker
> > > *AT)
> > > + : Worklist(WL), AT(AT) {}
> > > 
> > > void InsertHelper(Instruction *I, const Twine &Name, BasicBlock
> > > *BB,
> > > BasicBlock::iterator InsertPt) const {
> > > IRBuilderDefaultInserter<true>::InsertHelper(I, Name, BB,
> > > InsertPt);
> > > Worklist.Add(I);
> > > +
> > > + using namespace llvm::PatternMatch;
> > > + if ((match(I, m_Intrinsic<Intrinsic::assume>(m_Value()))))
> > > + AT->registerAssumption(cast<CallInst>(I));
> > > }
> > > };
> > > 
> > > @@ -86,6 +94,7 @@ public:
> > > class LLVM_LIBRARY_VISIBILITY InstCombiner
> > > : public FunctionPass,
> > > public InstVisitor<InstCombiner, Instruction *> {
> > > + AssumptionTracker *AT;
> > > const DataLayout *DL;
> > > TargetLibraryInfo *TLI;
> > > bool MadeIRChange;
> > > @@ -114,6 +123,8 @@ public:
> > > 
> > > void getAnalysisUsage(AnalysisUsage &AU) const override;
> > > 
> > > + AssumptionTracker *getAssumptionTracker() const { return AT; }
> > > +
> > > const DataLayout *getDataLayout() const { return DL; }
> > > 
> > > TargetLibraryInfo *getTargetLibraryInfo() const { return TLI; }
> > > 
> > > Modified:
> > > llvm/trunk/lib/Transforms/InstCombine/InstCombineCalls.cpp
> > > URL:
> > > http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/InstCombine/InstCombineCalls.cpp?rev=217334&r1=217333&r2=217334&view=diff
> > > ==============================================================================
> > > --- llvm/trunk/lib/Transforms/InstCombine/InstCombineCalls.cpp
> > > (original)
> > > +++ llvm/trunk/lib/Transforms/InstCombine/InstCombineCalls.cpp
> > > Sun
> > > Sep 7 07:44:26 2014
> > > @@ -996,6 +996,8 @@ Instruction *InstCombiner::visitCallInst
> > > }
> > > case Intrinsic::assume: {
> > > // Canonicalize assume(a && b) -> assume(a); assume(b);
> > > + // Note: New assumption intrinsics created here are registered
> > > by
> > > + // the InstCombineIRInserter object.
> > > Value *IIOperand = II->getArgOperand(0), *A, *B,
> > > *AssumeIntrinsic = II->getCalledValue();
> > > if (match(IIOperand, m_And(m_Value(A), m_Value(B)))) {
> > > @@ -1005,8 +1007,10 @@ Instruction *InstCombiner::visitCallInst
> > > }
> > > // assume(!(a || b)) -> assume(!a); assume(!b);
> > > if (match(IIOperand, m_Not(m_Or(m_Value(A), m_Value(B))))) {
> > > - Builder->CreateCall(AssumeIntrinsic, Builder->CreateNot(A),
> > > II->getName());
> > > - Builder->CreateCall(AssumeIntrinsic, Builder->CreateNot(B),
> > > II->getName());
> > > + Builder->CreateCall(AssumeIntrinsic, Builder->CreateNot(A),
> > > + II->getName());
> > > + Builder->CreateCall(AssumeIntrinsic, Builder->CreateNot(B),
> > > + II->getName());
> > > return EraseInstFromFunction(*II);
> > > }
> > > break;
> > > 
> > > Modified:
> > > llvm/trunk/lib/Transforms/InstCombine/InstructionCombining.cpp
> > > URL:
> > > http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/InstCombine/InstructionCombining.cpp?rev=217334&r1=217333&r2=217334&view=diff
> > > ==============================================================================
> > > ---
> > > llvm/trunk/lib/Transforms/InstCombine/InstructionCombining.cpp
> > > (original)
> > > +++
> > > llvm/trunk/lib/Transforms/InstCombine/InstructionCombining.cpp
> > > Sun Sep 7 07:44:26 2014
> > > @@ -39,6 +39,7 @@
> > > #include "llvm/ADT/SmallPtrSet.h"
> > > #include "llvm/ADT/Statistic.h"
> > > #include "llvm/ADT/StringSwitch.h"
> > > +#include "llvm/Analysis/AssumptionTracker.h"
> > > #include "llvm/Analysis/ConstantFolding.h"
> > > #include "llvm/Analysis/InstructionSimplify.h"
> > > #include "llvm/Analysis/MemoryBuiltins.h"
> > > @@ -85,12 +86,14 @@ void LLVMInitializeInstCombine(LLVMPassR
> > > char InstCombiner::ID = 0;
> > > INITIALIZE_PASS_BEGIN(InstCombiner, "instcombine",
> > > "Combine redundant instructions", false, false)
> > > +INITIALIZE_PASS_DEPENDENCY(AssumptionTracker)
> > > INITIALIZE_PASS_DEPENDENCY(TargetLibraryInfo)
> > > INITIALIZE_PASS_END(InstCombiner, "instcombine",
> > > "Combine redundant instructions", false, false)
> > > 
> > > void InstCombiner::getAnalysisUsage(AnalysisUsage &AU) const {
> > > AU.setPreservesCFG();
> > > + AU.addRequired<AssumptionTracker>();
> > > AU.addRequired<TargetLibraryInfo>();
> > > }
> > > 
> > > @@ -2907,6 +2910,7 @@ bool InstCombiner::runOnFunction(Functio
> > > if (skipOptnoneFunction(F))
> > > return false;
> > > 
> > > + AT = &getAnalysis<AssumptionTracker>();
> > > DataLayoutPass *DLP = getAnalysisIfAvailable<DataLayoutPass>();
> > > DL = DLP ? &DLP->getDataLayout() : nullptr;
> > > TLI = &getAnalysis<TargetLibraryInfo>();
> > > @@ -2918,7 +2922,7 @@ bool InstCombiner::runOnFunction(Functio
> > > /// instructions into the worklist when they are created.
> > > IRBuilder<true, TargetFolder, InstCombineIRInserter>
> > > TheBuilder(F.getContext(), TargetFolder(DL),
> > > - InstCombineIRInserter(Worklist));
> > > + InstCombineIRInserter(Worklist, AT));
> > > Builder = &TheBuilder;
> > > 
> > > InstCombinerLibCallSimplifier TheSimplifier(DL, TLI, this);
> > > 
> > > Modified: llvm/trunk/lib/Transforms/Scalar/LoopUnrollPass.cpp
> > > URL:
> > > http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Scalar/LoopUnrollPass.cpp?rev=217334&r1=217333&r2=217334&view=diff
> > > ==============================================================================
> > > --- llvm/trunk/lib/Transforms/Scalar/LoopUnrollPass.cpp
> > > (original)
> > > +++ llvm/trunk/lib/Transforms/Scalar/LoopUnrollPass.cpp Sun Sep 7
> > > 07:44:26 2014
> > > @@ -13,6 +13,7 @@
> > > //===----------------------------------------------------------------------===//
> > > 
> > > #include "llvm/Transforms/Scalar.h"
> > > +#include "llvm/Analysis/AssumptionTracker.h"
> > > #include "llvm/Analysis/CodeMetrics.h"
> > > #include "llvm/Analysis/LoopPass.h"
> > > #include "llvm/Analysis/ScalarEvolution.h"
> > > @@ -102,6 +103,7 @@ namespace {
> > > /// loop preheaders be inserted into the CFG...
> > > ///
> > > void getAnalysisUsage(AnalysisUsage &AU) const override {
> > > + AU.addRequired<AssumptionTracker>();
> > > AU.addRequired<LoopInfo>();
> > > AU.addPreserved<LoopInfo>();
> > > AU.addRequiredID(LoopSimplifyID);
> > > @@ -182,6 +184,7 @@ namespace {
> > > char LoopUnroll::ID = 0;
> > > INITIALIZE_PASS_BEGIN(LoopUnroll, "loop-unroll", "Unroll loops",
> > > false, false)
> > > INITIALIZE_AG_DEPENDENCY(TargetTransformInfo)
> > > +INITIALIZE_PASS_DEPENDENCY(AssumptionTracker)
> > > INITIALIZE_PASS_DEPENDENCY(LoopInfo)
> > > INITIALIZE_PASS_DEPENDENCY(LoopSimplify)
> > > INITIALIZE_PASS_DEPENDENCY(LCSSA)
> > > @@ -351,6 +354,7 @@ bool LoopUnroll::runOnLoop(Loop *L, LPPa
> > > LoopInfo *LI = &getAnalysis<LoopInfo>();
> > > ScalarEvolution *SE = &getAnalysis<ScalarEvolution>();
> > > const TargetTransformInfo &TTI =
> > > getAnalysis<TargetTransformInfo>();
> > > + AssumptionTracker *AT = &getAnalysis<AssumptionTracker>();
> > > 
> > > BasicBlock *Header = L->getHeader();
> > > DEBUG(dbgs() << "Loop Unroll: F[" <<
> > > Header->getParent()->getName()
> > > @@ -493,7 +497,8 @@ bool LoopUnroll::runOnLoop(Loop *L, LPPa
> > > }
> > > 
> > > // Unroll the loop.
> > > - if (!UnrollLoop(L, Count, TripCount, AllowRuntime,
> > > TripMultiple,
> > > LI, this, &LPM))
> > > + if (!UnrollLoop(L, Count, TripCount, AllowRuntime,
> > > TripMultiple,
> > > LI, this,
> > > + &LPM, AT))
> > > return false;
> > > 
> > > return true;
> > > 
> > > Modified: llvm/trunk/lib/Transforms/Scalar/LoopUnswitch.cpp
> > > URL:
> > > http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Scalar/LoopUnswitch.cpp?rev=217334&r1=217333&r2=217334&view=diff
> > > ==============================================================================
> > > --- llvm/trunk/lib/Transforms/Scalar/LoopUnswitch.cpp (original)
> > > +++ llvm/trunk/lib/Transforms/Scalar/LoopUnswitch.cpp Sun Sep 7
> > > 07:44:26 2014
> > > @@ -30,6 +30,7 @@
> > > #include "llvm/ADT/STLExtras.h"
> > > #include "llvm/ADT/SmallPtrSet.h"
> > > #include "llvm/ADT/Statistic.h"
> > > +#include "llvm/Analysis/AssumptionTracker.h"
> > > #include "llvm/Analysis/CodeMetrics.h"
> > > #include "llvm/Analysis/InstructionSimplify.h"
> > > #include "llvm/Analysis/LoopInfo.h"
> > > @@ -126,6 +127,7 @@ namespace {
> > > class LoopUnswitch : public LoopPass {
> > > LoopInfo *LI; // Loop information
> > > LPPassManager *LPM;
> > > + AssumptionTracker *AT;
> > > 
> > > // LoopProcessWorklist - Used to check if second loop needs
> > > processing
> > > // after RewriteLoopBodyWithConditionConstant rewrites first
> > > loop.
> > > @@ -164,6 +166,7 @@ namespace {
> > > /// loop preheaders be inserted into the CFG.
> > > ///
> > > void getAnalysisUsage(AnalysisUsage &AU) const override {
> > > + AU.addRequired<AssumptionTracker>();
> > > AU.addRequiredID(LoopSimplifyID);
> > > AU.addPreservedID(LoopSimplifyID);
> > > AU.addRequired<LoopInfo>();
> > > @@ -326,6 +329,7 @@ char LoopUnswitch::ID = 0;
> > > INITIALIZE_PASS_BEGIN(LoopUnswitch, "loop-unswitch", "Unswitch
> > > loops",
> > > false, false)
> > > INITIALIZE_AG_DEPENDENCY(TargetTransformInfo)
> > > +INITIALIZE_PASS_DEPENDENCY(AssumptionTracker)
> > > INITIALIZE_PASS_DEPENDENCY(LoopSimplify)
> > > INITIALIZE_PASS_DEPENDENCY(LoopInfo)
> > > INITIALIZE_PASS_DEPENDENCY(LCSSA)
> > > @@ -376,6 +380,7 @@ bool LoopUnswitch::runOnLoop(Loop *L, LP
> > > if (skipOptnoneFunction(L))
> > > return false;
> > > 
> > > + AT = &getAnalysis<AssumptionTracker>();
> > > LI = &getAnalysis<LoopInfo>();
> > > LPM = &LPM_Ref;
> > > DominatorTreeWrapperPass *DTWP =
> > > @@ -823,6 +828,10 @@ void LoopUnswitch::UnswitchNontrivialCon
> > > F->getBasicBlockList().splice(NewPreheader,
> > > F->getBasicBlockList(),
> > > NewBlocks[0], F->end());
> > > 
> > > + // FIXME: We could register any cloned assumptions instead of
> > > clearing the
> > > + // whole function's cache.
> > > + AT->forgetCachedAssumptions(F);
> > > +
> > > // Now we create the new Loop object for the versioned loop.
> > > Loop *NewLoop = CloneLoop(L, L->getParentLoop(), VMap, LI, LPM);
> > > 
> > > 
> > > Modified: llvm/trunk/lib/Transforms/Utils/InlineFunction.cpp
> > > URL:
> > > http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Utils/InlineFunction.cpp?rev=217334&r1=217333&r2=217334&view=diff
> > > ==============================================================================
> > > --- llvm/trunk/lib/Transforms/Utils/InlineFunction.cpp (original)
> > > +++ llvm/trunk/lib/Transforms/Utils/InlineFunction.cpp Sun Sep 7
> > > 07:44:26 2014
> > > @@ -18,6 +18,7 @@
> > > #include "llvm/ADT/SetVector.h"
> > > #include "llvm/ADT/StringExtras.h"
> > > #include "llvm/Analysis/AliasAnalysis.h"
> > > +#include "llvm/Analysis/AssumptionTracker.h"
> > > #include "llvm/Analysis/CallGraph.h"
> > > #include "llvm/Analysis/CaptureTracking.h"
> > > #include "llvm/Analysis/InstructionSimplify.h"
> > > @@ -982,6 +983,11 @@ bool llvm::InlineFunction(CallSite CS, I
> > > 
> > > // Add noalias metadata if necessary.
> > > AddAliasScopeMetadata(CS, VMap, IFI.DL, IFI.AA);
> > > +
> > > + // FIXME: We could register any cloned assumptions instead of
> > > clearing the
> > > + // whole function's cache.
> > > + if ( IFI.AT )
> > > + IFI.AT->forgetCachedAssumptions(Caller);
> > > }
> > > 
> > > // If there are any alloca instructions in the block that used to
> > > be
> > > the entry
> > > 
> > > Modified: llvm/trunk/lib/Transforms/Utils/LoopUnroll.cpp
> > > URL:
> > > http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Utils/LoopUnroll.cpp?rev=217334&r1=217333&r2=217334&view=diff
> > > ==============================================================================
> > > --- llvm/trunk/lib/Transforms/Utils/LoopUnroll.cpp (original)
> > > +++ llvm/trunk/lib/Transforms/Utils/LoopUnroll.cpp Sun Sep 7
> > > 07:44:26
> > > 2014
> > > @@ -19,6 +19,7 @@
> > > #include "llvm/Transforms/Utils/UnrollLoop.h"
> > > #include "llvm/ADT/SmallPtrSet.h"
> > > #include "llvm/ADT/Statistic.h"
> > > +#include "llvm/Analysis/AssumptionTracker.h"
> > > #include "llvm/Analysis/InstructionSimplify.h"
> > > #include "llvm/Analysis/LoopIterator.h"
> > > #include "llvm/Analysis/LoopPass.h"
> > > @@ -154,7 +155,8 @@ FoldBlockIntoPredecessor(BasicBlock *BB,
> > > /// available from the Pass it must also preserve those analyses.
> > > bool llvm::UnrollLoop(Loop *L, unsigned Count, unsigned
> > > TripCount,
> > > bool AllowRuntime, unsigned TripMultiple,
> > > - LoopInfo *LI, Pass *PP, LPPassManager *LPM) {
> > > + LoopInfo *LI, Pass *PP, LPPassManager *LPM,
> > > + AssumptionTracker *AT) {
> > > BasicBlock *Preheader = L->getLoopPreheader();
> > > if (!Preheader) {
> > > DEBUG(dbgs() << " Can't unroll; loop preheader-insertion
> > > failed.\n");
> > > @@ -442,6 +444,10 @@ bool llvm::UnrollLoop(Loop *L, unsigned
> > > }
> > > }
> > > 
> > > + // FIXME: We could register any cloned assumptions instead of
> > > clearing the
> > > + // whole function's cache.
> > > + AT->forgetCachedAssumptions(F);
> > > +
> > > DominatorTree *DT = nullptr;
> > > if (PP) {
> > > // FIXME: Reconstruct dom info, because it is not preserved
> > > properly.
> > > 
> > > 
> > > _______________________________________________
> > > llvm-commits mailing list
> > > llvm-commits at cs.uiuc.edu
> > > http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits
> > > 
> > > 
> > > 
> > > 
> > > --
> > > 
> > > Alexey Samsonov
> > > vonosmas at gmail.com
> > 
> > --
> > Hal Finkel
> > Assistant Computational Scientist
> > Leadership Computing Facility
> > Argonne National Laboratory
> > 
> > 
> > 
> > 
> > --
> > 
> > Alexey Samsonov
> > vonosmas at gmail.com
> 
> --
> Hal Finkel
> Assistant Computational Scientist
> Leadership Computing Facility
> Argonne National Laboratory
> 
> 
> 
> 
> --
> 
> Alexey Samsonov
> vonosmas at gmail.com

-- 
Hal Finkel
Assistant Computational Scientist
Leadership Computing Facility
Argonne National Laboratory



More information about the llvm-commits mailing list