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