diff --git a/llvm/lib/Transforms/Utils/LoopPeel.cpp b/llvm/lib/Transforms/Utils/LoopPeel.cpp --- a/llvm/lib/Transforms/Utils/LoopPeel.cpp +++ b/llvm/lib/Transforms/Utils/LoopPeel.cpp @@ -115,7 +115,12 @@ // This can be an indication of two different things: // 1) The loop is not rotated. // 2) The loop contains irreducible control flow that involves the latch. - if (L->getLoopLatch() != L->getExitingBlock()) + const BasicBlock *Latch = L->getLoopLatch(); + if (Latch != L->getExitingBlock()) + return false; + + // Peeling is only supported if the latch is a conditional branch. + if (!isa(Latch)) return false; return true; diff --git a/llvm/test/Transforms/LoopUnroll/peel-loop-conditions.ll b/llvm/test/Transforms/LoopUnroll/peel-loop-conditions.ll --- a/llvm/test/Transforms/LoopUnroll/peel-loop-conditions.ll +++ b/llvm/test/Transforms/LoopUnroll/peel-loop-conditions.ll @@ -1140,5 +1140,35 @@ ret void } +; Invoke is not a conditional branch that we can optimize, +; so this shouldn't be peeled at all. This is a reproducer +; for a bug where evaluating the loop would fail an assertion. +define void @test17() personality i8* undef{ +; CHECK-LABEL: @test17( +; CHECK-NEXT: body: +; CHECK-NEXT: br label [[LOOP:%.*]] +; CHECK: loop: +; CHECK-NEXT: [[CONST:%.*]] = phi i64 [ -33, [[LOOP]] ], [ -20, [[BODY:%.*]] ] +; CHECK-NEXT: invoke void @f1() +; CHECK-NEXT: to label [[LOOP]] unwind label [[EH_UNW_LOOPEXIT:%.*]] +; CHECK: eh.Unw.loopexit: +; CHECK-NEXT: [[LPAD_LOOPEXIT:%.*]] = landingpad { i8*, i32 } +; CHECK-NEXT: catch i8* null +; CHECK-NEXT: ret void +; +body: + br label %loop + +loop: + %const = phi i64 [ -33, %loop ], [ -20, %body ] + invoke void @f1() + to label %loop unwind label %eh.Unw.loopexit + +eh.Unw.loopexit: + %lpad.loopexit = landingpad { i8*, i32 } + catch i8* null + ret void +} + declare void @init() declare void @sink()