Skip to content

Commit 6feb637

Browse files
committed
[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
1 parent 79c88c3 commit 6feb637

File tree

5 files changed

+252
-76
lines changed

5 files changed

+252
-76
lines changed

llvm/lib/Transforms/Scalar/LoopInterchange.cpp

Lines changed: 54 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -411,8 +411,6 @@ class LoopInterchangeTransform {
411411
bool adjustLoopLinks();
412412
void adjustLoopPreheaders();
413413
bool adjustLoopBranches();
414-
void updateIncomingBlock(BasicBlock *CurrBlock, BasicBlock *OldPred,
415-
BasicBlock *NewPred);
416414

417415
Loop *OuterLoop;
418416
Loop *InnerLoop;
@@ -455,6 +453,7 @@ struct LoopInterchange : public FunctionPass {
455453
AU.addPreserved<DominatorTreeWrapperPass>();
456454
AU.addPreserved<LoopInfoWrapperPass>();
457455
AU.addPreserved<ScalarEvolutionWrapperPass>();
456+
AU.addPreservedID(LCSSAID);
458457
}
459458

460459
bool runOnFunction(Function &F) override {
@@ -1297,9 +1296,8 @@ static void moveBBContents(BasicBlock *FromBB, Instruction *InsertBefore) {
12971296
FromBB->getTerminator()->getIterator());
12981297
}
12991298

1300-
void LoopInterchangeTransform::updateIncomingBlock(BasicBlock *CurrBlock,
1301-
BasicBlock *OldPred,
1302-
BasicBlock *NewPred) {
1299+
static void updateIncomingBlock(BasicBlock *CurrBlock, BasicBlock *OldPred,
1300+
BasicBlock *NewPred) {
13031301
for (PHINode &PHI : CurrBlock->phis()) {
13041302
unsigned Num = PHI.getNumIncomingValues();
13051303
for (unsigned i = 0; i < Num; ++i) {
@@ -1330,6 +1328,52 @@ static void updateSuccessor(BranchInst *BI, BasicBlock *OldBB,
13301328
}
13311329
}
13321330

1331+
// Move Lcssa PHIs to the right place.
1332+
static void moveLCSSAPhis(BasicBlock *InnerExit, BasicBlock *InnerLatch,
1333+
BasicBlock *OuterLatch) {
1334+
SmallVector<PHINode *, 8> LcssaInnerExit;
1335+
for (PHINode &P : InnerExit->phis())
1336+
LcssaInnerExit.push_back(&P);
1337+
1338+
SmallVector<PHINode *, 8> LcssaInnerLatch;
1339+
for (PHINode &P : InnerLatch->phis())
1340+
LcssaInnerLatch.push_back(&P);
1341+
1342+
// Lcssa PHIs for values used outside the inner loop are in InnerExit.
1343+
// If a PHI node has users outside of InnerExit, it has a use outside the
1344+
// interchanged loop and we have to preserve it. We move these to
1345+
// InnerLatch, which will become the new exit block for the innermost
1346+
// loop after interchanging. For PHIs only used in InnerExit, we can just
1347+
// replace them with the incoming value.
1348+
for (PHINode *P : LcssaInnerExit) {
1349+
bool hasUsersOutside = false;
1350+
for (auto UI = P->use_begin(), E = P->use_end(); UI != E;) {
1351+
Use &U = *UI;
1352+
++UI;
1353+
auto *Usr = cast<Instruction>(U.getUser());
1354+
if (Usr->getParent() != InnerExit) {
1355+
hasUsersOutside = true;
1356+
continue;
1357+
}
1358+
U.set(P->getIncomingValueForBlock(InnerLatch));
1359+
}
1360+
if (hasUsersOutside)
1361+
P->moveBefore(InnerLatch->getFirstNonPHI());
1362+
else
1363+
P->eraseFromParent();
1364+
}
1365+
1366+
// If the inner loop latch contains LCSSA PHIs, those come from a child loop
1367+
// and we have to move them to the new inner latch.
1368+
for (PHINode *P : LcssaInnerLatch)
1369+
P->moveBefore(InnerExit->getFirstNonPHI());
1370+
1371+
// Now adjust the incoming blocks for the LCSSA PHIs.
1372+
// For PHIs moved from Inner's exit block, we need to replace Inner's latch
1373+
// with the new latch.
1374+
updateIncomingBlock(InnerLatch, InnerLatch, OuterLatch);
1375+
}
1376+
13331377
bool LoopInterchangeTransform::adjustLoopBranches() {
13341378
LLVM_DEBUG(dbgs() << "adjustLoopBranches called\n");
13351379
std::vector<DominatorTree::UpdateType> DTUpdates;
@@ -1409,17 +1453,6 @@ bool LoopInterchangeTransform::adjustLoopBranches() {
14091453
updateSuccessor(InnerLoopLatchPredecessorBI, InnerLoopLatch,
14101454
InnerLoopLatchSuccessor, DTUpdates);
14111455

1412-
// Adjust PHI nodes in InnerLoopLatchSuccessor. Update all uses of PHI with
1413-
// the value and remove this PHI node from inner loop.
1414-
SmallVector<PHINode *, 8> LcssaVec;
1415-
for (PHINode &P : InnerLoopLatchSuccessor->phis())
1416-
LcssaVec.push_back(&P);
1417-
1418-
for (PHINode *P : LcssaVec) {
1419-
Value *Incoming = P->getIncomingValueForBlock(InnerLoopLatch);
1420-
P->replaceAllUsesWith(Incoming);
1421-
P->eraseFromParent();
1422-
}
14231456

14241457
if (OuterLoopLatchBI->getSuccessor(0) == OuterLoopHeader)
14251458
OuterLoopLatchSuccessor = OuterLoopLatchBI->getSuccessor(1);
@@ -1431,12 +1464,15 @@ bool LoopInterchangeTransform::adjustLoopBranches() {
14311464
updateSuccessor(OuterLoopLatchBI, OuterLoopLatchSuccessor, InnerLoopLatch,
14321465
DTUpdates);
14331466

1434-
updateIncomingBlock(OuterLoopLatchSuccessor, OuterLoopLatch, InnerLoopLatch);
1435-
14361467
DT->applyUpdates(DTUpdates);
14371468
restructureLoops(OuterLoop, InnerLoop, InnerLoopPreHeader,
14381469
OuterLoopPreHeader);
14391470

1471+
moveLCSSAPhis(InnerLoopLatchSuccessor, InnerLoopLatch, OuterLoopLatch);
1472+
// For PHIs in the exit block of the outer loop, outer's latch has been
1473+
// replaced by Inners'.
1474+
updateIncomingBlock(OuterLoopLatchSuccessor, OuterLoopLatch, InnerLoopLatch);
1475+
14401476
// Now update the reduction PHIs in the inner and outer loop headers.
14411477
SmallVector<PHINode *, 4> InnerLoopPHIs, OuterLoopPHIs;
14421478
for (PHINode &PHI : drop_begin(InnerLoopHeader->phis(), 1))

llvm/test/Transforms/LoopInterchange/interchangeable.ll

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2-
; RUN: opt < %s -basicaa -loop-interchange -verify-dom-info -verify-loop-info -verify-scev -S | FileCheck %s
2+
; RUN: opt < %s -basicaa -loop-interchange -verify-dom-info -verify-loop-info -verify-scev -verify-loop-lcssa -S | FileCheck %s
33

44
target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
55
target triple = "x86_64-unknown-linux-gnu"

0 commit comments

Comments
 (0)