Index: lib/Transforms/Utils/LoopUnroll.cpp =================================================================== --- lib/Transforms/Utils/LoopUnroll.cpp +++ lib/Transforms/Utils/LoopUnroll.cpp @@ -199,11 +199,15 @@ assert(OriginalBB == OldLoop->getHeader() && "Header should be first in RPO"); + NewLoop = new Loop(); Loop *NewLoopParent = NewLoops.lookup(OldLoop->getParentLoop()); - assert(NewLoopParent && - "Expected parent loop before sub-loop in RPO"); - NewLoop = new Loop; - NewLoopParent->addChildLoop(NewLoop); + + if (NewLoopParent) { + NewLoopParent->addChildLoop(NewLoop); + } else { + LI->addTopLevelLoop(NewLoop); + } + NewLoop->addBasicBlockToLoop(ClonedBB, *LI); return OldLoop; } else { Index: lib/Transforms/Utils/LoopUnrollRuntime.cpp =================================================================== --- lib/Transforms/Utils/LoopUnrollRuntime.cpp +++ lib/Transforms/Utils/LoopUnrollRuntime.cpp @@ -311,17 +311,21 @@ } NewLoopsMap NewLoops; - NewLoops[L] = NewLoop; + if (NewLoop) + NewLoops[L] = NewLoop; + else if (ParentLoop) + NewLoops[L] = ParentLoop; // For each block in the original loop, create a new copy, // and update the value map with the newly created values. for (LoopBlocksDFS::RPOIterator BB = BlockBegin; BB != BlockEnd; ++BB) { BasicBlock *NewBB = CloneBasicBlock(*BB, VMap, "." + suffix, F); NewBlocks.push_back(NewBB); - - if (NewLoop) { - addClonedBlockToLoopInfo(*BB, NewBB, LI, NewLoops); - } else if (ParentLoop) - ParentLoop->addBasicBlockToLoop(NewBB, *LI); + + // If we're unrolling the outernmost loop, there's no remainder loop, + // and this block isn't in a nested loop, then the new block is not + // in any loop. Otherwise, add it to loopinfo. + if (CreateRemainderLoop || LI->getLoopFor(*BB) != L || ParentLoop) + addClonedBlockToLoopInfo(*BB, NewBB, LI, NewLoops); VMap[*BB] = NewBB; if (Header == *BB) { Index: test/Transforms/LoopUnroll/runtime-li.ll =================================================================== --- test/Transforms/LoopUnroll/runtime-li.ll +++ test/Transforms/LoopUnroll/runtime-li.ll @@ -0,0 +1,34 @@ +; RUN: opt -S -loop-unroll -unroll-runtime -unroll-count=2 -verify-loop-info -pass-remarks=loop-unroll < %s 2>&1 | FileCheck %s + +target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" +target triple = "x86_64-unknown-linux-gnu" + +; CHECK: remark: {{.*}}: unrolled loop by a factor of 2 with run-time trip count +; CHECK: @widget +; CHECK: ret void +define void @widget(double* %arg, double* %arg1) local_unnamed_addr { +bb: + br label %bb2 + +bb2: ; preds = %bb7, %bb + %tmp = phi double* [ %tmp8, %bb7 ], [ undef, %bb ] + br label %bb3 + +bb3: ; preds = %bb4, %bb2 + br i1 undef, label %bb4, label %bb7 + +bb4: ; preds = %bb3 + %tmp5 = load i64, i64* undef, align 8 + store i64 %tmp5, i64* undef, align 8 + %tmp6 = icmp eq double* undef, %arg + br label %bb3 + +bb7: ; preds = %bb3 + store double undef, double* undef, align 8 + %tmp8 = getelementptr inbounds double, double* %tmp, i64 1 + %tmp9 = icmp eq double* %tmp8, %arg1 + br i1 %tmp9, label %bb10, label %bb2 + +bb10: ; preds = %bb7 + ret void +}