From ebc64cf780e6e0200cd462f26e9925dcc7632f2b Mon Sep 17 00:00:00 2001 From: Richard Osborne Date: Wed, 10 Mar 2010 11:41:08 +0000 Subject: [PATCH] Lower add (mul a, b), c into MACCU / MACCS nodes which translate directly to the maccu / maccs instructions. We handle this in ExpandADDSUB since after type legalisation it is messy to recognise these operations. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@98150 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Target/XCore/XCoreISelDAGToDAG.cpp | 12 +++++ lib/Target/XCore/XCoreISelLowering.cpp | 67 ++++++++++++++++++++++++++ lib/Target/XCore/XCoreISelLowering.h | 7 +++ test/CodeGen/XCore/addsub64.ll | 24 +++++++++ 4 files changed, 110 insertions(+) diff --git a/lib/Target/XCore/XCoreISelDAGToDAG.cpp b/lib/Target/XCore/XCoreISelDAGToDAG.cpp index b1ab13272f3..12967d42de4 100644 --- a/lib/Target/XCore/XCoreISelDAGToDAG.cpp +++ b/lib/Target/XCore/XCoreISelDAGToDAG.cpp @@ -208,6 +208,18 @@ SDNode *XCoreDAGToDAGISel::Select(SDNode *N) { return CurDAG->getMachineNode(XCore::LSUB_l5r, dl, MVT::i32, MVT::i32, Ops, 3); } + case XCoreISD::MACCU: { + SDValue Ops[] = { N->getOperand(0), N->getOperand(1), + N->getOperand(2), N->getOperand(3) }; + return CurDAG->getMachineNode(XCore::MACCU_l4r, dl, MVT::i32, MVT::i32, + Ops, 4); + } + case XCoreISD::MACCS: { + SDValue Ops[] = { N->getOperand(0), N->getOperand(1), + N->getOperand(2), N->getOperand(3) }; + return CurDAG->getMachineNode(XCore::MACCS_l4r, dl, MVT::i32, MVT::i32, + Ops, 4); + } // Other cases are autogenerated. } } diff --git a/lib/Target/XCore/XCoreISelLowering.cpp b/lib/Target/XCore/XCoreISelLowering.cpp index 7ecd15135a9..b59ed54996c 100644 --- a/lib/Target/XCore/XCoreISelLowering.cpp +++ b/lib/Target/XCore/XCoreISelLowering.cpp @@ -54,6 +54,8 @@ getTargetNodeName(unsigned Opcode) const case XCoreISD::RETSP : return "XCoreISD::RETSP"; case XCoreISD::LADD : return "XCoreISD::LADD"; case XCoreISD::LSUB : return "XCoreISD::LSUB"; + case XCoreISD::MACCU : return "XCoreISD::MACCU"; + case XCoreISD::MACCS : return "XCoreISD::MACCS"; case XCoreISD::BR_JT : return "XCoreISD::BR_JT"; case XCoreISD::BR_JT32 : return "XCoreISD::BR_JT32"; default : return NULL; @@ -541,12 +543,77 @@ LowerSTORE(SDValue Op, SelectionDAG &DAG) return CallResult.second; } +SDValue XCoreTargetLowering:: +TryExpandADDSUBWithMul(SDNode *N, SelectionDAG &DAG) +{ + SDValue Mul; + SDValue Other; + if (N->getOperand(0).getOpcode() == ISD::MUL) { + Mul = N->getOperand(0); + Other = N->getOperand(1); + } else if (N->getOperand(1).getOpcode() == ISD::MUL) { + Mul = N->getOperand(1); + Other = N->getOperand(0); + } else { + return SDValue(); + } + DebugLoc dl = N->getDebugLoc(); + SDValue LL, RL, AddendL, AddendH; + LL = DAG.getNode(ISD::EXTRACT_ELEMENT, dl, MVT::i32, + Mul.getOperand(0), DAG.getConstant(0, MVT::i32)); + RL = DAG.getNode(ISD::EXTRACT_ELEMENT, dl, MVT::i32, + Mul.getOperand(1), DAG.getConstant(0, MVT::i32)); + AddendL = DAG.getNode(ISD::EXTRACT_ELEMENT, dl, MVT::i32, + Other, DAG.getConstant(0, MVT::i32)); + AddendH = DAG.getNode(ISD::EXTRACT_ELEMENT, dl, MVT::i32, + Other, DAG.getConstant(1, MVT::i32)); + APInt HighMask = APInt::getHighBitsSet(64, 32); + unsigned LHSSB = DAG.ComputeNumSignBits(Mul.getOperand(0)); + unsigned RHSSB = DAG.ComputeNumSignBits(Mul.getOperand(1)); + if (DAG.MaskedValueIsZero(Mul.getOperand(0), HighMask) && + DAG.MaskedValueIsZero(Mul.getOperand(1), HighMask)) { + // The inputs are both zero-extended. + SDValue Hi = DAG.getNode(XCoreISD::MACCU, dl, + DAG.getVTList(MVT::i32, MVT::i32), AddendH, + AddendL, LL, RL); + SDValue Lo(Hi.getNode(), 1); + return DAG.getNode(ISD::BUILD_PAIR, dl, MVT::i64, Lo, Hi); + } + if (LHSSB > 32 && RHSSB > 32) { + // The inputs are both sign-extended. + SDValue Hi = DAG.getNode(XCoreISD::MACCS, dl, + DAG.getVTList(MVT::i32, MVT::i32), AddendH, + AddendL, LL, RL); + SDValue Lo(Hi.getNode(), 1); + return DAG.getNode(ISD::BUILD_PAIR, dl, MVT::i64, Lo, Hi); + } + SDValue LH, RH; + LH = DAG.getNode(ISD::EXTRACT_ELEMENT, dl, MVT::i32, + Mul.getOperand(0), DAG.getConstant(1, MVT::i32)); + RH = DAG.getNode(ISD::EXTRACT_ELEMENT, dl, MVT::i32, + Mul.getOperand(1), DAG.getConstant(1, MVT::i32)); + SDValue Hi = DAG.getNode(XCoreISD::MACCU, dl, + DAG.getVTList(MVT::i32, MVT::i32), AddendH, + AddendL, LL, RL); + SDValue Lo(Hi.getNode(), 1); + RH = DAG.getNode(ISD::MUL, dl, MVT::i32, LL, RH); + LH = DAG.getNode(ISD::MUL, dl, MVT::i32, LH, RL); + Hi = DAG.getNode(ISD::ADD, dl, MVT::i32, Hi, RH); + Hi = DAG.getNode(ISD::ADD, dl, MVT::i32, Hi, LH); + return DAG.getNode(ISD::BUILD_PAIR, dl, MVT::i64, Lo, Hi); +} + SDValue XCoreTargetLowering:: ExpandADDSUB(SDNode *N, SelectionDAG &DAG) { assert(N->getValueType(0) == MVT::i64 && (N->getOpcode() == ISD::ADD || N->getOpcode() == ISD::SUB) && "Unknown operand to lower!"); + + SDValue Result = TryExpandADDSUBWithMul(N, DAG); + if (Result.getNode() != 0) + return Result; + DebugLoc dl = N->getDebugLoc(); // Extract components diff --git a/lib/Target/XCore/XCoreISelLowering.h b/lib/Target/XCore/XCoreISelLowering.h index f44c3243ee7..4013723111d 100644 --- a/lib/Target/XCore/XCoreISelLowering.h +++ b/lib/Target/XCore/XCoreISelLowering.h @@ -54,6 +54,12 @@ namespace llvm { // Corresponds to LSUB instruction LSUB, + // Corresponds to MACCU instruction + MACCU, + + // Corresponds to MACCS instruction + MACCS, + // Jumptable branch. BR_JT, @@ -140,6 +146,7 @@ namespace llvm { EVT VT) const; // Expand specifics + SDValue TryExpandADDSUBWithMul(SDNode *Op, SelectionDAG &DAG); SDValue ExpandADDSUB(SDNode *Op, SelectionDAG &DAG); virtual SDValue PerformDAGCombine(SDNode *N, DAGCombinerInfo &DCI) const; diff --git a/test/CodeGen/XCore/addsub64.ll b/test/CodeGen/XCore/addsub64.ll index 70536644c37..0432e5e712e 100644 --- a/test/CodeGen/XCore/addsub64.ll +++ b/test/CodeGen/XCore/addsub64.ll @@ -18,3 +18,27 @@ define i64 @sub64(i64 %a, i64 %b) { ; CHECK-NEXT: lsub r2, r0, r0, r2, r11 ; CHECK-NEXT: lsub r2, r1, r1, r3, r2 ; CHECK-NEXT: retsp 0 + +define i64 @maccu(i64 %a, i32 %b, i32 %c) { +entry: + %0 = zext i32 %b to i64 + %1 = zext i32 %c to i64 + %2 = mul i64 %1, %0 + %3 = add i64 %2, %a + ret i64 %3 +} +; CHECK: maccu: +; CHECK: maccu r1, r0, r3, r2 +; CHECK-NEXT: retsp 0 + +define i64 @maccs(i64 %a, i32 %b, i32 %c) { +entry: + %0 = sext i32 %b to i64 + %1 = sext i32 %c to i64 + %2 = mul i64 %1, %0 + %3 = add i64 %2, %a + ret i64 %3 +} +; CHECK: maccs: +; CHECK: maccs r1, r0, r3, r2 +; CHECK-NEXT: retsp 0