<div class="gmail_quote">On 14 January 2011 16:12, Chris Lattner <span dir="ltr"><<a href="mailto:sabre@nondot.org">sabre@nondot.org</a>></span> wrote:<br><blockquote class="gmail_quote" style="border-left: 1px solid rgb(204, 204, 204); margin: 0pt 0pt 0pt 0.8ex; padding-left: 1ex;">

Author: lattner<br>
Date: Fri Jan 14 18:12:35 2011<br>
New Revision: 123501<br>
<br>
URL: <a href="http://llvm.org/viewvc/llvm-project?rev=123501&view=rev" target="_blank">http://llvm.org/viewvc/llvm-project?rev=123501&view=rev</a><br>
Log:<br>
Generalize LoadAndStorePromoter a bit and switch LICM<br>
to use it.<br>
<br>
Modified:<br>
    llvm/trunk/include/llvm/Transforms/Utils/SSAUpdater.h<br>
    llvm/trunk/lib/Transforms/Scalar/LICM.cpp<br>
    llvm/trunk/lib/Transforms/Scalar/ScalarReplAggregates.cpp<br>
    llvm/trunk/lib/Transforms/Utils/SSAUpdater.cpp<br>
<br>
Modified: llvm/trunk/include/llvm/Transforms/Utils/SSAUpdater.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Transforms/Utils/SSAUpdater.h?rev=123501&r1=123500&r2=123501&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Transforms/Utils/SSAUpdater.h?rev=123501&r1=123500&r2=123501&view=diff</a><br>


==============================================================================<br>
--- llvm/trunk/include/llvm/Transforms/Utils/SSAUpdater.h (original)<br>
+++ llvm/trunk/include/llvm/Transforms/Utils/SSAUpdater.h Fri Jan 14 18:12:35 2011<br>
@@ -118,15 +118,17 @@<br>
 /// virtual methods.<br>
 ///<br>
 class LoadAndStorePromoter {<br>
+protected:<br>
+  SSAUpdater &SSA;<br>
 public:<br>
-  LoadAndStorePromoter() {}<br>
+  LoadAndStorePromoter(const SmallVectorImpl<Instruction*> &Insts,<br>
+                       SSAUpdater &S, StringRef Name = StringRef());<br>
   virtual ~LoadAndStorePromoter() {}<br>
<br>
   /// run - This does the promotion.  Insts is a list of loads and stores to<br>
   /// promote, and Name is the basename for the PHIs to insert.  After this is<br>
   /// complete, the loads and stores are removed from the code.<br>
-  void run(StringRef Name, const SmallVectorImpl<Instruction*> &Insts,<br>
-           SSAUpdater *SSA = 0);<br>
+  void run(const SmallVectorImpl<Instruction*> &Insts) const;<br>
<br>
<br>
   /// Return true if the specified instruction is in the Inst list (which was<br>
@@ -139,6 +141,21 @@<br>
         return true;<br>
     return false;<br>
   }<br>
+<br>
+  /// doExtraRewritesBeforeFinalDeletion - This hook is invoked after all the<br>
+  /// stores are found and inserted as available values, but<br></blockquote><div><br>But what?<br><br>NIck<br> </div><blockquote class="gmail_quote" style="border-left: 1px solid rgb(204, 204, 204); margin: 0pt 0pt 0pt 0.8ex; padding-left: 1ex;">


+  virtual void doExtraRewritesBeforeFinalDeletion() const {<br>
+  }<br>
+<br>
+  /// replaceLoadWithValue - Clients can choose to implement this to get<br>
+  /// notified right before a load is RAUW'd another value.<br>
+  virtual void replaceLoadWithValue(LoadInst *LI, Value *V) const {<br>
+  }<br>
+<br>
+  /// This is called before each instruction is deleted.<br>
+  virtual void instructionDeleted(Instruction *I) const {<br>
+  }<br>
+<br>
 };<br>
<br>
 } // End llvm namespace<br>
<br>
Modified: llvm/trunk/lib/Transforms/Scalar/LICM.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Scalar/LICM.cpp?rev=123501&r1=123500&r2=123501&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Scalar/LICM.cpp?rev=123501&r1=123500&r2=123501&view=diff</a><br>


==============================================================================<br>
--- llvm/trunk/lib/Transforms/Scalar/LICM.cpp (original)<br>
+++ llvm/trunk/lib/Transforms/Scalar/LICM.cpp Fri Jan 14 18:12:35 2011<br>
@@ -595,6 +595,53 @@<br>
   return true;<br>
 }<br>
