Add support for 64-bit integer multiply instructions.
authorAkira Hatanaka <ahatanaka@mips.com>
Mon, 3 Oct 2011 20:01:11 +0000 (20:01 +0000)
committerAkira Hatanaka <ahatanaka@mips.com>
Mon, 3 Oct 2011 20:01:11 +0000 (20:01 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@141017 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Target/Mips/Mips64InstrInfo.td
lib/Target/Mips/MipsISelDAGToDAG.cpp
test/CodeGen/Mips/mips64instrs.ll

index 3e65f999b5cfcb5287fcb39fcdadcaadf67189fe..2fdc2ff007e3979fe1a21c8b6935afe23e720fd7 100644 (file)
@@ -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
index 658bdcf82d5edc6077d58aad70ba698d12944fa1..3face6e342a2edc836895afaf55c9c4a7bedf538 100644 (file)
@@ -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);
     }
index 67776aae41d8bbc031d6a78885723714938828e3..98aff526de2cf581c09620fda2e9c1824cbbd3d3 100644 (file)
@@ -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
+}