<div dir="ltr">Hi Hal,<div class="gmail_extra"><br><div class="gmail_quote">On Sun, Sep 7, 2014 at 5:44 AM, Hal Finkel <span dir="ltr"><<a href="mailto:hfinkel@anl.gov" target="_blank">hfinkel@anl.gov</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex">Author: hfinkel<br>
Date: Sun Sep  7 07:44:26 2014<br>
New Revision: 217334<br>
<br>
URL: <a href="http://llvm.org/viewvc/llvm-project?rev=217334&view=rev" target="_blank">http://llvm.org/viewvc/llvm-project?rev=217334&view=rev</a><br>
Log:<br>
Add an Assumption-Tracking Pass<br>
<br>
This adds an immutable pass, AssumptionTracker, which keeps a cache of<br>
@llvm.assume call instructions within a module. It uses callback value handles<br>
to keep stale functions and intrinsics out of the map, and it relies on any<br>
code that creates new @llvm.assume calls to notify it of the new instructions.<br>
The benefit is that code needing to find @llvm.assume intrinsics can do so<br>
directly, without scanning the function, thus allowing the cost of @llvm.assume<br>
handling to be negligible when none are present.<br>
<br>
The current design is intended to be lightweight. We don't keep track of<br>
anything until we need a list of assumptions in some function. The first time<br>
this happens, we scan the function. After that, we add/remove @llvm.assume<br>
calls from the cache in response to registration calls and ValueHandle<br>
callbacks.<br>
<br>
There are no new direct test cases for this pass, but because it calls it<br>
validation function upon module finalization, we'll pick up detectable<br>
inconsistencies from the other tests that touch @llvm.assume calls.<br>
<br>
This pass will be used by follow-up commits that make use of @llvm.assume.<br>
<br>
Added:<br>
    llvm/trunk/include/llvm/Analysis/AssumptionTracker.h<br>
    llvm/trunk/lib/Analysis/AssumptionTracker.cpp<br>
Modified:<br>
    llvm/trunk/include/llvm/InitializePasses.h<br>
    llvm/trunk/include/llvm/Transforms/Utils/Cloning.h<br>
    llvm/trunk/include/llvm/Transforms/Utils/UnrollLoop.h<br>
    llvm/trunk/lib/Analysis/CMakeLists.txt<br>
    llvm/trunk/lib/Transforms/IPO/InlineAlways.cpp<br>
    llvm/trunk/lib/Transforms/IPO/InlineSimple.cpp<br>
    llvm/trunk/lib/Transforms/IPO/Inliner.cpp<br>
    llvm/trunk/lib/Transforms/InstCombine/InstCombine.h<br>
    llvm/trunk/lib/Transforms/InstCombine/InstCombineCalls.cpp<br>
    llvm/trunk/lib/Transforms/InstCombine/InstructionCombining.cpp<br>
    llvm/trunk/lib/Transforms/Scalar/LoopUnrollPass.cpp<br>
    llvm/trunk/lib/Transforms/Scalar/LoopUnswitch.cpp<br>
    llvm/trunk/lib/Transforms/Utils/InlineFunction.cpp<br>
    llvm/trunk/lib/Transforms/Utils/LoopUnroll.cpp<br>