<br>
+namespace {<br>
+  class LoopPromoter : public LoadAndStorePromoter {<br>
+    Value *SomePtr;  // Designated pointer to store to.<br>
+    SmallPtrSet<Value*, 4> &PointerMustAliases;<br>
+    SmallVectorImpl<BasicBlock*> &LoopExitBlocks;<br>
+    AliasSetTracker &AST;<br>
+  public:<br>
+    LoopPromoter(Value *SP,<br>
+                 const SmallVectorImpl<Instruction*> &Insts, SSAUpdater &S,<br>
+                 SmallPtrSet<Value*, 4> &PMA,<br>
+                 SmallVectorImpl<BasicBlock*> &LEB, AliasSetTracker &ast)<br>
+      : LoadAndStorePromoter(Insts, S), SomePtr(SP), PointerMustAliases(PMA),<br>
+        LoopExitBlocks(LEB), AST(ast) {}<br>
+<br>
+    virtual bool isInstInList(Instruction *I,<br>
+                              const SmallVectorImpl<Instruction*> &) const {<br>
+      Value *Ptr;<br>
+      if (LoadInst *LI = dyn_cast<LoadInst>(I))<br>
+        Ptr = LI->getOperand(0);<br>
+      else<br>
+        Ptr = cast<StoreInst>(I)->getPointerOperand();<br>
+      return PointerMustAliases.count(Ptr);<br>
+    }<br>
+<br>
+    virtual void doExtraRewritesBeforeFinalDeletion() const {<br>
+      // Insert stores after in the loop exit blocks.  Each exit block gets a<br>
+      // store of the live-out values that feed them.  Since we've already told<br>
+      // the SSA updater about the defs in the loop and the preheader<br>
+      // definition, it is all set and we can start using it.<br>
+      for (unsigned i = 0, e = LoopExitBlocks.size(); i != e; ++i) {<br>
+        BasicBlock *ExitBlock = LoopExitBlocks[i];<br>
+        Value *LiveInValue = SSA.GetValueInMiddleOfBlock(ExitBlock);<br>
+        Instruction *InsertPos = ExitBlock->getFirstNonPHI();<br>
+        new StoreInst(LiveInValue, SomePtr, InsertPos);<br>
+      }<br>
+    }<br>
+<br>
+    virtual void replaceLoadWithValue(LoadInst *LI, Value *V) const {<br>
+      // Update alias analysis.<br>
+      AST.copyValue(LI, V);<br>
+    }<br>
+    virtual void instructionDeleted(Instruction *I) const {<br>
+      AST.deleteValue(I);<br>
+    }<br>
+  };<br>
+} // end anon namespace<br>
+<br>
 /// PromoteAliasSet - Try to promote memory values to scalars by sinking<br>
 /// stores out of the loop and moving loads to before the loop.  We do this by<br>
 /// looping over the stores in the loop, looking for stores to Must pointers<br>
@@ -679,179 +726,43 @@<br>
   Changed = true;<br>
   ++NumPromoted;<br>
<br>
+  SmallVector<BasicBlock*, 8> ExitBlocks;<br>
+  CurLoop->getUniqueExitBlocks(ExitBlocks);<br>
+<br>
   // We use the SSAUpdater interface to insert phi nodes as required.<br>
   SmallVector<PHINode*, 16> NewPHIs;<br>
   SSAUpdater SSA(&NewPHIs);<br>
