Skip to content

Commit 338715a

Browse files
committed
Take care of loops that are moved from outside.
1 parent d09ba77 commit 338715a

File tree

1 file changed

+72
-8
lines changed

1 file changed

+72
-8
lines changed

lib/SILOptimizer/Mandatory/TFCanonicalizeCFG.cpp

Lines changed: 72 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -749,6 +749,40 @@ void SingleExitLoopTransformer::ensureSingleExitBlock() {
749749
continue;
750750
}
751751

752+
// Check if this is a preheader of another loop.
753+
SILLoop *succBlockLoop = nullptr;
754+
if (SILBasicBlock* succBlockLoopHeader = succ->getSingleSuccessorBlock()) {
755+
succBlockLoop = LI->getLoopFor(succBlockLoopHeader);
756+
if (succBlockLoop &&
757+
LI->getLoopFor(succ) != succBlockLoop &&
758+
succBlockLoop->getHeader() == succBlockLoopHeader &&
759+
!succBlockLoop->contains(loop) &&
760+
!loop->contains(succBlockLoop)) {
761+
// `succ` is a pre-header of a loop that does not contain this loop
762+
// or contained within this loop. Before moving this loop into our
763+
// loop, we should first perform the canonicalization on that loop
764+
// first.
765+
SingleExitLoopTransformer::doIt(deviceInfo, LI, DI, succBlockLoop, PDI);
766+
// // Remove from the top-level loops before making it a child.
767+
// if (succBlockLoop->getParentLoop() == nullptr) {
768+
// LI->removeLoop(llvm::find(*LI, succBlockLoop));
769+
// }
770+
// loop->addChildLoop(succBlockLoop);
771+
// // Add the block to this loop and all its parents.
772+
// for (SILBasicBlock* bb : succBlockLoop->getBlocks()) {
773+
// auto *L = loop;
774+
// while (L) {
775+
// L->addBlockEntry(bb);
776+
// L = L->getParentLoop();
777+
// }
778+
// }
779+
// Reinitialize succ as it might have been changed by the transformer.
780+
// succ = succBlockLoop->getHeader();
781+
} else {
782+
succBlockLoop = nullptr;
783+
}
784+
}
785+
752786
if (DI->properlyDominates(header, succ)) {
753787
worklist.insert(succ);
754788
continue;
@@ -766,6 +800,17 @@ void SingleExitLoopTransformer::ensureSingleExitBlock() {
766800

767801
// Clone the block and rewire the edge.
768802
SILBasicBlock *clonedSucc = cloner.initAndCloneBlock(succ);
803+
if (succBlockLoop) {
804+
// We will have to clone the entire loop now.
805+
SILLoop *clonedLoop =
806+
cloner.cloneLoop(LI, succBlockLoop, succBlockLoop->getHeader());
807+
//clonedLoop->setParentLoop(loop->getParentLoop());
808+
if (clonedLoop->getParentLoop() == nullptr) {
809+
LI->addTopLevelLoop(clonedLoop);
810+
}
811+
changeBranchTarget(clonedSucc->getTerminator(), 0, clonedLoop->getHeader(), /*preserveArgs*/ true);
812+
// succBlockLoop->addBasicBlockToLoop(clonedSucc, LI->getBase());
813+
}
769814
changeBranchTarget(current->getTerminator(), edgeIdx, clonedSucc,
770815
/*preserveArgs*/ true);
771816
worklist.insert(clonedSucc);
@@ -785,7 +830,9 @@ void SingleExitLoopTransformer::ensureSingleExitBlock() {
785830

786831
// Update loop info if this belongs to a parent loop.
787832
SILLoop *outsideBlockLoop = LI->getLoopFor(outsideBlock);
788-
if (outsideBlockLoop != nullptr) {
833+
if (outsideBlockLoop == nullptr) {
834+
loop->addBasicBlockToLoop(outsideBlock, LI->getBase());
835+
} else {
789836
// FIXME: We don't deal with cases where the nodes being moved in
790837
// belong to another loop yet. e.g.,
791838
// while ... {
@@ -795,15 +842,32 @@ void SingleExitLoopTransformer::ensureSingleExitBlock() {
795842
// }
796843
// }
797844
// Check that `loop` is nested within `reachableLoop`.
798-
assert(outsideBlockLoop->contains(loop) &&
799-
"Nodes being moved belong to a non-nested loop.");
800-
// Move the node into our loop.
801-
outsideBlockLoop->removeBlockFromLoop(outsideBlock);
802-
LI->changeLoopFor(outsideBlock, nullptr);
845+
// assert(outsideBlockLoop->contains(loop) &&
846+
// "Nodes being moved belong to a non-nested loop.");
847+
if (outsideBlockLoop->contains(loop)) {
848+
// `loop` is nested within `outsideBlockLoop`.
849+
// Move the node into our loop.
850+
outsideBlockLoop->removeBlockFromLoop(outsideBlock);
851+
LI->changeLoopFor(outsideBlock, nullptr);
852+
loop->addBasicBlockToLoop(outsideBlock, LI->getBase());
853+
} else {
854+
if (!loop->contains(outsideBlockLoop)) {
855+
if (outsideBlockLoop->getParentLoop() == nullptr) {
856+
LI->removeLoop(llvm::find(*LI, outsideBlockLoop));
857+
}
858+
loop->addChildLoop(outsideBlockLoop);
859+
}
860+
// Add the block to this loop and all its parents.
861+
auto *L = loop;
862+
while (L) {
863+
L->addBlockEntry(outsideBlock);
864+
L = L->getParentLoop();
865+
}
866+
}
803867
// top-level loop is already correct.
804868
}
805-
loop->addBasicBlockToLoop(outsideBlock, LI->getBase());
806869
}
870+
807871
if (cloner.hasCloned()) {
808872
// TODO(https://bugs.swift.org/browse/SR-8336): the transformations here are
809873
// simple that we should be able to incrementally update the DI & PDI.
@@ -1298,7 +1362,7 @@ void SESERegionBuilder::ensureSingleExitFromLoops() {
12981362
continue;
12991363
}
13001364
bool loopChanged =
1301-
SingleExitLoopTransformer::doIt(&deviceInfo, &LI, &DI, loop, &PDI);
1365+
SingleExitLoopTransformer::doIt(&deviceInfo, &LI, &DI, loop, &PDI);
13021366
changed |= loopChanged;
13031367
}
13041368
if (changed) {

0 commit comments

Comments
 (0)