Custom lower (S|U)MUL_LOHI -> MACC(S|U)
authorRichard Osborne <richard@xmos.com>
Wed, 10 Mar 2010 13:20:07 +0000 (13:20 +0000)
committerRichard Osborne <richard@xmos.com>
Wed, 10 Mar 2010 13:20:07 +0000 (13:20 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@98152 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Target/XCore/XCoreISelLowering.cpp
lib/Target/XCore/XCoreISelLowering.h
test/CodeGen/XCore/mul64.ll [new file with mode: 0644]

index 596abb350600505c8ba6ab84798e3c356615123d..70ceadd4df5873a8d6e30790e06bab4dc955ad34 100644 (file)
@@ -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)
 {
index 4013723111db53bd6e2075a818850947e55b4f9c..6b467c3f9c33799404e7fdb7181788ca6481d8f2 100644 (file)
@@ -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 (file)
index 0000000..c42c2f5
--- /dev/null
@@ -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