summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAkira Hatanaka <ahatanaka@mips.com>2011-10-03 20:01:11 +0000
committerAkira Hatanaka <ahatanaka@mips.com>2011-10-03 20:01:11 +0000
commit04d3762ff111085e21cb8f8570e68dff7f847b6d (patch)
treed40a0b111256d36a93af800361cbe2c42a763233
parent36787939b27d9b238e10fc4ba42cb621003a5a31 (diff)
downloadllvm-04d3762ff111085e21cb8f8570e68dff7f847b6d.tar.gz
llvm-04d3762ff111085e21cb8f8570e68dff7f847b6d.tar.bz2
llvm-04d3762ff111085e21cb8f8570e68dff7f847b6d.tar.xz
Add support for 64-bit integer multiply instructions.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@141017 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--lib/Target/Mips/Mips64InstrInfo.td12
-rw-r--r--lib/Target/Mips/MipsISelDAGToDAG.cpp18
-rw-r--r--test/CodeGen/Mips/mips64instrs.ll13
3 files changed, 39 insertions, 4 deletions
diff --git a/lib/Target/Mips/Mips64InstrInfo.td b/lib/Target/Mips/Mips64InstrInfo.td
index 3e65f999b5..2fdc2ff007 100644
--- a/lib/Target/Mips/Mips64InstrInfo.td
+++ b/lib/Target/Mips/Mips64InstrInfo.td
@@ -90,6 +90,14 @@ class LogicR_shift_rotate_reg64<bits<6> func, bits<5> _shamt, string instr_asm,
let shamt = _shamt;
}
+// Mul, Div
+let Defs = [HI64, LO64] in {
+ let isCommutable = 1 in
+ class Mul64<bits<6> func, string instr_asm, InstrItinClass itin>:
+ FR<0x00, func, (outs), (ins CPU64Regs:$a, CPU64Regs:$b),
+ !strconcat(instr_asm, "\t$a, $b"), [], itin>;
+}
+
// Move from Hi/Lo
let shamt = 0 in {
let rs = 0, rt = 0 in
@@ -139,6 +147,10 @@ let Predicates = [HasMips64r2] in {
def DROTRV : LogicR_shift_rotate_reg64<0x16, 0x01, "drotrv", rotr>;
}
+/// Multiply and Divide Instructions.
+def DMULT : Mul64<0x1c, "dmult", IIImul>;
+def DMULTu : Mul64<0x1d, "dmultu", IIImul>;
+
let Defs = [HI64] in
def MTHI64 : MoveToLOHI64<0x11, "mthi">;
let Defs = [LO64] in
diff --git a/lib/Target/Mips/MipsISelDAGToDAG.cpp b/lib/Target/Mips/MipsISelDAGToDAG.cpp
index 658bdcf82d..3face6e342 100644
--- a/lib/Target/Mips/MipsISelDAGToDAG.cpp
+++ b/lib/Target/Mips/MipsISelDAGToDAG.cpp
@@ -237,6 +237,8 @@ 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);
@@ -262,21 +264,29 @@ SDNode* MipsDAGToDAGISel::Select(SDNode *Node) {
/// Special Muls
case ISD::MUL:
- if (Subtarget.hasMips32())
+ // Mips32 has a 32-bit three operand mul instruction.
+ if (Subtarget.hasMips32() && Node->getValueType(0) == MVT::i32)
break;
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 : Mips::MULT);
+ 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)
- return CurDAG->getMachineNode(Mips::MFLO, dl, MVT::i32, InFlag);
+ if (Opcode == ISD::MUL) {
+ unsigned Opc = (Ty == MVT::i32 ? Mips::MFLO : Mips::MFLO64);
+ return CurDAG->getMachineNode(Opc, dl, Ty, InFlag);
+ }
else
return CurDAG->getMachineNode(Mips::MFHI, dl, MVT::i32, InFlag);
}
diff --git a/test/CodeGen/Mips/mips64instrs.ll b/test/CodeGen/Mips/mips64instrs.ll
index 67776aae41..98aff526de 100644
--- a/test/CodeGen/Mips/mips64instrs.ll
+++ b/test/CodeGen/Mips/mips64instrs.ll
@@ -70,3 +70,16 @@ entry:
ret i64 %xor
}
+define i64 @f12(i64 %a, i64 %b) nounwind readnone {
+entry:
+; CHECK: mult
+ %mul = mul nsw i64 %b, %a
+ ret i64 %mul
+}
+
+define i64 @f13(i64 %a, i64 %b) nounwind readnone {
+entry:
+; CHECK: mult
+ %mul = mul i64 %b, %a
+ ret i64 %mul
+}