+  LoopPromoter Promoter(SomePtr, LoopUses, SSA, PointerMustAliases, ExitBlocks,<br>
+                        *CurAST);<br>
<br>
-  // It wants to know some value of the same type as what we'll be inserting.<br>
-  Value *SomeValue;<br>
-  if (isa<LoadInst>(LoopUses[0]))<br>
-    SomeValue = LoopUses[0];<br>
-  else<br>
-    SomeValue = cast<StoreInst>(LoopUses[0])->getOperand(0);<br>
-  SSA.Initialize(SomeValue->getType(), SomeValue->getName());<br>
-<br>
-  // First step: bucket up uses of the pointers by the block they occur in.<br>
-  // This is important because we have to handle multiple defs/uses in a block<br>
-  // ourselves: SSAUpdater is purely for cross-block references.<br>
-  // FIXME: Want a TinyVector<Instruction*> since there is usually 0/1 element.<br>
-  DenseMap<BasicBlock*, std::vector<Instruction*> > UsesByBlock;<br>
-  for (unsigned i = 0, e = LoopUses.size(); i != e; ++i) {<br>
-    Instruction *User = LoopUses[i];<br>
-    UsesByBlock[User->getParent()].push_back(User);<br>
-  }<br>
-<br>
-  // Okay, now we can iterate over all the blocks in the loop with uses,<br>
-  // processing them.  Keep track of which loads are loading a live-in value.<br>
-  SmallVector<LoadInst*, 32> LiveInLoads;<br>
-  DenseMap<Value*, Value*> ReplacedLoads;<br>
-<br>
-  for (unsigned LoopUse = 0, e = LoopUses.size(); LoopUse != e; ++LoopUse) {<br>
-    Instruction *User = LoopUses[LoopUse];<br>
-    std::vector<Instruction*> &BlockUses = UsesByBlock[User->getParent()];<br>
-<br>
-    // If this block has already been processed, ignore this repeat use.<br>
-    if (BlockUses.empty()) continue;<br>
-<br>
-    // Okay, this is the first use in the block.  If this block just has a<br>
-    // single user in it, we can rewrite it trivially.<br>
-    if (BlockUses.size() == 1) {<br>
-      // If it is a store, it is a trivial def of the value in the block.<br>
-      if (isa<StoreInst>(User)) {<br>
-        SSA.AddAvailableValue(User->getParent(),<br>
-                              cast<StoreInst>(User)->getOperand(0));<br>
-      } else {<br>
-        // Otherwise it is a load, queue it to rewrite as a live-in load.<br>
-        LiveInLoads.push_back(cast<LoadInst>(User));<br>
-      }<br>
-      BlockUses.clear();<br>
-      continue;<br>
-    }<br>
-<br>
-    // Otherwise, check to see if this block is all loads.  If so, we can queue<br>
-    // them all as live in loads.<br>
-    bool HasStore = false;<br>
-    for (unsigned i = 0, e = BlockUses.size(); i != e; ++i) {<br>
-      if (isa<StoreInst>(BlockUses[i])) {<br>
-        HasStore = true;<br>
-        break;<br>
-      }<br>
-    }<br>
-<br>
-    if (!HasStore) {<br>
-      for (unsigned i = 0, e = BlockUses.size(); i != e; ++i)<br>
-        LiveInLoads.push_back(cast<LoadInst>(BlockUses[i]));<br>
-      BlockUses.clear();<br>
-      continue;<br>
-    }<br>
-<br>
-    // Otherwise, we have mixed loads and stores (or just a bunch of stores).<br>
-    // Since SSAUpdater is purely for cross-block values, we need to determine<br>
-    // the order of these instructions in the block.  If the first use in the<br>
-    // block is a load, then it uses the live in value.  The last store defines<br>
-    // the live out value.  We handle this by doing a linear scan of the block.<br>
-    BasicBlock *BB = User->getParent();<br>
-    Value *StoredValue = 0;<br>
-    for (BasicBlock::iterator II = BB->begin(), E = BB->end(); II != E; ++II) {<br>
-      if (LoadInst *L = dyn_cast<LoadInst>(II)) {<br>
-        // If this is a load from an unrelated pointer, ignore it.<br>
-        if (!PointerMustAliases.count(L->getOperand(0))) continue;<br>
-<br>
-        // If we haven't seen a store yet, this is a live in use, otherwise<br>
-        // use the stored value.<br>
-        if (StoredValue) {<br>
-          L->replaceAllUsesWith(StoredValue);<br>
-          ReplacedLoads[L] = StoredValue;<br>
-        } else {<br>
-          LiveInLoads.push_back(L);<br>
-        }<br>
-        continue;<br>
-      }<br>
-<br>
-      if (StoreInst *S = dyn_cast<StoreInst>(II)) {<br>
-        // If this is a store to an unrelated pointer, ignore it.<br>
-        if (!PointerMustAliases.count(S->getOperand(1))) continue;<br>
-<br>
-        // Remember that this is the active value in the block.<br>
-        StoredValue = S->getOperand(0);<br>
-      }<br>
-    }<br>
-<br>
-    // The last stored value that happened is the live-out for the block.<br>
-    assert(StoredValue && "Already checked that there is a store in block");<br>
-    SSA.AddAvailableValue(BB, StoredValue);<br>
-    BlockUses.clear();<br>
-  }<br>
-<br>
-  // Now that all the intra-loop values are classified, set up the preheader.<br>
-  // It gets a load of the pointer we're promoting, and it is the live-out value<br>
-  // from the preheader.<br>
-  LoadInst *PreheaderLoad = new LoadInst(SomePtr,SomePtr->getName()+".promoted",<br>
-                                         Preheader->getTerminator());<br>
+  // Set up the preheader to have a definition of the value.  It is the live-out<br>
+  // value from the preheader that uses in the loop will use.<br>
+  LoadInst *PreheaderLoad =<br>
+    new LoadInst(SomePtr, SomePtr->getName()+".promoted",<br>
+                 Preheader->getTerminator());<br>
   SSA.AddAvailableValue(Preheader, PreheaderLoad);<br>
