Index: llvm/trunk/include/llvm/CodeGen/GlobalISel/MachineIRBuilder.h =================================================================== --- llvm/trunk/include/llvm/CodeGen/GlobalISel/MachineIRBuilder.h +++ llvm/trunk/include/llvm/CodeGen/GlobalISel/MachineIRBuilder.h @@ -595,6 +595,20 @@ /// \return a MachineInstrBuilder for the newly created instruction. MachineInstrBuilder buildBrIndirect(unsigned Tgt); + /// Build and insert G_BRJT \p TablePtr, \p JTI, \p IndexReg + /// + /// G_BRJT is a jump table branch using a table base pointer \p TablePtr, + /// jump table index \p JTI and index \p IndexReg + /// + /// \pre setBasicBlock or setMI must have been called. + /// \pre \p TablePtr must be a generic virtual register with pointer type. + /// \pre \p JTI must be be a jump table index. + /// \pre \p IndexReg must be a generic virtual register with pointer type. + /// + /// \return a MachineInstrBuilder for the newly created instruction. + MachineInstrBuilder buildBrJT(unsigned TablePtr, unsigned JTI, + unsigned IndexReg); + /// Build and insert \p Res = G_CONSTANT \p Val /// /// G_CONSTANT is an integer constant with the specified size and value. \p Index: llvm/trunk/include/llvm/Support/TargetOpcodes.def =================================================================== --- llvm/trunk/include/llvm/Support/TargetOpcodes.def +++ llvm/trunk/include/llvm/Support/TargetOpcodes.def @@ -512,6 +512,9 @@ /// Generic BRANCH instruction. This is an unconditional branch. HANDLE_TARGET_OPCODE(G_BR) +/// Generic branch to jump table entry. +HANDLE_TARGET_OPCODE(G_BRJT) + /// Generic insertelement. HANDLE_TARGET_OPCODE(G_INSERT_VECTOR_ELT) Index: llvm/trunk/include/llvm/Target/GenericOpcodes.td =================================================================== --- llvm/trunk/include/llvm/Target/GenericOpcodes.td +++ llvm/trunk/include/llvm/Target/GenericOpcodes.td @@ -857,6 +857,15 @@ let isTerminator = 1; } +// Generic branch to jump table entry +def G_BRJT : GenericInstruction { + let OutOperandList = (outs); + let InOperandList = (ins ptype0:$tbl, unknown:$jti, type1:$idx); + let hasSideEffects = 0; + let isBranch = 1; + let isTerminator = 1; +} + //------------------------------------------------------------------------------ // Vector ops //------------------------------------------------------------------------------ Index: llvm/trunk/lib/CodeGen/GlobalISel/MachineIRBuilder.cpp =================================================================== --- llvm/trunk/lib/CodeGen/GlobalISel/MachineIRBuilder.cpp +++ llvm/trunk/lib/CodeGen/GlobalISel/MachineIRBuilder.cpp @@ -245,6 +245,17 @@ return buildInstr(TargetOpcode::G_BRINDIRECT).addUse(Tgt); } +MachineInstrBuilder MachineIRBuilder::buildBrJT(unsigned TablePtr, + unsigned JTI, + unsigned IndexReg) { + assert(getMRI()->getType(TablePtr).isPointer() && + "Table reg must be a pointer"); + return buildInstr(TargetOpcode::G_BRJT) + .addUse(TablePtr) + .addJumpTableIndex(JTI) + .addUse(IndexReg); +} + MachineInstrBuilder MachineIRBuilder::buildCopy(const DstOp &Res, const SrcOp &Op) { return buildInstr(TargetOpcode::COPY, Res, Op); Index: llvm/trunk/lib/CodeGen/MachineVerifier.cpp =================================================================== --- llvm/trunk/lib/CodeGen/MachineVerifier.cpp +++ llvm/trunk/lib/CodeGen/MachineVerifier.cpp @@ -1320,6 +1320,18 @@ report("G_JUMP_TABLE dest operand must have a pointer type", MI); break; } + case TargetOpcode::G_BRJT: { + if (!MRI->getType(MI->getOperand(0).getReg()).isPointer()) + report("G_BRJT src operand 0 must be a pointer type", MI); + + if (!MI->getOperand(1).isJTI()) + report("G_BRJT src operand 1 must be a jump table index", MI); + + const auto &IdxOp = MI->getOperand(2); + if (!IdxOp.isReg() || MRI->getType(IdxOp.getReg()).isPointer()) + report("G_BRJT src operand 2 must be a scalar reg type", MI); + break; + } default: break; } Index: llvm/trunk/test/CodeGen/AArch64/GlobalISel/legalizer-info-validation.mir =================================================================== --- llvm/trunk/test/CodeGen/AArch64/GlobalISel/legalizer-info-validation.mir +++ llvm/trunk/test/CodeGen/AArch64/GlobalISel/legalizer-info-validation.mir @@ -321,6 +321,9 @@ # DEBUG-NEXT: G_BR (opcode {{[0-9]+}}): 0 type indices # DEBUG: .. type index coverage check SKIPPED: no rules defined # +# DEBUG-NEXT: G_BRJT (opcode 137): 2 type indices +# DEBUG: .. type index coverage check SKIPPED: no rules defined +# # DEBUG-NEXT: G_INSERT_VECTOR_ELT (opcode {{[0-9]+}}): 3 type indices # DEBUG: .. type index coverage check SKIPPED: user-defined predicate detected # Index: llvm/trunk/test/MachineVerifier/test_g_brjt.mir =================================================================== --- llvm/trunk/test/MachineVerifier/test_g_brjt.mir +++ llvm/trunk/test/MachineVerifier/test_g_brjt.mir @@ -0,0 +1,30 @@ +# RUN: not llc -march=aarch64 -o /dev/null -run-pass=none -verify-machineinstrs %s 2>&1 | FileCheck %s +# REQUIRES: global-isel, aarch64-registered-target + +--- +name: test_jump_table +legalized: true +tracksRegLiveness: true +jumpTable: + kind: block-address + entries: + - id: 0 + blocks: [ '%bb.0' ] +body: | + bb.0: + liveins: $x0 + %0:_(s64) = COPY $x0 + %1:_(p0) = COPY $x0 + ; CHECK: Bad machine code: Too few operands + G_BRJT + + ; CHECK: G_BRJT src operand 0 must be a pointer type + G_BRJT %0, %jump-table.0, %0 + + ; CHECK: G_BRJT src operand 1 must be a jump table index + G_BRJT %1, %0, %0 + + ; CHECK: G_BRJT src operand 2 must be a scalar reg type + G_BRJT %1, %jump-table.0, %1 + +...