Skip to content

Commit

Permalink
[LCSSA] Implement linear algorithm for the isRecursivelyLCSSAForm
Browse files Browse the repository at this point in the history
For each block check that it doesn't have any uses outside of it's innermost loop.

Differential Revision: https://reviews.llvm.org/D25364

llvm-svn: 283877
  • Loading branch information
igor-laevsky committed Oct 11, 2016
1 parent 6d71f7b commit 04423cf
Show file tree
Hide file tree
Showing 5 changed files with 50 additions and 40 deletions.
2 changes: 1 addition & 1 deletion llvm/include/llvm/Analysis/LoopInfo.h
Expand Up @@ -412,7 +412,7 @@ class Loop : public LoopBase<BasicBlock, Loop> {
bool isLCSSAForm(DominatorTree &DT) const;

/// Return true if this Loop and all inner subloops are in LCSSA form.
bool isRecursivelyLCSSAForm(DominatorTree &DT) const;
bool isRecursivelyLCSSAForm(DominatorTree &DT, const LoopInfo &LI) const;

/// Return true if the Loop is in the form that the LoopSimplify form
/// transforms loops to, which is sometimes called normal form.
Expand Down
66 changes: 36 additions & 30 deletions llvm/lib/Analysis/LoopInfo.cpp
Expand Up @@ -143,42 +143,48 @@ PHINode *Loop::getCanonicalInductionVariable() const {
return nullptr;
}

bool Loop::isLCSSAForm(DominatorTree &DT) const {
for (BasicBlock *BB : this->blocks()) {
for (Instruction &I : *BB) {
// Tokens can't be used in PHI nodes and live-out tokens prevent loop
// optimizations, so for the purposes of considered LCSSA form, we
// can ignore them.
if (I.getType()->isTokenTy())
continue;
// Check that 'BB' doesn't have any uses outside of the 'L'
static bool isBlockInLCSSAForm(const Loop &L, const BasicBlock &BB,
DominatorTree &DT) {
for (const Instruction &I : BB) {
// Tokens can't be used in PHI nodes and live-out tokens prevent loop
// optimizations, so for the purposes of considered LCSSA form, we
// can ignore them.
if (I.getType()->isTokenTy())
continue;

for (Use &U : I.uses()) {
Instruction *UI = cast<Instruction>(U.getUser());
BasicBlock *UserBB = UI->getParent();
if (PHINode *P = dyn_cast<PHINode>(UI))
UserBB = P->getIncomingBlock(U);

// Check the current block, as a fast-path, before checking whether
// the use is anywhere in the loop. Most values are used in the same
// block they are defined in. Also, blocks not reachable from the
// entry are special; uses in them don't need to go through PHIs.
if (UserBB != BB &&
!contains(UserBB) &&
DT.isReachableFromEntry(UserBB))
return false;
}
for (const Use &U : I.uses()) {
const Instruction *UI = cast<Instruction>(U.getUser());
const BasicBlock *UserBB = UI->getParent();
if (const PHINode *P = dyn_cast<PHINode>(UI))
UserBB = P->getIncomingBlock(U);

// Check the current block, as a fast-path, before checking whether
// the use is anywhere in the loop. Most values are used in the same
// block they are defined in. Also, blocks not reachable from the
// entry are special; uses in them don't need to go through PHIs.
if (UserBB != &BB && !L.contains(UserBB) &&
DT.isReachableFromEntry(UserBB))
return false;
}
}

return true;
}

bool Loop::isRecursivelyLCSSAForm(DominatorTree &DT) const {
if (!isLCSSAForm(DT))
return false;

return all_of(*this,
[&](const Loop *L) { return L->isRecursivelyLCSSAForm(DT); });
bool Loop::isLCSSAForm(DominatorTree &DT) const {
// For each block we check that it doesn't have any uses outside of this loop.
return all_of(this->blocks(), [&](const BasicBlock *BB) {
return isBlockInLCSSAForm(*this, *BB, DT);
});
}

bool Loop::isRecursivelyLCSSAForm(DominatorTree &DT, const LoopInfo &LI) const {
// For each block we check that it doesn't have any uses outside of it's
// innermost loop. This process will transitivelly guarntee that current loop
// and all of the nested loops are in the LCSSA form.
return all_of(this->blocks(), [&](const BasicBlock *BB) {
return isBlockInLCSSAForm(*LI.getLoopFor(BB), *BB, DT);
});
}

bool Loop::isLoopSimplifyForm() const {
Expand Down
9 changes: 6 additions & 3 deletions llvm/lib/Transforms/Scalar/IndVarSimplify.cpp
Expand Up @@ -505,7 +505,8 @@ Value *IndVarSimplify::expandSCEVIfNeeded(SCEVExpander &Rewriter, const SCEV *S,
/// constant operands at the beginning of the loop.
void IndVarSimplify::rewriteLoopExitValues(Loop *L, SCEVExpander &Rewriter) {
// Check a pre-condition.
assert(L->isRecursivelyLCSSAForm(*DT) && "Indvars did not preserve LCSSA!");
assert(L->isRecursivelyLCSSAForm(*DT, *LI) &&
"Indvars did not preserve LCSSA!");

SmallVector<BasicBlock*, 8> ExitBlocks;
L->getUniqueExitBlocks(ExitBlocks);
Expand Down Expand Up @@ -2184,7 +2185,8 @@ void IndVarSimplify::sinkUnusedInvariants(Loop *L) {

bool IndVarSimplify::run(Loop *L) {
// We need (and expect!) the incoming loop to be in LCSSA.
assert(L->isRecursivelyLCSSAForm(*DT) && "LCSSA required to run indvars!");
assert(L->isRecursivelyLCSSAForm(*DT, *LI) &&
"LCSSA required to run indvars!");

// If LoopSimplify form is not available, stay out of trouble. Some notes:
// - LSR currently only supports LoopSimplify-form loops. Indvars'
Expand Down Expand Up @@ -2277,7 +2279,8 @@ bool IndVarSimplify::run(Loop *L) {
Changed |= DeleteDeadPHIs(L->getHeader(), TLI);

// Check a post-condition.
assert(L->isRecursivelyLCSSAForm(*DT) && "Indvars did not preserve LCSSA!");
assert(L->isRecursivelyLCSSAForm(*DT, *LI) &&
"Indvars did not preserve LCSSA!");

// Verify that LFTR, and any other change have not interfered with SCEV's
// ability to compute trip count.
Expand Down
3 changes: 2 additions & 1 deletion llvm/lib/Transforms/Utils/LCSSA.cpp
Expand Up @@ -323,7 +323,8 @@ struct LCSSAWrapperPass : public FunctionPass {
bool runOnFunction(Function &F) override;
void verifyAnalysis() const override {
assert(
all_of(*LI, [&](Loop *L) { return L->isRecursivelyLCSSAForm(*DT); }) &&
all_of(*LI,
[&](Loop *L) { return L->isRecursivelyLCSSAForm(*DT, *LI); }) &&
"LCSSA form is broken!");
};

Expand Down
10 changes: 5 additions & 5 deletions llvm/lib/Transforms/Utils/LoopSimplify.cpp
Expand Up @@ -366,7 +366,7 @@ static Loop *separateNestedLoop(Loop *L, BasicBlock *Preheader,
// already be a use of an LCSSA phi node.
formLCSSA(*L, *DT, LI, SE);

assert(NewOuter->isRecursivelyLCSSAForm(*DT) &&
assert(NewOuter->isRecursivelyLCSSAForm(*DT, *LI) &&
"LCSSA is broken after separating nested loops!");
}

Expand Down Expand Up @@ -810,8 +810,8 @@ bool LoopSimplify::runOnFunction(Function &F) {
if (PreserveLCSSA) {
assert(DT && "DT not available.");
assert(LI && "LI not available.");
bool InLCSSA =
all_of(*LI, [&](Loop *L) { return L->isRecursivelyLCSSAForm(*DT); });
bool InLCSSA = all_of(
*LI, [&](Loop *L) { return L->isRecursivelyLCSSAForm(*DT, *LI); });
assert(InLCSSA && "Requested to preserve LCSSA, but it's already broken.");
}
#endif
Expand All @@ -822,8 +822,8 @@ bool LoopSimplify::runOnFunction(Function &F) {

#ifndef NDEBUG
if (PreserveLCSSA) {
bool InLCSSA =
all_of(*LI, [&](Loop *L) { return L->isRecursivelyLCSSAForm(*DT); });
bool InLCSSA = all_of(
*LI, [&](Loop *L) { return L->isRecursivelyLCSSAForm(*DT, *LI); });
assert(InLCSSA && "LCSSA is broken after loop-simplify.");
}
#endif
Expand Down

0 comments on commit 04423cf

Please sign in to comment.