mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-10-19 02:52:53 +02:00
[GlobalISel] Add support for indirectbr
Differential Revision: https://reviews.llvm.org/D28079 llvm-svn: 293470
This commit is contained in:
parent
47c6fb27f5
commit
942514e271
@ -190,6 +190,8 @@ private:
|
||||
|
||||
bool translateSwitch(const User &U, MachineIRBuilder &MIRBuilder);
|
||||
|
||||
bool translateIndirectBr(const User &U, MachineIRBuilder &MIRBuilder);
|
||||
|
||||
bool translateExtractValue(const User &U, MachineIRBuilder &MIRBuilder);
|
||||
|
||||
bool translateInsertValue(const User &U, MachineIRBuilder &MIRBuilder);
|
||||
@ -304,9 +306,6 @@ private:
|
||||
|
||||
// Stubs to keep the compiler happy while we implement the rest of the
|
||||
// translation.
|
||||
bool translateIndirectBr(const User &U, MachineIRBuilder &MIRBuilder) {
|
||||
return false;
|
||||
}
|
||||
bool translateResume(const User &U, MachineIRBuilder &MIRBuilder) {
|
||||
return false;
|
||||
}
|
||||
|
@ -322,6 +322,16 @@ public:
|
||||
/// \return The newly created instruction.
|
||||
MachineInstrBuilder buildBrCond(unsigned Tst, MachineBasicBlock &BB);
|
||||
|
||||
/// Build and insert G_BRINDIRECT \p Tgt
|
||||
///
|
||||
/// G_BRINDIRECT is an indirect branch to \p Tgt.
|
||||
///
|
||||
/// \pre setBasicBlock or setMI must have been called.
|
||||
/// \pre \p Tgt must be a generic virtual register with pointer type.
|
||||
///
|
||||
/// \return a MachineInstrBuilder for the newly created instruction.
|
||||
MachineInstrBuilder buildBrIndirect(unsigned Tgt);
|
||||
|
||||
/// Build and insert \p Res = G_CONSTANT \p Val
|
||||
///
|
||||
/// G_CONSTANT is an integer constant with the specified size and value. \p
|
||||
|
@ -445,4 +445,13 @@ def G_BRCOND : Instruction {
|
||||
let isTerminator = 1;
|
||||
}
|
||||
|
||||
// Generic indirect branch.
|
||||
def G_BRINDIRECT : Instruction {
|
||||
let OutOperandList = (outs);
|
||||
let InOperandList = (ins type0:$src1);
|
||||
let hasSideEffects = 0;
|
||||
let isBranch = 1;
|
||||
let isTerminator = 1;
|
||||
}
|
||||
|
||||
// TODO: Add the other generic opcodes.
|
||||
|
@ -251,6 +251,9 @@ HANDLE_TARGET_OPCODE(G_STORE)
|
||||
/// Generic conditional branch instruction.
|
||||
HANDLE_TARGET_OPCODE(G_BRCOND)
|
||||
|
||||
/// Generic indirect branch instruction.
|
||||
HANDLE_TARGET_OPCODE(G_BRINDIRECT)
|
||||
|
||||
/// Generic intrinsic use (without side effects).
|
||||
HANDLE_TARGET_OPCODE(G_INTRINSIC)
|
||||
|
||||
|
@ -252,6 +252,21 @@ bool IRTranslator::translateSwitch(const User &U,
|
||||
return true;
|
||||
}
|
||||
|
||||
bool IRTranslator::translateIndirectBr(const User &U,
|
||||
MachineIRBuilder &MIRBuilder) {
|
||||
const IndirectBrInst &BrInst = cast<IndirectBrInst>(U);
|
||||
|
||||
const unsigned Tgt = getOrCreateVReg(*BrInst.getAddress());
|
||||
MIRBuilder.buildBrIndirect(Tgt);
|
||||
|
||||
// Link successors.
|
||||
MachineBasicBlock &CurBB = MIRBuilder.getMBB();
|
||||
for (const BasicBlock *Succ : BrInst.successors())
|
||||
CurBB.addSuccessor(&getOrCreateBB(*Succ));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool IRTranslator::translateLoad(const User &U, MachineIRBuilder &MIRBuilder) {
|
||||
const LoadInst &LI = cast<LoadInst>(U);
|
||||
|
||||
|
@ -217,6 +217,10 @@ MachineInstrBuilder MachineIRBuilder::buildBr(MachineBasicBlock &Dest) {
|
||||
return buildInstr(TargetOpcode::G_BR).addMBB(&Dest);
|
||||
}
|
||||
|
||||
MachineInstrBuilder MachineIRBuilder::buildBrIndirect(unsigned Tgt) {
|
||||
return buildInstr(TargetOpcode::G_BRINDIRECT).addUse(Tgt);
|
||||
}
|
||||
|
||||
MachineInstrBuilder MachineIRBuilder::buildCopy(unsigned Res, unsigned Op) {
|
||||
return buildInstr(TargetOpcode::COPY).addDef(Res).addUse(Op);
|
||||
}
|
||||
|
@ -525,6 +525,11 @@ bool AArch64InstructionSelector::select(MachineInstr &I) const {
|
||||
return constrainSelectedInstRegOperands(*MIB.getInstr(), TII, TRI, RBI);
|
||||
}
|
||||
|
||||
case TargetOpcode::G_BRINDIRECT: {
|
||||
I.setDesc(TII.get(AArch64::BR));
|
||||
return constrainSelectedInstRegOperands(I, TII, TRI, RBI);
|
||||
}
|
||||
|
||||
case TargetOpcode::G_FCONSTANT:
|
||||
case TargetOpcode::G_CONSTANT: {
|
||||
const bool isFP = Opcode == TargetOpcode::G_FCONSTANT;
|
||||
|
@ -167,6 +167,7 @@ AArch64LegalizerInfo::AArch64LegalizerInfo() {
|
||||
// Control-flow
|
||||
for (auto Ty : {s1, s8, s16, s32})
|
||||
setAction({G_BRCOND, Ty}, Legal);
|
||||
setAction({G_BRINDIRECT, p0}, Legal);
|
||||
|
||||
// Select
|
||||
for (auto Ty : {s1, s8, s16, s32, s64, p0})
|
||||
|
@ -79,6 +79,7 @@
|
||||
|
||||
define void @unconditional_br() { ret void }
|
||||
define void @conditional_br() { ret void }
|
||||
define void @indirect_br() { ret void }
|
||||
|
||||
define void @load_s64_gpr(i64* %addr) { ret void }
|
||||
define void @load_s32_gpr(i32* %addr) { ret void }
|
||||
@ -1510,6 +1511,28 @@ body: |
|
||||
bb.1:
|
||||
...
|
||||
|
||||
---
|
||||
# CHECK-LABEL: name: indirect_br
|
||||
name: indirect_br
|
||||
legalized: true
|
||||
regBankSelected: true
|
||||
|
||||
registers:
|
||||
- { id: 0, class: gpr }
|
||||
|
||||
# CHECK: body:
|
||||
# CHECK: bb.0:
|
||||
# CHECK: %0 = COPY %x0
|
||||
# CHECK: BR %0
|
||||
body: |
|
||||
bb.0:
|
||||
successors: %bb.0, %bb.1
|
||||
%0(p0) = COPY %x0
|
||||
G_BRINDIRECT %0(p0)
|
||||
|
||||
bb.1:
|
||||
...
|
||||
|
||||
---
|
||||
# CHECK-LABEL: name: load_s64_gpr
|
||||
name: load_s64_gpr
|
||||
|
@ -217,6 +217,42 @@ phi.block:
|
||||
ret i32 12
|
||||
}
|
||||
|
||||
; Tests for indirect br.
|
||||
; CHECK-LABEL: name: indirectbr
|
||||
; CHECK: body:
|
||||
;
|
||||
; ABI/constant lowering and IR-level entry basic block.
|
||||
; CHECK: {{bb.[0-9]+.entry}}:
|
||||
; Make sure we have one successor
|
||||
; CHECK-NEXT: successors: %[[BB_L1:bb.[0-9]+.L1]](0x80000000)
|
||||
; CHECK: G_BR %[[BB_L1]]
|
||||
;
|
||||
; Check basic block L1 has 2 successors: BBL1 and BBL2
|
||||
; CHECK: [[BB_L1]] (address-taken):
|
||||
; CHECK-NEXT: successors: %[[BB_L1]](0x40000000),
|
||||
; CHECK: %[[BB_L2:bb.[0-9]+.L2]](0x40000000)
|
||||
; CHECK: G_BRINDIRECT %{{[0-9]+}}(p0)
|
||||
;
|
||||
; Check basic block L2 is the return basic block
|
||||
; CHECK: [[BB_L2]] (address-taken):
|
||||
; CHECK-NEXT: RET_ReallyLR
|
||||
|
||||
@indirectbr.L = internal unnamed_addr constant [3 x i8*] [i8* blockaddress(@indirectbr, %L1), i8* blockaddress(@indirectbr, %L2), i8* null], align 8
|
||||
|
||||
define void @indirectbr() {
|
||||
entry:
|
||||
br label %L1
|
||||
L1: ; preds = %entry, %L1
|
||||
%i = phi i32 [ 0, %entry ], [ %inc, %L1 ]
|
||||
%inc = add i32 %i, 1
|
||||
%idxprom = zext i32 %i to i64
|
||||
%arrayidx = getelementptr inbounds [3 x i8*], [3 x i8*]* @indirectbr.L, i64 0, i64 %idxprom
|
||||
%brtarget = load i8*, i8** %arrayidx, align 8
|
||||
indirectbr i8* %brtarget, [label %L1, label %L2]
|
||||
L2: ; preds = %L1
|
||||
ret void
|
||||
}
|
||||
|
||||
; Tests for or.
|
||||
; CHECK-LABEL: name: ori64
|
||||
; CHECK: [[ARG1:%[0-9]+]](s64) = COPY %x0
|
||||
|
Loading…
Reference in New Issue
Block a user