1
0
mirror of https://github.com/RPCS3/llvm-mirror.git synced 2025-01-31 20:51:52 +01:00

[GlobalISel] Add a G_BRJT opcode.

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
This commit is contained in:
Amara Emerson 2019-06-14 17:55:48 +00:00
parent 9a5851ba0e
commit a21f959530
7 changed files with 82 additions and 0 deletions

View File

@ -595,6 +595,20 @@ public:
/// \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

View File

@ -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)

View File

@ -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
//------------------------------------------------------------------------------

View File

@ -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);

View File

@ -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;
}

View File

@ -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
#

View File

@ -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
...