[llvm-commits] [llvm] r123501 - in /llvm/trunk: include/llvm/Transforms/Utils/SSAUpdater.h lib/Transforms/Scalar/LICM.cpp lib/Transforms/Scalar/ScalarReplAggregates.cpp lib/Transforms/Utils/SSAUpdater.cpp

Nick Lewycky nlewycky at google.com
Wed Jul 6 11:10:56 PDT 2011


On 14 January 2011 16:12, Chris Lattner <sabre at nondot.org> wrote:

> Author: lattner
> Date: Fri Jan 14 18:12:35 2011
> New Revision: 123501
>
> URL: http://llvm.org/viewvc/llvm-project?rev=123501&view=rev
> Log:
> Generalize LoadAndStorePromoter a bit and switch LICM
> to use it.
>
> Modified:
>    llvm/trunk/include/llvm/Transforms/Utils/SSAUpdater.h
>    llvm/trunk/lib/Transforms/Scalar/LICM.cpp
>    llvm/trunk/lib/Transforms/Scalar/ScalarReplAggregates.cpp
>    llvm/trunk/lib/Transforms/Utils/SSAUpdater.cpp
>
> Modified: llvm/trunk/include/llvm/Transforms/Utils/SSAUpdater.h
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Transforms/Utils/SSAUpdater.h?rev=123501&r1=123500&r2=123501&view=diff
>
> ==============================================================================
> --- llvm/trunk/include/llvm/Transforms/Utils/SSAUpdater.h (original)
> +++ llvm/trunk/include/llvm/Transforms/Utils/SSAUpdater.h Fri Jan 14
> 18:12:35 2011
> @@ -118,15 +118,17 @@
>  /// virtual methods.
>  ///
>  class LoadAndStorePromoter {
> +protected:
> +  SSAUpdater &SSA;
>  public:
> -  LoadAndStorePromoter() {}
> +  LoadAndStorePromoter(const SmallVectorImpl<Instruction*> &Insts,
> +                       SSAUpdater &S, StringRef Name = StringRef());
>   virtual ~LoadAndStorePromoter() {}
>
>   /// run - This does the promotion.  Insts is a list of loads and stores
> to
>   /// promote, and Name is the basename for the PHIs to insert.  After this
> is
>   /// complete, the loads and stores are removed from the code.
> -  void run(StringRef Name, const SmallVectorImpl<Instruction*> &Insts,
> -           SSAUpdater *SSA = 0);
> +  void run(const SmallVectorImpl<Instruction*> &Insts) const;
>
>
>   /// Return true if the specified instruction is in the Inst list (which
> was
> @@ -139,6 +141,21 @@
>         return true;
>     return false;
>   }
> +
> +  /// doExtraRewritesBeforeFinalDeletion - This hook is invoked after all
> the
> +  /// stores are found and inserted as available values, but
>

But what?

NIck


