@@ -749,6 +749,40 @@ void SingleExitLoopTransformer::ensureSingleExitBlock() {
749
749
continue ;
750
750
}
751
751
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
+
752
786
if (DI->properlyDominates (header, succ)) {
753
787
worklist.insert (succ);
754
788
continue ;
@@ -766,6 +800,17 @@ void SingleExitLoopTransformer::ensureSingleExitBlock() {
766
800
767
801
// Clone the block and rewire the edge.
768
802
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
+ }
769
814
changeBranchTarget (current->getTerminator (), edgeIdx, clonedSucc,
770
815
/* preserveArgs*/ true );
771
816
worklist.insert (clonedSucc);
@@ -785,7 +830,9 @@ void SingleExitLoopTransformer::ensureSingleExitBlock() {
785
830
786
831
// Update loop info if this belongs to a parent loop.
787
832
SILLoop *outsideBlockLoop = LI->getLoopFor (outsideBlock);
788
- if (outsideBlockLoop != nullptr ) {
833
+ if (outsideBlockLoop == nullptr ) {
834
+ loop->addBasicBlockToLoop (outsideBlock, LI->getBase ());
835
+ } else {
789
836
// FIXME: We don't deal with cases where the nodes being moved in
790
837
// belong to another loop yet. e.g.,
791
838
// while ... {
@@ -795,15 +842,32 @@ void SingleExitLoopTransformer::ensureSingleExitBlock() {
795
842
// }
796
843
// }
797
844
// 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
+ }
803
867
// top-level loop is already correct.
804
868
}
805
- loop->addBasicBlockToLoop (outsideBlock, LI->getBase ());
806
869
}
870
+
807
871
if (cloner.hasCloned ()) {
808
872
// TODO(https://bugs.swift.org/browse/SR-8336): the transformations here are
809
873
// simple that we should be able to incrementally update the DI & PDI.
@@ -1298,7 +1362,7 @@ void SESERegionBuilder::ensureSingleExitFromLoops() {
1298
1362
continue ;
1299
1363
}
1300
1364
bool loopChanged =
1301
- SingleExitLoopTransformer::doIt (&deviceInfo, &LI, &DI, loop, &PDI);
1365
+ SingleExitLoopTransformer::doIt (&deviceInfo, &LI, &DI, loop, &PDI);
1302
1366
changed |= loopChanged;
1303
1367
}
1304
1368
if (changed) {
0 commit comments