<br>
Added: llvm/trunk/include/llvm/Analysis/AssumptionTracker.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Analysis/AssumptionTracker.h?rev=217334&view=auto" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Analysis/AssumptionTracker.h?rev=217334&view=auto</a><br>
==============================================================================<br>
--- llvm/trunk/include/llvm/Analysis/AssumptionTracker.h (added)<br>
+++ llvm/trunk/include/llvm/Analysis/AssumptionTracker.h Sun Sep  7 07:44:26 2014<br>
@@ -0,0 +1,128 @@<br>
+//===- llvm/Analysis/AssumptionTracker.h - Track @llvm.assume ---*- C++ -*-===//<br>
+//<br>
+//                     The LLVM Compiler Infrastructure<br>
+//<br>
+// This file is distributed under the University of Illinois Open Source<br>
+// License. See LICENSE.TXT for details.<br>
+//<br>
+//===----------------------------------------------------------------------===//<br>
+//<br>
+// This file contains a pass that keeps track of @llvm.assume intrinsics in<br>
+// the functions of a module (allowing assumptions within any function to be<br>
+// found cheaply by other parts of the optimizer).<br>
+//<br>
+//===----------------------------------------------------------------------===//<br>
+<br>
+#ifndef LLVM_ANALYSIS_ASSUMPTIONTRACKER_H<br>
+#define LLVM_ANALYSIS_ASSUMPTIONTRACKER_H<br>
+<br>
+#include "llvm/ADT/DenseMap.h"<br>
+#include "llvm/ADT/DenseSet.h"<br>
+#include "llvm/ADT/SmallSet.h"<br>
+#include "llvm/IR/Function.h"<br>
+#include "llvm/IR/Instructions.h"<br>
+#include "llvm/IR/ValueHandle.h"<br>
+#include "llvm/Pass.h"<br>
+#include <memory><br>
+<br>
+namespace llvm {<br>
+<br>
+/// An immutable pass that tracks @llvm.assume intrinsics in a module.<br>
+class AssumptionTracker : public ImmutablePass {<br>
+  /// A callback value handle applied to function objects, which we use to<br>
+  /// delete our cache of intrinsics for a function when it is deleted.<br>
+  class FunctionCallbackVH : public CallbackVH {<br>
+    AssumptionTracker *AT;<br>
+    void deleted() override;<br>
+<br>
+    public:<br>
+      typedef DenseMapInfo<Value *> DMI;<br>
+<br>
+      FunctionCallbackVH(Value *V, AssumptionTracker *AT = nullptr)<br>
+        : CallbackVH(V), AT(AT) {}<br>
+  };<br>
+<br>
+  /// A callback value handle applied to call instructions, which keeps<br>
+  /// track of the call's parent function so that we can remove a<br>
+  /// assumption intrinsic call from our cache when the instruction is<br>
+  /// deleted.<br>
+  class CallCallbackVH : public CallbackVH {<br>
+    AssumptionTracker *AT;<br>
+    void deleted() override;<br>
+<br>
+    // We store the function here because we need it to lookup the set<br>
+    // containing this handle when the underlying CallInst is being deleted.<br>
+    Function *F;<br>
+<br>
+    public:<br>
+      typedef DenseMapInfo<Instruction *> DMI;<br>
+<br>
+      CallCallbackVH(Instruction *I, AssumptionTracker *AT = nullptr)<br>
+        : CallbackVH(I), AT(AT), F(nullptr) {<br>
+        if (I != DMI::getEmptyKey() && I != DMI::getTombstoneKey())<br>
+          F = I->getParent()->getParent();<br>
+      }<br>
+<br>
+      operator CallInst*() const {<br>
+        Value *V = getValPtr();<br>
+        if (V == DMI::getEmptyKey() || V == DMI::getTombstoneKey())<br>
+          return static_cast<CallInst*>(V);<br></blockquote><div><br></div><div>^^ UBSan bootstrap bot reports undefined behavior here:</div><div><div>/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</div></div><div><div>(full log: <a href="http://lab.llvm.org:8011/builders/sanitizer-x86_64-linux-bootstrap/builds/4491/steps/check-llvm%20ubsan/logs/stdio">http://lab.llvm.org:8011/builders/sanitizer-x86_64-linux-bootstrap/builds/4491/steps/check-llvm%20ubsan/logs/stdio</a>)</div></div><div><br></div><div>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:</div><div>correct alignment of "fake pointers" of type T* depends on the natural alignment of T, while the definition of T might not be available.</div><div><br></div><div>Can you work around this problem somehow, and avoid bogus cast of fake pointer here?</div><div><br></div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex">
+<br>
+        return cast<CallInst>(V);<br>
+      }<br>
+<br>
+      CallInst *operator->() const { return cast<CallInst>(getValPtr()); }<br>
+      CallInst &operator*() const { return *cast<CallInst>(getValPtr()); }<br>
+  };<br>
+<br>
+  friend FunctionCallbackVH;<br>
+  friend CallCallbackVH;<br>
+<br>
+  // FIXME: SmallSet might be better here, but it currently has no iterators.<br>
+  typedef DenseSet<CallCallbackVH, CallCallbackVH::DMI> CallHandleSet;<br>
+  typedef DenseMap<FunctionCallbackVH, std::unique_ptr<CallHandleSet>,<br>
+                   FunctionCallbackVH::DMI> FunctionCallsMap;<br>
+  FunctionCallsMap CachedAssumeCalls;<br>
+<br>
+  /// Scan the provided function for @llvm.assume intrinsic calls. Returns an<br>
+  /// iterator to the set for this function in the CachedAssumeCalls map.<br>
+  FunctionCallsMap::iterator scanFunction(Function *F);<br>
+<br>
+public:<br>
+  /// Remove the cache of @llvm.assume intrinsics for the given function.<br>
+  void forgetCachedAssumptions(Function *F);<br>
+<br>
+  /// Add an @llvm.assume intrinsic to the cache for its parent function.<br>
+  void registerAssumption(CallInst *CI);<br>
+<br>
+  typedef CallHandleSet::iterator assumption_iterator;<br>
+  typedef iterator_range<assumption_iterator> assumption_range;<br>
+<br>
+  inline assumption_range assumptions(Function *F) {<br>
+    FunctionCallsMap::iterator I = CachedAssumeCalls.find(F);<br>
+    if (I == CachedAssumeCalls.end()) {<br>
+      I = scanFunction(F);<br>
+    }<br>
+<br>
+    return assumption_range(I->second->begin(), I->second->end());<br>
+  }<br>
+<br>
+  AssumptionTracker();<br>
+  ~AssumptionTracker();<br>
+<br>
+  void releaseMemory() override {<br>
+    CachedAssumeCalls.shrink_and_clear();<br>
+  }<br>
+<br>
+  void verifyAnalysis() const override;<br>
+  bool doFinalization(Module &) override {<br>
+    verifyAnalysis();<br>
+    return false;<br>
+  }<br>
+<br>
+  static char ID; // Pass identification, replacement for typeid<br>
+};<br>
+<br>
+} // end namespace llvm<br>
+<br>
+#endif<br>
<br>
Modified: llvm/trunk/include/llvm/InitializePasses.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/InitializePasses.h?rev=217334&r1=217333&r2=217334&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/InitializePasses.h?rev=217334&r1=217333&r2=217334&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/include/llvm/InitializePasses.h (original)<br>
+++ llvm/trunk/include/llvm/InitializePasses.h Sun Sep  7 07:44:26 2014<br>
@@ -262,6 +262,7 @@ void initializeDataLayoutPassPass(PassRe<br>
 void initializeTargetTransformInfoAnalysisGroup(PassRegistry&);<br>
 void initializeNoTTIPass(PassRegistry&);<br>
 void initializeTargetLibraryInfoPass(PassRegistry&);<br>
+void initializeAssumptionTrackerPass(PassRegistry &);<br>
 void initializeTwoAddressInstructionPassPass(PassRegistry&);<br>
 void initializeTypeBasedAliasAnalysisPass(PassRegistry&);<br>
 void initializeScopedNoAliasAAPass(PassRegistry&);<br>
<br>
Modified: llvm/trunk/include/llvm/Transforms/Utils/Cloning.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Transforms/Utils/Cloning.h?rev=217334&r1=217333&r2=217334&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Transforms/Utils/Cloning.h?rev=217334&r1=217333&r2=217334&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/include/llvm/Transforms/Utils/Cloning.h (original)<br>
+++ llvm/trunk/include/llvm/Transforms/Utils/Cloning.h Sun Sep  7 07:44:26 2014<br>
@@ -44,6 +44,7 @@ class Loop;<br>
 class LoopInfo;<br>
 class AllocaInst;<br>
 class AliasAnalysis;<br>
+class AssumptionTracker;<br>
<br>
 /// CloneModule - Return an exact copy of the specified module<br>
 ///<br>
@@ -160,14 +161,16 @@ class InlineFunctionInfo {<br>
 public:<br>
   explicit InlineFunctionInfo(CallGraph *cg = nullptr,<br>
                               const DataLayout *DL = nullptr,<br>
-                              AliasAnalysis *AA = nullptr)<br>
-    : CG(cg), DL(DL), AA(AA) {}<br>
+                              AliasAnalysis *AA = nullptr,<br>
+                              AssumptionTracker *AT = nullptr)<br>
+    : CG(cg), DL(DL), AA(AA), AT(AT) {}<br>
<br>
   /// CG - If non-null, InlineFunction will update the callgraph to reflect the<br>
   /// changes it makes.<br>
   CallGraph *CG;<br>
   const DataLayout *DL;<br>
   AliasAnalysis *AA;<br>
+  AssumptionTracker *AT;<br>
<br>
   /// StaticAllocas - InlineFunction fills this in with all static allocas that<br>
   /// get copied into the caller.<br>
<br>
Modified: llvm/trunk/include/llvm/Transforms/Utils/UnrollLoop.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Transforms/Utils/UnrollLoop.h?rev=217334&r1=217333&r2=217334&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Transforms/Utils/UnrollLoop.h?rev=217334&r1=217333&r2=217334&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/include/llvm/Transforms/Utils/UnrollLoop.h (original)<br>
+++ llvm/trunk/include/llvm/Transforms/Utils/UnrollLoop.h Sun Sep  7 07:44:26 2014<br>
@@ -18,6 +18,7 @@<br>
<br>
 namespace llvm {<br>
<br>
+class AssumptionTracker;<br>
 class Loop;<br>
 class LoopInfo;<br>
 class LPPassManager;<br>
@@ -25,7 +26,7 @@ class Pass;<br>
<br>
 bool UnrollLoop(Loop *L, unsigned Count, unsigned TripCount, bool AllowRuntime,<br>
                 unsigned TripMultiple, LoopInfo *LI, Pass *PP,<br>
-                LPPassManager *LPM);<br>
+                LPPassManager *LPM, AssumptionTracker *AT);<br>
<br>
 bool UnrollRuntimeLoopProlog(Loop *L, unsigned Count, LoopInfo *LI,<br>
                              LPPassManager* LPM);<br>
<br>
Added: llvm/trunk/lib/Analysis/AssumptionTracker.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Analysis/AssumptionTracker.cpp?rev=217334&view=auto" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Analysis/AssumptionTracker.cpp?rev=217334&view=auto</a><br>
==============================================================================<br>
--- llvm/trunk/lib/Analysis/AssumptionTracker.cpp (added)<br>
+++ llvm/trunk/lib/Analysis/AssumptionTracker.cpp Sun Sep  7 07:44:26 2014<br>
@@ -0,0 +1,113 @@<br>
+//===- AssumptionTracker.cpp - Track @llvm.assume -------------------------===//<br>
+//<br>
+//                     The LLVM Compiler Infrastructure<br>
+//<br>
+// This file is distributed under the University of Illinois Open Source<br>
+// License. See LICENSE.TXT for details.<br>
+//<br>
+//===----------------------------------------------------------------------===//<br>
+//<br>
+// This file contains a pass that keeps track of @llvm.assume intrinsics in<br>
+// the functions of a module.<br>
+//<br>
+//===----------------------------------------------------------------------===//<br>
+<br>
+#include "llvm/Analysis/AssumptionTracker.h"<br>
+#include "llvm/IR/CallSite.h"<br>
+#include "llvm/IR/Dominators.h"<br>
+#include "llvm/IR/Function.h"<br>
+#include "llvm/IR/Instructions.h"<br>
+#include "llvm/IR/IntrinsicInst.h"<br>
+#include "llvm/IR/PatternMatch.h"<br>
+#include "llvm/Support/Debug.h"<br>
+using namespace llvm;<br>
+using namespace llvm::PatternMatch;<br>
+<br>
+void AssumptionTracker::FunctionCallbackVH::deleted() {<br>
+  AT->forgetCachedAssumptions(cast<Function>(getValPtr()));<br>
+  // 'this' now dangles!<br>
+}<br>
+<br>
+void AssumptionTracker::forgetCachedAssumptions(Function *F) {<br>
+  CachedAssumeCalls.erase(F);<br>
+}<br>
+<br>
+void AssumptionTracker::CallCallbackVH::deleted() {<br>
+  assert(F && "delete callback called on dummy handle");<br>
+  FunctionCallsMap::iterator I = AT->CachedAssumeCalls.find(F);<br>
+  assert(I != AT->CachedAssumeCalls.end() &&<br>
+         "Function cleared from the map without removing the values?");<br>
+<br>
+  I->second->erase(*this);<br>
+  // 'this' now dangles!<br>
+}<br>
+<br>
+AssumptionTracker::FunctionCallsMap::iterator<br>
+AssumptionTracker::scanFunction(Function *F) {<br>
+  auto IP =<br>
+    CachedAssumeCalls.insert(std::make_pair(FunctionCallbackVH(F, this),<br>
+                                            std::unique_ptr<CallHandleSet>(<br>
+                                              new CallHandleSet())));<br>
+  assert(IP.second && "Scanning function already in the map?");<br>
+<br>
+  FunctionCallsMap::iterator I = IP.first;<br>
+<br>
+  // Go through all instructions in all blocks, add all calls to @llvm.assume<br>
+  // to our cache.<br>
+  for (BasicBlock &B : *F)<br>
+    for (Instruction &II : B)<br>
+      if (match(cast<Value>(&II), m_Intrinsic<Intrinsic::assume>(m_Value())))<br>
+        I->second->insert(CallCallbackVH(&II, this));<br>
+<br>
+  return I;<br>
+}<br>
+<br>
+void AssumptionTracker::verifyAnalysis() const {<br>
+#ifndef NDEBUG<br>
+  for (const auto &I : CachedAssumeCalls) {<br>
+    for (const BasicBlock &B : cast<Function>(*I.first))<br>
+      for (const Instruction &II : B) {<br>
+        Instruction *C = const_cast<Instruction*>(&II);<br>
+        if (match(C, m_Intrinsic<Intrinsic::assume>(m_Value()))) {<br>
+          assert(I.second->count(CallCallbackVH(C,<br>
+                   const_cast<AssumptionTracker*>(this))) &&<br>
+                 "Assumption in scanned function not in cache");<br>
+        }<br>
+    }<br>
+  }<br>
+#endif<br>
+}<br>
+<br>
+void AssumptionTracker::registerAssumption(CallInst *CI) {<br>
+  assert(match(cast<Value>(CI),<br>
+               m_Intrinsic<Intrinsic::assume>(m_Value())) &&<br>
+         "Registered call does not call @llvm.assume");<br>
+  assert(CI->getParent() &&<br>
+         "Cannot register @llvm.assume call not in a basic block");<br>
+<br>
+  Function *F = CI->getParent()->getParent();<br>
+  assert(F && "Cannot register @llvm.assume call not in a function");<br>
+<br>
+  FunctionCallsMap::iterator I = CachedAssumeCalls.find(F);<br>
+  if (I == CachedAssumeCalls.end()) {<br>
+    // If this function has not already been scanned, then don't do anything<br>
+    // here. This intrinsic will be found, if it still exists, if the list of<br>
+    // assumptions in this function is requested at some later point. This<br>
+    // maintains the following invariant: if a function is present in the<br>
+    // cache, then its list of assumption intrinsic calls is complete.<br>
+    return;<br>
+  }<br>
+<br>
+  I->second->insert(CallCallbackVH(CI, this));<br>
+}<br>
+<br>
+AssumptionTracker::AssumptionTracker() : ImmutablePass(ID) {<br>
+  initializeAssumptionTrackerPass(*PassRegistry::getPassRegistry());<br>
+}<br>
+<br>
+AssumptionTracker::~AssumptionTracker() {}<br>
+<br>
+INITIALIZE_PASS(AssumptionTracker, "assumption-tracker", "Assumption Tracker",<br>
+                false, true)<br>
+char AssumptionTracker::ID = 0;<br>
+<br>
<br>
Modified: llvm/trunk/lib/Analysis/CMakeLists.txt<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Analysis/CMakeLists.txt?rev=217334&r1=217333&r2=217334&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Analysis/CMakeLists.txt?rev=217334&r1=217333&r2=217334&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/lib/Analysis/CMakeLists.txt (original)<br>
+++ llvm/trunk/lib/Analysis/CMakeLists.txt Sun Sep  7 07:44:26 2014<br>
@@ -5,6 +5,7 @@ add_llvm_library(LLVMAnalysis<br>
   AliasDebugger.cpp<br>
   AliasSetTracker.cpp<br>
   Analysis.cpp<br>
+  AssumptionTracker.cpp<br>
   BasicAliasAnalysis.cpp<br>
   BlockFrequencyInfo.cpp<br>
   BlockFrequencyInfoImpl.cpp<br>
<br>
Modified: llvm/trunk/lib/Transforms/IPO/InlineAlways.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/IPO/InlineAlways.cpp?rev=217334&r1=217333&r2=217334&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/IPO/InlineAlways.cpp?rev=217334&r1=217333&r2=217334&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/lib/Transforms/IPO/InlineAlways.cpp (original)<br>
+++ llvm/trunk/lib/Transforms/IPO/InlineAlways.cpp Sun Sep  7 07:44:26 2014<br>
@@ -15,6 +15,7 @@<br>
 #include "llvm/Transforms/IPO.h"<br>
 #include "llvm/ADT/SmallPtrSet.h"<br>
 #include "llvm/Analysis/AliasAnalysis.h"<br>
+#include "llvm/Analysis/AssumptionTracker.h"<br>
 #include "llvm/Analysis/CallGraph.h"<br>
 #include "llvm/Analysis/InlineCost.h"<br>
 #include "llvm/IR/CallSite.h"<br>
@@ -67,6 +68,7 @@ char AlwaysInliner::ID = 0;<br>
 INITIALIZE_PASS_BEGIN(AlwaysInliner, "always-inline",<br>
                 "Inliner for always_inline functions", false, false)<br>
 INITIALIZE_AG_DEPENDENCY(AliasAnalysis)<br>
+INITIALIZE_PASS_DEPENDENCY(AssumptionTracker)<br>
 INITIALIZE_PASS_DEPENDENCY(CallGraphWrapperPass)<br>
 INITIALIZE_PASS_DEPENDENCY(InlineCostAnalysis)<br>
 INITIALIZE_PASS_END(AlwaysInliner, "always-inline",<br>
<br>
Modified: llvm/trunk/lib/Transforms/IPO/InlineSimple.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/IPO/InlineSimple.cpp?rev=217334&r1=217333&r2=217334&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/IPO/InlineSimple.cpp?rev=217334&r1=217333&r2=217334&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/lib/Transforms/IPO/InlineSimple.cpp (original)<br>
+++ llvm/trunk/lib/Transforms/IPO/InlineSimple.cpp Sun Sep  7 07:44:26 2014<br>
@@ -13,6 +13,7 @@<br>
<br>
 #include "llvm/Transforms/IPO.h"<br>
 #include "llvm/Analysis/AliasAnalysis.h"<br>
+#include "llvm/Analysis/AssumptionTracker.h"<br>
 #include "llvm/Analysis/CallGraph.h"<br>
 #include "llvm/Analysis/InlineCost.h"<br>
 #include "llvm/IR/CallSite.h"<br>
@@ -75,6 +76,7 @@ char SimpleInliner::ID = 0;<br>
 INITIALIZE_PASS_BEGIN(SimpleInliner, "inline",<br>
                 "Function Integration/Inlining", false, false)<br>
 INITIALIZE_AG_DEPENDENCY(AliasAnalysis)<br>
+INITIALIZE_PASS_DEPENDENCY(AssumptionTracker)<br>
 INITIALIZE_PASS_DEPENDENCY(CallGraphWrapperPass)<br>
 INITIALIZE_PASS_DEPENDENCY(InlineCostAnalysis)<br>
 INITIALIZE_PASS_END(SimpleInliner, "inline",<br>
<br>
Modified: llvm/trunk/lib/Transforms/IPO/Inliner.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/IPO/Inliner.cpp?rev=217334&r1=217333&r2=217334&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/IPO/Inliner.cpp?rev=217334&r1=217333&r2=217334&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/lib/Transforms/IPO/Inliner.cpp (original)<br>
+++ llvm/trunk/lib/Transforms/IPO/Inliner.cpp Sun Sep  7 07:44:26 2014<br>
@@ -17,6 +17,7 @@<br>
 #include "llvm/ADT/SmallPtrSet.h"<br>
 #include "llvm/ADT/Statistic.h"<br>
 #include "llvm/Analysis/AliasAnalysis.h"<br>
+#include "llvm/Analysis/AssumptionTracker.h"<br>
 #include "llvm/Analysis/CallGraph.h"<br>
 #include "llvm/Analysis/InlineCost.h"<br>
 #include "llvm/IR/CallSite.h"<br>
@@ -76,6 +77,7 @@ Inliner::Inliner(char &ID, int Threshold<br>
 /// always explicitly call the implementation here.<br>
 void Inliner::getAnalysisUsage(AnalysisUsage &AU) const {<br>
   AU.addRequired<AliasAnalysis>();<br>
+  AU.addRequired<AssumptionTracker>();<br>
   CallGraphSCCPass::getAnalysisUsage(AU);<br>
 }<br>
<br>
@@ -441,6 +443,7 @@ static bool InlineHistoryIncludes(Functi<br>
<br>
 bool Inliner::runOnSCC(CallGraphSCC &SCC) {<br>
   CallGraph &CG = getAnalysis<CallGraphWrapperPass>().getCallGraph();<br>
+  AssumptionTracker *AT = &getAnalysis<AssumptionTracker>();<br>
   DataLayoutPass *DLP = getAnalysisIfAvailable<DataLayoutPass>();<br>
   const DataLayout *DL = DLP ? &DLP->getDataLayout() : nullptr;<br>
   const TargetLibraryInfo *TLI = getAnalysisIfAvailable<TargetLibraryInfo>();<br>
@@ -503,7 +506,7 @@ bool Inliner::runOnSCC(CallGraphSCC &SCC<br>
<br>
<br>
   InlinedArrayAllocasTy InlinedArrayAllocas;<br>
-  InlineFunctionInfo InlineInfo(&CG, DL, AA);<br>
+  InlineFunctionInfo InlineInfo(&CG, DL, AA, AT);<br>
<br>
   // Now that we have all of the call sites, loop over them and inline them if<br>
   // it looks profitable to do so.<br>
<br>
Modified: llvm/trunk/lib/Transforms/InstCombine/InstCombine.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/InstCombine/InstCombine.h?rev=217334&r1=217333&r2=217334&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/InstCombine/InstCombine.h?rev=217334&r1=217333&r2=217334&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/lib/Transforms/InstCombine/InstCombine.h (original)<br>
+++ llvm/trunk/lib/Transforms/InstCombine/InstCombine.h Sun Sep  7 07:44:26 2014<br>
@@ -11,12 +11,14 @@<br>
 #define LLVM_LIB_TRANSFORMS_INSTCOMBINE_INSTCOMBINE_H<br>
<br>
 #include "InstCombineWorklist.h"<br>
+#include "llvm/Analysis/AssumptionTracker.h"<br>
 #include "llvm/Analysis/TargetFolder.h"<br>
 #include "llvm/Analysis/ValueTracking.h"<br>
 #include "llvm/IR/IRBuilder.h"<br>
 #include "llvm/IR/InstVisitor.h"<br>
 #include "llvm/IR/IntrinsicInst.h"<br>
 #include "llvm/IR/Operator.h"<br>
+#include "llvm/IR/PatternMatch.h"<br>
 #include "llvm/Pass.h"<br>
 #include "llvm/Transforms/Utils/SimplifyLibCalls.h"<br>
<br>
@@ -71,14 +73,20 @@ static inline Constant *SubOne(Constant<br>
 class LLVM_LIBRARY_VISIBILITY InstCombineIRInserter<br>
     : public IRBuilderDefaultInserter<true> {<br>
   InstCombineWorklist &Worklist;<br>
+  AssumptionTracker *AT;<br>
<br>
 public:<br>
-  InstCombineIRInserter(InstCombineWorklist &WL) : Worklist(WL) {}<br>
+  InstCombineIRInserter(InstCombineWorklist &WL, AssumptionTracker *AT)<br>
+    : Worklist(WL), AT(AT) {}<br>
<br>
   void InsertHelper(Instruction *I, const Twine &Name, BasicBlock *BB,<br>
                     BasicBlock::iterator InsertPt) const {<br>
     IRBuilderDefaultInserter<true>::InsertHelper(I, Name, BB, InsertPt);<br>
     Worklist.Add(I);<br>
+<br>
+    using namespace llvm::PatternMatch;<br>
+    if ((match(I, m_Intrinsic<Intrinsic::assume>(m_Value()))))<br>
+      AT->registerAssumption(cast<CallInst>(I));<br>
   }<br>
 };<br>
<br>
@@ -86,6 +94,7 @@ public:<br>
 class LLVM_LIBRARY_VISIBILITY InstCombiner<br>
     : public FunctionPass,<br>
       public InstVisitor<InstCombiner, Instruction *> {<br>
+  AssumptionTracker *AT;<br>
   const DataLayout *DL;<br>
   TargetLibraryInfo *TLI;<br>
   bool MadeIRChange;<br>
@@ -114,6 +123,8 @@ public:<br>
<br>
   void getAnalysisUsage(AnalysisUsage &AU) const override;<br>
<br>
+  AssumptionTracker *getAssumptionTracker() const { return AT; }<br>
+<br>
   const DataLayout *getDataLayout() const { return DL; }<br>
<br>
   TargetLibraryInfo *getTargetLibraryInfo() const { return TLI; }<br>
<br>
Modified: llvm/trunk/lib/Transforms/InstCombine/InstCombineCalls.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/InstCombine/InstCombineCalls.cpp?rev=217334&r1=217333&r2=217334&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/InstCombine/InstCombineCalls.cpp?rev=217334&r1=217333&r2=217334&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/lib/Transforms/InstCombine/InstCombineCalls.cpp (original)<br>
+++ llvm/trunk/lib/Transforms/InstCombine/InstCombineCalls.cpp Sun Sep  7 07:44:26 2014<br>
@@ -996,6 +996,8 @@ Instruction *InstCombiner::visitCallInst<br>
   }<br>
   case Intrinsic::assume: {<br>
     // Canonicalize assume(a && b) -> assume(a); assume(b);<br>
+    // Note: New assumption intrinsics created here are registered by<br>
+    // the InstCombineIRInserter object.<br>
     Value *IIOperand = II->getArgOperand(0), *A, *B,<br>
           *AssumeIntrinsic = II->getCalledValue();<br>
     if (match(IIOperand, m_And(m_Value(A), m_Value(B)))) {<br>
@@ -1005,8 +1007,10 @@ Instruction *InstCombiner::visitCallInst<br>
     }<br>
     // assume(!(a || b)) -> assume(!a); assume(!b);<br>
     if (match(IIOperand, m_Not(m_Or(m_Value(A), m_Value(B))))) {<br>
-      Builder->CreateCall(AssumeIntrinsic, Builder->CreateNot(A), II->getName());<br>
-      Builder->CreateCall(AssumeIntrinsic, Builder->CreateNot(B), II->getName());<br>
+      Builder->CreateCall(AssumeIntrinsic, Builder->CreateNot(A),<br>
+                          II->getName());<br>
+      Builder->CreateCall(AssumeIntrinsic, Builder->CreateNot(B),<br>
+                          II->getName());<br>
       return EraseInstFromFunction(*II);<br>
     }<br>
     break;<br>
<br>
Modified: llvm/trunk/lib/Transforms/InstCombine/InstructionCombining.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/InstCombine/InstructionCombining.cpp?rev=217334&r1=217333&r2=217334&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/InstCombine/InstructionCombining.cpp?rev=217334&r1=217333&r2=217334&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/lib/Transforms/InstCombine/InstructionCombining.cpp (original)<br>
+++ llvm/trunk/lib/Transforms/InstCombine/InstructionCombining.cpp Sun Sep  7 07:44:26 2014<br>
@@ -39,6 +39,7 @@<br>
 #include "llvm/ADT/SmallPtrSet.h"<br>
 #include "llvm/ADT/Statistic.h"<br>
 #include "llvm/ADT/StringSwitch.h"<br>
+#include "llvm/Analysis/AssumptionTracker.h"<br>
 #include "llvm/Analysis/ConstantFolding.h"<br>
 #include "llvm/Analysis/InstructionSimplify.h"<br>
 #include "llvm/Analysis/MemoryBuiltins.h"<br>
@@ -85,12 +86,14 @@ void LLVMInitializeInstCombine(LLVMPassR<br>
 char InstCombiner::ID = 0;<br>
 INITIALIZE_PASS_BEGIN(InstCombiner, "instcombine",<br>
                 "Combine redundant instructions", false, false)<br>
+INITIALIZE_PASS_DEPENDENCY(AssumptionTracker)<br>
 INITIALIZE_PASS_DEPENDENCY(TargetLibraryInfo)<br>
 INITIALIZE_PASS_END(InstCombiner, "instcombine",<br>
                 "Combine redundant instructions", false, false)<br>
<br>
 void InstCombiner::getAnalysisUsage(AnalysisUsage &AU) const {<br>
   AU.setPreservesCFG();<br>
+  AU.addRequired<AssumptionTracker>();<br>
   AU.addRequired<TargetLibraryInfo>();<br>
 }<br>
<br>
@@ -2907,6 +2910,7 @@ bool InstCombiner::runOnFunction(Functio<br>
   if (skipOptnoneFunction(F))<br>
     return false;<br>
<br>
+  AT = &getAnalysis<AssumptionTracker>();<br>
   DataLayoutPass *DLP = getAnalysisIfAvailable<DataLayoutPass>();<br>
   DL = DLP ? &DLP->getDataLayout() : nullptr;<br>
   TLI = &getAnalysis<TargetLibraryInfo>();<br>
@@ -2918,7 +2922,7 @@ bool InstCombiner::runOnFunction(Functio<br>
   /// instructions into the worklist when they are created.<br>
   IRBuilder<true, TargetFolder, InstCombineIRInserter><br>
     TheBuilder(F.getContext(), TargetFolder(DL),<br>
-               InstCombineIRInserter(Worklist));<br>
+               InstCombineIRInserter(Worklist, AT));<br>
   Builder = &TheBuilder;<br>
<br>
   InstCombinerLibCallSimplifier TheSimplifier(DL, TLI, this);<br>
<br>
Modified: llvm/trunk/lib/Transforms/Scalar/LoopUnrollPass.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Scalar/LoopUnrollPass.cpp?rev=217334&r1=217333&r2=217334&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Scalar/LoopUnrollPass.cpp?rev=217334&r1=217333&r2=217334&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/lib/Transforms/Scalar/LoopUnrollPass.cpp (original)<br>
+++ llvm/trunk/lib/Transforms/Scalar/LoopUnrollPass.cpp Sun Sep  7 07:44:26 2014<br>
@@ -13,6 +13,7 @@<br>
 //===----------------------------------------------------------------------===//<br>
<br>
 #include "llvm/Transforms/Scalar.h"<br>
+#include "llvm/Analysis/AssumptionTracker.h"<br>
 #include "llvm/Analysis/CodeMetrics.h"<br>
 #include "llvm/Analysis/LoopPass.h"<br>
 #include "llvm/Analysis/ScalarEvolution.h"<br>
@@ -102,6 +103,7 @@ namespace {<br>
     /// loop preheaders be inserted into the CFG...<br>
     ///<br>
     void getAnalysisUsage(AnalysisUsage &AU) const override {<br>
+      AU.addRequired<AssumptionTracker>();<br>
       AU.addRequired<LoopInfo>();<br>
       AU.addPreserved<LoopInfo>();<br>
       AU.addRequiredID(LoopSimplifyID);<br>
@@ -182,6 +184,7 @@ namespace {<br>
 char LoopUnroll::ID = 0;<br>
 INITIALIZE_PASS_BEGIN(LoopUnroll, "loop-unroll", "Unroll loops", false, false)<br>
 INITIALIZE_AG_DEPENDENCY(TargetTransformInfo)<br>
+INITIALIZE_PASS_DEPENDENCY(AssumptionTracker)<br>
 INITIALIZE_PASS_DEPENDENCY(LoopInfo)<br>
 INITIALIZE_PASS_DEPENDENCY(LoopSimplify)<br>
 INITIALIZE_PASS_DEPENDENCY(LCSSA)<br>
@@ -351,6 +354,7 @@ bool LoopUnroll::runOnLoop(Loop *L, LPPa<br>
   LoopInfo *LI = &getAnalysis<LoopInfo>();<br>
   ScalarEvolution *SE = &getAnalysis<ScalarEvolution>();<br>
   const TargetTransformInfo &TTI = getAnalysis<TargetTransformInfo>();<br>
+  AssumptionTracker *AT = &getAnalysis<AssumptionTracker>();<br>
<br>
   BasicBlock *Header = L->getHeader();<br>
   DEBUG(dbgs() << "Loop Unroll: F[" << Header->getParent()->getName()<br>
@@ -493,7 +497,8 @@ bool LoopUnroll::runOnLoop(Loop *L, LPPa<br>
   }<br>
<br>
   // Unroll the loop.<br>
-  if (!UnrollLoop(L, Count, TripCount, AllowRuntime, TripMultiple, LI, this, &LPM))<br>
+  if (!UnrollLoop(L, Count, TripCount, AllowRuntime, TripMultiple, LI, this,<br>
+                  &LPM, AT))<br>
     return false;<br>
<br>
   return true;<br>
<br>
Modified: llvm/trunk/lib/Transforms/Scalar/LoopUnswitch.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Scalar/LoopUnswitch.cpp?rev=217334&r1=217333&r2=217334&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Scalar/LoopUnswitch.cpp?rev=217334&r1=217333&r2=217334&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/lib/Transforms/Scalar/LoopUnswitch.cpp (original)<br>
+++ llvm/trunk/lib/Transforms/Scalar/LoopUnswitch.cpp Sun Sep  7 07:44:26 2014<br>
@@ -30,6 +30,7 @@<br>
 #include "llvm/ADT/STLExtras.h"<br>
 #include "llvm/ADT/SmallPtrSet.h"<br>
 #include "llvm/ADT/Statistic.h"<br>
+#include "llvm/Analysis/AssumptionTracker.h"<br>
 #include "llvm/Analysis/CodeMetrics.h"<br>
 #include "llvm/Analysis/InstructionSimplify.h"<br>
 #include "llvm/Analysis/LoopInfo.h"<br>
@@ -126,6 +127,7 @@ namespace {<br>
   class LoopUnswitch : public LoopPass {<br>
     LoopInfo *LI;  // Loop information<br>
     LPPassManager *LPM;<br>
+    AssumptionTracker *AT;<br>
<br>
     // LoopProcessWorklist - Used to check if second loop needs processing<br>
     // after RewriteLoopBodyWithConditionConstant rewrites first loop.<br>
@@ -164,6 +166,7 @@ namespace {<br>
     /// loop preheaders be inserted into the CFG.<br>
     ///<br>
     void getAnalysisUsage(AnalysisUsage &AU) const override {<br>
+      AU.addRequired<AssumptionTracker>();<br>
       AU.addRequiredID(LoopSimplifyID);<br>
       AU.addPreservedID(LoopSimplifyID);<br>
       AU.addRequired<LoopInfo>();<br>
@@ -326,6 +329,7 @@ char LoopUnswitch::ID = 0;<br>
 INITIALIZE_PASS_BEGIN(LoopUnswitch, "loop-unswitch", "Unswitch loops",<br>
                       false, false)<br>
 INITIALIZE_AG_DEPENDENCY(TargetTransformInfo)<br>
+INITIALIZE_PASS_DEPENDENCY(AssumptionTracker)<br>
 INITIALIZE_PASS_DEPENDENCY(LoopSimplify)<br>
 INITIALIZE_PASS_DEPENDENCY(LoopInfo)<br>
 INITIALIZE_PASS_DEPENDENCY(LCSSA)<br>
@@ -376,6 +380,7 @@ bool LoopUnswitch::runOnLoop(Loop *L, LP<br>
   if (skipOptnoneFunction(L))<br>
     return false;<br>
<br>
+  AT = &getAnalysis<AssumptionTracker>();<br>
   LI = &getAnalysis<LoopInfo>();<br>
   LPM = &LPM_Ref;<br>
   DominatorTreeWrapperPass *DTWP =<br>
@@ -823,6 +828,10 @@ void LoopUnswitch::UnswitchNontrivialCon<br>
   F->getBasicBlockList().splice(NewPreheader, F->getBasicBlockList(),<br>
                                 NewBlocks[0], F->end());<br>
<br>
+  // FIXME: We could register any cloned assumptions instead of clearing the<br>
+  // whole function's cache.<br>
+  AT->forgetCachedAssumptions(F);<br>
+<br>
   // Now we create the new Loop object for the versioned loop.<br>
   Loop *NewLoop = CloneLoop(L, L->getParentLoop(), VMap, LI, LPM);<br>
<br>
<br>
Modified: llvm/trunk/lib/Transforms/Utils/InlineFunction.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Utils/InlineFunction.cpp?rev=217334&r1=217333&r2=217334&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Utils/InlineFunction.cpp?rev=217334&r1=217333&r2=217334&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/lib/Transforms/Utils/InlineFunction.cpp (original)<br>
+++ llvm/trunk/lib/Transforms/Utils/InlineFunction.cpp Sun Sep  7 07:44:26 2014<br>
@@ -18,6 +18,7 @@<br>
 #include "llvm/ADT/SetVector.h"<br>
 #include "llvm/ADT/StringExtras.h"<br>
 #include "llvm/Analysis/AliasAnalysis.h"<br>
+#include "llvm/Analysis/AssumptionTracker.h"<br>
 #include "llvm/Analysis/CallGraph.h"<br>
 #include "llvm/Analysis/CaptureTracking.h"<br>
 #include "llvm/Analysis/InstructionSimplify.h"<br>
@@ -982,6 +983,11 @@ bool llvm::InlineFunction(CallSite CS, I<br>
<br>
     // Add noalias metadata if necessary.<br>
     AddAliasScopeMetadata(CS, VMap, IFI.DL, IFI.AA);<br>
+<br>
+    // FIXME: We could register any cloned assumptions instead of clearing the<br>
+    // whole function's cache.<br>
+    if (<a href="http://IFI.AT" target="_blank">IFI.AT</a>)<br>
+      IFI.AT->forgetCachedAssumptions(Caller);<br>
   }<br>
<br>
   // If there are any alloca instructions in the block that used to be the entry<br>
<br>
Modified: llvm/trunk/lib/Transforms/Utils/LoopUnroll.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Utils/LoopUnroll.cpp?rev=217334&r1=217333&r2=217334&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Utils/LoopUnroll.cpp?rev=217334&r1=217333&r2=217334&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/lib/Transforms/Utils/LoopUnroll.cpp (original)<br>
+++ llvm/trunk/lib/Transforms/Utils/LoopUnroll.cpp Sun Sep  7 07:44:26 2014<br>
@@ -19,6 +19,7 @@<br>
 #include "llvm/Transforms/Utils/UnrollLoop.h"<br>
 #include "llvm/ADT/SmallPtrSet.h"<br>
 #include "llvm/ADT/Statistic.h"<br>
+#include "llvm/Analysis/AssumptionTracker.h"<br>
 #include "llvm/Analysis/InstructionSimplify.h"<br>
 #include "llvm/Analysis/LoopIterator.h"<br>
 #include "llvm/Analysis/LoopPass.h"<br>
@@ -154,7 +155,8 @@ FoldBlockIntoPredecessor(BasicBlock *BB,<br>
 /// available from the Pass it must also preserve those analyses.<br>
 bool llvm::UnrollLoop(Loop *L, unsigned Count, unsigned TripCount,<br>
                       bool AllowRuntime, unsigned TripMultiple,<br>
-                      LoopInfo *LI, Pass *PP, LPPassManager *LPM) {<br>
+                      LoopInfo *LI, Pass *PP, LPPassManager *LPM,<br>
+                      AssumptionTracker *AT) {<br>
   BasicBlock *Preheader = L->getLoopPreheader();<br>
   if (!Preheader) {<br>
     DEBUG(dbgs() << "  Can't unroll; loop preheader-insertion failed.\n");<br>
@@ -442,6 +444,10 @@ bool llvm::UnrollLoop(Loop *L, unsigned<br>
     }<br>
   }<br>
<br>
+  // FIXME: We could register any cloned assumptions instead of clearing the<br>
+  // whole function's cache.<br>
+  AT->forgetCachedAssumptions(F);<br>
+<br>
   DominatorTree *DT = nullptr;<br>
   if (PP) {<br>
     // FIXME: Reconstruct dom info, because it is not preserved properly.<br>
<br>
<br>
_______________________________________________<br>
llvm-commits mailing list<br>
<a href="mailto:llvm-commits@cs.uiuc.edu">llvm-commits@cs.uiuc.edu</a><br>
<a href="http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits" target="_blank">http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits</a><br>
</blockquote></div><br><br clear="all"><div><br></div>-- <br><div dir="ltr">Alexey Samsonov<br><a href="mailto:vonosmas@gmail.com" target="_blank">vonosmas@gmail.com</a></div>
</div></div>