summaryrefslogtreecommitdiffstats
path: root/llvm/lib
diff options
context:
space:
mode:
Diffstat (limited to 'llvm/lib')
-rw-r--r--llvm/lib/Target/Mips/MipsCondMov.td10
-rw-r--r--llvm/lib/Target/Mips/MipsISelLowering.cpp88
-rw-r--r--llvm/lib/Target/Mips/MipsISelLowering.h2
-rw-r--r--llvm/lib/Target/Mips/MipsSEISelDAGToDAG.cpp18
4 files changed, 118 insertions, 0 deletions
diff --git a/llvm/lib/Target/Mips/MipsCondMov.td b/llvm/lib/Target/Mips/MipsCondMov.td
index 39dc2654aa6..0d7e3e200b5 100644
--- a/llvm/lib/Target/Mips/MipsCondMov.td
+++ b/llvm/lib/Target/Mips/MipsCondMov.td
@@ -296,3 +296,13 @@ def PseudoSELECTFP_F_I64 : SelectFP_Pseudo_F<GPR64Opnd>;
def PseudoSELECTFP_F_S : SelectFP_Pseudo_F<FGR32Opnd>;
def PseudoSELECTFP_F_D32 : SelectFP_Pseudo_F<AFGR64Opnd>, FGR_32;
def PseudoSELECTFP_F_D64 : SelectFP_Pseudo_F<FGR64Opnd>, FGR_64;
+
+let usesCustomInserter = 1 in {
+class D_SELECT_CLASS<RegisterOperand RC> :
+ PseudoSE<(outs RC:$dst1, RC:$dst2),
+ (ins GPR32Opnd:$cond, RC:$a1, RC:$a2, RC:$b1, RC:$b2), []>,
+ ISA_MIPS1_NOT_4_32;
+}
+
+def PseudoD_SELECT_I : D_SELECT_CLASS<GPR32Opnd>;
+def PseudoD_SELECT_I64 : D_SELECT_CLASS<GPR64Opnd>;
diff --git a/llvm/lib/Target/Mips/MipsISelLowering.cpp b/llvm/lib/Target/Mips/MipsISelLowering.cpp
index 104fa4090ec..8c2a364cdfa 100644
--- a/llvm/lib/Target/Mips/MipsISelLowering.cpp
+++ b/llvm/lib/Target/Mips/MipsISelLowering.cpp
@@ -1396,6 +1396,9 @@ MipsTargetLowering::EmitInstrWithCustomInserter(MachineInstr &MI,
case Mips::PseudoSELECTFP_T_D32:
case Mips::PseudoSELECTFP_T_D64:
return emitPseudoSELECT(MI, BB, true, Mips::BC1T);
+ case Mips::PseudoD_SELECT_I:
+ case Mips::PseudoD_SELECT_I64:
+ return emitPseudoD_SELECT(MI, BB);
}
}
@@ -2427,6 +2430,16 @@ SDValue MipsTargetLowering::lowerShiftRightParts(SDValue Op, SelectionDAG &DAG,
DAG.getConstant(VT.getSizeInBits(), DL, MVT::i32));
SDValue Ext = DAG.getNode(ISD::SRA, DL, VT, Hi,
DAG.getConstant(VT.getSizeInBits() - 1, DL, VT));
+
+ if (!(Subtarget.hasMips4() || Subtarget.hasMips32())) {
+ SDVTList VTList = DAG.getVTList(VT, VT);
+ return DAG.getNode(Subtarget.isGP64bit() ? Mips::PseudoD_SELECT_I64
+ : Mips::PseudoD_SELECT_I,
+ DL, VTList, Cond, ShiftRightHi,
+ IsSRA ? Ext : DAG.getConstant(0, DL, VT), Or,
+ ShiftRightHi);
+ }
+
Lo = DAG.getNode(ISD::SELECT, DL, VT, Cond, ShiftRightHi, Or);
Hi = DAG.getNode(ISD::SELECT, DL, VT, Cond,
IsSRA ? Ext : DAG.getConstant(0, DL, VT), ShiftRightHi);
@@ -4345,6 +4358,81 @@ MachineBasicBlock *MipsTargetLowering::emitPseudoSELECT(MachineInstr &MI,
return BB;
}
+MachineBasicBlock *MipsTargetLowering::emitPseudoD_SELECT(MachineInstr &MI,
+ MachineBasicBlock *BB) const {
+ assert(!(Subtarget.hasMips4() || Subtarget.hasMips32()) &&
+ "Subtarget already supports SELECT nodes with the use of"
+ "conditional-move instructions.");
+
+ const TargetInstrInfo *TII = Subtarget.getInstrInfo();
+ DebugLoc DL = MI.getDebugLoc();
+
+ // D_SELECT substitutes two SELECT nodes that goes one after another and
+ // have the same condition operand. On machines which don't have
+ // conditional-move instruction, it reduces unnecessary branch instructions
+ // which are result of using two diamond patterns that are result of two
+ // SELECT pseudo instructions.
+ const BasicBlock *LLVM_BB = BB->getBasicBlock();
+ MachineFunction::iterator It = ++BB->getIterator();
+
+ // 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,
+ std::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);
+
+ // bne rs, $0, sinkMBB
+ BuildMI(BB, DL, TII->get(Mips::BNE))
+ .addReg(MI.getOperand(2).getReg())
+ .addReg(Mips::ZERO)
+ .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;
+
+ // Use two PHI nodes to select two reults
+ BuildMI(*BB, BB->begin(), DL, TII->get(Mips::PHI), MI.getOperand(0).getReg())
+ .addReg(MI.getOperand(3).getReg())
+ .addMBB(thisMBB)
+ .addReg(MI.getOperand(5).getReg())
+ .addMBB(copy0MBB);
+ BuildMI(*BB, BB->begin(), DL, TII->get(Mips::PHI), MI.getOperand(1).getReg())
+ .addReg(MI.getOperand(4).getReg())
+ .addMBB(thisMBB)
+ .addReg(MI.getOperand(6).getReg())
+ .addMBB(copy0MBB);
+
+ MI.eraseFromParent(); // The pseudo instruction is gone now.
+
+ return BB;
+}
+
// FIXME? Maybe this could be a TableGen attribute on some registers and
// this table could be generated automatically from RegInfo.
unsigned MipsTargetLowering::getRegisterByName(const char* RegName, EVT VT,
diff --git a/llvm/lib/Target/Mips/MipsISelLowering.h b/llvm/lib/Target/Mips/MipsISelLowering.h
index 5a0de45c44f..e043f133a09 100644
--- a/llvm/lib/Target/Mips/MipsISelLowering.h
+++ b/llvm/lib/Target/Mips/MipsISelLowering.h
@@ -699,6 +699,8 @@ class TargetRegisterClass;
MachineBasicBlock *emitSEL_D(MachineInstr &MI, MachineBasicBlock *BB) const;
MachineBasicBlock *emitPseudoSELECT(MachineInstr &MI, MachineBasicBlock *BB,
bool isFPCmp, unsigned Opc) const;
+ MachineBasicBlock *emitPseudoD_SELECT(MachineInstr &MI,
+ MachineBasicBlock *BB) const;
};
/// Create MipsTargetLowering objects.
diff --git a/llvm/lib/Target/Mips/MipsSEISelDAGToDAG.cpp b/llvm/lib/Target/Mips/MipsSEISelDAGToDAG.cpp
index f030f83295d..cf196b59727 100644
--- a/llvm/lib/Target/Mips/MipsSEISelDAGToDAG.cpp
+++ b/llvm/lib/Target/Mips/MipsSEISelDAGToDAG.cpp
@@ -795,6 +795,24 @@ bool MipsSEDAGToDAGISel::trySelect(SDNode *Node) {
switch(Opcode) {
default: break;
+ case Mips::PseudoD_SELECT_I:
+ case Mips::PseudoD_SELECT_I64: {
+ MVT VT = Subtarget->isGP64bit() ? MVT::i64 : MVT::i32;
+ SDValue cond = Node->getOperand(0);
+ SDValue Hi1 = Node->getOperand(1);
+ SDValue Lo1 = Node->getOperand(2);
+ SDValue Hi2 = Node->getOperand(3);
+ SDValue Lo2 = Node->getOperand(4);
+
+ SDValue ops[] = {cond, Hi1, Lo1, Hi2, Lo2};
+ EVT NodeTys[] = {VT, VT};
+ ReplaceNode(Node, CurDAG->getMachineNode(Subtarget->isGP64bit()
+ ? Mips::PseudoD_SELECT_I64
+ : Mips::PseudoD_SELECT_I,
+ DL, NodeTys, ops));
+ return true;
+ }
+
case ISD::ADDE: {
selectAddE(Node, DL);
return true;
OpenPOWER on IntegriCloud