> +  virtual void doExtraRewritesBeforeFinalDeletion() const {
> +  }
> +
> +  /// replaceLoadWithValue - Clients can choose to implement this to get
> +  /// notified right before a load is RAUW'd another value.
> +  virtual void replaceLoadWithValue(LoadInst *LI, Value *V) const {
> +  }
> +
> +  /// This is called before each instruction is deleted.
> +  virtual void instructionDeleted(Instruction *I) const {
> +  }
> +
>  };
>
>  } // End llvm namespace
>
> Modified: llvm/trunk/lib/Transforms/Scalar/LICM.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Scalar/LICM.cpp?rev=123501&r1=123500&r2=123501&view=diff
>
> ==============================================================================
> --- llvm/trunk/lib/Transforms/Scalar/LICM.cpp (original)
> +++ llvm/trunk/lib/Transforms/Scalar/LICM.cpp Fri Jan 14 18:12:35 2011
> @@ -595,6 +595,53 @@
>   return true;
>  }
>
> +namespace {
> +  class LoopPromoter : public LoadAndStorePromoter {
> +    Value *SomePtr;  // Designated pointer to store to.
> +    SmallPtrSet<Value*, 4> &PointerMustAliases;
> +    SmallVectorImpl<BasicBlock*> &LoopExitBlocks;
> +    AliasSetTracker &AST;
> +  public:
> +    LoopPromoter(Value *SP,
> +                 const SmallVectorImpl<Instruction*> &Insts, SSAUpdater
> &S,
> +                 SmallPtrSet<Value*, 4> &PMA,
> +                 SmallVectorImpl<BasicBlock*> &LEB, AliasSetTracker &ast)
> +      : LoadAndStorePromoter(Insts, S), SomePtr(SP),
> PointerMustAliases(PMA),
> +        LoopExitBlocks(LEB), AST(ast) {}
> +
> +    virtual bool isInstInList(Instruction *I,
> +                              const SmallVectorImpl<Instruction*> &) const
> {
> +      Value *Ptr;
> +      if (LoadInst *LI = dyn_cast<LoadInst>(I))
> +        Ptr = LI->getOperand(0);
> +      else
> +        Ptr = cast<StoreInst>(I)->getPointerOperand();
> +      return PointerMustAliases.count(Ptr);
> +    }
> +
> +    virtual void doExtraRewritesBeforeFinalDeletion() const {
> +      // Insert stores after in the loop exit blocks.  Each exit block
> gets a
> +      // store of the live-out values that feed them.  Since we've already
> told
> +      // the SSA updater about the defs in the loop and the preheader
> +      // definition, it is all set and we can start using it.
> +      for (unsigned i = 0, e = LoopExitBlocks.size(); i != e; ++i) {
> +        BasicBlock *ExitBlock = LoopExitBlocks[i];
> +        Value *LiveInValue = SSA.GetValueInMiddleOfBlock(ExitBlock);
> +        Instruction *InsertPos = ExitBlock->getFirstNonPHI();
> +        new StoreInst(LiveInValue, SomePtr, InsertPos);
> +      }
> +    }
> +
> +    virtual void replaceLoadWithValue(LoadInst *LI, Value *V) const {
> +      // Update alias analysis.
> +      AST.copyValue(LI, V);
> +    }
> +    virtual void instructionDeleted(Instruction *I) const {
> +      AST.deleteValue(I);
> +    }
> +  };
> +} // end anon namespace
> +
>  /// PromoteAliasSet - Try to promote memory values to scalars by sinking
>  /// stores out of the loop and moving loads to before the loop.  We do
> this by
>  /// looping over the stores in the loop, looking for stores to Must
> pointers
> @@ -679,179 +726,43 @@
>   Changed = true;
>   ++NumPromoted;
>
> +  SmallVector<BasicBlock*, 8> ExitBlocks;
> +  CurLoop->getUniqueExitBlocks(ExitBlocks);
> +
>   // We use the SSAUpdater interface to insert phi nodes as required.
>   SmallVector<PHINode*, 16> NewPHIs;
>   SSAUpdater SSA(&NewPHIs);
> +  LoopPromoter Promoter(SomePtr, LoopUses, SSA, PointerMustAliases,
> ExitBlocks,
> +                        *CurAST);
>
> -  // It wants to know some value of the same type as what we'll be
> inserting.
> -  Value *SomeValue;
> -  if (isa<LoadInst>(LoopUses[0]))
> -    SomeValue = LoopUses[0];
> -  else
> -    SomeValue = cast<StoreInst>(LoopUses[0])->getOperand(0);
> -  SSA.Initialize(SomeValue->getType(), SomeValue->getName());
> -
> -  // First step: bucket up uses of the pointers by the block they occur
> in.
> -  // This is important because we have to handle multiple defs/uses in a
> block
> -  // ourselves: SSAUpdater is purely for cross-block references.
> -  // FIXME: Want a TinyVector<Instruction*> since there is usually 0/1
> element.
> -  DenseMap<BasicBlock*, std::vector<Instruction*> > UsesByBlock;
> -  for (unsigned i = 0, e = LoopUses.size(); i != e; ++i) {
> -    Instruction *User = LoopUses[i];
> -    UsesByBlock[User->getParent()].push_back(User);
> -  }
> -
> -  // Okay, now we can iterate over all the blocks in the loop with uses,
> -  // processing them.  Keep track of which loads are loading a live-in
> value.
> -  SmallVector<LoadInst*, 32> LiveInLoads;
> -  DenseMap<Value*, Value*> ReplacedLoads;
> -
> -  for (unsigned LoopUse = 0, e = LoopUses.size(); LoopUse != e; ++LoopUse)
> {
> -    Instruction *User = LoopUses[LoopUse];
> -    std::vector<Instruction*> &BlockUses = UsesByBlock[User->getParent()];
> -
> -    // If this block has already been processed, ignore this repeat use.
> -    if (BlockUses.empty()) continue;
> -
> -    // Okay, this is the first use in the block.  If this block just has a
> -    // single user in it, we can rewrite it trivially.
> -    if (BlockUses.size() == 1) {
> -      // If it is a store, it is a trivial def of the value in the block.
> -      if (isa<StoreInst>(User)) {
> -        SSA.AddAvailableValue(User->getParent(),
> -                              cast<StoreInst>(User)->getOperand(0));
> -      } else {
> -        // Otherwise it is a load, queue it to rewrite as a live-in load.
> -        LiveInLoads.push_back(cast<LoadInst>(User));
> -      }
> -      BlockUses.clear();
> -      continue;
> -    }
> -
> -    // Otherwise, check to see if this block is all loads.  If so, we can
> queue
> -    // them all as live in loads.
> -    bool HasStore = false;
> -    for (unsigned i = 0, e = BlockUses.size(); i != e; ++i) {
> -      if (isa<StoreInst>(BlockUses[i])) {
> -        HasStore = true;
> -        break;
> -      }
> -    }
> -
> -    if (!HasStore) {
> -      for (unsigned i = 0, e = BlockUses.size(); i != e; ++i)
> -        LiveInLoads.push_back(cast<LoadInst>(BlockUses[i]));
> -      BlockUses.clear();
> -      continue;
> -    }
> -
> -    // Otherwise, we have mixed loads and stores (or just a bunch of
> stores).
> -    // Since SSAUpdater is purely for cross-block values, we need to
> determine
> -    // the order of these instructions in the block.  If the first use in
> the
> -    // block is a load, then it uses the live in value.  The last store
> defines
> -    // the live out value.  We handle this by doing a linear scan of the
> block.
> -    BasicBlock *BB = User->getParent();
> -    Value *StoredValue = 0;
> -    for (BasicBlock::iterator II = BB->begin(), E = BB->end(); II != E;
> ++II) {
> -      if (LoadInst *L = dyn_cast<LoadInst>(II)) {
> -        // If this is a load from an unrelated pointer, ignore it.
> -        if (!PointerMustAliases.count(L->getOperand(0))) continue;
> -
> -        // If we haven't seen a store yet, this is a live in use,
> otherwise
> -        // use the stored value.
> -        if (StoredValue) {
> -          L->replaceAllUsesWith(StoredValue);
> -          ReplacedLoads[L] = StoredValue;
> -        } else {
> -          LiveInLoads.push_back(L);
> -        }
> -        continue;
> -      }
> -
> -      if (StoreInst *S = dyn_cast<StoreInst>(II)) {
> -        // If this is a store to an unrelated pointer, ignore it.
> -        if (!PointerMustAliases.count(S->getOperand(1))) continue;
> -
> -        // Remember that this is the active value in the block.
> -        StoredValue = S->getOperand(0);
> -      }
> -    }
> -
> -    // The last stored value that happened is the live-out for the block.
> -    assert(StoredValue && "Already checked that there is a store in
> block");
> -    SSA.AddAvailableValue(BB, StoredValue);
> -    BlockUses.clear();
> -  }
> -
> -  // Now that all the intra-loop values are classified, set up the
> preheader.
> -  // It gets a load of the pointer we're promoting, and it is the live-out
> value
> -  // from the preheader.
> -  LoadInst *PreheaderLoad = new
> LoadInst(SomePtr,SomePtr->getName()+".promoted",
> -                                         Preheader->getTerminator());
> +  // Set up the preheader to have a definition of the value.  It is the
> live-out
> +  // value from the preheader that uses in the loop will use.
> +  LoadInst *PreheaderLoad =
> +    new LoadInst(SomePtr, SomePtr->getName()+".promoted",
> +                 Preheader->getTerminator());
>   SSA.AddAvailableValue(Preheader, PreheaderLoad);
>
> -  // Now that the preheader is good to go, set up the exit blocks.  Each
> exit
> -  // block gets a store of the live-out values that feed them.  Since
> we've
> -  // already told the SSA updater about the defs in the loop and the
> preheader
> -  // definition, it is all set and we can start using it.
> -  SmallVector<BasicBlock*, 8> ExitBlocks;
> -  CurLoop->getUniqueExitBlocks(ExitBlocks);
> -  for (unsigned i = 0, e = ExitBlocks.size(); i != e; ++i) {
> -    BasicBlock *ExitBlock = ExitBlocks[i];
> -    Value *LiveInValue = SSA.GetValueInMiddleOfBlock(ExitBlock);
> -    Instruction *InsertPos = ExitBlock->getFirstNonPHI();
> -    new StoreInst(LiveInValue, SomePtr, InsertPos);
> +  // Copy any value stored to or loaded from a must-alias of the pointer.
> +  if (PreheaderLoad->getType()->isPointerTy()) {
> +    Value *SomeValue;
> +    if (LoadInst *LI = dyn_cast<LoadInst>(LoopUses[0]))
> +      SomeValue = LI;
> +    else
> +      SomeValue = cast<StoreInst>(LoopUses[0])->getValueOperand();
> +
> +    CurAST->copyValue(SomeValue, PreheaderLoad);
>   }
>
> -  // Okay, now we rewrite all loads that use live-in values in the loop,
> -  // inserting PHI nodes as necessary.
> -  for (unsigned i = 0, e = LiveInLoads.size(); i != e; ++i) {
> -    LoadInst *ALoad = LiveInLoads[i];
> -    Value *NewVal = SSA.GetValueInMiddleOfBlock(ALoad->getParent());
> -    ALoad->replaceAllUsesWith(NewVal);
> -    CurAST->copyValue(ALoad, NewVal);
> -    ReplacedLoads[ALoad] = NewVal;
> -  }
> +  // Rewrite all the loads in the loop and remember all the definitions
> from
> +  // stores in the loop.
> +  Promoter.run(LoopUses);
>
>   // If the preheader load is itself a pointer, we need to tell alias
> analysis
>   // about the new pointer we created in the preheader block and about any
> PHI
>   // nodes that just got inserted.
>   if (PreheaderLoad->getType()->isPointerTy()) {
> -    // Copy any value stored to or loaded from a must-alias of the
> pointer.
> -    CurAST->copyValue(SomeValue, PreheaderLoad);
> -
>     for (unsigned i = 0, e = NewPHIs.size(); i != e; ++i)
> -      CurAST->copyValue(SomeValue, NewPHIs[i]);
> -  }
> -
> -  // Now that everything is rewritten, delete the old instructions from
> the body
> -  // of the loop.  They should all be dead now.
> -  for (unsigned i = 0, e = LoopUses.size(); i != e; ++i) {
> -    Instruction *User = LoopUses[i];
> -
> -    // If this is a load that still has uses, then the load must have been
> added
> -    // as a live value in the SSAUpdate data structure for a block (e.g.
> because
> -    // the loaded value was stored later).  In this case, we need to
> recursively
> -    // propagate the updates until we get to the real value.
> -    if (!User->use_empty()) {
> -      Value *NewVal = ReplacedLoads[User];
> -      assert(NewVal && "not a replaced load?");
> -
> -      // Propagate down to the ultimate replacee.  The intermediately
> loads
> -      // could theoretically already have been deleted, so we don't want
> to
> -      // dereference the Value*'s.
> -      DenseMap<Value*, Value*>::iterator RLI = ReplacedLoads.find(NewVal);
> -      while (RLI != ReplacedLoads.end()) {
> -        NewVal = RLI->second;
> -        RLI = ReplacedLoads.find(NewVal);
> -      }
> -
> -      User->replaceAllUsesWith(NewVal);
> -      CurAST->copyValue(User, NewVal);
> -    }
> -
> -    CurAST->deleteValue(User);
> -    User->eraseFromParent();
> +      CurAST->copyValue(PreheaderLoad, NewPHIs[i]);
>   }
>
>   // fwew, we're done!
>
> Modified: llvm/trunk/lib/Transforms/Scalar/ScalarReplAggregates.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Scalar/ScalarReplAggregates.cpp?rev=123501&r1=123500&r2=123501&view=diff
>
> ==============================================================================
> --- llvm/trunk/lib/Transforms/Scalar/ScalarReplAggregates.cpp (original)
> +++ llvm/trunk/lib/Transforms/Scalar/ScalarReplAggregates.cpp Fri Jan 14
> 18:12:35 2011
> @@ -844,20 +844,13 @@
>  class AllocaPromoter : public LoadAndStorePromoter {
>   AllocaInst *AI;
>  public:
> -  AllocaPromoter() : AI(0) {}
> +  AllocaPromoter(const SmallVectorImpl<Instruction*> &Insts, SSAUpdater
> &S)
> +    : LoadAndStorePromoter(Insts, S), AI(0) {}
>
> -  void run(AllocaInst *AI, SSAUpdater &SSA) {
> +  void run(AllocaInst *AI, const SmallVectorImpl<Instruction*> &Insts) {
>     // Remember which alloca we're promoting (for isInstInList).
>     this->AI = AI;
> -
> -    // Build the list of instructions to promote.
> -    SmallVector<Instruction*, 64> Insts;
> -    for (Value::use_iterator UI = AI->use_begin(), E = AI->use_end();
> -         UI != E; ++UI)
> -      Insts.push_back(cast<Instruction>(*UI));
> -
> -    LoadAndStorePromoter::run(AI->getName(), Insts, &SSA);
> -
> +    LoadAndStorePromoter::run(Insts);
>     AI->eraseFromParent();
>   }
>
> @@ -882,7 +875,7 @@
>   BasicBlock &BB = F.getEntryBlock();  // Get the entry node for the
> function
>
>   bool Changed = false;
> -
> +  SmallVector<Instruction*, 64> Insts;
>   while (1) {
>     Allocas.clear();
>
> @@ -899,9 +892,17 @@
>       PromoteMemToReg(Allocas, *DT, *DF);
>     else {
>       SSAUpdater SSA;
> -      AllocaPromoter Promoter;
> -      for (unsigned i = 0, e = Allocas.size(); i != e; ++i)
> -        Promoter.run(Allocas[i], SSA);
> +      for (unsigned i = 0, e = Allocas.size(); i != e; ++i) {
> +        AllocaInst *AI = Allocas[i];
> +
> +        // Build list of instructions to promote.
> +        for (Value::use_iterator UI = AI->use_begin(), E = AI->use_end();
> +             UI != E; ++UI)
> +          Insts.push_back(cast<Instruction>(*UI));
> +
> +        AllocaPromoter(Insts, SSA).run(AI, Insts);
> +        Insts.clear();
> +      }
>     }
>     NumPromoted += Allocas.size();
>     Changed = true;
>
> Modified: llvm/trunk/lib/Transforms/Utils/SSAUpdater.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Utils/SSAUpdater.cpp?rev=123501&r1=123500&r2=123501&view=diff
>
> ==============================================================================
> --- llvm/trunk/lib/Transforms/Utils/SSAUpdater.cpp (original)
> +++ llvm/trunk/lib/Transforms/Utils/SSAUpdater.cpp Fri Jan 14 18:12:35 2011
> @@ -348,23 +348,25 @@
>  // LoadAndStorePromoter Implementation
>
>  //===----------------------------------------------------------------------===//
>
> -void LoadAndStorePromoter::run(StringRef BaseName,
> -                               const SmallVectorImpl<Instruction*> &Insts,
> -                               SSAUpdater *SSA) {
> +LoadAndStorePromoter::
> +LoadAndStorePromoter(const SmallVectorImpl<Instruction*> &Insts,
> +                     SSAUpdater &S, StringRef BaseName) : SSA(S) {
>   if (Insts.empty()) return;
>
> -  // If no SSAUpdater was provided, use a default one.  This allows the
> client
> -  // to capture inserted PHI nodes etc if they want.
> -  SSAUpdater DefaultSSA;
> -  if (SSA == 0) SSA = &DefaultSSA;
> -
> -  const Type *ValTy;
> +  Value *SomeVal;
>   if (LoadInst *LI = dyn_cast<LoadInst>(Insts[0]))
> -    ValTy = LI->getType();
> +    SomeVal = LI;
>   else
> -    ValTy = cast<StoreInst>(Insts[0])->getOperand(0)->getType();
> -
> -  SSA->Initialize(ValTy, BaseName);
> +    SomeVal = cast<StoreInst>(Insts[0])->getOperand(0);
> +
> +  if (BaseName.empty())
> +    BaseName = SomeVal->getName();
> +  SSA.Initialize(SomeVal->getType(), BaseName);
> +}
> +
> +
> +void LoadAndStorePromoter::
> +run(const SmallVectorImpl<Instruction*> &Insts) const {
>
>   // First step: bucket up uses of the alloca by the block they occur in.
>   // This is important because we have to handle multiple defs/uses in a
> block
> @@ -396,7 +398,7 @@
>     if (BlockUses.size() == 1) {
>       // If it is a store, it is a trivial def of the value in the block.
>       if (StoreInst *SI = dyn_cast<StoreInst>(User))
> -        SSA->AddAvailableValue(BB, SI->getOperand(0));
> +        SSA.AddAvailableValue(BB, SI->getOperand(0));
>       else
>         // Otherwise it is a load, queue it to rewrite as a live-in load.
>         LiveInLoads.push_back(cast<LoadInst>(User));
> @@ -437,6 +439,7 @@
>         // If we haven't seen a store yet, this is a live in use, otherwise
>         // use the stored value.
>         if (StoredValue) {
> +          replaceLoadWithValue(L, StoredValue);
>           L->replaceAllUsesWith(StoredValue);
>           ReplacedLoads[L] = StoredValue;
>         } else {
> @@ -456,7 +459,7 @@
>
>     // The last stored value that happened is the live-out for the block.
>     assert(StoredValue && "Already checked that there is a store in
> block");
> -    SSA->AddAvailableValue(BB, StoredValue);
> +    SSA.AddAvailableValue(BB, StoredValue);
>     BlockUses.clear();
>   }
>
> @@ -464,11 +467,15 @@
>   // inserting PHI nodes as necessary.
>   for (unsigned i = 0, e = LiveInLoads.size(); i != e; ++i) {
>     LoadInst *ALoad = LiveInLoads[i];
> -    Value *NewVal = SSA->GetValueInMiddleOfBlock(ALoad->getParent());
> +    Value *NewVal = SSA.GetValueInMiddleOfBlock(ALoad->getParent());
> +    replaceLoadWithValue(ALoad, NewVal);
>     ALoad->replaceAllUsesWith(NewVal);
>     ReplacedLoads[ALoad] = NewVal;
>   }
>
> +  // Allow the client to do stuff before we start nuking things.
> +  doExtraRewritesBeforeFinalDeletion();
> +
>   // Now that everything is rewritten, delete the old instructions from the
>   // function.  They should all be dead now.
>   for (unsigned i = 0, e = Insts.size(); i != e; ++i) {
> @@ -491,9 +498,11 @@
>         RLI = ReplacedLoads.find(NewVal);
>       }
>
> +      replaceLoadWithValue(cast<LoadInst>(User), NewVal);
>       User->replaceAllUsesWith(NewVal);
>     }
>
> +    instructionDeleted(User);
>     User->eraseFromParent();
>   }
>  }
>
>
> _______________________________________________
> llvm-commits mailing list
> llvm-commits at cs.uiuc.edu
> http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20110706/53769586/attachment.html>


More information about the llvm-commits mailing list