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:
parent
9a5851ba0e
commit
a21f959530
@ -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
|
||||
|
@ -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)
|
||||
|
||||
|
@ -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
|
||||
//------------------------------------------------------------------------------
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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
|
||||
#
|
||||
|
30
test/MachineVerifier/test_g_brjt.mir
Normal file
30
test/MachineVerifier/test_g_brjt.mir
Normal 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
|
||||
|
||||
...
|
Loading…
x
Reference in New Issue
Block a user