diff --git a/lib/Target/XCore/XCoreISelLowering.cpp b/lib/Target/XCore/XCoreISelLowering.cpp index 596abb35060..70ceadd4df5 100644 --- a/lib/Target/XCore/XCoreISelLowering.cpp +++ b/lib/Target/XCore/XCoreISelLowering.cpp @@ -98,6 +98,8 @@ XCoreTargetLowering::XCoreTargetLowering(XCoreTargetMachine &XTM) // 64bit setOperationAction(ISD::ADD, MVT::i64, Custom); setOperationAction(ISD::SUB, MVT::i64, Custom); + setOperationAction(ISD::SMUL_LOHI, MVT::i32, Custom); + setOperationAction(ISD::UMUL_LOHI, MVT::i32, Custom); setOperationAction(ISD::MULHS, MVT::i32, Expand); setOperationAction(ISD::MULHU, MVT::i32, Expand); setOperationAction(ISD::SHL_PARTS, MVT::i32, Expand); @@ -167,6 +169,8 @@ LowerOperation(SDValue Op, SelectionDAG &DAG) { case ISD::SELECT_CC: return LowerSELECT_CC(Op, DAG); case ISD::VAARG: return LowerVAARG(Op, DAG); case ISD::VASTART: return LowerVASTART(Op, DAG); + case ISD::SMUL_LOHI: return LowerSMUL_LOHI(Op, DAG); + case ISD::UMUL_LOHI: return LowerUMUL_LOHI(Op, DAG); // FIXME: Remove these when LegalizeDAGTypes lands. case ISD::ADD: case ISD::SUB: return ExpandADDSUB(Op.getNode(), DAG); @@ -543,6 +547,40 @@ LowerSTORE(SDValue Op, SelectionDAG &DAG) return CallResult.second; } +SDValue XCoreTargetLowering:: +LowerSMUL_LOHI(SDValue Op, SelectionDAG &DAG) +{ + assert(Op.getValueType() == MVT::i32 && Op.getOpcode() == ISD::SMUL_LOHI && + "Unexpected operand to lower!"); + DebugLoc dl = Op.getDebugLoc(); + SDValue LHS = Op.getOperand(0); + SDValue RHS = Op.getOperand(1); + SDValue Zero = DAG.getConstant(0, MVT::i32); + SDValue Hi = DAG.getNode(XCoreISD::MACCS, dl, + DAG.getVTList(MVT::i32, MVT::i32), Zero, Zero, + LHS, RHS); + SDValue Lo(Hi.getNode(), 1); + SDValue Ops[] = { Lo, Hi }; + return DAG.getMergeValues(Ops, 2, dl); +} + +SDValue XCoreTargetLowering:: +LowerUMUL_LOHI(SDValue Op, SelectionDAG &DAG) +{ + assert(Op.getValueType() == MVT::i32 && Op.getOpcode() == ISD::UMUL_LOHI && + "Unexpected operand to lower!"); + DebugLoc dl = Op.getDebugLoc(); + SDValue LHS = Op.getOperand(0); + SDValue RHS = Op.getOperand(1); + SDValue Zero = DAG.getConstant(0, MVT::i32); + SDValue Hi = DAG.getNode(XCoreISD::MACCU, dl, + DAG.getVTList(MVT::i32, MVT::i32), Zero, Zero, + LHS, RHS); + SDValue Lo(Hi.getNode(), 1); + SDValue Ops[] = { Lo, Hi }; + return DAG.getMergeValues(Ops, 2, dl); +} + SDValue XCoreTargetLowering:: TryExpandADDSUBWithMul(SDNode *N, SelectionDAG &DAG) { diff --git a/lib/Target/XCore/XCoreISelLowering.h b/lib/Target/XCore/XCoreISelLowering.h index 4013723111d..6b467c3f9c3 100644 --- a/lib/Target/XCore/XCoreISelLowering.h +++ b/lib/Target/XCore/XCoreISelLowering.h @@ -138,6 +138,8 @@ namespace llvm { SDValue LowerSELECT_CC(SDValue Op, SelectionDAG &DAG); SDValue LowerVAARG(SDValue Op, SelectionDAG &DAG); SDValue LowerVASTART(SDValue Op, SelectionDAG &DAG); + SDValue LowerUMUL_LOHI(SDValue Op, SelectionDAG &DAG); + SDValue LowerSMUL_LOHI(SDValue Op, SelectionDAG &DAG); SDValue LowerFRAMEADDR(SDValue Op, SelectionDAG &DAG); // Inline asm support diff --git a/test/CodeGen/XCore/mul64.ll b/test/CodeGen/XCore/mul64.ll new file mode 100644 index 00000000000..c42c2f59cd3 --- /dev/null +++ b/test/CodeGen/XCore/mul64.ll @@ -0,0 +1,30 @@ +; RUN: llc < %s -march=xcore | FileCheck %s +define i64 @umul_lohi(i32 %a, i32 %b) { +entry: + %0 = zext i32 %a to i64 + %1 = zext i32 %b to i64 + %2 = mul i64 %1, %0 + ret i64 %2 +} +; CHECK: umul_lohi: +; CHECK: ldc r2, 0 +; CHECK-NEXT: mov r3, r2 +; CHECK-NEXT: maccu r2, r3, r1, r0 +; CHECK-NEXT: mov r0, r3 +; CHECK-NEXT: mov r1, r2 +; CHECK-NEXT: retsp 0 + +define i64 @smul_lohi(i32 %a, i32 %b) { +entry: + %0 = sext i32 %a to i64 + %1 = sext i32 %b to i64 + %2 = mul i64 %1, %0 + ret i64 %2 +} +; CHECK: smul_lohi: +; CHECK: ldc r2, 0 +; CHECK-NEXT: mov r3, r2 +; CHECK-NEXT: maccs r2, r3, r1, r0 +; CHECK-NEXT: mov r0, r3 +; CHECK-NEXT: mov r1, r2 +; CHECK-NEXT: retsp 0