1
0
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:
Kristof Beyls 2017-01-30 09:13:18 +00:00
parent 47c6fb27f5
commit 942514e271
10 changed files with 108 additions and 3 deletions

View File

@ -190,6 +190,8 @@ private:
bool translateSwitch(const User &U, MachineIRBuilder &MIRBuilder); bool translateSwitch(const User &U, MachineIRBuilder &MIRBuilder);
bool translateIndirectBr(const User &U, MachineIRBuilder &MIRBuilder);
bool translateExtractValue(const User &U, MachineIRBuilder &MIRBuilder); bool translateExtractValue(const User &U, MachineIRBuilder &MIRBuilder);
bool translateInsertValue(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 // Stubs to keep the compiler happy while we implement the rest of the
// translation. // translation.
bool translateIndirectBr(const User &U, MachineIRBuilder &MIRBuilder) {
return false;
}
bool translateResume(const User &U, MachineIRBuilder &MIRBuilder) { bool translateResume(const User &U, MachineIRBuilder &MIRBuilder) {
return false; return false;
} }

View File

@ -322,6 +322,16 @@ public:
/// \return The newly created instruction. /// \return The newly created instruction.
MachineInstrBuilder buildBrCond(unsigned Tst, MachineBasicBlock &BB); 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 /// Build and insert \p Res = G_CONSTANT \p Val
/// ///
/// G_CONSTANT is an integer constant with the specified size and value. \p /// G_CONSTANT is an integer constant with the specified size and value. \p

View File

@ -445,4 +445,13 @@ def G_BRCOND : Instruction {
let isTerminator = 1; 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. // TODO: Add the other generic opcodes.

View File

@ -251,6 +251,9 @@ HANDLE_TARGET_OPCODE(G_STORE)
/// Generic conditional branch instruction. /// Generic conditional branch instruction.
HANDLE_TARGET_OPCODE(G_BRCOND) HANDLE_TARGET_OPCODE(G_BRCOND)
/// Generic indirect branch instruction.
HANDLE_TARGET_OPCODE(G_BRINDIRECT)
/// Generic intrinsic use (without side effects). /// Generic intrinsic use (without side effects).
HANDLE_TARGET_OPCODE(G_INTRINSIC) HANDLE_TARGET_OPCODE(G_INTRINSIC)

View File

@ -252,6 +252,21 @@ bool IRTranslator::translateSwitch(const User &U,
return true; 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) { bool IRTranslator::translateLoad(const User &U, MachineIRBuilder &MIRBuilder) {
const LoadInst &LI = cast<LoadInst>(U); const LoadInst &LI = cast<LoadInst>(U);

View File

@ -217,6 +217,10 @@ MachineInstrBuilder MachineIRBuilder::buildBr(MachineBasicBlock &Dest) {
return buildInstr(TargetOpcode::G_BR).addMBB(&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) { MachineInstrBuilder MachineIRBuilder::buildCopy(unsigned Res, unsigned Op) {
return buildInstr(TargetOpcode::COPY).addDef(Res).addUse(Op); return buildInstr(TargetOpcode::COPY).addDef(Res).addUse(Op);
} }

View File

@ -525,6 +525,11 @@ bool AArch64InstructionSelector::select(MachineInstr &I) const {
return constrainSelectedInstRegOperands(*MIB.getInstr(), TII, TRI, RBI); 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_FCONSTANT:
case TargetOpcode::G_CONSTANT: { case TargetOpcode::G_CONSTANT: {
const bool isFP = Opcode == TargetOpcode::G_FCONSTANT; const bool isFP = Opcode == TargetOpcode::G_FCONSTANT;

View File

@ -167,6 +167,7 @@ AArch64LegalizerInfo::AArch64LegalizerInfo() {
// Control-flow // Control-flow
for (auto Ty : {s1, s8, s16, s32}) for (auto Ty : {s1, s8, s16, s32})
setAction({G_BRCOND, Ty}, Legal); setAction({G_BRCOND, Ty}, Legal);
setAction({G_BRINDIRECT, p0}, Legal);
// Select // Select
for (auto Ty : {s1, s8, s16, s32, s64, p0}) for (auto Ty : {s1, s8, s16, s32, s64, p0})

View File

@ -79,6 +79,7 @@
define void @unconditional_br() { ret void } define void @unconditional_br() { ret void }
define void @conditional_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_s64_gpr(i64* %addr) { ret void }
define void @load_s32_gpr(i32* %addr) { ret void } define void @load_s32_gpr(i32* %addr) { ret void }
@ -1510,6 +1511,28 @@ body: |
bb.1: 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 # CHECK-LABEL: name: load_s64_gpr
name: load_s64_gpr name: load_s64_gpr

View File

@ -217,6 +217,42 @@ phi.block:
ret i32 12 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. ; Tests for or.
; CHECK-LABEL: name: ori64 ; CHECK-LABEL: name: ori64
; CHECK: [[ARG1:%[0-9]+]](s64) = COPY %x0 ; CHECK: [[ARG1:%[0-9]+]](s64) = COPY %x0