Skip to content

Commit

Permalink
[LPM] Make LCSSA a utility with a FunctionPass that applies it to all
Browse files Browse the repository at this point in the history
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.

llvm-svn: 200067
  • Loading branch information
chandlerc committed Jan 25, 2014
1 parent 6e20554 commit 8765cf7
Show file tree
Hide file tree
Showing 6 changed files with 298 additions and 182 deletions.
13 changes: 13 additions & 0 deletions llvm/include/llvm/Transforms/Utils/LoopUtils.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,19 @@ BasicBlock *InsertPreheaderForLoop(Loop *L, Pass *P);
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
77 changes: 70 additions & 7 deletions llvm/lib/Transforms/Scalar/LICM.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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>();
}

Expand Down Expand Up @@ -193,6 +196,8 @@ INITIALIZE_PASS_BEGIN(LICM, "licm", "Loop Invariant Code Motion", false, false)
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)
Expand Down Expand Up @@ -283,6 +288,14 @@ bool LICM::runOnLoop(Loop *L, LPPassManager &LPM) {
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;
Expand Down Expand Up @@ -451,6 +464,19 @@ bool LICM::canSinkOrHoistInst(Instruction &I) {
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.
Expand All @@ -459,18 +485,48 @@ bool LICM::isNotUsedInLoop(Instruction &I) {
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.
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down
Loading

0 comments on commit 8765cf7

Please sign in to comment.