summaryrefslogtreecommitdiffstats
path: root/llvm/lib/Transforms
diff options
context:
space:
mode:
authorFlorian Hahn <florian.hahn@arm.com>2018-09-26 19:34:25 +0000
committerFlorian Hahn <florian.hahn@arm.com>2018-09-26 19:34:25 +0000
commit6feb637124e5bf5a3bb45c1b2106d622b93e7c28 (patch)
treeca308325099cf164a112bd309bfdf4bd7d41e347 /llvm/lib/Transforms
parent79c88c31056fc52f8414c497f2d6e2e53749c48b (diff)
downloadbcm5719-llvm-6feb637124e5bf5a3bb45c1b2106d622b93e7c28.tar.gz
bcm5719-llvm-6feb637124e5bf5a3bb45c1b2106d622b93e7c28.zip
[LoopInterchange] Preserve LCSSA.
This patch extends LoopInterchange to move LCSSA to the right place after interchanging. This is required for LoopInterchange to become a function pass. An alternative to the manual moving of the PHIs, we could also re-form the LCSSA phis for a set of interchanged loops, but that's more expensive. Reviewers: efriedma, mcrosier, davide Reviewed By: efriedma Differential Revision: https://reviews.llvm.org/D52154 llvm-svn: 343132
Diffstat (limited to 'llvm/lib/Transforms')
-rw-r--r--llvm/lib/Transforms/Scalar/LoopInterchange.cpp72
1 files changed, 54 insertions, 18 deletions
diff --git a/llvm/lib/Transforms/Scalar/LoopInterchange.cpp b/llvm/lib/Transforms/Scalar/LoopInterchange.cpp
index 38c9396b954..3be41646741 100644
--- a/llvm/lib/Transforms/Scalar/LoopInterchange.cpp
+++ b/llvm/lib/Transforms/Scalar/LoopInterchange.cpp
@@ -411,8 +411,6 @@ private:
bool adjustLoopLinks();
void adjustLoopPreheaders();
bool adjustLoopBranches();
- void updateIncomingBlock(BasicBlock *CurrBlock, BasicBlock *OldPred,
- BasicBlock *NewPred);
Loop *OuterLoop;
Loop *InnerLoop;
@@ -455,6 +453,7 @@ struct LoopInterchange : public FunctionPass {
AU.addPreserved<DominatorTreeWrapperPass>();
AU.addPreserved<LoopInfoWrapperPass>();
AU.addPreserved<ScalarEvolutionWrapperPass>();
+ AU.addPreservedID(LCSSAID);
}
bool runOnFunction(Function &F) override {
@@ -1297,9 +1296,8 @@ static void moveBBContents(BasicBlock *FromBB, Instruction *InsertBefore) {
FromBB->getTerminator()->getIterator());
}
-void LoopInterchangeTransform::updateIncomingBlock(BasicBlock *CurrBlock,
- BasicBlock *OldPred,
- BasicBlock *NewPred) {
+static void updateIncomingBlock(BasicBlock *CurrBlock, BasicBlock *OldPred,
+ BasicBlock *NewPred) {
for (PHINode &PHI : CurrBlock->phis()) {
unsigned Num = PHI.getNumIncomingValues();
for (unsigned i = 0; i < Num; ++i) {
@@ -1330,6 +1328,52 @@ static void updateSuccessor(BranchInst *BI, BasicBlock *OldBB,
}
}
+// Move Lcssa PHIs to the right place.
+static void moveLCSSAPhis(BasicBlock *InnerExit, BasicBlock *InnerLatch,
+ BasicBlock *OuterLatch) {
+ SmallVector<PHINode *, 8> LcssaInnerExit;
+ for (PHINode &P : InnerExit->phis())
+ LcssaInnerExit.push_back(&P);
+
+ SmallVector<PHINode *, 8> LcssaInnerLatch;
+ for (PHINode &P : InnerLatch->phis())
+ LcssaInnerLatch.push_back(&P);
+
+ // Lcssa PHIs for values used outside the inner loop are in InnerExit.
+ // If a PHI node has users outside of InnerExit, it has a use outside the
+ // interchanged loop and we have to preserve it. We move these to
+ // InnerLatch, which will become the new exit block for the innermost
+ // loop after interchanging. For PHIs only used in InnerExit, we can just
+ // replace them with the incoming value.
+ for (PHINode *P : LcssaInnerExit) {
+ bool hasUsersOutside = false;
+ for (auto UI = P->use_begin(), E = P->use_end(); UI != E;) {
+ Use &U = *UI;
+ ++UI;
+ auto *Usr = cast<Instruction>(U.getUser());
+ if (Usr->getParent() != InnerExit) {
+ hasUsersOutside = true;
+ continue;
+ }
+ U.set(P->getIncomingValueForBlock(InnerLatch));
+ }
+ if (hasUsersOutside)
+ P->moveBefore(InnerLatch->getFirstNonPHI());
+ else
+ P->eraseFromParent();
+ }
+
+ // If the inner loop latch contains LCSSA PHIs, those come from a child loop
+ // and we have to move them to the new inner latch.
+ for (PHINode *P : LcssaInnerLatch)
+ P->moveBefore(InnerExit->getFirstNonPHI());
+
+ // Now adjust the incoming blocks for the LCSSA PHIs.
+ // For PHIs moved from Inner's exit block, we need to replace Inner's latch
+ // with the new latch.
+ updateIncomingBlock(InnerLatch, InnerLatch, OuterLatch);
+}
+
bool LoopInterchangeTransform::adjustLoopBranches() {
LLVM_DEBUG(dbgs() << "adjustLoopBranches called\n");
std::vector<DominatorTree::UpdateType> DTUpdates;
@@ -1409,17 +1453,6 @@ bool LoopInterchangeTransform::adjustLoopBranches() {
updateSuccessor(InnerLoopLatchPredecessorBI, InnerLoopLatch,
InnerLoopLatchSuccessor, DTUpdates);
- // Adjust PHI nodes in InnerLoopLatchSuccessor. Update all uses of PHI with
- // the value and remove this PHI node from inner loop.
- SmallVector<PHINode *, 8> LcssaVec;
- for (PHINode &P : InnerLoopLatchSuccessor->phis())
- LcssaVec.push_back(&P);
-
- for (PHINode *P : LcssaVec) {
- Value *Incoming = P->getIncomingValueForBlock(InnerLoopLatch);
- P->replaceAllUsesWith(Incoming);
- P->eraseFromParent();
- }
if (OuterLoopLatchBI->getSuccessor(0) == OuterLoopHeader)
OuterLoopLatchSuccessor = OuterLoopLatchBI->getSuccessor(1);
@@ -1431,12 +1464,15 @@ bool LoopInterchangeTransform::adjustLoopBranches() {
updateSuccessor(OuterLoopLatchBI, OuterLoopLatchSuccessor, InnerLoopLatch,
DTUpdates);
- updateIncomingBlock(OuterLoopLatchSuccessor, OuterLoopLatch, InnerLoopLatch);
-
DT->applyUpdates(DTUpdates);
restructureLoops(OuterLoop, InnerLoop, InnerLoopPreHeader,
OuterLoopPreHeader);
+ moveLCSSAPhis(InnerLoopLatchSuccessor, InnerLoopLatch, OuterLoopLatch);
+ // For PHIs in the exit block of the outer loop, outer's latch has been
+ // replaced by Inners'.
+ updateIncomingBlock(OuterLoopLatchSuccessor, OuterLoopLatch, InnerLoopLatch);
+
// Now update the reduction PHIs in the inner and outer loop headers.
SmallVector<PHINode *, 4> InnerLoopPHIs, OuterLoopPHIs;
for (PHINode &PHI : drop_begin(InnerLoopHeader->phis(), 1))
OpenPOWER on IntegriCloud