diff --git a/llvm/lib/Transforms/Scalar/SimpleLoopUnswitch.cpp b/llvm/lib/Transforms/Scalar/SimpleLoopUnswitch.cpp --- a/llvm/lib/Transforms/Scalar/SimpleLoopUnswitch.cpp +++ b/llvm/lib/Transforms/Scalar/SimpleLoopUnswitch.cpp @@ -2775,14 +2775,15 @@ SmallVector ExitBlocks; L.getUniqueExitBlocks(ExitBlocks); - // We cannot unswitch if exit blocks contain a cleanuppad instruction as we - // don't know how to split those exit blocks. + // We cannot unswitch if exit blocks contain a cleanuppad/catchswitch + // instruction as we don't know how to split those exit blocks. // FIXME: We should teach SplitBlock to handle this and remove this // restriction. for (auto *ExitBB : ExitBlocks) { - if (isa(ExitBB->getFirstNonPHI())) { - LLVM_DEBUG( - dbgs() << "Cannot unswitch because of cleanuppad in exit block\n"); + auto *I = ExitBB->getFirstNonPHI(); + if (isa(I) || isa(I)) { + LLVM_DEBUG(dbgs() << "Cannot unswitch because of cleanuppad/catchswitch " + "in exit block\n"); return false; } } diff --git a/llvm/lib/Transforms/Utils/BasicBlockUtils.cpp b/llvm/lib/Transforms/Utils/BasicBlockUtils.cpp --- a/llvm/lib/Transforms/Utils/BasicBlockUtils.cpp +++ b/llvm/lib/Transforms/Utils/BasicBlockUtils.cpp @@ -766,8 +766,10 @@ BBName); } BasicBlock::iterator SplitIt = SplitPt->getIterator(); - while (isa(SplitIt) || SplitIt->isEHPad()) + while (isa(SplitIt) || SplitIt->isEHPad()) { ++SplitIt; + assert(SplitIt != SplitPt->getParent()->end()); + } std::string Name = BBName.str(); BasicBlock *New = Old->splitBasicBlock( SplitIt, Name.empty() ? Old->getName() + ".split" : Name); diff --git a/llvm/test/Transforms/SimpleLoopUnswitch/catchswitch.ll b/llvm/test/Transforms/SimpleLoopUnswitch/catchswitch.ll new file mode 100644 --- /dev/null +++ b/llvm/test/Transforms/SimpleLoopUnswitch/catchswitch.ll @@ -0,0 +1,33 @@ +; RUN: opt -passes=simple-loop-unswitch -enable-nontrivial-unswitch < %s -S | FileCheck %s + +; CHECK: if.end{{.*}}: +; CHECK-NOT: if.end{{.*}}: +declare i32 @__gxx_wasm_personality_v0(...) + +declare void @foo() + +define void @test(i1 %arg) personality i8* bitcast (i32 (...)* @__gxx_wasm_personality_v0 to i8*) { +entry: + br label %while.body + +while.body: ; preds = %cleanup, %entry + br i1 %arg, label %if.end, label %if.then + +if.then: ; preds = %while.body + br label %if.end + +if.end: ; preds = %if.then, %while.body + invoke void @foo() + to label %cleanup unwind label %catch.dispatch + +catch.dispatch: ; preds = %invoke.cont, %if.end + %0 = catchswitch within none [label %catch] unwind to caller + +catch: ; preds = %catch.dispatch + %1 = catchpad within %0 [i8* null] + unreachable + +cleanup: ; preds = %invoke.cont + br label %while.body +} +