let Constraints = "$rx_ = $rx";
}
+class FRI16_B_ins<bits<5> _op, string asmstr,
+ InstrItinClass itin>:
+ FRI16<_op, (outs), (ins CPU16Regs:$rx, brtarget:$imm),
+ !strconcat(asmstr, "\t$rx, $imm # 16 bit inst"), [], itin>;
//
// Compare a register and immediate and place result in CC
// Implicit use of T8
!strconcat(op, "\t$rt, .+4\n\t\n\tmove $rd, $rs"), []> {
//let isCodeGenOnly=1;
let Constraints = "$rd = $rd_";
+ let usesCustomInserter = 1;
}
//
//
// Format: BEQZ rx, offset MIPS16e
+// Purpose: Branch on Equal to Zero
+// To test a GPR then do a PC-relative conditional branch.
+//
+def BeqzRxImm16: FRI16_B_ins<0b00100, "beqz", IIAlu>, cbranch16;
+
+
+//
+// Format: BEQZ rx, offset MIPS16e
// Purpose: Branch on Equal to Zero (Extended)
// To test a GPR then do a PC-relative conditional branch.
//
//
// Format: BNEZ rx, offset MIPS16e
+// Purpose: Branch on Not Equal to Zero
+// To test a GPR then do a PC-relative conditional branch.
+//
+def BnezRxImm16: FRI16_B_ins<0b00101, "bnez", IIAlu>, cbranch16;
+
+//
+// Format: BNEZ rx, offset MIPS16e
// Purpose: Branch on Not Equal to Zero (Extended)
// To test a GPR then do a PC-relative conditional branch.
//
cl::desc("MIPS: mips16 hard float enable."),
cl::init(false));
+static cl::opt<bool> DontExpandCondPseudos16(
+ "mips16-dont-expand-cond-pseudo",
+ cl::init(false),
+ cl::desc("Dont expand conditional move related "
+ "pseudos for Mips 16"),
+ cl::Hidden);
static const uint16_t O32IntRegs[4] = {
return Sink;
}
+MachineBasicBlock *MipsTargetLowering::EmitSel16(unsigned Opc, MachineInstr *MI,
+ MachineBasicBlock *BB) const {
+ if (DontExpandCondPseudos16)
+ return BB;
+ const TargetInstrInfo *TII = getTargetMachine().getInstrInfo();
+ DebugLoc dl = MI->getDebugLoc();
+ // To "insert" a SELECT_CC instruction, we actually have to insert the
+ // diamond control-flow pattern. The incoming instruction knows the
+ // destination vreg to set, the condition code register to branch on, the
+ // true/false values to select between, and a branch opcode to use.
+ const BasicBlock *LLVM_BB = BB->getBasicBlock();
+ MachineFunction::iterator It = BB;
+ ++It;
+
+ // thisMBB:
+ // ...
+ // TrueVal = ...
+ // setcc r1, r2, r3
+ // bNE r1, r0, copy1MBB
+ // fallthrough --> copy0MBB
+ MachineBasicBlock *thisMBB = BB;
+ MachineFunction *F = BB->getParent();
+ MachineBasicBlock *copy0MBB = F->CreateMachineBasicBlock(LLVM_BB);
+ MachineBasicBlock *sinkMBB = F->CreateMachineBasicBlock(LLVM_BB);
+ F->insert(It, copy0MBB);
+ F->insert(It, sinkMBB);
+
+ // Transfer the remainder of BB and its successor edges to sinkMBB.
+ sinkMBB->splice(sinkMBB->begin(), BB,
+ llvm::next(MachineBasicBlock::iterator(MI)),
+ BB->end());
+ sinkMBB->transferSuccessorsAndUpdatePHIs(BB);
+
+ // Next, add the true and fallthrough blocks as its successors.
+ BB->addSuccessor(copy0MBB);
+ BB->addSuccessor(sinkMBB);
+
+ BuildMI(BB, dl, TII->get(Opc)).addReg(MI->getOperand(3).getReg())
+ .addMBB(sinkMBB);
+
+ // copy0MBB:
+ // %FalseValue = ...
+ // # fallthrough to sinkMBB
+ BB = copy0MBB;
+
+ // Update machine-CFG edges
+ BB->addSuccessor(sinkMBB);
+
+ // sinkMBB:
+ // %Result = phi [ %TrueValue, thisMBB ], [ %FalseValue, copy0MBB ]
+ // ...
+ BB = sinkMBB;
+
+ BuildMI(*BB, BB->begin(), dl,
+ TII->get(Mips::PHI), MI->getOperand(0).getReg())
+ .addReg(MI->getOperand(1).getReg()).addMBB(thisMBB)
+ .addReg(MI->getOperand(2).getReg()).addMBB(copy0MBB);
+
+ MI->eraseFromParent(); // The pseudo instruction is gone now.
+ return BB;
+}
+
MachineBasicBlock *
MipsTargetLowering::EmitInstrWithCustomInserter(MachineInstr *MI,
MachineBasicBlock *BB) const {
switch (MI->getOpcode()) {
- default: llvm_unreachable("Unexpected instr type to insert");
+ default:
+ llvm_unreachable("Unexpected instr type to insert");
case Mips::ATOMIC_LOAD_ADD_I8:
case Mips::ATOMIC_LOAD_ADD_I8_P8:
return EmitAtomicBinaryPartword(MI, BB, 1, Mips::ADDu);
return EmitAtomicCmpSwap(MI, BB, 8);
case Mips::BPOSGE32_PSEUDO:
return EmitBPOSGE32(MI, BB);
+ case Mips::SelBeqZ:
+ return EmitSel16(Mips::BeqzRxImm16, MI, BB);
+ case Mips::SelBneZ:
+ return EmitSel16(Mips::BnezRxImm16, MI, BB);
}
}
%2 = load i32* @f, align 4
%cond = select i1 %cmp, i32 %1, i32 %2
store i32 %cond, i32* @z1, align 4
-; 16: beqz ${{[0-9]+}}, .+4
+; 16: beqz ${{[0-9]+}}, $BB{{[0-9]+}}_{{[0-9]}}
; 16: move ${{[0-9]+}}, ${{[0-9]+}}
%3 = load i32* @b, align 4
%cmp1 = icmp eq i32 %3, 0
%2 = load i32* @t, align 4
%cond = select i1 %cmp, i32 %1, i32 %2
store i32 %cond, i32* @z1, align 4
-; 16: bnez ${{[0-9]+}}, .+4
+; 16: bnez ${{[0-9]+}}, $BB{{[0-9]+}}_{{[0-9]}}
; 16: move ${{[0-9]+}}, ${{[0-9]+}}
%3 = load i32* @b, align 4
%cmp1 = icmp ne i32 %3, 0
%2 = load i32* @t, align 4
%cond = select i1 %tobool, i32 %1, i32 %2
store i32 %cond, i32* @z1, align 4
-; 16: bnez ${{[0-9]+}}, .+4
+; 16: bnez ${{[0-9]+}}, $BB{{[0-9]+}}_{{[0-9]}}
; 16: move ${{[0-9]+}}, ${{[0-9]+}}
%3 = load i32* @b, align 4
%tobool1 = icmp ne i32 %3, 0