Skip to content

Commit

Permalink
[GlobalISel] Add a G_BRJT opcode.
Browse files Browse the repository at this point in the history
This is a branch opcode that takes a jump table pointer, jump table index and an
index into the table to do an indirect branch.

We pass both the table pointer and JTI to allow targets like ARM64 to more
easily use the existing jump table compression optimization without having to
walk up the block to find a paired G_JUMP_TABLE.

Differential Revision: https://reviews.llvm.org/D63159

llvm-svn: 363434
  • Loading branch information
aemerson committed Jun 14, 2019
1 parent ff4e0a9 commit f79d3bc
Show file tree
Hide file tree
Showing 7 changed files with 82 additions and 0 deletions.
14 changes: 14 additions & 0 deletions llvm/include/llvm/CodeGen/GlobalISel/MachineIRBuilder.h
Expand Up @@ -595,6 +595,20 @@ class MachineIRBuilder {
/// \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
Expand Down
3 changes: 3 additions & 0 deletions llvm/include/llvm/Support/TargetOpcodes.def
Expand Up @@ -512,6 +512,9 @@ HANDLE_TARGET_OPCODE(G_UMAX)
/// 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)

Expand Down
9 changes: 9 additions & 0 deletions llvm/include/llvm/Target/GenericOpcodes.td
Expand Up @@ -857,6 +857,15 @@ def G_BRINDIRECT : GenericInstruction {
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
//------------------------------------------------------------------------------
Expand Down
11 changes: 11 additions & 0 deletions llvm/lib/CodeGen/GlobalISel/MachineIRBuilder.cpp
Expand Up @@ -245,6 +245,17 @@ MachineInstrBuilder MachineIRBuilder::buildBrIndirect(unsigned Tgt) {
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);
Expand Down
12 changes: 12 additions & 0 deletions llvm/lib/CodeGen/MachineVerifier.cpp
Expand Up @@ -1320,6 +1320,18 @@ void MachineVerifier::verifyPreISelGenericInstruction(const MachineInstr *MI) {
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;
}
Expand Down
Expand Up @@ -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
#
Expand Down
30 changes: 30 additions & 0 deletions llvm/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
...

0 comments on commit f79d3bc

Please sign in to comment.