summaryrefslogtreecommitdiff
path: root/llvm/lib/Transforms/Scalar/LoopInterchange.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'llvm/lib/Transforms/Scalar/LoopInterchange.cpp')
-rw-r--r--llvm/lib/Transforms/Scalar/LoopInterchange.cpp65
1 files changed, 36 insertions, 29 deletions
diff --git a/llvm/lib/Transforms/Scalar/LoopInterchange.cpp b/llvm/lib/Transforms/Scalar/LoopInterchange.cpp
index 6ce2d06058cf3..7787c0bccd4ce 100644
--- a/llvm/lib/Transforms/Scalar/LoopInterchange.cpp
+++ b/llvm/lib/Transforms/Scalar/LoopInterchange.cpp
@@ -412,7 +412,6 @@ public:
private:
bool adjustLoopLinks();
- void adjustLoopPreheaders();
bool adjustLoopBranches();
Loop *OuterLoop;
@@ -580,6 +579,12 @@ struct LoopInterchange : public LoopPass {
LIT.transform();
LLVM_DEBUG(dbgs() << "Loops interchanged.\n");
LoopsInterchanged++;
+
+ assert(InnerLoop->isLCSSAForm(*DT) &&
+ "Inner loop not left in LCSSA form after loop interchange!");
+ assert(OuterLoop->isLCSSAForm(*DT) &&
+ "Outer loop not left in LCSSA form after loop interchange!");
+
return true;
}
};
@@ -689,7 +694,7 @@ bool LoopInterchangeLegality::findInductionAndReductions(
// PHIs in inner loops need to be part of a reduction in the outer loop,
// discovered when checking the PHIs of the outer loop earlier.
if (!InnerLoop) {
- if (OuterInnerReductions.find(&PHI) == OuterInnerReductions.end()) {
+ if (!OuterInnerReductions.count(&PHI)) {
LLVM_DEBUG(dbgs() << "Inner loop PHI is not part of reductions "
"across the outer loop.\n");
return false;
@@ -903,8 +908,8 @@ areInnerLoopExitPHIsSupported(Loop *InnerL, Loop *OuterL,
return false;
if (any_of(PHI.users(), [&Reductions, OuterL](User *U) {
PHINode *PN = dyn_cast<PHINode>(U);
- return !PN || (Reductions.find(PN) == Reductions.end() &&
- OuterL->contains(PN->getParent()));
+ return !PN ||
+ (!Reductions.count(PN) && OuterL->contains(PN->getParent()));
})) {
return false;
}
@@ -1319,6 +1324,23 @@ static void moveBBContents(BasicBlock *FromBB, Instruction *InsertBefore) {
FromBB->getTerminator()->getIterator());
}
+/// Swap instructions between \p BB1 and \p BB2 but keep terminators intact.
+static void swapBBContents(BasicBlock *BB1, BasicBlock *BB2) {
+ // Save all non-terminator instructions of BB1 into TempInstrs and unlink them
+ // from BB1 afterwards.
+ auto Iter = map_range(*BB1, [](Instruction &I) { return &I; });
+ SmallVector<Instruction *, 4> TempInstrs(Iter.begin(), std::prev(Iter.end()));
+ for (Instruction *I : TempInstrs)
+ I->removeFromParent();
+
+ // Move instructions from BB2 to BB1.
+ moveBBContents(BB2, BB1->getTerminator());
+
+ // Move instructions from TempInstrs to BB2.
+ for (Instruction *I : TempInstrs)
+ I->insertBefore(BB2->getTerminator());
+}
+
// Update BI to jump to NewBB instead of OldBB. Records updates to the
// dominator tree in DTUpdates. If \p MustUpdateOnce is true, assert that
// \p OldBB is exactly once in BI's successor list.
@@ -1560,13 +1582,11 @@ bool LoopInterchangeTransform::adjustLoopBranches() {
// outer loop and all the remains to do is and updating the incoming blocks.
for (PHINode *PHI : OuterLoopPHIs) {
PHI->moveBefore(InnerLoopHeader->getFirstNonPHI());
- assert(OuterInnerReductions.find(PHI) != OuterInnerReductions.end() &&
- "Expected a reduction PHI node");
+ assert(OuterInnerReductions.count(PHI) && "Expected a reduction PHI node");
}
for (PHINode *PHI : InnerLoopPHIs) {
PHI->moveBefore(OuterLoopHeader->getFirstNonPHI());
- assert(OuterInnerReductions.find(PHI) != OuterInnerReductions.end() &&
- "Expected a reduction PHI node");
+ assert(OuterInnerReductions.count(PHI) && "Expected a reduction PHI node");
}
// Update the incoming blocks for moved PHI nodes.
@@ -1578,30 +1598,17 @@ bool LoopInterchangeTransform::adjustLoopBranches() {
return true;
}
-void LoopInterchangeTransform::adjustLoopPreheaders() {
- // We have interchanged the preheaders so we need to interchange the data in
- // the preheader as well.
- // This is because the content of inner preheader was previously executed
- // inside the outer loop.
- BasicBlock *OuterLoopPreHeader = OuterLoop->getLoopPreheader();
- BasicBlock *InnerLoopPreHeader = InnerLoop->getLoopPreheader();
- BasicBlock *OuterLoopHeader = OuterLoop->getHeader();
- BranchInst *InnerTermBI =
- cast<BranchInst>(InnerLoopPreHeader->getTerminator());
-
- // These instructions should now be executed inside the loop.
- // Move instruction into a new block after outer header.
- moveBBContents(InnerLoopPreHeader, OuterLoopHeader->getTerminator());
- // These instructions were not executed previously in the loop so move them to
- // the older inner loop preheader.
- moveBBContents(OuterLoopPreHeader, InnerTermBI);
-}
-
bool LoopInterchangeTransform::adjustLoopLinks() {
// Adjust all branches in the inner and outer loop.
bool Changed = adjustLoopBranches();
- if (Changed)
- adjustLoopPreheaders();
+ if (Changed) {
+ // We have interchanged the preheaders so we need to interchange the data in
+ // the preheaders as well. This is because the content of the inner
+ // preheader was previously executed inside the outer loop.
+ BasicBlock *OuterLoopPreHeader = OuterLoop->getLoopPreheader();
+ BasicBlock *InnerLoopPreHeader = InnerLoop->getLoopPreheader();
+ swapBBContents(OuterLoopPreHeader, InnerLoopPreHeader);
+ }
return Changed;
}