diff --git a/llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp b/llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp --- a/llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp +++ b/llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp @@ -838,9 +838,16 @@ MIRBuilder.buildBrIndirect(Tgt); // Link successors. + SmallPtrSet AddedSuccessors; MachineBasicBlock &CurBB = MIRBuilder.getMBB(); - for (const BasicBlock *Succ : successors(&BrInst)) + for (const BasicBlock *Succ : successors(&BrInst)) { + // It's legal for indirectbr instructions to have duplicate blocks in the + // destination list. We don't allow this in MIR. Skip anything that's + // already a successor. + if (!AddedSuccessors.insert(Succ).second) + continue; CurBB.addSuccessor(&getMBB(*Succ)); + } return true; } diff --git a/llvm/test/CodeGen/AArch64/GlobalISel/irtranslator-indirect-br-repeated-block.ll b/llvm/test/CodeGen/AArch64/GlobalISel/irtranslator-indirect-br-repeated-block.ll new file mode 100644 --- /dev/null +++ b/llvm/test/CodeGen/AArch64/GlobalISel/irtranslator-indirect-br-repeated-block.ll @@ -0,0 +1,26 @@ +; NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py +; RUN: llc -O0 -mtriple=aarch64-apple-ios -global-isel -stop-after=irtranslator -verify-machineinstrs %s -o - | FileCheck %s +; +; Make sure that we don't duplicate successors/predecessors when translating +; indirectbr instructions with duplicate block labels. + +define void @foo() { + ; CHECK-LABEL: name: foo + ; CHECK: bb.1 (%ir-block.0): + ; CHECK: successors: %bb.2(0x2aaaaaaa), %bb.4(0x2aaaaaaa), %bb.3(0x2aaaaaaa) + ; CHECK: [[DEF:%[0-9]+]]:_(p0) = G_IMPLICIT_DEF + ; CHECK: G_BRINDIRECT [[DEF]](p0) + ; CHECK: bb.2 (%ir-block.1): + ; CHECK: successors: + ; CHECK: bb.3 (%ir-block.2): + ; CHECK: successors: + ; CHECK: bb.4 (%ir-block.3): + ; CHECK: RET_ReallyLR + indirectbr i8* undef, [label %1, label %3, label %2, label %3, label %3] +1: + unreachable +2: + unreachable +3: + ret void +}