diff --git a/llvm/include/llvm/Target/GenericOpcodes.td b/llvm/include/llvm/Target/GenericOpcodes.td --- a/llvm/include/llvm/Target/GenericOpcodes.td +++ b/llvm/include/llvm/Target/GenericOpcodes.td @@ -1085,6 +1085,8 @@ let hasSideEffects = 0; let isBranch = 1; let isTerminator = 1; + let isBarrier = 1; + let isIndirectBranch = 1; } // Generic branch to jump table entry @@ -1094,6 +1096,8 @@ let hasSideEffects = 0; let isBranch = 1; let isTerminator = 1; + let isBarrier = 1; + let isIndirectBranch = 1; } def G_READ_REGISTER : GenericInstruction { diff --git a/llvm/lib/CodeGen/MachineVerifier.cpp b/llvm/lib/CodeGen/MachineVerifier.cpp --- a/llvm/lib/CodeGen/MachineVerifier.cpp +++ b/llvm/lib/CodeGen/MachineVerifier.cpp @@ -863,6 +863,22 @@ const MCInstrDesc &MCID = MI->getDesc(); unsigned NumOps = MI->getNumOperands(); + // Branches must reference a basic block if they are not indirect + if (MI->isBranch() && !MI->isIndirectBranch()) { + bool HasMBB = false; + for (const MachineOperand &Op : MI->operands()) { + if (Op.isMBB()) { + HasMBB = true; + break; + } + } + + if (!HasMBB) + report("Branch instruction is missing a basic block operand or " + "isIndirectBranch property", + MI); + } + // Check types. SmallVector Types; for (unsigned I = 0, E = std::min(MCID.getNumOperands(), NumOps); diff --git a/llvm/test/CodeGen/AArch64/GlobalISel/legalize-blockaddress.mir b/llvm/test/CodeGen/AArch64/GlobalISel/legalize-blockaddress.mir --- a/llvm/test/CodeGen/AArch64/GlobalISel/legalize-blockaddress.mir +++ b/llvm/test/CodeGen/AArch64/GlobalISel/legalize-blockaddress.mir @@ -25,7 +25,6 @@ body: | ; CHECK-LABEL: name: test_blockaddress ; CHECK: bb.0 (%ir-block.0): - ; CHECK: successors: %bb.1(0x80000000) ; CHECK: [[BLOCK_ADDR:%[0-9]+]]:_(p0) = G_BLOCK_ADDR blockaddress(@test_blockaddress, %ir-block.block) ; CHECK: [[ADRP:%[0-9]+]]:gpr64(p0) = ADRP target-flags(aarch64-page) @addr ; CHECK: [[ADD_LOW:%[0-9]+]]:_(p0) = G_ADD_LOW [[ADRP]](p0), target-flags(aarch64-pageoff, aarch64-nc) @addr diff --git a/llvm/test/CodeGen/AArch64/GlobalISel/select-blockaddress.mir b/llvm/test/CodeGen/AArch64/GlobalISel/select-blockaddress.mir --- a/llvm/test/CodeGen/AArch64/GlobalISel/select-blockaddress.mir +++ b/llvm/test/CodeGen/AArch64/GlobalISel/select-blockaddress.mir @@ -30,7 +30,6 @@ body: | ; CHECK-LABEL: name: test_blockaddress ; CHECK: bb.0 (%ir-block.0): - ; CHECK: successors: %bb.1(0x80000000) ; CHECK: [[MOVaddrBA:%[0-9]+]]:gpr64 = MOVaddrBA target-flags(aarch64-page) blockaddress(@test_blockaddress, %ir-block.block), target-flags(aarch64-pageoff, aarch64-nc) blockaddress(@test_blockaddress, %ir-block.block) ; CHECK: [[MOVaddr:%[0-9]+]]:gpr64common = MOVaddr target-flags(aarch64-page) @addr, target-flags(aarch64-pageoff, aarch64-nc) @addr ; CHECK: STRXui [[MOVaddrBA]], [[MOVaddr]], 0 :: (store 8 into @addr) @@ -39,7 +38,6 @@ ; CHECK: RET_ReallyLR ; LARGE-LABEL: name: test_blockaddress ; LARGE: bb.0 (%ir-block.0): - ; LARGE: successors: %bb.1(0x80000000) ; LARGE: [[MOVZXi:%[0-9]+]]:gpr64 = MOVZXi target-flags(aarch64-g0, aarch64-nc) blockaddress(@test_blockaddress, %ir-block.block), 0 ; LARGE: [[MOVKXi:%[0-9]+]]:gpr64 = MOVKXi [[MOVZXi]], target-flags(aarch64-g1, aarch64-nc) blockaddress(@test_blockaddress, %ir-block.block), 16 ; LARGE: [[MOVKXi1:%[0-9]+]]:gpr64 = MOVKXi [[MOVKXi]], target-flags(aarch64-g2, aarch64-nc) blockaddress(@test_blockaddress, %ir-block.block), 32 diff --git a/llvm/test/MachineVerifier/test_g_brindirect_is_indirect_branch.mir b/llvm/test/MachineVerifier/test_g_brindirect_is_indirect_branch.mir new file mode 100644 --- /dev/null +++ b/llvm/test/MachineVerifier/test_g_brindirect_is_indirect_branch.mir @@ -0,0 +1,20 @@ +# RUN: llc -march=riscv32 -o - -run-pass=none -verify-machineinstrs %s | FileCheck %s +# REQUIRES: global-isel, riscv-registered-target + +# This test checks that the G_BRINDIRECT is an indirect branch by leveraging +# RISCV's version of analyzeBranch. If G_BRINDIRECT would not be an indirect +# branch, this test would crash. + +--- +name: test_indirect_branch +legalized: true +tracksRegLiveness: true +body: | + bb.0: + liveins: $x0 + %0:_(p0) = COPY $x0 + + ; CHECK-NOT: Branch instruction is missing a basic block operand or isIndirectBranch property + G_BRINDIRECT %0 + +... diff --git a/llvm/test/MachineVerifier/test_g_brjt_is_indirect_branch.mir b/llvm/test/MachineVerifier/test_g_brjt_is_indirect_branch.mir new file mode 100644 --- /dev/null +++ b/llvm/test/MachineVerifier/test_g_brjt_is_indirect_branch.mir @@ -0,0 +1,26 @@ +# RUN: llc -march=riscv32 -o - -run-pass=none -verify-machineinstrs %s | FileCheck %s +# REQUIRES: global-isel, riscv-registered-target + +# This test checks that the G_BRJT is an indirect branch by leveraging RISCV's +# version of analyzeBranch. If G_BRJT would not be an indirect branch, this +# test would crash. + +--- +name: test_jump_table +legalized: true +tracksRegLiveness: true +jumpTable: + kind: block-address + entries: + - id: 0 + blocks: [ '%bb.0' ] +body: | + bb.0: + liveins: $x0 + %0:_(s32) = COPY $x0 + %1:_(p0) = COPY $x0 + + ; CHECK-NOT: Branch instruction is missing a basic block operand or isIndirectBranch property + G_BRJT %1, %jump-table.0, %0 + +...