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

Tom Stellard tom at stellard.net
Tue Apr 8 13:00:26 PDT 2014


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





More information about the llvm-commits mailing list