[llvm] r200067 - [LPM] Make LCSSA a utility with a FunctionPass that applies it to all

Bruno Cardoso Lopes bruno.cardoso at gmail.com
Thu Dec 11 12:07:23 PST 2014


Hi Chandler,

Sorry for the commit necromancy,

On Sat, Jan 25, 2014 at 2:07 AM, Chandler Carruth <chandlerc at gmail.com> wrote:
> Author: chandlerc
> Date: Fri Jan 24 22:07:24 2014
> New Revision: 200067
>
> URL: http://llvm.org/viewvc/llvm-project?rev=200067&view=rev
> Log:
> [LPM] Make LCSSA a utility with a FunctionPass that applies it to all
> the loops in a function, and teach LICM to work in the presance of
> LCSSA.
>
> Previously, LCSSA was a loop pass. That made passes requiring it also be
> loop passes and unable to depend on function analysis passes easily. It
> also caused outer loops to have a different "canonical" form from inner
> loops during analysis. Instead, we go into LCSSA form and preserve it
> through the loop pass manager run.
>
> Note that this has the same problem as LoopSimplify that prevents
> enabling its verification -- loop passes which run at the end of the loop
> pass manager and don't preserve these are valid, but the subsequent loop
> pass runs of outer loops that do preserve this pass trigger too much
> verification and fail because the inner loop no longer verifies.
>
> The other problem this exposed is that LICM was completely unable to
> handle LCSSA form. It didn't preserve it and it actually would give up
> on moving instructions in many cases when they were used by an LCSSA phi
> node. I've taught LICM to support detecting LCSSA-form PHI nodes and to
> hoist and sink around them. This may actually let LICM fire
> significantly more because we put everything into LCSSA form to rotate
> the loop before running LICM. =/ Now LICM should handle that fine and
> preserve it correctly. The down side is that LICM has to require LCSSA
> in order to preserve it. This is just a fact of life for LCSSA. It's
> entirely possible we should completely remove LCSSA from the optimizer.
>
> The test updates are essentially accomodating LCSSA phi nodes in the
> output of LICM, and the fact that we now completely sink every
> instruction in ashr-crash below the loop bodies prior to unrolling.
>
> With this change, LCSSA is computed only three times in the pass
> pipeline. One of them could be removed (and potentially a SCEV run and
> a separate LoopPassManager entirely!) if we had a LoopPass variant of
> InstCombine that ran InstCombine on the loop body but refused to combine
> away LCSSA PHI nodes. Currently, this also prevents loop unrolling from
> being in the same loop pass manager is rotate, LICM, and unswitch.
>
> There is one thing that I *really* don't like -- preserving LCSSA in
> LICM is quite expensive. We end up having to re-run LCSSA twice for some
> loops after LICM runs because LICM can undo LCSSA both in the current
> loop and the parent loop. I don't really see good solutions to this
> other than to completely move away from LCSSA and using tools like
> SSAUpdater instead.
>
> Modified:
>     llvm/trunk/include/llvm/Transforms/Utils/LoopUtils.h
>     llvm/trunk/lib/Transforms/Scalar/LICM.cpp
>     llvm/trunk/lib/Transforms/Utils/LCSSA.cpp
>     llvm/trunk/test/Transforms/LICM/scalar_promote.ll
>     llvm/trunk/test/Transforms/LICM/sinking.ll
>     llvm/trunk/test/Transforms/LoopSimplify/ashr-crash.ll
>
> Modified: llvm/trunk/include/llvm/Transforms/Utils/LoopUtils.h
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Transforms/Utils/LoopUtils.h?rev=200067&r1=200066&r2=200067&view=diff
> ==============================================================================
> --- llvm/trunk/include/llvm/Transforms/Utils/LoopUtils.h (original)
> +++ llvm/trunk/include/llvm/Transforms/Utils/LoopUtils.h Fri Jan 24 22:07:24 2014
> @@ -34,6 +34,19 @@ BasicBlock *InsertPreheaderForLoop(Loop
>  bool simplifyLoop(Loop *L, DominatorTree *DT, LoopInfo *LI, Pass *PP,
>                    AliasAnalysis *AA = 0, ScalarEvolution *SE = 0);
>
> +/// \brief Put loop into LCSSA form.
> +///
> +/// Looks at all instructions in the loop which have uses outside of the
> +/// current loop. For each, an LCSSA PHI node is inserted and the uses outside
> +/// the loop are rewritten to use this node.
> +///
> +/// LoopInfo and DominatorTree are required and preserved.
> +///
> +/// If ScalarEvolution is passed in, it will be preserved.
> +///
> +/// Returns true if any modifications are made to the loop.
> +bool formLCSSA(Loop &L, DominatorTree &DT, ScalarEvolution *SE = 0);
> +
>  }
>
>  #endif
>
> Modified: llvm/trunk/lib/Transforms/Scalar/LICM.cpp
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Scalar/LICM.cpp?rev=200067&r1=200066&r2=200067&view=diff
> ==============================================================================
> --- llvm/trunk/lib/Transforms/Scalar/LICM.cpp (original)
> +++ llvm/trunk/lib/Transforms/Scalar/LICM.cpp Fri Jan 24 22:07:24 2014
> @@ -54,6 +54,7 @@
>  #include "llvm/Support/raw_ostream.h"
>  #include "llvm/Target/TargetLibraryInfo.h"
>  #include "llvm/Transforms/Utils/Local.h"
> +#include "llvm/Transforms/Utils/LoopUtils.h"
>  #include "llvm/Transforms/Utils/SSAUpdater.h"
>  #include <algorithm>
>  using namespace llvm;
> @@ -85,10 +86,12 @@ namespace {
>        AU.addRequired<DominatorTreeWrapperPass>();
>        AU.addRequired<LoopInfo>();
>        AU.addRequiredID(LoopSimplifyID);
> +      AU.addPreservedID(LoopSimplifyID);
> +      AU.addRequiredID(LCSSAID);
> +      AU.addPreservedID(LCSSAID);
>        AU.addRequired<AliasAnalysis>();
>        AU.addPreserved<AliasAnalysis>();
>        AU.addPreserved<ScalarEvolution>();
> -      AU.addPreservedID(LoopSimplifyID);
>        AU.addRequired<TargetLibraryInfo>();
>      }
>
> @@ -193,6 +196,8 @@ INITIALIZE_PASS_BEGIN(LICM, "licm", "Loo
>  INITIALIZE_PASS_DEPENDENCY(DominatorTreeWrapperPass)
>  INITIALIZE_PASS_DEPENDENCY(LoopInfo)
>  INITIALIZE_PASS_DEPENDENCY(LoopSimplify)
> +INITIALIZE_PASS_DEPENDENCY(LCSSA)
> +INITIALIZE_PASS_DEPENDENCY(ScalarEvolution)
>  INITIALIZE_PASS_DEPENDENCY(TargetLibraryInfo)
>  INITIALIZE_AG_DEPENDENCY(AliasAnalysis)
>  INITIALIZE_PASS_END(LICM, "licm", "Loop Invariant Code Motion", false, false)
> @@ -283,6 +288,14 @@ bool LICM::runOnLoop(Loop *L, LPPassMana
>        PromoteAliasSet(*I, ExitBlocks, InsertPts);
>    }
>
> +  // If we have successfully changed the loop, re-form LCSSA and also re-form
> +  // LCSSA in the parent loop as hoisting or sinking may have broken it.
> +  if (Changed) {
> +    formLCSSA(*L, *DT, getAnalysisIfAvailable<ScalarEvolution>());
> +    if (Loop *ParentL = L->getParentLoop())
> +      formLCSSA(*ParentL, *DT, getAnalysisIfAvailable<ScalarEvolution>());
> +  }
> +
>    // Clear out loops state information for the next iteration
>    CurLoop = 0;
>    Preheader = 0;
> @@ -451,6 +464,19 @@ bool LICM::canSinkOrHoistInst(Instructio
>    return isSafeToExecuteUnconditionally(I);
>  }
>
> +/// \brief Returns true if a PHINode is a trivially replaceable with an
> +/// Instruction.
> +///
> +/// This is true when all incoming values are that instruction. This pattern
> +/// occurs most often with LCSSA PHI nodes.
> +static bool isTriviallyReplacablePHI(PHINode &PN, Instruction &I) {
> +  for (unsigned i = 0, e = PN.getNumIncomingValues(); i != e; ++i)
> +    if (PN.getIncomingValue(i) != &I)
> +      return false;
> +
> +  return true;
> +}
> +
>  /// isNotUsedInLoop - Return true if the only users of this instruction are
>  /// outside of the loop.  If this is true, we can sink the instruction to the
>  /// exit blocks of the loop.
> @@ -459,18 +485,48 @@ bool LICM::isNotUsedInLoop(Instruction &
>    for (Value::use_iterator UI = I.use_begin(), E = I.use_end(); UI != E; ++UI) {
>      Instruction *User = cast<Instruction>(*UI);
>      if (PHINode *PN = dyn_cast<PHINode>(User)) {
> -      // PHI node uses occur in predecessor blocks!
> +      // A PHI node where all of the incoming values are this instruction are
> +      // special -- they can just be RAUW'ed with the instruction and thus
> +      // don't require a use in the predecessor. This is a particular important
> +      // special case because it is the pattern found in LCSSA form.
> +      if (isTriviallyReplacablePHI(*PN, I)) {
> +        if (CurLoop->contains(PN))
> +          return false;
> +        else
> +          continue;
> +      }
> +
> +      // Otherwise, PHI node uses occur in predecessor blocks if the incoming
> +      // values. Check for such a use being inside the loop.
>        for (unsigned i = 0, e = PN->getNumIncomingValues(); i != e; ++i)
>          if (PN->getIncomingValue(i) == &I)
>            if (CurLoop->contains(PN->getIncomingBlock(i)))
>              return false;
> -    } else if (CurLoop->contains(User)) {
> -      return false;
> +
> +      continue;
>      }
> +
> +    if (CurLoop->contains(User))
> +      return false;
>    }
>    return true;
>  }
>
> +static BasicBlock::iterator
> +replaceTrivialPHIsAndGetInsertionPt(BasicBlock &BB, Instruction &I) {
> +  BasicBlock::iterator II = BB.begin();
> +  while (PHINode *PN = dyn_cast<PHINode>(II)) {
> +    ++II;
> +    if (isTriviallyReplacablePHI(*PN, I)) {
> +      PN->replaceAllUsesWith(&I);
> +      PN->eraseFromParent();
> +    }
> +  }
> +  if (isa<LandingPadInst>(II))
> +    ++II;
> +
> +  return II;
> +}
>
>  /// sink - When an instruction is found to only be used outside of the loop,
>  /// this function moves it to the exit blocks and patches up SSA form as needed.
> @@ -502,9 +558,14 @@ void LICM::sink(Instruction &I) {
>          I.replaceAllUsesWith(UndefValue::get(I.getType()));
>        I.eraseFromParent();
>      } else {
> +      // Look for any LCSSA PHI nodes for this instruction in the exit blocks
> +      // and replace them.
> +      BasicBlock::iterator II =
> +          replaceTrivialPHIsAndGetInsertionPt(*ExitBlocks[0], I);
> +
>        // Move the instruction to the start of the exit block, after any PHI
>        // nodes in it.
> -      I.moveBefore(ExitBlocks[0]->getFirstInsertionPt());
> +      I.moveBefore(II);
>
>        // This instruction is no longer in the AST for the current loop, because
>        // we just sunk it out of the loop.  If we just sunk it into an outer
> @@ -546,8 +607,10 @@ void LICM::sink(Instruction &I) {
>      if (!DT->dominates(InstOrigBB, ExitBlock))
>        continue;
>
> -    // Insert the code after the last PHI node.
> -    BasicBlock::iterator InsertPt = ExitBlock->getFirstInsertionPt();
> +    // Look for any LCSSA PHI nodes for this instruction in the exit blocks
> +    // and replace them. Then get the insertion point after the last PHI.
> +    BasicBlock::iterator InsertPt =
> +      replaceTrivialPHIsAndGetInsertionPt(*ExitBlock, I);
>
>      // If this is the first exit block processed, just move the original
>      // instruction, otherwise clone the original instruction and insert
>
> Modified: llvm/trunk/lib/Transforms/Utils/LCSSA.cpp
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Utils/LCSSA.cpp?rev=200067&r1=200066&r2=200067&view=diff
> ==============================================================================
> --- llvm/trunk/lib/Transforms/Utils/LCSSA.cpp (original)
> +++ llvm/trunk/lib/Transforms/Utils/LCSSA.cpp Fri Jan 24 22:07:24 2014
> @@ -39,208 +39,95 @@
>  #include "llvm/IR/Instructions.h"
>  #include "llvm/Pass.h"
>  #include "llvm/Support/PredIteratorCache.h"
> +#include "llvm/Transforms/Utils/LoopUtils.h"
>  #include "llvm/Transforms/Utils/SSAUpdater.h"
>  using namespace llvm;
>
>  STATISTIC(NumLCSSA, "Number of live out of a loop variables");
>
> -namespace {
> -  struct LCSSA : public LoopPass {
> -    static char ID; // Pass identification, replacement for typeid
> -    LCSSA() : LoopPass(ID) {
> -      initializeLCSSAPass(*PassRegistry::getPassRegistry());
> -    }
> -
> -    // Cached analysis information for the current function.
> -    DominatorTree *DT;
> -    LoopInfo *LI;
> -    ScalarEvolution *SE;
> -    PredIteratorCache PredCache;
> -    Loop *L;
> -
> -    virtual bool runOnLoop(Loop *L, LPPassManager &LPM);
> -
> -    /// This transformation requires natural loop information & requires that
> -    /// loop preheaders be inserted into the CFG.  It maintains both of these,
> -    /// as well as the CFG.  It also requires dominator information.
> -    ///
> -    virtual void getAnalysisUsage(AnalysisUsage &AU) const {
> -      AU.setPreservesCFG();
> -
> -      AU.addRequired<DominatorTreeWrapperPass>();
> -      AU.addRequired<LoopInfo>();
> -      AU.addPreservedID(LoopSimplifyID);
> -      AU.addPreserved<ScalarEvolution>();
> -    }
> -  private:
> -    bool ProcessInstruction(Instruction *Inst,
> -                            const SmallVectorImpl<BasicBlock*> &ExitBlocks);
> -
> -    /// verifyAnalysis() - Verify loop nest.
> -    virtual void verifyAnalysis() const {
> -      // Check the special guarantees that LCSSA makes.
> -      assert(L->isLCSSAForm(*DT) && "LCSSA form not preserved!");
> -    }
> -  };
> -}
> -
> -char LCSSA::ID = 0;
> -INITIALIZE_PASS_BEGIN(LCSSA, "lcssa", "Loop-Closed SSA Form Pass", false, false)
> -INITIALIZE_PASS_DEPENDENCY(DominatorTreeWrapperPass)
> -INITIALIZE_PASS_DEPENDENCY(LoopInfo)
> -INITIALIZE_PASS_END(LCSSA, "lcssa", "Loop-Closed SSA Form Pass", false, false)
> -
> -Pass *llvm::createLCSSAPass() { return new LCSSA(); }
> -char &llvm::LCSSAID = LCSSA::ID;
> -
> -
> -/// BlockDominatesAnExit - Return true if the specified block dominates at least
> -/// one of the blocks in the specified list.
> -static bool BlockDominatesAnExit(BasicBlock *BB,
> -                                 const SmallVectorImpl<BasicBlock*> &ExitBlocks,
> -                                 DominatorTree *DT) {
> -  DomTreeNode *DomNode = DT->getNode(BB);
> -  for (unsigned i = 0, e = ExitBlocks.size(); i != e; ++i)
> -    if (DT->dominates(DomNode, DT->getNode(ExitBlocks[i])))
> -      return true;
> -
> -  return false;
> -}
> -
> -
> -/// runOnFunction - Process all loops in the function, inner-most out.
> -bool LCSSA::runOnLoop(Loop *TheLoop, LPPassManager &LPM) {
> -  L = TheLoop;
> -
> -  DT = &getAnalysis<DominatorTreeWrapperPass>().getDomTree();
> -  LI = &getAnalysis<LoopInfo>();
> -  SE = getAnalysisIfAvailable<ScalarEvolution>();
> -
> -  // Get the set of exiting blocks.
> -  SmallVector<BasicBlock*, 8> ExitBlocks;
> -  L->getExitBlocks(ExitBlocks);
> -
> -  if (ExitBlocks.empty())
> -    return false;
> -
> -  // Look at all the instructions in the loop, checking to see if they have uses
> -  // outside the loop.  If so, rewrite those uses.
> -  bool MadeChange = false;
> -
> -  for (Loop::block_iterator BBI = L->block_begin(), E = L->block_end();
> -       BBI != E; ++BBI) {
> -    BasicBlock *BB = *BBI;
> -
> -    // For large loops, avoid use-scanning by using dominance information:  In
> -    // particular, if a block does not dominate any of the loop exits, then none
> -    // of the values defined in the block could be used outside the loop.
> -    if (!BlockDominatesAnExit(BB, ExitBlocks, DT))
> -      continue;
> -
> -    for (BasicBlock::iterator I = BB->begin(), E = BB->end();
> -         I != E; ++I) {
> -      // Reject two common cases fast: instructions with no uses (like stores)
> -      // and instructions with one use that is in the same block as this.
> -      if (I->use_empty() ||
> -          (I->hasOneUse() && I->use_back()->getParent() == BB &&
> -           !isa<PHINode>(I->use_back())))
> -        continue;
> -
> -      MadeChange |= ProcessInstruction(I, ExitBlocks);
> -    }
> -  }
> -
> -  // If we modified the code, remove any caches about the loop from SCEV to
> -  // avoid dangling entries.
> -  // FIXME: This is a big hammer, can we clear the cache more selectively?
> -  if (SE && MadeChange)
> -    SE->forgetLoop(L);
> -
> -  assert(L->isLCSSAForm(*DT));
> -  PredCache.clear();
> -
> -  return MadeChange;
> -}
> -
> -/// isExitBlock - Return true if the specified block is in the list.
> +/// Return true if the specified block is in the list.
>  static bool isExitBlock(BasicBlock *BB,
> -                        const SmallVectorImpl<BasicBlock*> &ExitBlocks) {
> +                        const SmallVectorImpl<BasicBlock *> &ExitBlocks) {
>    for (unsigned i = 0, e = ExitBlocks.size(); i != e; ++i)
>      if (ExitBlocks[i] == BB)
>        return true;
>    return false;
>  }
>
> -/// ProcessInstruction - Given an instruction in the loop, check to see if it
> -/// has any uses that are outside the current loop.  If so, insert LCSSA PHI
> -/// nodes and rewrite the uses.
> -bool LCSSA::ProcessInstruction(Instruction *Inst,
> -                               const SmallVectorImpl<BasicBlock*> &ExitBlocks) {
> -  SmallVector<Use*, 16> UsesToRewrite;
> -
> -  BasicBlock *InstBB = Inst->getParent();
> -
> -  for (Value::use_iterator UI = Inst->use_begin(), E = Inst->use_end();
> -       UI != E; ++UI) {
> +/// Given an instruction in the loop, check to see if it has any uses that are
> +/// outside the current loop.  If so, insert LCSSA PHI nodes and rewrite the
> +/// uses.
> +static bool processInstruction(Loop &L, Instruction &Inst, DominatorTree &DT,
> +                               const SmallVectorImpl<BasicBlock *> &ExitBlocks,
> +                               PredIteratorCache &PredCache) {
> +  SmallVector<Use *, 16> UsesToRewrite;
> +
> +  BasicBlock *InstBB = Inst.getParent();
> +
> +  for (Value::use_iterator UI = Inst.use_begin(), E = Inst.use_end(); UI != E;
> +       ++UI) {
>      User *U = *UI;
>      BasicBlock *UserBB = cast<Instruction>(U)->getParent();
>      if (PHINode *PN = dyn_cast<PHINode>(U))
>        UserBB = PN->getIncomingBlock(UI);
> -
> -    if (InstBB != UserBB && !L->contains(UserBB))
> +
> +    if (InstBB != UserBB && !L.contains(UserBB))
>        UsesToRewrite.push_back(&UI.getUse());
>    }
>
>    // If there are no uses outside the loop, exit with no change.
> -  if (UsesToRewrite.empty()) return false;
> -
> +  if (UsesToRewrite.empty())
> +    return false;
> +
>    ++NumLCSSA; // We are applying the transformation
>
>    // Invoke instructions are special in that their result value is not available
> -  // along their unwind edge. The code below tests to see whether DomBB dominates
> +  // along their unwind edge. The code below tests to see whether DomBB
> +  // dominates
>    // the value, so adjust DomBB to the normal destination block, which is
>    // effectively where the value is first usable.
> -  BasicBlock *DomBB = Inst->getParent();
> -  if (InvokeInst *Inv = dyn_cast<InvokeInst>(Inst))
> +  BasicBlock *DomBB = Inst.getParent();
> +  if (InvokeInst *Inv = dyn_cast<InvokeInst>(&Inst))
>      DomBB = Inv->getNormalDest();
>
> -  DomTreeNode *DomNode = DT->getNode(DomBB);
> +  DomTreeNode *DomNode = DT.getNode(DomBB);
>
> -  SmallVector<PHINode*, 16> AddedPHIs;
> +  SmallVector<PHINode *, 16> AddedPHIs;
>
>    SSAUpdater SSAUpdate;
> -  SSAUpdate.Initialize(Inst->getType(), Inst->getName());
> -
> +  SSAUpdate.Initialize(Inst.getType(), Inst.getName());
> +
>    // Insert the LCSSA phi's into all of the exit blocks dominated by the
>    // value, and add them to the Phi's map.
> -  for (SmallVectorImpl<BasicBlock*>::const_iterator BBI = ExitBlocks.begin(),
> -      BBE = ExitBlocks.end(); BBI != BBE; ++BBI) {
> +  for (SmallVectorImpl<BasicBlock *>::const_iterator BBI = ExitBlocks.begin(),
> +                                                     BBE = ExitBlocks.end();
> +       BBI != BBE; ++BBI) {
>      BasicBlock *ExitBB = *BBI;
> -    if (!DT->dominates(DomNode, DT->getNode(ExitBB))) continue;
> -
> +    if (!DT.dominates(DomNode, DT.getNode(ExitBB)))
> +      continue;
> +
>      // If we already inserted something for this BB, don't reprocess it.
> -    if (SSAUpdate.HasValueForBlock(ExitBB)) continue;
> -
> -    PHINode *PN = PHINode::Create(Inst->getType(),
> -                                  PredCache.GetNumPreds(ExitBB),
> -                                  Inst->getName()+".lcssa",
> -                                  ExitBB->begin());
> +    if (SSAUpdate.HasValueForBlock(ExitBB))
> +      continue;
> +
> +    PHINode *PN = PHINode::Create(Inst.getType(), PredCache.GetNumPreds(ExitBB),
> +                                  Inst.getName() + ".lcssa", ExitBB->begin());
>
>      // Add inputs from inside the loop for this PHI.
>      for (BasicBlock **PI = PredCache.GetPreds(ExitBB); *PI; ++PI) {
> -      PN->addIncoming(Inst, *PI);
> +      PN->addIncoming(&Inst, *PI);
>
>        // If the exit block has a predecessor not within the loop, arrange for
>        // the incoming value use corresponding to that predecessor to be
>        // rewritten in terms of a different LCSSA PHI.
> -      if (!L->contains(*PI))
> +      if (!L.contains(*PI))
>          UsesToRewrite.push_back(
> -          &PN->getOperandUse(
> -            PN->getOperandNumForIncomingValue(PN->getNumIncomingValues()-1)));
> +            &PN->getOperandUse(PN->getOperandNumForIncomingValue(
> +                 PN->getNumIncomingValues() - 1)));
>      }
>
>      AddedPHIs.push_back(PN);
> -
> +
>      // Remember that this phi makes the value alive in this block.
>      SSAUpdate.AddAvailableValue(ExitBB, PN);
>    }
> @@ -257,15 +144,14 @@ bool LCSSA::ProcessInstruction(Instructi
>      if (PHINode *PN = dyn_cast<PHINode>(User))
>        UserBB = PN->getIncomingBlock(*UsesToRewrite[i]);
>
> -    if (isa<PHINode>(UserBB->begin()) &&
> -        isExitBlock(UserBB, ExitBlocks)) {
> +    if (isa<PHINode>(UserBB->begin()) && isExitBlock(UserBB, ExitBlocks)) {
>        // Tell the VHs that the uses changed. This updates SCEV's caches.
>        if (UsesToRewrite[i]->get()->hasValueHandle())
>          ValueHandleBase::ValueIsRAUWd(*UsesToRewrite[i], UserBB->begin());
>        UsesToRewrite[i]->set(UserBB->begin());
>        continue;
>      }
> -
> +
>      // Otherwise, do full PHI insertion.
>      SSAUpdate.RewriteUse(*UsesToRewrite[i]);
>    }
> @@ -275,7 +161,152 @@ bool LCSSA::ProcessInstruction(Instructi
>      if (AddedPHIs[i]->use_empty())
>        AddedPHIs[i]->eraseFromParent();
>    }
> -
> +
>    return true;
>  }
>
> +/// Return true if the specified block dominates at least
> +/// one of the blocks in the specified list.
> +static bool
> +blockDominatesAnExit(BasicBlock *BB,
> +                     DominatorTree &DT,
> +                     const SmallVectorImpl<BasicBlock *> &ExitBlocks) {
> +  DomTreeNode *DomNode = DT.getNode(BB);
> +  for (unsigned i = 0, e = ExitBlocks.size(); i != e; ++i)
> +    if (DT.dominates(DomNode, DT.getNode(ExitBlocks[i])))
> +      return true;
> +
> +  return false;
> +}
> +
> +bool llvm::formLCSSA(Loop &L, DominatorTree &DT, ScalarEvolution *SE) {
> +  bool Changed = false;
> +
> +  // Get the set of exiting blocks.
> +  SmallVector<BasicBlock *, 8> ExitBlocks;
> +  L.getExitBlocks(ExitBlocks);
> +
> +  if (ExitBlocks.empty())
> +    return false;
> +
> +  PredIteratorCache PredCache;
> +
> +  // Look at all the instructions in the loop, checking to see if they have uses
> +  // outside the loop.  If so, rewrite those uses.
> +  for (Loop::block_iterator BBI = L.block_begin(), BBE = L.block_end();
> +       BBI != BBE; ++BBI) {
> +    BasicBlock *BB = *BBI;
> +
> +    // For large loops, avoid use-scanning by using dominance information:  In
> +    // particular, if a block does not dominate any of the loop exits, then none
> +    // of the values defined in the block could be used outside the loop.
> +    if (!blockDominatesAnExit(BB, DT, ExitBlocks))
> +      continue;
> +
> +    for (BasicBlock::iterator I = BB->begin(), E = BB->end(); I != E; ++I) {
> +      // Reject two common cases fast: instructions with no uses (like stores)
> +      // and instructions with one use that is in the same block as this.
> +      if (I->use_empty() ||
> +          (I->hasOneUse() && I->use_back()->getParent() == BB &&
> +           !isa<PHINode>(I->use_back())))
> +        continue;
> +
> +      Changed |= processInstruction(L, *I, DT, ExitBlocks, PredCache);
> +    }
> +  }
> +
> +  // If we modified the code, remove any caches about the loop from SCEV to
> +  // avoid dangling entries.
> +  // FIXME: This is a big hammer, can we clear the cache more selectively?
> +  if (SE && Changed)
> +    SE->forgetLoop(&L);
> +
> +  assert(L.isLCSSAForm(DT));
> +
> +  return Changed;
> +}
> +
> +namespace {
> +struct LCSSA : public FunctionPass {
> +  static char ID; // Pass identification, replacement for typeid
> +  LCSSA() : FunctionPass(ID) {
> +    initializeLCSSAPass(*PassRegistry::getPassRegistry());
> +  }
> +
> +  // Cached analysis information for the current function.
> +  DominatorTree *DT;
> +  LoopInfo *LI;
> +  ScalarEvolution *SE;
> +
> +  virtual bool runOnFunction(Function &F);
> +
> +  /// This transformation requires natural loop information & requires that
> +  /// loop preheaders be inserted into the CFG.  It maintains both of these,
> +  /// as well as the CFG.  It also requires dominator information.
> +  virtual void getAnalysisUsage(AnalysisUsage &AU) const {
> +    AU.setPreservesCFG();
> +
> +    AU.addRequired<DominatorTreeWrapperPass>();
> +    AU.addRequired<LoopInfo>();
> +    AU.addPreservedID(LoopSimplifyID);
> +    AU.addPreserved<ScalarEvolution>();
> +  }
> +
> +private:
> +  bool processLoop(Loop &L);
> +
> +  virtual void verifyAnalysis() const;
> +};
> +}
> +
> +char LCSSA::ID = 0;
> +INITIALIZE_PASS_BEGIN(LCSSA, "lcssa", "Loop-Closed SSA Form Pass", false, false)
> +INITIALIZE_PASS_DEPENDENCY(DominatorTreeWrapperPass)
> +INITIALIZE_PASS_DEPENDENCY(LoopInfo)
> +INITIALIZE_PASS_END(LCSSA, "lcssa", "Loop-Closed SSA Form Pass", false, false)
> +
> +Pass *llvm::createLCSSAPass() { return new LCSSA(); }
> +char &llvm::LCSSAID = LCSSA::ID;
> +
> +
> +/// Process all loops in the function, inner-most out.
> +bool LCSSA::runOnFunction(Function &F) {
> +  bool Changed = false;
> +  LI = &getAnalysis<LoopInfo>();
> +  DT = &getAnalysis<DominatorTreeWrapperPass>().getDomTree();
> +  SE = getAnalysisIfAvailable<ScalarEvolution>();
> +
> +  // Simplify each loop nest in the function.
> +  for (LoopInfo::iterator I = LI->begin(), E = LI->end(); I != E; ++I)
> +    Changed |= processLoop(**I);
> +
> +  return Changed;
> +}
> +
> +/// Process a loop nest depth first.
> +bool LCSSA::processLoop(Loop &L) {
> +  bool Changed = false;
> +
> +  // Recurse depth-first through inner loops.
> +  for (Loop::iterator LI = L.begin(), LE = L.end(); LI != LE; ++LI)
> +    Changed |= processLoop(**LI);
> +
> +  Changed |= formLCSSA(L, *DT, SE);
> +  return Changed;
> +}
> +
> +static void verifyLoop(Loop &L, DominatorTree &DT) {
> +  // Recurse depth-first through inner loops.
> +  for (Loop::iterator LI = L.begin(), LE = L.end(); LI != LE; ++LI)
> +    verifyLoop(**LI, DT);
> +
> +  // Check the special guarantees that LCSSA makes.
> +  //assert(L.isLCSSAForm(DT) && "LCSSA form not preserved!");
> +}

Do you recall any specific reason for commenting out this assertion?
Compile time performance?
I just sent out a patch to fix a issue in LCSSA and having this on
would have catch that before, I was wondering about turning it on
again.

Thanks,

-- 
Bruno Cardoso Lopes
http://www.brunocardoso.cc



More information about the llvm-commits mailing list