mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2025-01-31 20:51:52 +01:00
GlobalISel: add generic conditional branch.
Just the basic equivalent to DAG's condbr for now, we'll get to things like br_cc when we start doing more legalization. llvm-svn: 277184
This commit is contained in:
parent
3adce2360c
commit
ca6435867c
@ -140,6 +140,17 @@ public:
|
||||
/// \return a MachineInstrBuilder for the newly created instruction.
|
||||
MachineInstrBuilder buildBr(MachineBasicBlock &BB);
|
||||
|
||||
/// Build and insert G_BRCOND \p Ty \p Tst, \p Dest
|
||||
///
|
||||
/// G_BRCOND is a conditional branch to \p Dest. At the beginning of
|
||||
/// legalization, \p Ty will be a single bit (s1). Targets with interesting
|
||||
/// flags registers may change this.
|
||||
///
|
||||
/// \pre setBasicBlock or setMI must have been called.
|
||||
///
|
||||
/// \return The newly created instruction.
|
||||
MachineInstrBuilder buildBrCond(LLT Ty, unsigned Tst, MachineBasicBlock &BB);
|
||||
|
||||
/// Build and insert \p Res<def> = COPY Op
|
||||
///
|
||||
/// Register-to-register COPY sets \p Res to \p Op.
|
||||
|
@ -135,6 +135,16 @@ def G_BR : Instruction {
|
||||
let hasSideEffects = 0;
|
||||
let isBranch = 1;
|
||||
let isTerminator = 1;
|
||||
let isBarrier = 1;
|
||||
}
|
||||
|
||||
// Generic conditional branch.
|
||||
def G_BRCOND : Instruction {
|
||||
let OutOperandList = (outs);
|
||||
let InOperandList = (ins unknown:$tst, unknown:$truebb);
|
||||
let hasSideEffects = 0;
|
||||
let isBranch = 1;
|
||||
let isTerminator = 1;
|
||||
}
|
||||
|
||||
// TODO: Add the other generic opcodes.
|
||||
|
@ -199,6 +199,9 @@ HANDLE_TARGET_OPCODE(G_LOAD)
|
||||
/// Generic store.
|
||||
HANDLE_TARGET_OPCODE(G_STORE)
|
||||
|
||||
/// Generic conditional branch instruction.
|
||||
HANDLE_TARGET_OPCODE(G_BRCOND)
|
||||
|
||||
/// Generic BRANCH instruction. This is an unconditional branch.
|
||||
HANDLE_TARGET_OPCODE(G_BR)
|
||||
|
||||
|
@ -104,13 +104,20 @@ bool IRTranslator::translateReturn(const Instruction &Inst) {
|
||||
bool IRTranslator::translateBr(const Instruction &Inst) {
|
||||
assert(isa<BranchInst>(Inst) && "Branch expected");
|
||||
const BranchInst &BrInst = *cast<BranchInst>(&Inst);
|
||||
if (BrInst.isUnconditional()) {
|
||||
const BasicBlock &BrTgt = *cast<BasicBlock>(BrInst.getOperand(0));
|
||||
MachineBasicBlock &TgtBB = getOrCreateBB(BrTgt);
|
||||
MIRBuilder.buildBr(TgtBB);
|
||||
} else {
|
||||
assert(0 && "Not yet implemented");
|
||||
|
||||
unsigned Succ = 0;
|
||||
if (!BrInst.isUnconditional()) {
|
||||
// We want a G_BRCOND to the true BB followed by an unconditional branch.
|
||||
unsigned Tst = getOrCreateVReg(*BrInst.getCondition());
|
||||
const BasicBlock &TrueTgt = *cast<BasicBlock>(BrInst.getSuccessor(Succ++));
|
||||
MachineBasicBlock &TrueBB = getOrCreateBB(TrueTgt);
|
||||
MIRBuilder.buildBrCond(LLT{*BrInst.getCondition()->getType()}, Tst, TrueBB);
|
||||
}
|
||||
|
||||
const BasicBlock &BrTgt = *cast<BasicBlock>(BrInst.getSuccessor(Succ));
|
||||
MachineBasicBlock &TgtBB = getOrCreateBB(BrTgt);
|
||||
MIRBuilder.buildBr(TgtBB);
|
||||
|
||||
// Link successors.
|
||||
MachineBasicBlock &CurBB = MIRBuilder.getMBB();
|
||||
for (const BasicBlock *Succ : BrInst.successors())
|
||||
|
@ -95,7 +95,13 @@ MachineInstrBuilder MachineIRBuilder::buildCopy(unsigned Res, unsigned Op) {
|
||||
return buildInstr(TargetOpcode::COPY).addDef(Res).addUse(Op);
|
||||
}
|
||||
|
||||
MachineInstrBuilder MachineIRBuilder::buildLoad(LLT VTy, LLT PTy, unsigned Res,
|
||||
MachineInstrBuilder MachineIRBuilder::buildBrCond(LLT Ty, unsigned Tst,
|
||||
MachineBasicBlock &Dest) {
|
||||
return buildInstr(TargetOpcode::G_BRCOND, Ty).addUse(Tst).addMBB(&Dest);
|
||||
}
|
||||
|
||||
|
||||
MachineInstrBuilder MachineIRBuilder::buildLoad(LLT VTy, LLT PTy, unsigned Res,
|
||||
unsigned Addr,
|
||||
MachineMemOperand &MMO) {
|
||||
return buildInstr(TargetOpcode::G_LOAD, {VTy, PTy})
|
||||
|
@ -58,6 +58,37 @@ end:
|
||||
ret void
|
||||
}
|
||||
|
||||
; Tests for conditional br.
|
||||
; CHECK-LABEL: name: condbr
|
||||
; CHECK: body:
|
||||
;
|
||||
; Entry basic block.
|
||||
; CHECK: {{[0-9a-zA-Z._-]+}}:
|
||||
;
|
||||
; Make sure we have two successors
|
||||
; CHECK-NEXT: successors: %[[TRUE:[0-9a-zA-Z._-]+]]({{0x[a-f0-9]+ / 0x[a-f0-9]+}} = 50.00%),
|
||||
; CHECK: %[[FALSE:[0-9a-zA-Z._-]+]]({{0x[a-f0-9]+ / 0x[a-f0-9]+}} = 50.00%)
|
||||
;
|
||||
; Check that we emit the correct branch.
|
||||
; CHECK: [[ADDR:%.*]](64) = COPY %x0
|
||||
; CHECK: [[TST:%.*]](1) = G_LOAD { s1, p0 } [[ADDR]]
|
||||
; CHECK: G_BRCOND s1 [[TST]], %[[TRUE]]
|
||||
; CHECK: G_BR unsized %[[FALSE]]
|
||||
;
|
||||
; Check that each successor contains the return instruction.
|
||||
; CHECK: [[TRUE]]:
|
||||
; CHECK-NEXT: RET_ReallyLR
|
||||
; CHECK: [[FALSE]]:
|
||||
; CHECK-NEXT: RET_ReallyLR
|
||||
define void @condbr(i1* %tstaddr) {
|
||||
%tst = load i1, i1* %tstaddr
|
||||
br i1 %tst, label %true, label %false
|
||||
true:
|
||||
ret void
|
||||
false:
|
||||
ret void
|
||||
}
|
||||
|
||||
; Tests for or.
|
||||
; CHECK-LABEL: name: ori64
|
||||
; CHECK: [[ARG1:%[0-9]+]](64) = COPY %x0
|
||||
|
Loading…
x
Reference in New Issue
Block a user