<br>
-  // Now that the preheader is good to go, set up the exit blocks.  Each exit<br>
-  // block gets a store of the live-out values that feed them.  Since we've<br>
-  // already told the SSA updater about the defs in the loop and the preheader<br>
-  // definition, it is all set and we can start using it.<br>
-  SmallVector<BasicBlock*, 8> ExitBlocks;<br>
-  CurLoop->getUniqueExitBlocks(ExitBlocks);<br>
-  for (unsigned i = 0, e = ExitBlocks.size(); i != e; ++i) {<br>
-    BasicBlock *ExitBlock = ExitBlocks[i];<br>
-    Value *LiveInValue = SSA.GetValueInMiddleOfBlock(ExitBlock);<br>
-    Instruction *InsertPos = ExitBlock->getFirstNonPHI();<br>
-    new StoreInst(LiveInValue, SomePtr, InsertPos);<br>
+  // Copy any value stored to or loaded from a must-alias of the pointer.<br>
+  if (PreheaderLoad->getType()->isPointerTy()) {<br>
+    Value *SomeValue;<br>
+    if (LoadInst *LI = dyn_cast<LoadInst>(LoopUses[0]))<br>
+      SomeValue = LI;<br>
+    else<br>
+      SomeValue = cast<StoreInst>(LoopUses[0])->getValueOperand();<br>
+<br>
+    CurAST->copyValue(SomeValue, PreheaderLoad);<br>
   }<br>
<br>
-  // Okay, now we rewrite all loads that use live-in values in the loop,<br>
-  // inserting PHI nodes as necessary.<br>
-  for (unsigned i = 0, e = LiveInLoads.size(); i != e; ++i) {<br>
-    LoadInst *ALoad = LiveInLoads[i];<br>
-    Value *NewVal = SSA.GetValueInMiddleOfBlock(ALoad->getParent());<br>
-    ALoad->replaceAllUsesWith(NewVal);<br>
-    CurAST->copyValue(ALoad, NewVal);<br>
-    ReplacedLoads[ALoad] = NewVal;<br>
-  }<br>
+  // Rewrite all the loads in the loop and remember all the definitions from<br>
+  // stores in the loop.<br>
+  Promoter.run(LoopUses);<br>
<br>
   // If the preheader load is itself a pointer, we need to tell alias analysis<br>
   // about the new pointer we created in the preheader block and about any PHI<br>
   // nodes that just got inserted.<br>
   if (PreheaderLoad->getType()->isPointerTy()) {<br>
-    // Copy any value stored to or loaded from a must-alias of the pointer.<br>
-    CurAST->copyValue(SomeValue, PreheaderLoad);<br>
-<br>
     for (unsigned i = 0, e = NewPHIs.size(); i != e; ++i)<br>
-      CurAST->copyValue(SomeValue, NewPHIs[i]);<br>
-  }<br>
-<br>
-  // Now that everything is rewritten, delete the old instructions from the body<br>
-  // of the loop.  They should all be dead now.<br>
-  for (unsigned i = 0, e = LoopUses.size(); i != e; ++i) {<br>
-    Instruction *User = LoopUses[i];<br>
-<br>
-    // If this is a load that still has uses, then the load must have been added<br>
-    // as a live value in the SSAUpdate data structure for a block (e.g. because<br>
-    // the loaded value was stored later).  In this case, we need to recursively<br>
-    // propagate the updates until we get to the real value.<br>
-    if (!User->use_empty()) {<br>
-      Value *NewVal = ReplacedLoads[User];<br>
-      assert(NewVal && "not a replaced load?");<br>
-<br>
-      // Propagate down to the ultimate replacee.  The intermediately loads<br>
-      // could theoretically already have been deleted, so we don't want to<br>
-      // dereference the Value*'s.<br>
-      DenseMap<Value*, Value*>::iterator RLI = ReplacedLoads.find(NewVal);<br>
-      while (RLI != ReplacedLoads.end()) {<br>
-        NewVal = RLI->second;<br>
-        RLI = ReplacedLoads.find(NewVal);<br>
-      }<br>
-<br>
-      User->replaceAllUsesWith(NewVal);<br>
-      CurAST->copyValue(User, NewVal);<br>
-    }<br>
-<br>
-    CurAST->deleteValue(User);<br>
-    User->eraseFromParent();<br>
+      CurAST->copyValue(PreheaderLoad, NewPHIs[i]);<br>
   }<br>
<br>
   // fwew, we're done!<br>
<br>
Modified: llvm/trunk/lib/Transforms/Scalar/ScalarReplAggregates.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Scalar/ScalarReplAggregates.cpp?rev=123501&r1=123500&r2=123501&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Scalar/ScalarReplAggregates.cpp?rev=123501&r1=123500&r2=123501&view=diff</a><br>


==============================================================================<br>
--- llvm/trunk/lib/Transforms/Scalar/ScalarReplAggregates.cpp (original)<br>
+++ llvm/trunk/lib/Transforms/Scalar/ScalarReplAggregates.cpp Fri Jan 14 18:12:35 2011<br>
@@ -844,20 +844,13 @@<br>
 class AllocaPromoter : public LoadAndStorePromoter {<br>
   AllocaInst *AI;<br>
 public:<br>
-  AllocaPromoter() : AI(0) {}<br>
+  AllocaPromoter(const SmallVectorImpl<Instruction*> &Insts, SSAUpdater &S)<br>
+    : LoadAndStorePromoter(Insts, S), AI(0) {}<br>
<br>
-  void run(AllocaInst *AI, SSAUpdater &SSA) {<br>
+  void run(AllocaInst *AI, const SmallVectorImpl<Instruction*> &Insts) {<br>
     // Remember which alloca we're promoting (for isInstInList).<br>
     this->AI = AI;<br>
-<br>
-    // Build the list of instructions to promote.<br>
-    SmallVector<Instruction*, 64> Insts;<br>
-    for (Value::use_iterator UI = AI->use_begin(), E = AI->use_end();<br>
-         UI != E; ++UI)<br>
-      Insts.push_back(cast<Instruction>(*UI));<br>
-<br>
-    LoadAndStorePromoter::run(AI->getName(), Insts, &SSA);<br>
-<br>
+    LoadAndStorePromoter::run(Insts);<br>
     AI->eraseFromParent();<br>
   }<br>
<br>
@@ -882,7 +875,7 @@<br>
   BasicBlock &BB = F.getEntryBlock();  // Get the entry node for the function<br>
<br>
   bool Changed = false;<br>
-<br>
+  SmallVector<Instruction*, 64> Insts;<br>
   while (1) {<br>
     Allocas.clear();<br>
<br>
@@ -899,9 +892,17 @@<br>
       PromoteMemToReg(Allocas, *DT, *DF);<br>
     else {<br>
       SSAUpdater SSA;<br>
-      AllocaPromoter Promoter;<br>
-      for (unsigned i = 0, e = Allocas.size(); i != e; ++i)<br>
-        Promoter.run(Allocas[i], SSA);<br>
+      for (unsigned i = 0, e = Allocas.size(); i != e; ++i) {<br>
+        AllocaInst *AI = Allocas[i];<br>
+<br>
+        // Build list of instructions to promote.<br>
+        for (Value::use_iterator UI = AI->use_begin(), E = AI->use_end();<br>
+             UI != E; ++UI)<br>
+          Insts.push_back(cast<Instruction>(*UI));<br>
+<br>
+        AllocaPromoter(Insts, SSA).run(AI, Insts);<br>
+        Insts.clear();<br>
+      }<br>
     }<br>
     NumPromoted += Allocas.size();<br>
     Changed = true;<br>
<br>
Modified: llvm/trunk/lib/Transforms/Utils/SSAUpdater.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Utils/SSAUpdater.cpp?rev=123501&r1=123500&r2=123501&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Utils/SSAUpdater.cpp?rev=123501&r1=123500&r2=123501&view=diff</a><br>


==============================================================================<br>
--- llvm/trunk/lib/Transforms/Utils/SSAUpdater.cpp (original)<br>
+++ llvm/trunk/lib/Transforms/Utils/SSAUpdater.cpp Fri Jan 14 18:12:35 2011<br>
@@ -348,23 +348,25 @@<br>
 // LoadAndStorePromoter Implementation<br>
 //===----------------------------------------------------------------------===//<br>
<br>
-void LoadAndStorePromoter::run(StringRef BaseName,<br>
-                               const SmallVectorImpl<Instruction*> &Insts,<br>
-                               SSAUpdater *SSA) {<br>
+LoadAndStorePromoter::<br>
+LoadAndStorePromoter(const SmallVectorImpl<Instruction*> &Insts,<br>
+                     SSAUpdater &S, StringRef BaseName) : SSA(S) {<br>
   if (Insts.empty()) return;<br>
<br>
-  // If no SSAUpdater was provided, use a default one.  This allows the client<br>
-  // to capture inserted PHI nodes etc if they want.<br>
-  SSAUpdater DefaultSSA;<br>
-  if (SSA == 0) SSA = &DefaultSSA;<br>
-<br>
-  const Type *ValTy;<br>
+  Value *SomeVal;<br>
   if (LoadInst *LI = dyn_cast<LoadInst>(Insts[0]))<br>
-    ValTy = LI->getType();<br>
+    SomeVal = LI;<br>
   else<br>
-    ValTy = cast<StoreInst>(Insts[0])->getOperand(0)->getType();<br>
-<br>
-  SSA->Initialize(ValTy, BaseName);<br>
+    SomeVal = cast<StoreInst>(Insts[0])->getOperand(0);<br>
+<br>
+  if (BaseName.empty())<br>
+    BaseName = SomeVal->getName();<br>
+  SSA.Initialize(SomeVal->getType(), BaseName);<br>
+}<br>
+<br>
+<br>
+void LoadAndStorePromoter::<br>
+run(const SmallVectorImpl<Instruction*> &Insts) const {<br>
<br>
   // First step: bucket up uses of the alloca by the block they occur in.<br>
   // This is important because we have to handle multiple defs/uses in a block<br>
@@ -396,7 +398,7 @@<br>
     if (BlockUses.size() == 1) {<br>
       // If it is a store, it is a trivial def of the value in the block.<br>
       if (StoreInst *SI = dyn_cast<StoreInst>(User))<br>
-        SSA->AddAvailableValue(BB, SI->getOperand(0));<br>
+        SSA.AddAvailableValue(BB, SI->getOperand(0));<br>
       else<br>
         // Otherwise it is a load, queue it to rewrite as a live-in load.<br>
         LiveInLoads.push_back(cast<LoadInst>(User));<br>
@@ -437,6 +439,7 @@<br>
         // If we haven't seen a store yet, this is a live in use, otherwise<br>
         // use the stored value.<br>
         if (StoredValue) {<br>
+          replaceLoadWithValue(L, StoredValue);<br>
           L->replaceAllUsesWith(StoredValue);<br>
           ReplacedLoads[L] = StoredValue;<br>
         } else {<br>
@@ -456,7 +459,7 @@<br>
<br>
     // The last stored value that happened is the live-out for the block.<br>
     assert(StoredValue && "Already checked that there is a store in block");<br>
-    SSA->AddAvailableValue(BB, StoredValue);<br>
+    SSA.AddAvailableValue(BB, StoredValue);<br>
     BlockUses.clear();<br>
   }<br>
<br>
@@ -464,11 +467,15 @@<br>
   // inserting PHI nodes as necessary.<br>
   for (unsigned i = 0, e = LiveInLoads.size(); i != e; ++i) {<br>
     LoadInst *ALoad = LiveInLoads[i];<br>
-    Value *NewVal = SSA->GetValueInMiddleOfBlock(ALoad->getParent());<br>
+    Value *NewVal = SSA.GetValueInMiddleOfBlock(ALoad->getParent());<br>
+    replaceLoadWithValue(ALoad, NewVal);<br>
     ALoad->replaceAllUsesWith(NewVal);<br>
     ReplacedLoads[ALoad] = NewVal;<br>
   }<br>
<br>
+  // Allow the client to do stuff before we start nuking things.<br>
+  doExtraRewritesBeforeFinalDeletion();<br>
+<br>
   // Now that everything is rewritten, delete the old instructions from the<br>
   // function.  They should all be dead now.<br>
   for (unsigned i = 0, e = Insts.size(); i != e; ++i) {<br>
@@ -491,9 +498,11 @@<br>
         RLI = ReplacedLoads.find(NewVal);<br>
       }<br>
<br>
+      replaceLoadWithValue(cast<LoadInst>(User), NewVal);<br>
       User->replaceAllUsesWith(NewVal);<br>
     }<br>
<br>
+    instructionDeleted(User);<br>
     User->eraseFromParent();<br>
   }<br>
 }<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>