From: Akira Hatanaka Date: Mon, 3 Oct 2011 20:01:11 +0000 (+0000) Subject: Add support for 64-bit integer multiply instructions. X-Git-Url: http://demsky.eecs.uci.edu/git/?a=commitdiff_plain;h=04d3762ff111085e21cb8f8570e68dff7f847b6d;p=oota-llvm.git 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 --- diff --git a/lib/Target/Mips/Mips64InstrInfo.td b/lib/Target/Mips/Mips64InstrInfo.td index 3e65f999b5c..2fdc2ff007e 100644 --- a/lib/Target/Mips/Mips64InstrInfo.td +++ b/lib/Target/Mips/Mips64InstrInfo.td @@ -90,6 +90,14 @@ class LogicR_shift_rotate_reg64 func, bits<5> _shamt, string instr_asm, let shamt = _shamt; } +// Mul, Div +let Defs = [HI64, LO64] in { + let isCommutable = 1 in + class Mul64 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 658bdcf82d5..3face6e342a 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 67776aae41d..98aff526de2 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 +}