Index: lib/Transforms/Utils/CloneFunction.cpp =================================================================== --- lib/Transforms/Utils/CloneFunction.cpp +++ lib/Transforms/Utils/CloneFunction.cpp @@ -684,6 +684,22 @@ RF_NoModuleLevelChanges | RF_IgnoreMissingLocals); } +/// \brief Clones the original loop \p OrigLoop structure +/// and keeps it ready to add the basic blocks. +static void createNewLoops(Loop *OrigLoop, LoopInfo *LI, Loop *ParentLoop, + std::map &ClonedLoopMap) { + if (OrigLoop->empty()) return; + + for (auto CurrLoop : OrigLoop->getSubLoops()) { + Loop *NewLoop = new Loop(); + ParentLoop->addChildLoop(NewLoop); + ClonedLoopMap[CurrLoop] = NewLoop; + + // Recursively add the new loops. + createNewLoops(CurrLoop, LI, NewLoop, ClonedLoopMap); + } +} + /// \brief Clones a loop \p OrigLoop. Returns the loop and the blocks in \p /// Blocks. /// @@ -694,8 +710,6 @@ const Twine &NameSuffix, LoopInfo *LI, DominatorTree *DT, SmallVectorImpl &Blocks) { - assert(OrigLoop->getSubLoops().empty() && - "Loop to be cloned cannot have inner loop"); Function *F = OrigLoop->getHeader()->getParent(); Loop *ParentLoop = OrigLoop->getParentLoop(); @@ -705,6 +719,14 @@ else LI->addTopLevelLoop(NewLoop); + // Map each old Loop with new one. + std::map ClonedLoopMap; + // Add the top level loop provided for cloning. + ClonedLoopMap[OrigLoop] = NewLoop; + + // Recursively clone the loop structure. + createNewLoops(OrigLoop, LI, NewLoop, ClonedLoopMap); + BasicBlock *OrigPH = OrigLoop->getLoopPreheader(); assert(OrigPH && "No preheader"); BasicBlock *NewPH = CloneBasicBlock(OrigPH, VMap, NameSuffix, F); @@ -723,8 +745,13 @@ BasicBlock *NewBB = CloneBasicBlock(BB, VMap, NameSuffix, F); VMap[BB] = NewBB; + // Get the innermost loop for the BB. + Loop* L = LI->getLoopFor(BB); + // Get the corresponding cloned loop. + Loop* NewClonedLoop = ClonedLoopMap[L]; + assert(NewClonedLoop && "Could not find the corresponding cloned loop"); // Update LoopInfo. - NewLoop->addBasicBlockToLoop(NewBB, *LI); + NewClonedLoop->addBasicBlockToLoop(NewBB, *LI); // Add DominatorTree node. After seeing all blocks, update to correct IDom. DT->addNewBlock(NewBB, NewPH);