Skip to content

Commit 145c9d4

Browse files
committed
Cleanup the canonicalization code.
1 parent 338715a commit 145c9d4

File tree

1 file changed

+46
-44
lines changed

1 file changed

+46
-44
lines changed

lib/SILOptimizer/Mandatory/TFCanonicalizeCFG.cpp

Lines changed: 46 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -725,6 +725,24 @@ void SingleExitLoopTransformer::ensureSingleExitBlock() {
725725
<< SILPrintContext(llvm::dbgs()).getID(nearestCommonPD)
726726
<< "\n");
727727

728+
// Compute the set of preheaders of loops that are unrelated to our loop w.r.t
729+
// nesting. This will be used when needing to identify cases where a loop
730+
// from outside is moved into the current loop. e.g.,
731+
// while ... {
732+
// if ... {
733+
// for(...) {...} // This should be nested into the while loop.
734+
// break;
735+
// }
736+
// }
737+
SmallPtrSet<SILBasicBlock *, 32> unrelatedPreheaders;
738+
for (auto *otherLoop : *LI) {
739+
// If loop and otherLoop are not nested into either, remember the preheader.
740+
if (!otherLoop->contains(loop) && !loop->contains(otherLoop)) {
741+
unrelatedPreheaders.insert(otherLoop->getLoopPreheader());
742+
}
743+
}
744+
745+
728746
// Collect all the blocks from each exiting block up to nearest common PD.
729747
SmallPtrSet<SILBasicBlock *, 32> blocksToBeMoved;
730748
for (SILBasicBlock *exitBlock : exitBlockList) {
@@ -749,38 +767,17 @@ void SingleExitLoopTransformer::ensureSingleExitBlock() {
749767
continue;
750768
}
751769

752-
// Check if this is a preheader of another loop.
770+
// Check if `succ` is a preheader of another loop.
753771
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-
}
772+
if (unrelatedPreheaders.count(succ) > 0) {
773+
// We are about a move a loop from outside. Perform canonicalization
774+
// of that loop first.
775+
SILBasicBlock *unrelatedHeader = succ->getSingleSuccessorBlock();
776+
assert(unrelatedHeader &&
777+
"There should be a single successor for a preheader.");
778+
succBlockLoop = LI->getLoopFor(unrelatedHeader);
779+
SingleExitLoopTransformer::doIt(deviceInfo, LI, DI, succBlockLoop,
780+
PDI);
784781
}
785782

786783
if (DI->properlyDominates(header, succ)) {
@@ -800,16 +797,23 @@ void SingleExitLoopTransformer::ensureSingleExitBlock() {
800797

801798
// Clone the block and rewire the edge.
802799
SILBasicBlock *clonedSucc = cloner.initAndCloneBlock(succ);
800+
// If `succ` is a preheader of an unrelated loop, we will have to clone
801+
// the entire loop now so that we can also incrementally update LoopInfo.
803802
if (succBlockLoop) {
804-
// We will have to clone the entire loop now.
805803
SILLoop *clonedLoop =
806804
cloner.cloneLoop(LI, succBlockLoop, succBlockLoop->getHeader());
807-
//clonedLoop->setParentLoop(loop->getParentLoop());
808-
if (clonedLoop->getParentLoop() == nullptr) {
809-
LI->addTopLevelLoop(clonedLoop);
805+
changeBranchTarget(clonedSucc->getTerminator(), 0,
806+
clonedLoop->getHeader(), /*preserveArgs*/ true);
807+
// Note that all the nodes of `clonedLoop` should be moved into the
808+
// current loop. We do that here itself as an optimization and also
809+
// because the dominator and post-dominator information for the new
810+
// blocks in `clonedLoop` are stale and cannot be relied upon.
811+
for (SILBasicBlock *bb : clonedLoop->getBlocks()) {
812+
blocksToBeMoved.insert(bb);
810813
}
811-
changeBranchTarget(clonedSucc->getTerminator(), 0, clonedLoop->getHeader(), /*preserveArgs*/ true);
812-
// succBlockLoop->addBasicBlockToLoop(clonedSucc, LI->getBase());
814+
// Add the header to worklist for processing the exit edge.
815+
// (Other successor edges are already processed above.)
816+
worklist.insert(clonedLoop->getHeader());
813817
}
814818
changeBranchTarget(current->getTerminator(), edgeIdx, clonedSucc,
815819
/*preserveArgs*/ true);
@@ -833,26 +837,24 @@ void SingleExitLoopTransformer::ensureSingleExitBlock() {
833837
if (outsideBlockLoop == nullptr) {
834838
loop->addBasicBlockToLoop(outsideBlock, LI->getBase());
835839
} else {
836-
// FIXME: We don't deal with cases where the nodes being moved in
837-
// belong to another loop yet. e.g.,
840+
// We deal with the case where the nodes being moved in
841+
// belong to another loop. e.g.,
838842
// while ... {
839843
// if ... {
840844
// for(...) {...}
841845
// break;
842846
// }
843847
// }
844-
// Check that `loop` is nested within `reachableLoop`.
845-
// assert(outsideBlockLoop->contains(loop) &&
846-
// "Nodes being moved belong to a non-nested loop.");
847848
if (outsideBlockLoop->contains(loop)) {
848-
// `loop` is nested within `outsideBlockLoop`.
849-
// Move the node into our loop.
849+
// `loop` is nested within `outsideBlockLoop`. Move the node from
850+
// `outsideBlockLoop` into our `loop`.
850851
outsideBlockLoop->removeBlockFromLoop(outsideBlock);
851852
LI->changeLoopFor(outsideBlock, nullptr);
852853
loop->addBasicBlockToLoop(outsideBlock, LI->getBase());
853854
} else {
854855
if (!loop->contains(outsideBlockLoop)) {
855856
if (outsideBlockLoop->getParentLoop() == nullptr) {
857+
// Remove from top-level loops as we are nesting it in `loop`.
856858
LI->removeLoop(llvm::find(*LI, outsideBlockLoop));
857859
}
858860
loop->addChildLoop(outsideBlockLoop);

0 commit comments

Comments
 (0)