[PATCH] SelectionDAG: Share ISD::MUL lowering code between the SelectionDAGLegalize and DAGTypeLegalizer

Owen Anderson resistor at mac.com
Thu Apr 10 22:52:25 PDT 2014


Looks good to me.

—Owen

On Apr 8, 2014, at 1:00 PM, Tom Stellard <tom at stellard.net> wrote:

> Ping.
> 
> On Mon, Mar 31, 2014 at 07:25:30AM -0700, Tom Stellard wrote:
>> On Fri, Feb 07, 2014 at 02:54:39PM -0800, Owen Anderson wrote:
>>> 
>>> On Feb 7, 2014, at 2:20 PM, Hal Finkel <hfinkel at anl.gov> wrote:
>>> 
>>>> ----- Original Message -----
>>>>> From: "Tom Stellard" <tom at stellard.net>
>>>>> To: llvm-commits at cs.uiuc.edu
>>>>> Sent: Friday, February 7, 2014 4:12:13 PM
>>>>> Subject: [PATCH] SelectionDAG: Share ISD::MUL lowering code between the	SelectionDAGLegalize and DAGTypeLegalizer
>>>>> 
>>>>> Hi,
>>>>> 
>>>>> The attached patches allow the SelectionDAGLegalizer to reuse ISD:MUL
>>>>> lowering code from the DAGTypeLegalizer.
>>>>> 
>>>>> The first patch moves the DAGTypeLegalizer ISD:MUL lowering code into
>>>>> a public
>>>>> SelectionDAG function called expandMUL() and the second patch
>>>>> modifies
>>>>> the SelectionDAGLegalizer to use this code.
>>>>> 
>>>>> I think there may be other opportunities to share code between these
>>>>> two classes,
>>>>> so I'm wondering if the approach I've taken would work for other
>>>>> operations too.
>>>>> I'm interested in hearing what other people think.
>>>> 
>>>> I've not yet looked at the patch, but I'll add: There is also expansion logic hidden away in the legalization code that could be used by *ISelLowering in the various targets, and I think that moving things into utility functions in SelectionDAG will help with reuse there as well (GatherAllAliases comes to mind, for example). So, generally speaking, I think this kind of refactoring is a good idea.
>>> 
>>> I agree with Hal, and the general sentiment that it would be great to share more of these expansions between type and operation legalization.  That said, I’d like to find a cleaner way to factor them out than just moving them all into methods on SelectionDAG.
>>> 
>> 
>> I wasn't sure where else to put these functions, so I moved them into
>> the TargetLowering class.  What do you think?
>> 
>> -Tom
> 
>> From ce43dc06f3274eca0b2bac2e1032d90c58a0d3be Mon Sep 17 00:00:00 2001
>> From: Tom Stellard <thomas.stellard at amd.com>
>> Date: Fri, 7 Feb 2014 14:06:04 -0500
>> Subject: [PATCH 1/2] SelectionDAG: Factor ISD::MUL lowering code out of
>> DAGTypeLegalizer
>> 
>> This code has been moved to a new function in the TargetLowering
>> class called expandMUL().  The purpose of this is to be able
>> to share lowering code between the SelectionDAGLegalize and
>> DAGTypeLegalizer classes.
>> 
>> No functionality changed intended.
>> ---
>> include/llvm/Target/TargetLowering.h              |  18 ++++
>> lib/CodeGen/SelectionDAG/LegalizeIntegerTypes.cpp |  73 ++-------------
>> lib/CodeGen/SelectionDAG/TargetLowering.cpp       | 107 ++++++++++++++++++++++
>> 3 files changed, 131 insertions(+), 67 deletions(-)
>> 
>> diff --git a/include/llvm/Target/TargetLowering.h b/include/llvm/Target/TargetLowering.h
>> index 8f00ac8f..c0c2c74 100644
>> --- a/include/llvm/Target/TargetLowering.h
>> +++ b/include/llvm/Target/TargetLowering.h
>> @@ -2326,6 +2326,24 @@ public:
>>                       std::vector<SDNode*> *Created) const;
>> 
>>   //===--------------------------------------------------------------------===//
>> +  // Legalization utility functions
>> +  //
>> +
>> +  /// Expand a MUL into two nodes.  One that computes the high bits of
>> +  /// the result and one that computes the low bits.
>> +  /// \param VT The value type to use for the Lo and Hi nodes.
>> +  /// \param LL Low bits of the LHS of the MUL.  You can use this parameter
>> +  ///        if you want to control how low bits are extracted from the LHS.
>> +  /// \param LH High bits of the LHS of the MUL.  See LL for meaning.
>> +  /// \param RL Low bits of the RHS of the MUL.  See LL for meaning
>> +  /// \param RH High bits of the RHS of the MUL.  See LL for meaning.
>> +  /// \returns true if the node has been expanded. false if it has not
>> +  bool expandMUL(SDNode *N, SDValue &Lo, SDValue &Hi, EVT HiLoVT,
>> +                 SelectionDAG &DAG, SDValue LL = SDValue(),
>> +		 SDValue LH = SDValue(), SDValue RL = SDValue(),
>> +		 SDValue RH = SDValue()) const;
>> +
>> +  //===--------------------------------------------------------------------===//
>>   // Instruction Emitting Hooks
>>   //
>> 
>> diff --git a/lib/CodeGen/SelectionDAG/LegalizeIntegerTypes.cpp b/lib/CodeGen/SelectionDAG/LegalizeIntegerTypes.cpp
>> index 18b2376..630cd79 100644
>> --- a/lib/CodeGen/SelectionDAG/LegalizeIntegerTypes.cpp
>> +++ b/lib/CodeGen/SelectionDAG/LegalizeIntegerTypes.cpp
>> @@ -1923,73 +1923,12 @@ void DAGTypeLegalizer::ExpandIntRes_MUL(SDNode *N,
>>   EVT NVT = TLI.getTypeToTransformTo(*DAG.getContext(), VT);
>>   SDLoc dl(N);
>> 
>> -  bool HasMULHS = TLI.isOperationLegalOrCustom(ISD::MULHS, NVT);
>> -  bool HasMULHU = TLI.isOperationLegalOrCustom(ISD::MULHU, NVT);
>> -  bool HasSMUL_LOHI = TLI.isOperationLegalOrCustom(ISD::SMUL_LOHI, NVT);
>> -  bool HasUMUL_LOHI = TLI.isOperationLegalOrCustom(ISD::UMUL_LOHI, NVT);
>> -  if (HasMULHU || HasMULHS || HasUMUL_LOHI || HasSMUL_LOHI) {
>> -    SDValue LL, LH, RL, RH;
>> -    GetExpandedInteger(N->getOperand(0), LL, LH);
>> -    GetExpandedInteger(N->getOperand(1), RL, RH);
>> -    unsigned OuterBitSize = VT.getSizeInBits();
>> -    unsigned InnerBitSize = NVT.getSizeInBits();
>> -    unsigned LHSSB = DAG.ComputeNumSignBits(N->getOperand(0));
>> -    unsigned RHSSB = DAG.ComputeNumSignBits(N->getOperand(1));
>> -
>> -    APInt HighMask = APInt::getHighBitsSet(OuterBitSize, InnerBitSize);
>> -    if (DAG.MaskedValueIsZero(N->getOperand(0), HighMask) &&
>> -        DAG.MaskedValueIsZero(N->getOperand(1), HighMask)) {
>> -      // The inputs are both zero-extended.
>> -      if (HasUMUL_LOHI) {
>> -        // We can emit a umul_lohi.
>> -        Lo = DAG.getNode(ISD::UMUL_LOHI, dl, DAG.getVTList(NVT, NVT), LL, RL);
>> -        Hi = SDValue(Lo.getNode(), 1);
>> -        return;
>> -      }
>> -      if (HasMULHU) {
>> -        // We can emit a mulhu+mul.
>> -        Lo = DAG.getNode(ISD::MUL, dl, NVT, LL, RL);
>> -        Hi = DAG.getNode(ISD::MULHU, dl, NVT, LL, RL);
>> -        return;
>> -      }
>> -    }
>> -    if (LHSSB > InnerBitSize && RHSSB > InnerBitSize) {
>> -      // The input values are both sign-extended.
>> -      if (HasSMUL_LOHI) {
>> -        // We can emit a smul_lohi.
>> -        Lo = DAG.getNode(ISD::SMUL_LOHI, dl, DAG.getVTList(NVT, NVT), LL, RL);
>> -        Hi = SDValue(Lo.getNode(), 1);
>> -        return;
>> -      }
>> -      if (HasMULHS) {
>> -        // We can emit a mulhs+mul.
>> -        Lo = DAG.getNode(ISD::MUL, dl, NVT, LL, RL);
>> -        Hi = DAG.getNode(ISD::MULHS, dl, NVT, LL, RL);
>> -        return;
>> -      }
>> -    }
>> -    if (HasUMUL_LOHI) {
>> -      // Lo,Hi = umul LHS, RHS.
>> -      SDValue UMulLOHI = DAG.getNode(ISD::UMUL_LOHI, dl,
>> -                                       DAG.getVTList(NVT, NVT), LL, RL);
>> -      Lo = UMulLOHI;
>> -      Hi = UMulLOHI.getValue(1);
>> -      RH = DAG.getNode(ISD::MUL, dl, NVT, LL, RH);
>> -      LH = DAG.getNode(ISD::MUL, dl, NVT, LH, RL);
>> -      Hi = DAG.getNode(ISD::ADD, dl, NVT, Hi, RH);
>> -      Hi = DAG.getNode(ISD::ADD, dl, NVT, Hi, LH);
>> -      return;
>> -    }
>> -    if (HasMULHU) {
>> -      Lo = DAG.getNode(ISD::MUL, dl, NVT, LL, RL);
>> -      Hi = DAG.getNode(ISD::MULHU, dl, NVT, LL, RL);
>> -      RH = DAG.getNode(ISD::MUL, dl, NVT, LL, RH);
>> -      LH = DAG.getNode(ISD::MUL, dl, NVT, LH, RL);
>> -      Hi = DAG.getNode(ISD::ADD, dl, NVT, Hi, RH);
>> -      Hi = DAG.getNode(ISD::ADD, dl, NVT, Hi, LH);
>> -      return;
>> -    }
>> -  }
>> +  SDValue LL, LH, RL, RH;
>> +  GetExpandedInteger(N->getOperand(0), LL, LH);
>> +  GetExpandedInteger(N->getOperand(1), RL, RH);
>> +
>> +  if (TLI.expandMUL(N, Lo, Hi, NVT, DAG, LL, LH, RL, RH))
>> +    return;
>> 
>>   // If nothing else, we can make a libcall.
>>   RTLIB::Libcall LC = RTLIB::UNKNOWN_LIBCALL;
>> diff --git a/lib/CodeGen/SelectionDAG/TargetLowering.cpp b/lib/CodeGen/SelectionDAG/TargetLowering.cpp
>> index 82e5ae8..dc4a219 100644
>> --- a/lib/CodeGen/SelectionDAG/TargetLowering.cpp
>> +++ b/lib/CodeGen/SelectionDAG/TargetLowering.cpp
>> @@ -2682,3 +2682,110 @@ verifyReturnAddressArgumentIsConstant(SDValue Op, SelectionDAG &DAG) const {
>> 
>>   return false;
>> }
>> +
>> +//===----------------------------------------------------------------------===//
>> +// Legalization Utilities
>> +//===----------------------------------------------------------------------===//
>> +
>> +bool TargetLowering::expandMUL(SDNode *N, SDValue &Lo, SDValue &Hi, EVT HiLoVT,
>> +                               SelectionDAG &DAG, SDValue LL, SDValue LH,
>> +			       SDValue RL, SDValue RH) const {
>> +  EVT VT = N->getValueType(0);
>> +  SDLoc dl(N);
>> +
>> +  bool HasMULHS = isOperationLegalOrCustom(ISD::MULHS, HiLoVT);
>> +  bool HasMULHU = isOperationLegalOrCustom(ISD::MULHU, HiLoVT);
>> +  bool HasSMUL_LOHI = isOperationLegalOrCustom(ISD::SMUL_LOHI, HiLoVT);
>> +  bool HasUMUL_LOHI = isOperationLegalOrCustom(ISD::UMUL_LOHI, HiLoVT);
>> +  if (HasMULHU || HasMULHS || HasUMUL_LOHI || HasSMUL_LOHI) {
>> +    unsigned OuterBitSize = VT.getSizeInBits();
>> +    unsigned InnerBitSize = HiLoVT.getSizeInBits();
>> +    unsigned LHSSB = DAG.ComputeNumSignBits(N->getOperand(0));
>> +    unsigned RHSSB = DAG.ComputeNumSignBits(N->getOperand(1));
>> +
>> +    // LL, LH, RL, and RH must be either all NULL or all set to a value.
>> +    assert((LL.getNode() && LH.getNode() && RL.getNode() && RH.getNode()) ||
>> +           (!LL.getNode() && !LH.getNode() && !RL.getNode() && !RH.getNode()));
>> +
>> +    if (!LL.getNode() && !RL.getNode() &&
>> +        isOperationLegalOrCustom(ISD::TRUNCATE, HiLoVT)) {
>> +      LL = DAG.getNode(ISD::TRUNCATE, dl, HiLoVT, N->getOperand(0));
>> +      RL = DAG.getNode(ISD::TRUNCATE, dl, HiLoVT, N->getOperand(1));
>> +    }
>> +
>> +    if (!LL.getNode())
>> +      return false;
>> +
>> +    APInt HighMask = APInt::getHighBitsSet(OuterBitSize, InnerBitSize);
>> +    if (DAG.MaskedValueIsZero(N->getOperand(0), HighMask) &&
>> +        DAG.MaskedValueIsZero(N->getOperand(1), HighMask)) {
>> +      // The inputs are both zero-extended.
>> +      if (HasUMUL_LOHI) {
>> +        // We can emit a umul_lohi.
>> +        Lo = DAG.getNode(ISD::UMUL_LOHI, dl,
>> +	                 DAG.getVTList(HiLoVT, HiLoVT), LL, RL);
>> +        Hi = SDValue(Lo.getNode(), 1);
>> +        return true;
>> +      }
>> +      if (HasMULHU) {
>> +        // We can emit a mulhu+mul.
>> +        Lo = DAG.getNode(ISD::MUL, dl, HiLoVT, LL, RL);
>> +        Hi = DAG.getNode(ISD::MULHU, dl, HiLoVT, LL, RL);
>> +        return true;
>> +      }
>> +    }
>> +    if (LHSSB > InnerBitSize && RHSSB > InnerBitSize) {
>> +      // The input values are both sign-extended.
>> +      if (HasSMUL_LOHI) {
>> +        // We can emit a smul_lohi.
>> +        Lo = DAG.getNode(ISD::SMUL_LOHI, dl,
>> +	                 DAG.getVTList(HiLoVT, HiLoVT), LL, RL);
>> +        Hi = SDValue(Lo.getNode(), 1);
>> +        return true;
>> +      }
>> +      if (HasMULHS) {
>> +        // We can emit a mulhs+mul.
>> +        Lo = DAG.getNode(ISD::MUL, dl, HiLoVT, LL, RL);
>> +        Hi = DAG.getNode(ISD::MULHS, dl, HiLoVT, LL, RL);
>> +        return true;
>> +      }
>> +    }
>> +
>> +    if (!LH.getNode() && !RH.getNode() &&
>> +        isOperationLegalOrCustom(ISD::SRL, VT) &&
>> +        isOperationLegalOrCustom(ISD::TRUNCATE, HiLoVT)) {
>> +      unsigned ShiftAmt = VT.getSizeInBits() - HiLoVT.getSizeInBits();
>> +      SDValue Shift = DAG.getConstant(ShiftAmt, getShiftAmountTy(VT));
>> +      LH = DAG.getNode(ISD::SRL, dl, VT, N->getOperand(0), Shift);
>> +      LH = DAG.getNode(ISD::TRUNCATE, dl, HiLoVT, LH);
>> +      RH = DAG.getNode(ISD::SRL, dl, VT, N->getOperand(1), Shift);
>> +      RH = DAG.getNode(ISD::TRUNCATE, dl, HiLoVT, RH);
>> +    }
>> +
>> +    if (!LH.getNode())
>> +      return false;
>> +
>> +    if (HasUMUL_LOHI) {
>> +      // Lo,Hi = umul LHS, RHS.
>> +      SDValue UMulLOHI = DAG.getNode(ISD::UMUL_LOHI, dl,
>> +                                     DAG.getVTList(HiLoVT, HiLoVT), LL, RL);
>> +      Lo = UMulLOHI;
>> +      Hi = UMulLOHI.getValue(1);
>> +      RH = DAG.getNode(ISD::MUL, dl, HiLoVT, LL, RH);
>> +      LH = DAG.getNode(ISD::MUL, dl, HiLoVT, LH, RL);
>> +      Hi = DAG.getNode(ISD::ADD, dl, HiLoVT, Hi, RH);
>> +      Hi = DAG.getNode(ISD::ADD, dl, HiLoVT, Hi, LH);
>> +      return true;
>> +    }
>> +    if (HasMULHU) {
>> +      Lo = DAG.getNode(ISD::MUL, dl, HiLoVT, LL, RL);
>> +      Hi = DAG.getNode(ISD::MULHU, dl, HiLoVT, LL, RL);
>> +      RH = DAG.getNode(ISD::MUL, dl, HiLoVT, LL, RH);
>> +      LH = DAG.getNode(ISD::MUL, dl, HiLoVT, LH, RL);
>> +      Hi = DAG.getNode(ISD::ADD, dl, HiLoVT, Hi, RH);
>> +      Hi = DAG.getNode(ISD::ADD, dl, HiLoVT, Hi, LH);
>> +      return true;
>> +    }
>> +  }
>> +  return false;
>> +}
>> -- 
>> 1.8.1.5
>> 
> 
>> From 6d0c42f9efad75990293d3955d068b64f5edd857 Mon Sep 17 00:00:00 2001
>> From: Tom Stellard <thomas.stellard at amd.com>
>> Date: Fri, 7 Feb 2014 14:59:37 -0500
>> Subject: [PATCH 2/2] SelectionDAG: Use helper function to improve legalization
>> of ISD::MUL
>> 
>> The TargetLowering::expandMUL() helper contains lowering code extracted
>> from the DAGTypeLegalizer and allows the SelectionDAGLegalizer to expand more
>> ISD::MUL patterns without having to use a library call.
>> ---
>> lib/CodeGen/SelectionDAG/LegalizeDAG.cpp | 17 +++++++++
>> test/CodeGen/R600/mul.ll                 | 63 +++++++++++++++++++++++---------
>> 2 files changed, 62 insertions(+), 18 deletions(-)
>> 
>> diff --git a/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp b/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp
>> index 74c01ca..667ad0f 100644
>> --- a/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp
>> +++ b/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp
>> @@ -3490,6 +3490,23 @@ void SelectionDAGLegalize::ExpandNode(SDNode *Node) {
>>                                     Node->getOperand(1)));
>>       break;
>>     }
>> +
>> +    SDValue Lo, Hi;
>> +    EVT HalfType = VT.getHalfSizedIntegerVT(*DAG.getContext());
>> +    if (TLI.isOperationLegalOrCustom(ISD::ZERO_EXTEND, VT) &&
>> +        TLI.isOperationLegalOrCustom(ISD::ANY_EXTEND, VT) &&
>> +        TLI.isOperationLegalOrCustom(ISD::SHL, VT) &&
>> +        TLI.isOperationLegalOrCustom(ISD::OR, VT) &&
>> +        TLI.expandMUL(Node, Lo, Hi, HalfType, DAG)) {
>> +      Lo = DAG.getNode(ISD::ZERO_EXTEND, dl, VT, Lo);
>> +      Hi = DAG.getNode(ISD::ANY_EXTEND, dl, VT, Hi);
>> +      SDValue Shift = DAG.getConstant(HalfType.getSizeInBits(),
>> +                                      TLI.getShiftAmountTy(HalfType));
>> +      Hi = DAG.getNode(ISD::SHL, dl, VT, Hi, Shift);
>> +      Results.push_back(DAG.getNode(ISD::OR, dl, VT, Lo, Hi));
>> +      break;
>> +    }
>> +
>>     Tmp1 = ExpandIntLibCall(Node, false,
>>                             RTLIB::MUL_I8,
>>                             RTLIB::MUL_I16, RTLIB::MUL_I32,
>> diff --git a/test/CodeGen/R600/mul.ll b/test/CodeGen/R600/mul.ll
>> index 8c27e28..5926700 100644
>> --- a/test/CodeGen/R600/mul.ll
>> +++ b/test/CodeGen/R600/mul.ll
>> @@ -1,15 +1,14 @@
>> -; RUN: llc < %s -march=r600 -mcpu=redwood | FileCheck --check-prefix=EG-CHECK %s
>> -; RUN: llc < %s -march=r600 -mcpu=verde -verify-machineinstrs | FileCheck --check-prefix=SI-CHECK %s
>> +; RUN: llc < %s -march=r600 -mcpu=redwood | FileCheck --check-prefix=EG %s --check-prefix=FUNC
>> +; RUN: llc < %s -march=r600 -mcpu=verde -verify-machineinstrs | FileCheck --check-prefix=SI --check-prefix=FUNC %s
>> 
>> ; mul24 and mad24 are affected
>> 
>> -;EG-CHECK: @test2
>> -;EG-CHECK: MULLO_INT {{\*? *}}T{{[0-9]+\.[XYZW], T[0-9]+\.[XYZW], T[0-9]+\.[XYZW]}}
>> -;EG-CHECK: MULLO_INT {{\*? *}}T{{[0-9]+\.[XYZW], T[0-9]+\.[XYZW], T[0-9]+\.[XYZW]}}
>> +;FUNC-LABEL: @test2
>> +;EG: MULLO_INT {{\*? *}}T{{[0-9]+\.[XYZW], T[0-9]+\.[XYZW], T[0-9]+\.[XYZW]}}
>> +;EG: MULLO_INT {{\*? *}}T{{[0-9]+\.[XYZW], T[0-9]+\.[XYZW], T[0-9]+\.[XYZW]}}
>> 
>> -;SI-CHECK: @test2
>> -;SI-CHECK: V_MUL_LO_I32 v{{[0-9]+, v[0-9]+, v[0-9]+}}
>> -;SI-CHECK: V_MUL_LO_I32 v{{[0-9]+, v[0-9]+, v[0-9]+}}
>> +;SI: V_MUL_LO_I32 v{{[0-9]+, v[0-9]+, v[0-9]+}}
>> +;SI: V_MUL_LO_I32 v{{[0-9]+, v[0-9]+, v[0-9]+}}
>> 
>> define void @test2(<2 x i32> addrspace(1)* %out, <2 x i32> addrspace(1)* %in) {
>>   %b_ptr = getelementptr <2 x i32> addrspace(1)* %in, i32 1
>> @@ -20,17 +19,16 @@ define void @test2(<2 x i32> addrspace(1)* %out, <2 x i32> addrspace(1)* %in) {
>>   ret void
>> }
>> 
>> -;EG-CHECK: @test4
>> -;EG-CHECK: MULLO_INT {{\*? *}}T{{[0-9]+\.[XYZW], T[0-9]+\.[XYZW], T[0-9]+\.[XYZW]}}
>> -;EG-CHECK: MULLO_INT {{\*? *}}T{{[0-9]+\.[XYZW], T[0-9]+\.[XYZW], T[0-9]+\.[XYZW]}}
>> -;EG-CHECK: MULLO_INT {{\*? *}}T{{[0-9]+\.[XYZW], T[0-9]+\.[XYZW], T[0-9]+\.[XYZW]}}
>> -;EG-CHECK: MULLO_INT {{\*? *}}T{{[0-9]+\.[XYZW], T[0-9]+\.[XYZW], T[0-9]+\.[XYZW]}}
>> +;FUNC-LABEL: @test4
>> +;EG: MULLO_INT {{\*? *}}T{{[0-9]+\.[XYZW], T[0-9]+\.[XYZW], T[0-9]+\.[XYZW]}}
>> +;EG: MULLO_INT {{\*? *}}T{{[0-9]+\.[XYZW], T[0-9]+\.[XYZW], T[0-9]+\.[XYZW]}}
>> +;EG: MULLO_INT {{\*? *}}T{{[0-9]+\.[XYZW], T[0-9]+\.[XYZW], T[0-9]+\.[XYZW]}}
>> +;EG: MULLO_INT {{\*? *}}T{{[0-9]+\.[XYZW], T[0-9]+\.[XYZW], T[0-9]+\.[XYZW]}}
>> 
>> -;SI-CHECK: @test4
>> -;SI-CHECK: V_MUL_LO_I32 v{{[0-9]+, v[0-9]+, v[0-9]+}}
>> -;SI-CHECK: V_MUL_LO_I32 v{{[0-9]+, v[0-9]+, v[0-9]+}}
>> -;SI-CHECK: V_MUL_LO_I32 v{{[0-9]+, v[0-9]+, v[0-9]+}}
>> -;SI-CHECK: V_MUL_LO_I32 v{{[0-9]+, v[0-9]+, v[0-9]+}}
>> +;SI: V_MUL_LO_I32 v{{[0-9]+, v[0-9]+, v[0-9]+}}
>> +;SI: V_MUL_LO_I32 v{{[0-9]+, v[0-9]+, v[0-9]+}}
>> +;SI: V_MUL_LO_I32 v{{[0-9]+, v[0-9]+, v[0-9]+}}
>> +;SI: V_MUL_LO_I32 v{{[0-9]+, v[0-9]+, v[0-9]+}}
>> 
>> define void @test4(<4 x i32> addrspace(1)* %out, <4 x i32> addrspace(1)* %in) {
>>   %b_ptr = getelementptr <4 x i32> addrspace(1)* %in, i32 1
>> @@ -40,3 +38,32 @@ define void @test4(<4 x i32> addrspace(1)* %out, <4 x i32> addrspace(1)* %in) {
>>   store <4 x i32> %result, <4 x i32> addrspace(1)* %out
>>   ret void
>> }
>> +
>> +; This 64-bit multiply should just use MUL_HI and MUL_LO, since the top
>> +; 32-bits of both arguments are sign bits.
>> +; FUNC-LABEL: @mul64_sext_c
>> +; EG-DAG: MULLO_INT
>> +; EG-DAG: MULHI_INT
>> +; SI-DAG: V_MUL_LO_I32
>> +; SI-DAG: V_MUL_HI_I32
>> +define void @mul64_sext_c(i64 addrspace(1)* %out, i32 %in) {
>> +entry:
>> +  %0 = sext i32 %in to i64
>> +  %1 = mul i64 %0, 80
>> +  store i64 %1, i64 addrspace(1)* %out
>> +  ret void
>> +}
>> +
>> +; A standard 64-bit multiply.  The expansion should be around 6 instructions.
>> +; It would be difficult to match the expansion correctly without writing
>> +; a really complicated list of FileCheck expressions.  I don't want
>> +; to confuse people who may 'break' this test with a correct optimization,
>> +; so this test just uses FUNC-LABEL to make sure the compiler does not
>> +; crash with a 'failed to select' error.
>> +; FUNC-LABEL: @mul64
>> +define void @mul64(i64 addrspace(1)* %out, i64 %a, i64 %b) {
>> +entry:
>> +  %0 = mul i64 %a, %b
>> +  store i64 %0, i64 addrspace(1)* %out
>> +  ret void
>> +}
>> -- 
>> 1.8.1.5
>> 
> 
>> _______________________________________________
>> llvm-commits mailing list
>> llvm-commits at cs.uiuc.edu
>> http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20140410/652b520a/attachment.html>


More information about the llvm-commits mailing list