[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