1
0
mirror of https://github.com/RPCS3/llvm-mirror.git synced 2025-01-31 20:51:52 +01:00

Add function MipsDAGToDAGISel::SelectMULT and factor out code that generates

nodes needed for multiplication. Add code for selecting 64-bit MULHS and MULHU
nodes.

llvm-svn: 147008
This commit is contained in:
Akira Hatanaka 2011-12-20 23:10:57 +00:00
parent 8e3e6b14c8
commit 2e4f1786b1
2 changed files with 55 additions and 37 deletions

View File

@ -81,6 +81,10 @@ private:
}
SDNode *getGlobalBaseReg();
std::pair<SDNode*, SDNode*> SelectMULT(SDNode *N, unsigned Opc, DebugLoc dl,
EVT Ty, bool HasLo, bool HasHi);
SDNode *Select(SDNode *N);
// Complex Pattern.
@ -176,6 +180,28 @@ SelectAddr(SDValue Addr, SDValue &Base, SDValue &Offset) {
return true;
}
/// Select multiply instructions.
std::pair<SDNode*, SDNode*>
MipsDAGToDAGISel::SelectMULT(SDNode *N, unsigned Opc, DebugLoc dl, EVT Ty,
bool HasLo, bool HasHi) {
SDNode *Lo, *Hi;
SDNode *Mul = CurDAG->getMachineNode(Opc, dl, MVT::Glue, N->getOperand(0),
N->getOperand(1));
SDValue InFlag = SDValue(Mul, 0);
if (HasLo) {
Lo = CurDAG->getMachineNode(Ty == MVT::i32 ? Mips::MFLO : Mips::MFLO64, dl,
Ty, MVT::Glue, InFlag);
InFlag = SDValue(Lo, 1);
}
if (HasHi)
Hi = CurDAG->getMachineNode(Ty == MVT::i32 ? Mips::MFHI : Mips::MFHI64, dl,
Ty, InFlag);
return std::make_pair(Lo, Hi);
}
/// Select instructions not customized! Used for
/// expanded, promoted and normal instructions
SDNode* MipsDAGToDAGISel::Select(SDNode *Node) {
@ -195,6 +221,9 @@ SDNode* MipsDAGToDAGISel::Select(SDNode *Node) {
// Instruction Selection not handled by the auto-generated
// tablegen selection should be handled here.
///
EVT NodeTy = Node->getValueType(0);
unsigned MultOpc;
switch(Opcode) {
default: break;
@ -232,58 +261,39 @@ SDNode* MipsDAGToDAGISel::Select(SDNode *Node) {
/// Mul with two results
case ISD::SMUL_LOHI:
case ISD::UMUL_LOHI: {
assert(Node->getValueType(0) != MVT::i64 &&
"64-bit multiplication with two results not handled.");
SDValue Op1 = Node->getOperand(0);
SDValue Op2 = Node->getOperand(1);
if (NodeTy == MVT::i32)
MultOpc = (Opcode == ISD::UMUL_LOHI ? Mips::MULTu : Mips::MULT);
else
MultOpc = (Opcode == ISD::UMUL_LOHI ? Mips::DMULTu : Mips::DMULT);
unsigned Op;
Op = (Opcode == ISD::UMUL_LOHI ? Mips::MULTu : Mips::MULT);
SDNode *Mul = CurDAG->getMachineNode(Op, dl, MVT::Glue, Op1, Op2);
SDValue InFlag = SDValue(Mul, 0);
SDNode *Lo = CurDAG->getMachineNode(Mips::MFLO, dl, MVT::i32,
MVT::Glue, InFlag);
InFlag = SDValue(Lo,1);
SDNode *Hi = CurDAG->getMachineNode(Mips::MFHI, dl, MVT::i32, InFlag);
std::pair<SDNode*, SDNode*> LoHi = SelectMULT(Node, MultOpc, dl, NodeTy,
true, true);
if (!SDValue(Node, 0).use_empty())
ReplaceUses(SDValue(Node, 0), SDValue(Lo,0));
ReplaceUses(SDValue(Node, 0), SDValue(LoHi.first, 0));
if (!SDValue(Node, 1).use_empty())
ReplaceUses(SDValue(Node, 1), SDValue(Hi,0));
ReplaceUses(SDValue(Node, 1), SDValue(LoHi.second, 0));
return NULL;
}
/// Special Muls
case ISD::MUL:
case ISD::MUL: {
// Mips32 has a 32-bit three operand mul instruction.
if (Subtarget.hasMips32() && Node->getValueType(0) == MVT::i32)
if (Subtarget.hasMips32() && NodeTy == MVT::i32)
break;
return SelectMULT(Node, NodeTy == MVT::i32 ? Mips::MULT : Mips::DMULT,
dl, NodeTy, true, false).first;
}
case ISD::MULHS:
case ISD::MULHU: {
assert((Opcode == ISD::MUL || Node->getValueType(0) != MVT::i64) &&
"64-bit MULH* not handled.");
EVT Ty = Node->getValueType(0);
SDValue MulOp1 = Node->getOperand(0);
SDValue MulOp2 = Node->getOperand(1);
unsigned MulOp = (Opcode == ISD::MULHU ?
Mips::MULTu :
(Ty == MVT::i32 ? Mips::MULT : Mips::DMULT));
SDNode *MulNode = CurDAG->getMachineNode(MulOp, dl,
MVT::Glue, MulOp1, MulOp2);
SDValue InFlag = SDValue(MulNode, 0);
if (Opcode == ISD::MUL) {
unsigned Opc = (Ty == MVT::i32 ? Mips::MFLO : Mips::MFLO64);
return CurDAG->getMachineNode(Opc, dl, Ty, InFlag);
}
if (NodeTy == MVT::i32)
MultOpc = (Opcode == ISD::MULHU ? Mips::MULTu : Mips::MULT);
else
return CurDAG->getMachineNode(Mips::MFHI, dl, MVT::i32, InFlag);
MultOpc = (Opcode == ISD::MULHU ? Mips::DMULTu : Mips::DMULT);
return SelectMULT(Node, MultOpc, dl, NodeTy, false, true).second;
}
// Get target GOT address.

View File

@ -8,6 +8,14 @@ entry:
ret i64 %mul
}
define i64 @m1(i64 %a) nounwind readnone {
entry:
; CHECK: dmult
; CHECK: mfhi
%div = sdiv i64 %a, 3
ret i64 %div
}
define i64 @d0(i64 %a0, i64 %a1) nounwind readnone {
entry:
; CHECK: ddivu