aboutsummaryrefslogtreecommitdiff
path: root/lib/Transforms/Utils/LoopUnroll.cpp
diff options
context:
space:
mode:
authorDimitry Andric <dim@FreeBSD.org>2019-08-20 20:50:12 +0000
committerDimitry Andric <dim@FreeBSD.org>2019-08-20 20:50:12 +0000
commite6d1592492a3a379186bfb02bd0f4eda0669c0d5 (patch)
tree599ab169a01f1c86eda9adc774edaedde2f2db5b /lib/Transforms/Utils/LoopUnroll.cpp
parent1a56a5ead7a2e84bee8240f5f6b033b5f1707154 (diff)
Diffstat (limited to 'lib/Transforms/Utils/LoopUnroll.cpp')
-rw-r--r--lib/Transforms/Utils/LoopUnroll.cpp424
1 files changed, 243 insertions, 181 deletions
diff --git a/lib/Transforms/Utils/LoopUnroll.cpp b/lib/Transforms/Utils/LoopUnroll.cpp
index da7ed2bd1652..e39ade523714 100644
--- a/lib/Transforms/Utils/LoopUnroll.cpp
+++ b/lib/Transforms/Utils/LoopUnroll.cpp
@@ -1,9 +1,8 @@
//===-- UnrollLoop.cpp - Loop unrolling utilities -------------------------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
@@ -45,6 +44,8 @@ using namespace llvm;
// TODO: Should these be here or in LoopUnroll?
STATISTIC(NumCompletelyUnrolled, "Number of loops completely unrolled");
STATISTIC(NumUnrolled, "Number of loops unrolled (completely or otherwise)");
+STATISTIC(NumUnrolledWithHeader, "Number of loops unrolled without a "
+ "conditional latch (completely or otherwise)");
static cl::opt<bool>
UnrollRuntimeEpilog("unroll-runtime-epilog", cl::init(false), cl::Hidden,
@@ -94,66 +95,6 @@ void llvm::remapInstruction(Instruction *I, ValueToValueMapTy &VMap) {
}
}
-/// Folds a basic block into its predecessor if it only has one predecessor, and
-/// that predecessor only has one successor.
-/// The LoopInfo Analysis that is passed will be kept consistent.
-BasicBlock *llvm::foldBlockIntoPredecessor(BasicBlock *BB, LoopInfo *LI,
- ScalarEvolution *SE,
- DominatorTree *DT) {
- // Merge basic blocks into their predecessor if there is only one distinct
- // pred, and if there is only one distinct successor of the predecessor, and
- // if there are no PHI nodes.
- BasicBlock *OnlyPred = BB->getSinglePredecessor();
- if (!OnlyPred) return nullptr;
-
- if (OnlyPred->getTerminator()->getNumSuccessors() != 1)
- return nullptr;
-
- LLVM_DEBUG(dbgs() << "Merging: " << BB->getName() << " into "
- << OnlyPred->getName() << "\n");
-
- // Resolve any PHI nodes at the start of the block. They are all
- // guaranteed to have exactly one entry if they exist, unless there are
- // multiple duplicate (but guaranteed to be equal) entries for the
- // incoming edges. This occurs when there are multiple edges from
- // OnlyPred to OnlySucc.
- FoldSingleEntryPHINodes(BB);
-
- // Delete the unconditional branch from the predecessor...
- OnlyPred->getInstList().pop_back();
-
- // Make all PHI nodes that referred to BB now refer to Pred as their
- // source...
- BB->replaceAllUsesWith(OnlyPred);
-
- // Move all definitions in the successor to the predecessor...
- OnlyPred->getInstList().splice(OnlyPred->end(), BB->getInstList());
-
- // OldName will be valid until erased.
- StringRef OldName = BB->getName();
-
- // Erase the old block and update dominator info.
- if (DT)
- if (DomTreeNode *DTN = DT->getNode(BB)) {
- DomTreeNode *PredDTN = DT->getNode(OnlyPred);
- SmallVector<DomTreeNode *, 8> Children(DTN->begin(), DTN->end());
- for (auto *DI : Children)
- DT->changeImmediateDominator(DI, PredDTN);
-
- DT->eraseNode(BB);
- }
-
- LI->removeBlock(BB);
-
- // Inherit predecessor's name if it exists...
- if (!OldName.empty() && !OnlyPred->hasName())
- OnlyPred->setName(OldName);
-
- BB->eraseFromParent();
-
- return OnlyPred;
-}
-
/// Check if unrolling created a situation where we need to insert phi nodes to
/// preserve LCSSA form.
/// \param Blocks is a vector of basic blocks representing unrolled loop.
@@ -332,12 +273,11 @@ void llvm::simplifyLoopAfterUnroll(Loop *L, bool SimplifyIVs, LoopInfo *LI,
///
/// If RemainderLoop is non-null, it will receive the remainder loop (if
/// required and not fully unrolled).
-LoopUnrollResult llvm::UnrollLoop(
- Loop *L, unsigned Count, unsigned TripCount, bool Force, bool AllowRuntime,
- bool AllowExpensiveTripCount, bool PreserveCondBr, bool PreserveOnlyFirst,
- unsigned TripMultiple, unsigned PeelCount, bool UnrollRemainder,
- LoopInfo *LI, ScalarEvolution *SE, DominatorTree *DT, AssumptionCache *AC,
- OptimizationRemarkEmitter *ORE, bool PreserveLCSSA, Loop **RemainderLoop) {
+LoopUnrollResult llvm::UnrollLoop(Loop *L, UnrollLoopOptions ULO, LoopInfo *LI,
+ ScalarEvolution *SE, DominatorTree *DT,
+ AssumptionCache *AC,
+ OptimizationRemarkEmitter *ORE,
+ bool PreserveLCSSA, Loop **RemainderLoop) {
BasicBlock *Preheader = L->getLoopPreheader();
if (!Preheader) {
@@ -357,28 +297,46 @@ LoopUnrollResult llvm::UnrollLoop(
return LoopUnrollResult::Unmodified;
}
- // The current loop unroll pass can only unroll loops with a single latch
+ // The current loop unroll pass can unroll loops with a single latch or header
// that's a conditional branch exiting the loop.
// FIXME: The implementation can be extended to work with more complicated
// cases, e.g. loops with multiple latches.
BasicBlock *Header = L->getHeader();
+ BranchInst *HeaderBI = dyn_cast<BranchInst>(Header->getTerminator());
BranchInst *BI = dyn_cast<BranchInst>(LatchBlock->getTerminator());
- if (!BI || BI->isUnconditional()) {
- // The loop-rotate pass can be helpful to avoid this in many cases.
+ // FIXME: Support loops without conditional latch and multiple exiting blocks.
+ if (!BI ||
+ (BI->isUnconditional() && (!HeaderBI || HeaderBI->isUnconditional() ||
+ L->getExitingBlock() != Header))) {
+ LLVM_DEBUG(dbgs() << " Can't unroll; loop not terminated by a conditional "
+ "branch in the latch or header.\n");
+ return LoopUnrollResult::Unmodified;
+ }
+
+ auto CheckLatchSuccessors = [&](unsigned S1, unsigned S2) {
+ return BI->isConditional() && BI->getSuccessor(S1) == Header &&
+ !L->contains(BI->getSuccessor(S2));
+ };
+
+ // If we have a conditional latch, it must exit the loop.
+ if (BI && BI->isConditional() && !CheckLatchSuccessors(0, 1) &&
+ !CheckLatchSuccessors(1, 0)) {
LLVM_DEBUG(
- dbgs()
- << " Can't unroll; loop not terminated by a conditional branch.\n");
+ dbgs() << "Can't unroll; a conditional latch must exit the loop");
return LoopUnrollResult::Unmodified;
}
- auto CheckSuccessors = [&](unsigned S1, unsigned S2) {
- return BI->getSuccessor(S1) == Header && !L->contains(BI->getSuccessor(S2));
+ auto CheckHeaderSuccessors = [&](unsigned S1, unsigned S2) {
+ return HeaderBI && HeaderBI->isConditional() &&
+ L->contains(HeaderBI->getSuccessor(S1)) &&
+ !L->contains(HeaderBI->getSuccessor(S2));
};
- if (!CheckSuccessors(0, 1) && !CheckSuccessors(1, 0)) {
- LLVM_DEBUG(dbgs() << "Can't unroll; only loops with one conditional latch"
- " exiting the loop can be unrolled\n");
+ // If we do not have a conditional latch, the header must exit the loop.
+ if (BI && !BI->isConditional() && HeaderBI && HeaderBI->isConditional() &&
+ !CheckHeaderSuccessors(0, 1) && !CheckHeaderSuccessors(1, 0)) {
+ LLVM_DEBUG(dbgs() << "Can't unroll; conditional header must exit the loop");
return LoopUnrollResult::Unmodified;
}
@@ -389,28 +347,28 @@ LoopUnrollResult llvm::UnrollLoop(
return LoopUnrollResult::Unmodified;
}
- if (TripCount != 0)
- LLVM_DEBUG(dbgs() << " Trip Count = " << TripCount << "\n");
- if (TripMultiple != 1)
- LLVM_DEBUG(dbgs() << " Trip Multiple = " << TripMultiple << "\n");
+ if (ULO.TripCount != 0)
+ LLVM_DEBUG(dbgs() << " Trip Count = " << ULO.TripCount << "\n");
+ if (ULO.TripMultiple != 1)
+ LLVM_DEBUG(dbgs() << " Trip Multiple = " << ULO.TripMultiple << "\n");
// Effectively "DCE" unrolled iterations that are beyond the tripcount
// and will never be executed.
- if (TripCount != 0 && Count > TripCount)
- Count = TripCount;
+ if (ULO.TripCount != 0 && ULO.Count > ULO.TripCount)
+ ULO.Count = ULO.TripCount;
// Don't enter the unroll code if there is nothing to do.
- if (TripCount == 0 && Count < 2 && PeelCount == 0) {
+ if (ULO.TripCount == 0 && ULO.Count < 2 && ULO.PeelCount == 0) {
LLVM_DEBUG(dbgs() << "Won't unroll; almost nothing to do\n");
return LoopUnrollResult::Unmodified;
}
- assert(Count > 0);
- assert(TripMultiple > 0);
- assert(TripCount == 0 || TripCount % TripMultiple == 0);
+ assert(ULO.Count > 0);
+ assert(ULO.TripMultiple > 0);
+ assert(ULO.TripCount == 0 || ULO.TripCount % ULO.TripMultiple == 0);
// Are we eliminating the loop control altogether?
- bool CompletelyUnroll = Count == TripCount;
+ bool CompletelyUnroll = ULO.Count == ULO.TripCount;
SmallVector<BasicBlock *, 4> ExitBlocks;
L->getExitBlocks(ExitBlocks);
std::vector<BasicBlock*> OriginalLoopBlocks = L->getBlocks();
@@ -429,24 +387,29 @@ LoopUnrollResult llvm::UnrollLoop(
// We assume a run-time trip count if the compiler cannot
// figure out the loop trip count and the unroll-runtime
// flag is specified.
- bool RuntimeTripCount = (TripCount == 0 && Count > 0 && AllowRuntime);
+ bool RuntimeTripCount =
+ (ULO.TripCount == 0 && ULO.Count > 0 && ULO.AllowRuntime);
- assert((!RuntimeTripCount || !PeelCount) &&
+ assert((!RuntimeTripCount || !ULO.PeelCount) &&
"Did not expect runtime trip-count unrolling "
"and peeling for the same loop");
bool Peeled = false;
- if (PeelCount) {
- Peeled = peelLoop(L, PeelCount, LI, SE, DT, AC, PreserveLCSSA);
+ if (ULO.PeelCount) {
+ Peeled = peelLoop(L, ULO.PeelCount, LI, SE, DT, AC, PreserveLCSSA);
// Successful peeling may result in a change in the loop preheader/trip
// counts. If we later unroll the loop, we want these to be updated.
if (Peeled) {
- BasicBlock *ExitingBlock = L->getExitingBlock();
+ // According to our guards and profitability checks the only
+ // meaningful exit should be latch block. Other exits go to deopt,
+ // so we do not worry about them.
+ BasicBlock *ExitingBlock = L->getLoopLatch();
assert(ExitingBlock && "Loop without exiting block?");
+ assert(L->isLoopExiting(ExitingBlock) && "Latch is not exiting?");
Preheader = L->getLoopPreheader();
- TripCount = SE->getSmallConstantTripCount(L, ExitingBlock);
- TripMultiple = SE->getSmallConstantTripMultiple(L, ExitingBlock);
+ ULO.TripCount = SE->getSmallConstantTripCount(L, ExitingBlock);
+ ULO.TripMultiple = SE->getSmallConstantTripMultiple(L, ExitingBlock);
}
}
@@ -459,7 +422,7 @@ LoopUnrollResult llvm::UnrollLoop(
for (auto &I : *BB)
if (auto CS = CallSite(&I))
HasConvergent |= CS.isConvergent();
- assert((!HasConvergent || TripMultiple % Count == 0) &&
+ assert((!HasConvergent || ULO.TripMultiple % ULO.Count == 0) &&
"Unroll count must divide trip multiple if loop contains a "
"convergent operation.");
});
@@ -468,11 +431,12 @@ LoopUnrollResult llvm::UnrollLoop(
UnrollRuntimeEpilog.getNumOccurrences() ? UnrollRuntimeEpilog
: isEpilogProfitable(L);
- if (RuntimeTripCount && TripMultiple % Count != 0 &&
- !UnrollRuntimeLoopRemainder(L, Count, AllowExpensiveTripCount,
- EpilogProfitability, UnrollRemainder, LI, SE,
- DT, AC, PreserveLCSSA, RemainderLoop)) {
- if (Force)
+ if (RuntimeTripCount && ULO.TripMultiple % ULO.Count != 0 &&
+ !UnrollRuntimeLoopRemainder(L, ULO.Count, ULO.AllowExpensiveTripCount,
+ EpilogProfitability, ULO.UnrollRemainder,
+ ULO.ForgetAllSCEV, LI, SE, DT, AC,
+ PreserveLCSSA, RemainderLoop)) {
+ if (ULO.Force)
RuntimeTripCount = false;
else {
LLVM_DEBUG(dbgs() << "Won't unroll; remainder loop could not be "
@@ -483,35 +447,35 @@ LoopUnrollResult llvm::UnrollLoop(
// If we know the trip count, we know the multiple...
unsigned BreakoutTrip = 0;
- if (TripCount != 0) {
- BreakoutTrip = TripCount % Count;
- TripMultiple = 0;
+ if (ULO.TripCount != 0) {
+ BreakoutTrip = ULO.TripCount % ULO.Count;
+ ULO.TripMultiple = 0;
} else {
// Figure out what multiple to use.
- BreakoutTrip = TripMultiple =
- (unsigned)GreatestCommonDivisor64(Count, TripMultiple);
+ BreakoutTrip = ULO.TripMultiple =
+ (unsigned)GreatestCommonDivisor64(ULO.Count, ULO.TripMultiple);
}
using namespace ore;
// Report the unrolling decision.
if (CompletelyUnroll) {
LLVM_DEBUG(dbgs() << "COMPLETELY UNROLLING loop %" << Header->getName()
- << " with trip count " << TripCount << "!\n");
+ << " with trip count " << ULO.TripCount << "!\n");
if (ORE)
ORE->emit([&]() {
return OptimizationRemark(DEBUG_TYPE, "FullyUnrolled", L->getStartLoc(),
L->getHeader())
<< "completely unrolled loop with "
- << NV("UnrollCount", TripCount) << " iterations";
+ << NV("UnrollCount", ULO.TripCount) << " iterations";
});
- } else if (PeelCount) {
+ } else if (ULO.PeelCount) {
LLVM_DEBUG(dbgs() << "PEELING loop %" << Header->getName()
- << " with iteration count " << PeelCount << "!\n");
+ << " with iteration count " << ULO.PeelCount << "!\n");
if (ORE)
ORE->emit([&]() {
return OptimizationRemark(DEBUG_TYPE, "Peeled", L->getStartLoc(),
L->getHeader())
- << " peeled loop by " << NV("PeelCount", PeelCount)
+ << " peeled loop by " << NV("PeelCount", ULO.PeelCount)
<< " iterations";
});
} else {
@@ -519,24 +483,25 @@ LoopUnrollResult llvm::UnrollLoop(
OptimizationRemark Diag(DEBUG_TYPE, "PartialUnrolled", L->getStartLoc(),
L->getHeader());
return Diag << "unrolled loop by a factor of "
- << NV("UnrollCount", Count);
+ << NV("UnrollCount", ULO.Count);
};
LLVM_DEBUG(dbgs() << "UNROLLING loop %" << Header->getName() << " by "
- << Count);
- if (TripMultiple == 0 || BreakoutTrip != TripMultiple) {
+ << ULO.Count);
+ if (ULO.TripMultiple == 0 || BreakoutTrip != ULO.TripMultiple) {
LLVM_DEBUG(dbgs() << " with a breakout at trip " << BreakoutTrip);
if (ORE)
ORE->emit([&]() {
return DiagBuilder() << " with a breakout at trip "
<< NV("BreakoutTrip", BreakoutTrip);
});
- } else if (TripMultiple != 1) {
- LLVM_DEBUG(dbgs() << " with " << TripMultiple << " trips per branch");
+ } else if (ULO.TripMultiple != 1) {
+ LLVM_DEBUG(dbgs() << " with " << ULO.TripMultiple << " trips per branch");
if (ORE)
ORE->emit([&]() {
- return DiagBuilder() << " with " << NV("TripMultiple", TripMultiple)
- << " trips per branch";
+ return DiagBuilder()
+ << " with " << NV("TripMultiple", ULO.TripMultiple)
+ << " trips per branch";
});
} else if (RuntimeTripCount) {
LLVM_DEBUG(dbgs() << " with run-time trip count");
@@ -555,11 +520,24 @@ LoopUnrollResult llvm::UnrollLoop(
// and if something changes inside them then any of outer loops may also
// change. When we forget outermost loop, we also forget all contained loops
// and this is what we need here.
- if (SE)
- SE->forgetTopmostLoop(L);
+ if (SE) {
+ if (ULO.ForgetAllSCEV)
+ SE->forgetAllLoops();
+ else
+ SE->forgetTopmostLoop(L);
+ }
- bool ContinueOnTrue = L->contains(BI->getSuccessor(0));
- BasicBlock *LoopExit = BI->getSuccessor(ContinueOnTrue);
+ bool ContinueOnTrue;
+ bool LatchIsExiting = BI->isConditional();
+ BasicBlock *LoopExit = nullptr;
+ if (LatchIsExiting) {
+ ContinueOnTrue = L->contains(BI->getSuccessor(0));
+ LoopExit = BI->getSuccessor(ContinueOnTrue);
+ } else {
+ NumUnrolledWithHeader++;
+ ContinueOnTrue = L->contains(HeaderBI->getSuccessor(0));
+ LoopExit = HeaderBI->getSuccessor(ContinueOnTrue);
+ }
// For the first iteration of the loop, we should use the precloned values for
// PHI nodes. Insert associations now.
@@ -569,11 +547,23 @@ LoopUnrollResult llvm::UnrollLoop(
OrigPHINode.push_back(cast<PHINode>(I));
}
- std::vector<BasicBlock*> Headers;
- std::vector<BasicBlock*> Latches;
+ std::vector<BasicBlock *> Headers;
+ std::vector<BasicBlock *> HeaderSucc;
+ std::vector<BasicBlock *> Latches;
Headers.push_back(Header);
Latches.push_back(LatchBlock);
+ if (!LatchIsExiting) {
+ auto *Term = cast<BranchInst>(Header->getTerminator());
+ if (Term->isUnconditional() || L->contains(Term->getSuccessor(0))) {
+ assert(L->contains(Term->getSuccessor(0)));
+ HeaderSucc.push_back(Term->getSuccessor(0));
+ } else {
+ assert(L->contains(Term->getSuccessor(1)));
+ HeaderSucc.push_back(Term->getSuccessor(1));
+ }
+ }
+
// The current on-the-fly SSA update requires blocks to be processed in
// reverse postorder so that LastValueMap contains the correct value at each
// exit.
@@ -599,7 +589,7 @@ LoopUnrollResult llvm::UnrollLoop(
for (Instruction &I : *BB)
if (!isa<DbgInfoIntrinsic>(&I))
if (const DILocation *DIL = I.getDebugLoc()) {
- auto NewDIL = DIL->cloneWithDuplicationFactor(Count);
+ auto NewDIL = DIL->cloneByMultiplyingDuplicationFactor(ULO.Count);
if (NewDIL)
I.setDebugLoc(NewDIL.getValue());
else
@@ -608,7 +598,7 @@ LoopUnrollResult llvm::UnrollLoop(
<< DIL->getFilename() << " Line: " << DIL->getLine());
}
- for (unsigned It = 1; It != Count; ++It) {
+ for (unsigned It = 1; It != ULO.Count; ++It) {
std::vector<BasicBlock*> NewBlocks;
SmallDenseMap<const Loop *, Loop *, 4> NewLoops;
NewLoops[L] = L;
@@ -663,6 +653,13 @@ LoopUnrollResult llvm::UnrollLoop(
if (*BB == LatchBlock)
Latches.push_back(New);
+ // Keep track of the successor of the new header in the current iteration.
+ for (auto *Pred : predecessors(*BB))
+ if (Pred == Header) {
+ HeaderSucc.push_back(New);
+ break;
+ }
+
NewBlocks.push_back(New);
UnrolledLoopBlocks.push_back(New);
@@ -699,8 +696,7 @@ LoopUnrollResult llvm::UnrollLoop(
if (CompletelyUnroll) {
PN->replaceAllUsesWith(PN->getIncomingValueForBlock(Preheader));
Header->getInstList().erase(PN);
- }
- else if (Count > 1) {
+ } else if (ULO.Count > 1) {
Value *InVal = PN->removeIncomingValue(LatchBlock, false);
// If this value was defined in the loop, take the value defined by the
// last iteration of the loop.
@@ -713,39 +709,11 @@ LoopUnrollResult llvm::UnrollLoop(
}
}
- // Now that all the basic blocks for the unrolled iterations are in place,
- // set up the branches to connect them.
- for (unsigned i = 0, e = Latches.size(); i != e; ++i) {
- // The original branch was replicated in each unrolled iteration.
- BranchInst *Term = cast<BranchInst>(Latches[i]->getTerminator());
-
- // The branch destination.
- unsigned j = (i + 1) % e;
- BasicBlock *Dest = Headers[j];
- bool NeedConditional = true;
-
- if (RuntimeTripCount && j != 0) {
- NeedConditional = false;
- }
-
- // For a complete unroll, make the last iteration end with a branch
- // to the exit block.
- if (CompletelyUnroll) {
- if (j == 0)
- Dest = LoopExit;
- // If using trip count upper bound to completely unroll, we need to keep
- // the conditional branch except the last one because the loop may exit
- // after any iteration.
- assert(NeedConditional &&
- "NeedCondition cannot be modified by both complete "
- "unrolling and runtime unrolling");
- NeedConditional = (PreserveCondBr && j && !(PreserveOnlyFirst && i != 0));
- } else if (j != BreakoutTrip && (TripMultiple == 0 || j % TripMultiple != 0)) {
- // If we know the trip count or a multiple of it, we can safely use an
- // unconditional branch for some iterations.
- NeedConditional = false;
- }
-
+ auto setDest = [LoopExit, ContinueOnTrue](BasicBlock *Src, BasicBlock *Dest,
+ ArrayRef<BasicBlock *> NextBlocks,
+ BasicBlock *CurrentHeader,
+ bool NeedConditional) {
+ auto *Term = cast<BranchInst>(Src->getTerminator());
if (NeedConditional) {
// Update the conditional branch's successor for the following
// iteration.
@@ -753,9 +721,9 @@ LoopUnrollResult llvm::UnrollLoop(
} else {
// Remove phi operands at this loop exit
if (Dest != LoopExit) {
- BasicBlock *BB = Latches[i];
- for (BasicBlock *Succ: successors(BB)) {
- if (Succ == Headers[i])
+ BasicBlock *BB = Src;
+ for (BasicBlock *Succ : successors(BB)) {
+ if (Succ == CurrentHeader)
continue;
for (PHINode &Phi : Succ->phis())
Phi.removeIncomingValue(BB, false);
@@ -765,13 +733,97 @@ LoopUnrollResult llvm::UnrollLoop(
BranchInst::Create(Dest, Term);
Term->eraseFromParent();
}
+ };
+
+ // Now that all the basic blocks for the unrolled iterations are in place,
+ // set up the branches to connect them.
+ if (LatchIsExiting) {
+ // Set up latches to branch to the new header in the unrolled iterations or
+ // the loop exit for the last latch in a fully unrolled loop.
+ for (unsigned i = 0, e = Latches.size(); i != e; ++i) {
+ // The branch destination.
+ unsigned j = (i + 1) % e;
+ BasicBlock *Dest = Headers[j];
+ bool NeedConditional = true;
+
+ if (RuntimeTripCount && j != 0) {
+ NeedConditional = false;
+ }
+
+ // For a complete unroll, make the last iteration end with a branch
+ // to the exit block.
+ if (CompletelyUnroll) {
+ if (j == 0)
+ Dest = LoopExit;
+ // If using trip count upper bound to completely unroll, we need to keep
+ // the conditional branch except the last one because the loop may exit
+ // after any iteration.
+ assert(NeedConditional &&
+ "NeedCondition cannot be modified by both complete "
+ "unrolling and runtime unrolling");
+ NeedConditional =
+ (ULO.PreserveCondBr && j && !(ULO.PreserveOnlyFirst && i != 0));
+ } else if (j != BreakoutTrip &&
+ (ULO.TripMultiple == 0 || j % ULO.TripMultiple != 0)) {
+ // If we know the trip count or a multiple of it, we can safely use an
+ // unconditional branch for some iterations.
+ NeedConditional = false;
+ }
+
+ setDest(Latches[i], Dest, Headers, Headers[i], NeedConditional);
+ }
+ } else {
+ // Setup headers to branch to their new successors in the unrolled
+ // iterations.
+ for (unsigned i = 0, e = Headers.size(); i != e; ++i) {
+ // The branch destination.
+ unsigned j = (i + 1) % e;
+ BasicBlock *Dest = HeaderSucc[i];
+ bool NeedConditional = true;
+
+ if (RuntimeTripCount && j != 0)
+ NeedConditional = false;
+
+ if (CompletelyUnroll)
+ // We cannot drop the conditional branch for the last condition, as we
+ // may have to execute the loop body depending on the condition.
+ NeedConditional = j == 0 || ULO.PreserveCondBr;
+ else if (j != BreakoutTrip &&
+ (ULO.TripMultiple == 0 || j % ULO.TripMultiple != 0))
+ // If we know the trip count or a multiple of it, we can safely use an
+ // unconditional branch for some iterations.
+ NeedConditional = false;
+
+ setDest(Headers[i], Dest, Headers, Headers[i], NeedConditional);
+ }
+
+ // Set up latches to branch to the new header in the unrolled iterations or
+ // the loop exit for the last latch in a fully unrolled loop.
+
+ for (unsigned i = 0, e = Latches.size(); i != e; ++i) {
+ // The original branch was replicated in each unrolled iteration.
+ BranchInst *Term = cast<BranchInst>(Latches[i]->getTerminator());
+
+ // The branch destination.
+ unsigned j = (i + 1) % e;
+ BasicBlock *Dest = Headers[j];
+
+ // When completely unrolling, the last latch becomes unreachable.
+ if (CompletelyUnroll && j == 0)
+ new UnreachableInst(Term->getContext(), Term);
+ else
+ // Replace the conditional branch with an unconditional one.
+ BranchInst::Create(Dest, Term);
+
+ Term->eraseFromParent();
+ }
}
// Update dominators of blocks we might reach through exits.
// Immediate dominator of such block might change, because we add more
// routes which can lead to the exit: we can now reach it from the copied
// iterations too.
- if (DT && Count > 1) {
+ if (DT && ULO.Count > 1) {
for (auto *BB : OriginalLoopBlocks) {
auto *BBDomNode = DT->getNode(BB);
SmallVector<BasicBlock *, 16> ChildrenToUpdate;
@@ -781,7 +833,9 @@ LoopUnrollResult llvm::UnrollLoop(
ChildrenToUpdate.push_back(ChildBB);
}
BasicBlock *NewIDom;
- if (BB == LatchBlock) {
+ BasicBlock *&TermBlock = LatchIsExiting ? LatchBlock : Header;
+ auto &TermBlocks = LatchIsExiting ? Latches : Headers;
+ if (BB == TermBlock) {
// The latch is special because we emit unconditional branches in
// some cases where the original loop contained a conditional branch.
// Since the latch is always at the bottom of the loop, if the latch
@@ -789,11 +843,13 @@ LoopUnrollResult llvm::UnrollLoop(
// must also be a latch. Specifically, the dominator is the first
// latch which ends in a conditional branch, or the last latch if
// there is no such latch.
- NewIDom = Latches.back();
- for (BasicBlock *IterLatch : Latches) {
- Instruction *Term = IterLatch->getTerminator();
+ // For loops exiting from the header, we limit the supported loops
+ // to have a single exiting block.
+ NewIDom = TermBlocks.back();
+ for (BasicBlock *Iter : TermBlocks) {
+ Instruction *Term = Iter->getTerminator();
if (isa<BranchInst>(Term) && cast<BranchInst>(Term)->isConditional()) {
- NewIDom = IterLatch;
+ NewIDom = Iter;
break;
}
}
@@ -810,14 +866,20 @@ LoopUnrollResult llvm::UnrollLoop(
}
assert(!DT || !UnrollVerifyDomtree ||
- DT->verify(DominatorTree::VerificationLevel::Fast));
+ DT->verify(DominatorTree::VerificationLevel::Fast));
+ DomTreeUpdater DTU(DT, DomTreeUpdater::UpdateStrategy::Eager);
// Merge adjacent basic blocks, if possible.
for (BasicBlock *Latch : Latches) {
- BranchInst *Term = cast<BranchInst>(Latch->getTerminator());
- if (Term->isUnconditional()) {
+ BranchInst *Term = dyn_cast<BranchInst>(Latch->getTerminator());
+ assert((Term ||
+ (CompletelyUnroll && !LatchIsExiting && Latch == Latches.back())) &&
+ "Need a branch as terminator, except when fully unrolling with "
+ "unconditional latch");
+ if (Term && Term->isUnconditional()) {
BasicBlock *Dest = Term->getSuccessor(0);
- if (BasicBlock *Fold = foldBlockIntoPredecessor(Dest, LI, SE, DT)) {
+ BasicBlock *Fold = Dest->getUniquePredecessor();
+ if (MergeBlockIntoPredecessor(Dest, &DTU, LI)) {
// Dest has been folded into Fold. Update our worklists accordingly.
std::replace(Latches.begin(), Latches.end(), Dest, Fold);
UnrolledLoopBlocks.erase(std::remove(UnrolledLoopBlocks.begin(),
@@ -829,8 +891,8 @@ LoopUnrollResult llvm::UnrollLoop(
// At this point, the code is well formed. We now simplify the unrolled loop,
// doing constant propagation and dead code elimination as we go.
- simplifyLoopAfterUnroll(L, !CompletelyUnroll && (Count > 1 || Peeled), LI, SE,
- DT, AC);
+ simplifyLoopAfterUnroll(L, !CompletelyUnroll && (ULO.Count > 1 || Peeled), LI,
+ SE, DT, AC);
NumCompletelyUnrolled += CompletelyUnroll;
++NumUnrolled;
@@ -878,11 +940,11 @@ LoopUnrollResult llvm::UnrollLoop(
// TODO: That potentially might be compile-time expensive. We should try
// to fix the loop-simplified form incrementally.
- simplifyLoop(OuterL, DT, LI, SE, AC, PreserveLCSSA);
+ simplifyLoop(OuterL, DT, LI, SE, AC, nullptr, PreserveLCSSA);
} else {
// Simplify loops for which we might've broken loop-simplify form.
for (Loop *SubLoop : LoopsToSimplify)
- simplifyLoop(SubLoop, DT, LI, SE, AC, PreserveLCSSA);
+ simplifyLoop(SubLoop, DT, LI, SE, AC, nullptr, PreserveLCSSA);
}
}