<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>