<div dir="ltr"><div>Sure - sorry I didn't notice the problem:</div><div><a href="https://reviews.llvm.org/rL335468" rel="noreferrer" target="_blank">https://reviews.llvm.org/<wbr>rL335468</a><br></div></div><div class="gmail_extra"><br><div class="gmail_quote">On Sun, Jun 24, 2018 at 10:52 PM, Zachary Turner <span dir="ltr"><<a href="mailto:zturner@google.com" target="_blank">zturner@google.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir="ltr">This is causing thousands of lines of warning spam on some of the bots (for example: <a href="http://lab.llvm.org:8011/builders/llvm-clang-lld-x86_64-scei-ps4-ubuntu-fast" target="_blank">http://lab.llvm.org:<wbr>8011/builders/llvm-clang-lld-<wbr>x86_64-scei-ps4-ubuntu-fast</a>)<div><br></div><div><pre style="font-family:"Courier New",courier,monotype,monospace;font-size:medium"><span class="m_2212213198322558453inbox-inbox-stdout">/home/buildslave/ps4-<wbr>buildslave4/llvm-clang-lld-<wbr>x86_64-scei-ps4-ubuntu-fast/<wbr>llvm.src/include/llvm/IR/<wbr>Instructions.h:2587:16: warning: HTML start tag prematurely ended, expected attribute name or '>' [-Wdocumentation]
  ///   m0 = <a, b>
               ^
/home/buildslave/ps4-<wbr>buildslave4/llvm-clang-lld-<wbr>x86_64-scei-ps4-ubuntu-fast/<wbr>llvm.src/include/llvm/IR/<wbr>Instructions.h:2591:16: warning: HTML start tag prematurely ended, expected attribute name or '>' [-Wdocumentation]
  ///   t0 = <a, c> = shufflevector m0, m1, <0, 2>
               ^
/home/buildslave/ps4-<wbr>buildslave4/llvm-clang-lld-<wbr>x86_64-scei-ps4-ubuntu-fast/<wbr>llvm.src/include/llvm/IR/<wbr>Instructions.h:2592:16: warning: HTML start tag prematurely ended, expected attribute name or '>' [-Wdocumentation]
  ///   t1 = <b, d> = shufflevector m0, m1, <1, 3>
               ^
/home/buildslave/ps4-<wbr>buildslave4/llvm-clang-lld-<wbr>x86_64-scei-ps4-ubuntu-fast/<wbr>llvm.src/include/llvm/IR/<wbr>Instructions.h:2601:16: warning: HTML start tag prematurely ended, expected attribute name or '>' [-Wdocumentation]
  ///   m0 = <a, b, c, d>
               ^
/home/buildslave/ps4-<wbr>buildslave4/llvm-clang-lld-<wbr>x86_64-scei-ps4-ubuntu-fast/<wbr>llvm.src/include/llvm/IR/<wbr>Instructions.h:2605:16: warning: HTML start tag prematurely ended, expected attribute name or '>' [-Wdocumentation]
  ///   t0 = <a, e, c, g> = shufflevector m0, m1 <0, 4, 2, 6>
               ^
/home/buildslave/ps4-<wbr>buildslave4/llvm-clang-lld-<wbr>x86_64-scei-ps4-ubuntu-fast/<wbr>llvm.src/include/llvm/IR/<wbr>Instructions.h:2606:16: warning: HTML start tag prematurely ended, expected attribute name or '>' [-Wdocumentation]
  ///   t1 = <b, f, d, h> = shufflevector m0, m1 <1, 5, 3, 7>
               ^
/home/buildslave/ps4-<wbr>buildslave4/llvm-clang-lld-<wbr>x86_64-scei-ps4-ubuntu-fast/<wbr>llvm.src/include/llvm/IR/<wbr>Instructions.h:2606:15: warning: HTML tag 'b' requires an end tag [-Wdocumentation-html]
  ///   t1 = <b, f, d, h> = shufflevector m0, m1 <1, 5, 3, 7></span></pre><pre style="font-family:"Courier New",courier,monotype,monospace;font-size:medium"><span class="m_2212213198322558453inbox-inbox-stdout"><br></span></pre><pre style="font-family:"Courier New",courier,monotype,monospace;font-size:medium"><span class="m_2212213198322558453inbox-inbox-stdout">Would you mind addressing this?
</span></pre></div></div><div class="HOEnZb"><div class="h5"><br><div class="gmail_quote"><div dir="ltr">On Tue, Jun 19, 2018 at 11:48 AM Sanjay Patel via llvm-commits <<a href="mailto:llvm-commits@lists.llvm.org" target="_blank">llvm-commits@lists.llvm.org</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Author: spatel<br>
Date: Tue Jun 19 11:44:00 2018<br>
New Revision: 335067<br>
<br>
URL: <a href="http://llvm.org/viewvc/llvm-project?rev=335067&view=rev" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project?rev=335067&view=rev</a><br>
Log:<br>
[IR] move shuffle mask queries from TTI to ShuffleVectorInst<br>
<br>
The optimizer is getting smarter (eg, D47986) about differentiating shuffles <br>
based on its mask values, so we should make queries on the mask constant <br>
operand generally available to avoid code duplication.<br>
<br>
We'll probably use this soon in the vectorizers and instcombine (D48023 and <br>
<a href="https://bugs.llvm.org/show_bug.cgi?id=37806" rel="noreferrer" target="_blank">https://bugs.llvm.org/show_<wbr>bug.cgi?id=37806</a>).<br>
<br>
We might clean up TTI a bit more once all of its current 'SK_*' options are <br>
covered.<br>
<br>
Differential Revision: <a href="https://reviews.llvm.org/D48236" rel="noreferrer" target="_blank">https://reviews.llvm.org/<wbr>D48236</a><br>
<br>
Modified:<br>
    llvm/trunk/include/llvm/IR/<wbr>Instructions.h<br>
    llvm/trunk/lib/Analysis/<wbr>TargetTransformInfo.cpp<br>
    llvm/trunk/lib/IR/<wbr>Instructions.cpp<br>
    llvm/trunk/unittests/IR/<wbr>InstructionsTest.cpp<br>
<br>
Modified: llvm/trunk/include/llvm/IR/<wbr>Instructions.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/IR/Instructions.h?rev=335067&r1=335066&r2=335067&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project/llvm/trunk/include/<wbr>llvm/IR/Instructions.h?rev=<wbr>335067&r1=335066&r2=335067&<wbr>view=diff</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- llvm/trunk/include/llvm/IR/<wbr>Instructions.h (original)<br>
+++ llvm/trunk/include/llvm/IR/<wbr>Instructions.h Tue Jun 19 11:44:00 2018<br>
@@ -2426,7 +2426,7 @@ public:<br>
<br>
   /// Return the shuffle mask value for the specified element of the mask.<br>
   /// Return -1 if the element is undef.<br>
-  static int getMaskValue(Constant *Mask, unsigned Elt);<br>
+  static int getMaskValue(const Constant *Mask, unsigned Elt);<br>
<br>
   /// Return the shuffle mask value of this instruction for the given element<br>
   /// index. Return -1 if the element is undef.<br>
@@ -2436,7 +2436,8 @@ public:<br>
<br>
   /// Convert the input shuffle mask operand to a vector of integers. Undefined<br>
   /// elements of the mask are returned as -1.<br>
-  static void getShuffleMask(Constant *Mask, SmallVectorImpl<int> &Result);<br>
+  static void getShuffleMask(const Constant *Mask,<br>
+                             SmallVectorImpl<int> &Result);<br>
<br>
   /// Return the mask for this instruction as a vector of integers. Undefined<br>
   /// elements of the mask are returned as -1.<br>
@@ -2450,6 +2451,176 @@ public:<br>
     return Mask;<br>
   }<br>
<br>
+  /// Return true if this shuffle returns a vector with a different number of<br>
+  /// elements than its source elements.<br>
+  /// Example: shufflevector <4 x n> A, <4 x n> B, <1,2><br>
+  bool changesLength() const {<br>
+    unsigned NumSourceElts = Op<0>()->getType()-><wbr>getVectorNumElements();<br>
+    unsigned NumMaskElts = getMask()->getType()-><wbr>getVectorNumElements();<br>
+    return NumSourceElts != NumMaskElts;<br>
+  }<br>
+<br>
+  /// Return true if this shuffle mask chooses elements from exactly one source<br>
+  /// vector.<br>
+  /// Example: <7,5,undef,7><br>
+  /// This assumes that vector operands are the same length as the mask.<br>
+  static bool isSingleSourceMask(ArrayRef<<wbr>int> Mask);<br>
+  static bool isSingleSourceMask(const Constant *Mask) {<br>
+    assert(Mask->getType()-><wbr>isVectorTy() && "Shuffle needs vector constant.");<br>
+    SmallVector<int, 16> MaskAsInts;<br>
+    getShuffleMask(Mask, MaskAsInts);<br>
+    return isSingleSourceMask(MaskAsInts)<wbr>;<br>
+  }<br>
+<br>
+  /// Return true if this shuffle chooses elements from exactly one source<br>
+  /// vector without changing the length of that vector.<br>
+  /// Example: shufflevector <4 x n> A, <4 x n> B, <3,0,undef,3><br>
+  /// TODO: Optionally allow length-changing shuffles.<br>
+  bool isSingleSource() const {<br>
+    return !changesLength() && isSingleSourceMask(getMask());<br>
+  }<br>
+<br>
+  /// Return true if this shuffle mask chooses elements from exactly one source<br>
+  /// vector without lane crossings. A shuffle using this mask is not<br>
+  /// necessarily a no-op because it may change the number of elements from its<br>
+  /// input vectors or it may provide demanded bits knowledge via undef lanes.<br>
+  /// Example: <undef,undef,2,3><br>
+  static bool isIdentityMask(ArrayRef<int> Mask);<br>
+  static bool isIdentityMask(const Constant *Mask) {<br>
+    assert(Mask->getType()-><wbr>isVectorTy() && "Shuffle needs vector constant.");<br>
+    SmallVector<int, 16> MaskAsInts;<br>
+    getShuffleMask(Mask, MaskAsInts);<br>
+    return isIdentityMask(MaskAsInts);<br>
+  }<br>
+<br>
+  /// Return true if this shuffle mask chooses elements from exactly one source<br>
+  /// vector without lane crossings and does not change the number of elements<br>
+  /// from its input vectors.<br>
+  /// Example: shufflevector <4 x n> A, <4 x n> B, <4,undef,6,undef><br>
+  /// TODO: Optionally allow length-changing shuffles.<br>
+  bool isIdentity() const {<br>
+    return !changesLength() && isIdentityMask(getShuffleMask(<wbr>));<br>
+  }<br>
+<br>
+  /// Return true if this shuffle mask chooses elements from its source vectors<br>
+  /// without lane crossings. A shuffle using this mask would be<br>
+  /// equivalent to a vector select with a constant condition operand.<br>
+  /// Example: <4,1,6,undef><br>
+  /// This returns false if the mask does not choose from both input vectors.<br>
+  /// In that case, the shuffle is better classified as an identity shuffle.<br>
+  /// This assumes that vector operands are the same length as the mask<br>
+  /// (a length-changing shuffle can never be equivalent to a vector select).<br>
+  static bool isSelectMask(ArrayRef<int> Mask);<br>
+  static bool isSelectMask(const Constant *Mask) {<br>
+    assert(Mask->getType()-><wbr>isVectorTy() && "Shuffle needs vector constant.");<br>
+    SmallVector<int, 16> MaskAsInts;<br>
+    getShuffleMask(Mask, MaskAsInts);<br>
+    return isSelectMask(MaskAsInts);<br>
+  }<br>
+<br>
+  /// Return true if this shuffle chooses elements from its source vectors<br>
+  /// without lane crossings and all operands have the same number of elements.<br>
+  /// In other words, this shuffle is equivalent to a vector select with a<br>
+  /// constant condition operand.<br>
+  /// Example: shufflevector <4 x n> A, <4 x n> B, <undef,1,6,3><br>
+  /// This returns false if the mask does not choose from both input vectors.<br>
+  /// In that case, the shuffle is better classified as an identity shuffle.<br>
+  /// TODO: Optionally allow length-changing shuffles.<br>
+  bool isSelect() const {<br>
+    return !changesLength() && isSelectMask(getMask());<br>
+  }<br>
+<br>
+  /// Return true if this shuffle mask swaps the order of elements from exactly<br>
+  /// one source vector.<br>
+  /// Example: <7,6,undef,4><br>
+  /// This assumes that vector operands are the same length as the mask.<br>
+  static bool isReverseMask(ArrayRef<int> Mask);<br>
+  static bool isReverseMask(const Constant *Mask) {<br>
+    assert(Mask->getType()-><wbr>isVectorTy() && "Shuffle needs vector constant.");<br>
+    SmallVector<int, 16> MaskAsInts;<br>
+    getShuffleMask(Mask, MaskAsInts);<br>
+    return isReverseMask(MaskAsInts);<br>
+  }<br>
+<br>
+  /// Return true if this shuffle swaps the order of elements from exactly<br>
+  /// one source vector.<br>
+  /// Example: shufflevector <4 x n> A, <4 x n> B, <3,undef,1,undef><br>
+  /// TODO: Optionally allow length-changing shuffles.<br>
+  bool isReverse() const {<br>
+    return !changesLength() && isReverseMask(getMask());<br>
+  }<br>
+<br>
+  /// Return true if this shuffle mask chooses all elements with the same value<br>
+  /// as the first element of exactly one source vector.<br>
+  /// Example: <4,undef,undef,4><br>
+  /// This assumes that vector operands are the same length as the mask.<br>
+  static bool isZeroEltSplatMask(ArrayRef<<wbr>int> Mask);<br>
+  static bool isZeroEltSplatMask(const Constant *Mask) {<br>
+    assert(Mask->getType()-><wbr>isVectorTy() && "Shuffle needs vector constant.");<br>
+    SmallVector<int, 16> MaskAsInts;<br>
+    getShuffleMask(Mask, MaskAsInts);<br>
+    return isZeroEltSplatMask(MaskAsInts)<wbr>;<br>
+  }<br>
+<br>
+  /// Return true if all elements of this shuffle are the same value as the<br>
+  /// first element of exactly one source vector without changing the length<br>
+  /// of that vector.<br>
+  /// Example: shufflevector <4 x n> A, <4 x n> B, <undef,0,undef,0><br>
+  /// TODO: Optionally allow length-changing shuffles.<br>
+  /// TODO: Optionally allow splats from other elements.<br>
+  bool isZeroEltSplat() const {<br>
+    return !changesLength() && isZeroEltSplatMask(getMask());<br>
+  }<br>
+<br>
+  /// Return true if this shuffle mask is a transpose mask.<br>
+  /// Transpose vector masks transpose a 2xn matrix. They read corresponding<br>
+  /// even- or odd-numbered vector elements from two n-dimensional source<br>
+  /// vectors and write each result into consecutive elements of an<br>
+  /// n-dimensional destination vector. Two shuffles are necessary to complete<br>
+  /// the transpose, one for the even elements and another for the odd elements.<br>
+  /// This description closely follows how the TRN1 and TRN2 AArch64<br>
+  /// instructions operate.<br>
+  ///<br>
+  /// For example, a simple 2x2 matrix can be transposed with:<br>
+  ///<br>
+  ///   ; Original matrix<br>
+  ///   m0 = <a, b><br>
+  ///   m1 = <c, d><br>
+  ///<br>
+  ///   ; Transposed matrix<br>
+  ///   t0 = <a, c> = shufflevector m0, m1, <0, 2><br>
+  ///   t1 = <b, d> = shufflevector m0, m1, <1, 3><br>
+  ///<br>
+  /// For matrices having greater than n columns, the resulting nx2 transposed<br>
+  /// matrix is stored in two result vectors such that one vector contains<br>
+  /// interleaved elements from all the even-numbered rows and the other vector<br>
+  /// contains interleaved elements from all the odd-numbered rows. For example,<br>
+  /// a 2x4 matrix can be transposed with:<br>
+  ///<br>
+  ///   ; Original matrix<br>
+  ///   m0 = <a, b, c, d><br>
+  ///   m1 = <e, f, g, h><br>
+  ///<br>
+  ///   ; Transposed matrix<br>
+  ///   t0 = <a, e, c, g> = shufflevector m0, m1 <0, 4, 2, 6><br>
+  ///   t1 = <b, f, d, h> = shufflevector m0, m1 <1, 5, 3, 7><br>
+  static bool isTransposeMask(ArrayRef<int> Mask);<br>
+  static bool isTransposeMask(const Constant *Mask) {<br>
+    assert(Mask->getType()-><wbr>isVectorTy() && "Shuffle needs vector constant.");<br>
+    SmallVector<int, 16> MaskAsInts;<br>
+    getShuffleMask(Mask, MaskAsInts);<br>
+    return isTransposeMask(MaskAsInts);<br>
+  }<br>
+<br>
+  /// Return true if this shuffle transposes the elements of its inputs without<br>
+  /// changing the length of the vectors. This operation may also be known as a<br>
+  /// merge or interleave. See the description for isTransposeMask() for the<br>
+  /// exact specification.<br>
+  /// Example: shufflevector <4 x n> A, <4 x n> B, <0,4,2,6><br>
+  bool isTranspose() const {<br>
+    return !changesLength() && isTransposeMask(getMask());<br>
+  }<br>
+<br>
   /// Change values in a shuffle permute mask assuming the two vector operands<br>
   /// of length InVecNumElts have swapped position.<br>
   static void commuteShuffleMask(<wbr>MutableArrayRef<int> Mask,<br>
<br>
Modified: llvm/trunk/lib/Analysis/<wbr>TargetTransformInfo.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Analysis/TargetTransformInfo.cpp?rev=335067&r1=335066&r2=335067&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project/llvm/trunk/lib/<wbr>Analysis/TargetTransformInfo.<wbr>cpp?rev=335067&r1=335066&r2=<wbr>335067&view=diff</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- llvm/trunk/lib/Analysis/<wbr>TargetTransformInfo.cpp (original)<br>
+++ llvm/trunk/lib/Analysis/<wbr>TargetTransformInfo.cpp Tue Jun 19 11:44:00 2018<br>
@@ -630,147 +630,6 @@ int TargetTransformInfo::<wbr>getInstructionL<br>
   return TTIImpl-><wbr>getInstructionLatency(I);<br>
 }<br>
<br>
-static bool isReverseVectorMask(ArrayRef<<wbr>int> Mask) {<br>
-  bool ReverseLHS = true;<br>
-  bool ReverseRHS = true;<br>
-  unsigned MaskSize = Mask.size();<br>
-<br>
-  for (unsigned i = 0; i < MaskSize && (ReverseLHS || ReverseRHS); ++i) {<br>
-    if (Mask[i] < 0)<br>
-      continue;<br>
-    ReverseLHS &= (Mask[i] == (int)(MaskSize - 1 - i));<br>
-    ReverseRHS &= (Mask[i] == (int)(MaskSize + MaskSize - 1 - i));<br>
-  }<br>
-  return ReverseLHS || ReverseRHS;<br>
-}<br>
-<br>
-static bool isSingleSourceVectorMask(<wbr>ArrayRef<int> Mask) {<br>
-  bool ShuffleLHS = false;<br>
-  bool ShuffleRHS = false;<br>
-  unsigned MaskSize = Mask.size();<br>
-<br>
-  for (unsigned i = 0; i < MaskSize && !(ShuffleLHS && ShuffleRHS); ++i) {<br>
-    if (Mask[i] < 0)<br>
-      continue;<br>
-    if ((unsigned)Mask[i] >= MaskSize)<br>
-      ShuffleRHS = true;<br>
-    else<br>
-      ShuffleLHS = true;<br>
-  }<br>
-  return !(ShuffleLHS && ShuffleRHS);<br>
-}<br>
-<br>
-static bool isZeroEltBroadcastVectorMask(<wbr>ArrayRef<int> Mask) {<br>
-  bool BroadcastLHS = true;<br>
-  bool BroadcastRHS = true;<br>
-  unsigned MaskSize = Mask.size();<br>
-<br>
-  for (unsigned i = 0; i < MaskSize && (BroadcastLHS || BroadcastRHS); ++i) {<br>
-    if (Mask[i] < 0)<br>
-      continue;<br>
-    BroadcastLHS &= (Mask[i] == 0);<br>
-    BroadcastRHS &= (Mask[i] == (int)MaskSize);<br>
-  }<br>
-  return BroadcastLHS || BroadcastRHS;<br>
-}<br>
-<br>
-static bool isIdentityVectorMask(ArrayRef<<wbr>int> Mask) {<br>
-  bool IdentityLHS = true;<br>
-  bool IdentityRHS = true;<br>
-  unsigned MaskSize = Mask.size();<br>
-<br>
-  // Example: shufflevector A, B, <0,1,u,3><br>
-  // Example: shufflevector A, B, <4,u,6,u><br>
-  for (unsigned i = 0; i < MaskSize && (IdentityLHS || IdentityRHS); ++i) {<br>
-    if (Mask[i] < 0)<br>
-      continue;<br>
-    IdentityLHS &= (Mask[i] == (int)i);<br>
-    IdentityRHS &= (Mask[i] == (int)(i + MaskSize));<br>
-  }<br>
-  return IdentityLHS || IdentityRHS;<br>
-}<br>
-<br>
-static bool isSelectVectorMask(ArrayRef<<wbr>int> Mask) {<br>
-  bool IsSelect = true;<br>
-  bool FoundLHS = false;<br>
-  bool FoundRHS = false;<br>
-  unsigned MaskSize = Mask.size();<br>
-<br>
-  // Example: shufflevector A, B, <0,1,6,3><br>
-  // Example: shufflevector A, B, <4,1,6,3><br>
-  for (unsigned i = 0; i < MaskSize && IsSelect; ++i) {<br>
-    if (Mask[i] < 0)<br>
-      continue;<br>
-    bool IsLHS = (Mask[i] == (int)i);<br>
-    bool IsRHS = (Mask[i] == (int)(i + MaskSize));<br>
-    FoundLHS |= IsLHS;<br>
-    FoundRHS |= IsRHS;<br>
-    IsSelect = IsLHS || IsRHS;<br>
-  }<br>
-  // If we don't use both vectors this is really an Identity mask.<br>
-  return IsSelect && FoundLHS && FoundRHS;<br>
-}<br>
-<br>
-static bool isTransposeVectorMask(<wbr>ArrayRef<int> Mask) {<br>
-  // Transpose vector masks transpose a 2xn matrix. They read corresponding<br>
-  // even- or odd-numbered vector elements from two n-dimensional source<br>
-  // vectors and write each result into consecutive elements of an<br>
-  // n-dimensional destination vector. Two shuffles are necessary to complete<br>
-  // the transpose, one for the even elements and another for the odd elements.<br>
-  // This description closely follows how the TRN1 and TRN2 AArch64<br>
-  // instructions operate.<br>
-  //<br>
-  // For example, a simple 2x2 matrix can be transposed with:<br>
-  //<br>
-  //   ; Original matrix<br>
-  //   m0 = <a, b><br>
-  //   m1 = <c, d><br>
-  //<br>
-  //   ; Transposed matrix<br>
-  //   t0 = <a, c> = shufflevector m0, m1, <0, 2><br>
-  //   t1 = <b, d> = shufflevector m0, m1, <1, 3><br>
-  //<br>
-  // For matrices having greater than n columns, the resulting nx2 transposed<br>
-  // matrix is stored in two result vectors such that one vector contains<br>
-  // interleaved elements from all the even-numbered rows and the other vector<br>
-  // contains interleaved elements from all the odd-numbered rows. For example,<br>
-  // a 2x4 matrix can be transposed with:<br>
-  //<br>
-  //   ; Original matrix<br>
-  //   m0 = <a, b, c, d><br>
-  //   m1 = <e, f, g, h><br>
-  //<br>
-  //   ; Transposed matrix<br>
-  //   t0 = <a, e, c, g> = shufflevector m0, m1 <0, 4, 2, 6><br>
-  //   t1 = <b, f, d, h> = shufflevector m0, m1 <1, 5, 3, 7><br>
-  //<br>
-  // The above explanation places limitations on what valid transpose masks can<br>
-  // look like. These limitations are defined by the checks below.<br>
-  //<br>
-  // 1. The number of elements in the mask must be a power of two.<br>
-  if (!isPowerOf2_32(Mask.size()))<br>
-    return false;<br>
-<br>
-  // 2. The first element of the mask must be either a zero (for the<br>
-  // even-numbered vector elements) or a one (for the odd-numbered vector<br>
-  // elements).<br>
-  if (Mask[0] != 0 && Mask[0] != 1)<br>
-    return false;<br>
-<br>
-  // 3. The difference between the first two elements must be equal to the<br>
-  // number of elements in the mask.<br>
-  if (Mask[1] - Mask[0] != (int)Mask.size())<br>
-    return false;<br>
-<br>
-  // 4. The difference between consecutive even-numbered and odd-numbered<br>
-  // elements must be equal to two.<br>
-  for (int I = 2; I < (int)Mask.size(); ++I)<br>
-    if (Mask[I] - Mask[I - 2] != 2)<br>
-      return false;<br>
-<br>
-  return true;<br>
-}<br>
-<br>
 static TargetTransformInfo::<wbr>OperandValueKind<br>
 getOperandInfo(Value *V, TargetTransformInfo::<wbr>OperandValueProperties &OpProps) {<br>
   TargetTransformInfo::<wbr>OperandValueKind OpInfo =<br>
@@ -1236,39 +1095,30 @@ int TargetTransformInfo::<wbr>getInstructionT<br>
   }<br>
   case Instruction::ShuffleVector: {<br>
     const ShuffleVectorInst *Shuffle = cast<ShuffleVectorInst>(I);<br>
-    Type *VecTypOp0 = Shuffle->getOperand(0)-><wbr>getType();<br>
-    unsigned NumVecElems = VecTypOp0-><wbr>getVectorNumElements();<br>
-    SmallVector<int, 16> Mask = Shuffle->getShuffleMask();<br>
+    // TODO: Identify and add costs for insert/extract subvector, etc.<br>
+    if (Shuffle->changesLength())<br>
+      return -1;<br>
+    <br>
+    if (Shuffle->isIdentity())<br>
+      return 0;<br>
+<br>
+    Type *Ty = Shuffle->getType();<br>
+    if (Shuffle->isReverse())<br>
+      return TTIImpl->getShuffleCost(SK_<wbr>Reverse, Ty, 0, nullptr);<br>
+<br>
+    if (Shuffle->isSelect())<br>
+      return TTIImpl->getShuffleCost(SK_<wbr>Select, Ty, 0, nullptr);<br>
+<br>
+    if (Shuffle->isTranspose())<br>
+      return TTIImpl->getShuffleCost(SK_<wbr>Transpose, Ty, 0, nullptr);<br>
<br>
-    if (NumVecElems == Mask.size()) {<br>
-      if (isIdentityVectorMask(Mask))<br>
-        return 0;<br>
-<br>
-      if (isReverseVectorMask(Mask))<br>
-        return TTIImpl->getShuffleCost(<wbr>TargetTransformInfo::SK_<wbr>Reverse,<br>
-                                       VecTypOp0, 0, nullptr);<br>
-<br>
-      if (isSelectVectorMask(Mask))<br>
-        return TTIImpl->getShuffleCost(<wbr>TargetTransformInfo::SK_<wbr>Select,<br>
-                                       VecTypOp0, 0, nullptr);<br>
-<br>
-      if (isTransposeVectorMask(Mask))<br>
-        return TTIImpl->getShuffleCost(<wbr>TargetTransformInfo::SK_<wbr>Transpose,<br>
-                                       VecTypOp0, 0, nullptr);<br>
-<br>
-      if (isZeroEltBroadcastVectorMask(<wbr>Mask))<br>
-        return TTIImpl->getShuffleCost(<wbr>TargetTransformInfo::SK_<wbr>Broadcast,<br>
-                                       VecTypOp0, 0, nullptr);<br>
-<br>
-      if (isSingleSourceVectorMask(<wbr>Mask))<br>
-        return TTIImpl->getShuffleCost(<wbr>TargetTransformInfo::SK_<wbr>PermuteSingleSrc,<br>
-                                       VecTypOp0, 0, nullptr);<br>
+    if (Shuffle->isZeroEltSplat())<br>
+      return TTIImpl->getShuffleCost(SK_<wbr>Broadcast, Ty, 0, nullptr);<br>
<br>
-      return TTIImpl->getShuffleCost(<wbr>TargetTransformInfo::SK_<wbr>PermuteTwoSrc,<br>
-                                     VecTypOp0, 0, nullptr);<br>
-    }<br>
+    if (Shuffle->isSingleSource())<br>
+      return TTIImpl->getShuffleCost(SK_<wbr>PermuteSingleSrc, Ty, 0, nullptr);<br>
<br>
-    return -1;<br>
+    return TTIImpl->getShuffleCost(SK_<wbr>PermuteTwoSrc, Ty, 0, nullptr);<br>
   }<br>
   case Instruction::Call:<br>
     if (const IntrinsicInst *II = dyn_cast<IntrinsicInst>(I)) {<br>
<br>
Modified: llvm/trunk/lib/IR/<wbr>Instructions.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/IR/Instructions.cpp?rev=335067&r1=335066&r2=335067&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project/llvm/trunk/lib/IR/<wbr>Instructions.cpp?rev=335067&<wbr>r1=335066&r2=335067&view=diff</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- llvm/trunk/lib/IR/<wbr>Instructions.cpp (original)<br>
+++ llvm/trunk/lib/IR/<wbr>Instructions.cpp Tue Jun 19 11:44:00 2018<br>
@@ -1658,7 +1658,7 @@ bool ShuffleVectorInst::<wbr>isValidOperands(<br>
   return false;<br>
 }<br>
<br>
-int ShuffleVectorInst::<wbr>getMaskValue(Constant *Mask, unsigned i) {<br>
+int ShuffleVectorInst::<wbr>getMaskValue(const Constant *Mask, unsigned i) {<br>
   assert(i < Mask->getType()-><wbr>getVectorNumElements() && "Index out of range");<br>
   if (auto *CDS = dyn_cast<<wbr>ConstantDataSequential>(Mask))<br>
     return CDS->getElementAsInteger(i);<br>
@@ -1668,7 +1668,7 @@ int ShuffleVectorInst::<wbr>getMaskValue(Cons<br>
   return cast<ConstantInt>(C)-><wbr>getZExtValue();<br>
 }<br>
<br>
-void ShuffleVectorInst::<wbr>getShuffleMask(Constant *Mask,<br>
+void ShuffleVectorInst::<wbr>getShuffleMask(const Constant *Mask,<br>
                                        SmallVectorImpl<int> &Result) {<br>
   unsigned NumElts = Mask->getType()-><wbr>getVectorNumElements();<br>
<br>
@@ -1684,6 +1684,108 @@ void ShuffleVectorInst::<wbr>getShuffleMask(C<br>
   }<br>
 }<br>
<br>
+bool ShuffleVectorInst::<wbr>isSingleSourceMask(ArrayRef<<wbr>int> Mask) {<br>
+  assert(!Mask.empty() && "Shuffle mask must contain elements");<br>
+  bool UsesLHS = false;<br>
+  bool UsesRHS = false;<br>
+  for (int i = 0, NumElts = Mask.size(); i < NumElts; ++i) {<br>
+    if (Mask[i] == -1)<br>
+      continue;<br>
+    assert(Mask[i] >= 0 && Mask[i] < (NumElts * 2) &&<br>
+           "Out-of-bounds shuffle mask element");<br>
+    UsesLHS |= (Mask[i] < NumElts);<br>
+    UsesRHS |= (Mask[i] >= NumElts);<br>
+    if (UsesLHS && UsesRHS)<br>
+      return false;<br>
+  }<br>
+  assert((UsesLHS ^ UsesRHS) && "Should have selected from exactly 1 source");<br>
+  return true;<br>
+}<br>
+<br>
+bool ShuffleVectorInst::<wbr>isIdentityMask(ArrayRef<int> Mask) {<br>
+  if (!isSingleSourceMask(Mask))<br>
+    return false;<br>
+  for (int i = 0, NumElts = Mask.size(); i < NumElts; ++i) {<br>
+    if (Mask[i] == -1)<br>
+      continue;<br>
+    if (Mask[i] != i && Mask[i] != (NumElts + i))<br>
+      return false;<br>
+  }<br>
+  return true;<br>
+}<br>
+<br>
+bool ShuffleVectorInst::<wbr>isReverseMask(ArrayRef<int> Mask) {<br>
+  if (!isSingleSourceMask(Mask))<br>
+    return false;<br>
+  for (int i = 0, NumElts = Mask.size(); i < NumElts; ++i) {<br>
+    if (Mask[i] == -1)<br>
+      continue;<br>
+    if (Mask[i] != (NumElts - 1 - i) && Mask[i] != (NumElts + NumElts - 1 - i))<br>
+      return false;<br>
+  }<br>
+  return true;<br>
+}<br>
+<br>
+bool ShuffleVectorInst::<wbr>isZeroEltSplatMask(ArrayRef<<wbr>int> Mask) {<br>
+  if (!isSingleSourceMask(Mask))<br>
+    return false;<br>
+  for (int i = 0, NumElts = Mask.size(); i < NumElts; ++i) {<br>
+    if (Mask[i] == -1)<br>
+      continue;<br>
+    if (Mask[i] != 0 && Mask[i] != NumElts)<br>
+      return false;<br>
+  }<br>
+  return true;<br>
+}<br>
+<br>
+bool ShuffleVectorInst::<wbr>isSelectMask(ArrayRef<int> Mask) {<br>
+  // Select is differentiated from identity. It requires using both sources.<br>
+  if (isSingleSourceMask(Mask))<br>
+    return false;<br>
+  for (int i = 0, NumElts = Mask.size(); i < NumElts; ++i) {<br>
+    if (Mask[i] == -1)<br>
+      continue;<br>
+    if (Mask[i] != i && Mask[i] != (NumElts + i))<br>
+      return false;<br>
+  }<br>
+  return true;<br>
+}<br>
+<br>
+bool ShuffleVectorInst::<wbr>isTransposeMask(ArrayRef<int> Mask) {<br>
+  // Example masks that will return true:<br>
+  // v1 = <a, b, c, d><br>
+  // v2 = <e, f, g, h><br>
+  // trn1 = shufflevector v1, v2 <0, 4, 2, 6> = <a, e, c, g><br>
+  // trn2 = shufflevector v1, v2 <1, 5, 3, 7> = <b, f, d, h><br>
+<br>
+  // 1. The number of elements in the mask must be a power-of-2 and at least 2.<br>
+  int NumElts = Mask.size();<br>
+  if (NumElts < 2 || !isPowerOf2_32(NumElts))<br>
+    return false;<br>
+<br>
+  // 2. The first element of the mask must be either a 0 or a 1.<br>
+  if (Mask[0] != 0 && Mask[0] != 1)<br>
+    return false;<br>
+<br>
+  // 3. The difference between the first 2 elements must be equal to the<br>
+  // number of elements in the mask.<br>
+  if ((Mask[1] - Mask[0]) != NumElts)<br>
+    return false;<br>
+<br>
+  // 4. The difference between consecutive even-numbered and odd-numbered<br>
+  // elements must be equal to 2.<br>
+  for (int i = 2; i < NumElts; ++i) {<br>
+    int MaskEltVal = Mask[i];<br>
+    if (MaskEltVal == -1)<br>
+      return false;<br>
+    int MaskEltPrevVal = Mask[i - 2];<br>
+    if (MaskEltVal - MaskEltPrevVal != 2)<br>
+      return false;<br>
+  }<br>
+  return true;<br>
+}<br>
+<br>
+<br>
 //===------------------------<wbr>------------------------------<wbr>----------------===//<br>
 //                             InsertValueInst Class<br>
 //===------------------------<wbr>------------------------------<wbr>----------------===//<br>
<br>
Modified: llvm/trunk/unittests/IR/<wbr>InstructionsTest.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/unittests/IR/InstructionsTest.cpp?rev=335067&r1=335066&r2=335067&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project/llvm/trunk/unittests/<wbr>IR/InstructionsTest.cpp?rev=<wbr>335067&r1=335066&r2=335067&<wbr>view=diff</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- llvm/trunk/unittests/IR/<wbr>InstructionsTest.cpp (original)<br>
+++ llvm/trunk/unittests/IR/<wbr>InstructionsTest.cpp Tue Jun 19 11:44:00 2018<br>
@@ -747,5 +747,87 @@ TEST(InstructionsTest, CommuteShuffleMas<br>
   EXPECT_THAT(Indices, testing::ContainerEq(ArrayRef<<wbr>int>({-1, 4, 3})));<br>
 }<br>
<br>
+TEST(InstructionsTest, ShuffleMaskQueries) {<br>
+  // Create the elements for various constant vectors.<br>
+  LLVMContext Ctx;<br>
+  Type *Int32Ty = Type::getInt32Ty(Ctx);<br>
+  Constant *CU = UndefValue::get(Int32Ty);<br>
+  Constant *C0 = ConstantInt::get(Int32Ty, 0);<br>
+  Constant *C1 = ConstantInt::get(Int32Ty, 1);<br>
+  Constant *C2 = ConstantInt::get(Int32Ty, 2);<br>
+  Constant *C3 = ConstantInt::get(Int32Ty, 3);<br>
+  Constant *C4 = ConstantInt::get(Int32Ty, 4);<br>
+  Constant *C5 = ConstantInt::get(Int32Ty, 5);<br>
+  Constant *C6 = ConstantInt::get(Int32Ty, 6);<br>
+  Constant *C7 = ConstantInt::get(Int32Ty, 7);<br>
+<br>
+  Constant *Identity = ConstantVector::get({C0, CU, C2, C3, C4});<br>
+  EXPECT_TRUE(ShuffleVectorInst:<wbr>:isIdentityMask(Identity));<br>
+  EXPECT_FALSE(<wbr>ShuffleVectorInst::<wbr>isSelectMask(Identity)); // identity is distinguished from select<br>
+  EXPECT_FALSE(<wbr>ShuffleVectorInst::<wbr>isReverseMask(Identity));<br>
+  EXPECT_TRUE(ShuffleVectorInst:<wbr>:isSingleSourceMask(Identity))<wbr>; // identity is always single source<br>
+  EXPECT_FALSE(<wbr>ShuffleVectorInst::<wbr>isZeroEltSplatMask(Identity));<br>
+  EXPECT_FALSE(<wbr>ShuffleVectorInst::<wbr>isTransposeMask(Identity));<br>
+<br>
+  Constant *Select = ConstantVector::get({CU, C1, C5});<br>
+  EXPECT_FALSE(<wbr>ShuffleVectorInst::<wbr>isIdentityMask(Select));<br>
+  EXPECT_TRUE(ShuffleVectorInst:<wbr>:isSelectMask(Select));<br>
+  EXPECT_FALSE(<wbr>ShuffleVectorInst::<wbr>isReverseMask(Select));<br>
+  EXPECT_FALSE(<wbr>ShuffleVectorInst::<wbr>isSingleSourceMask(Select));<br>
+  EXPECT_FALSE(<wbr>ShuffleVectorInst::<wbr>isZeroEltSplatMask(Select));<br>
+  EXPECT_FALSE(<wbr>ShuffleVectorInst::<wbr>isTransposeMask(Select));<br>
+  <br>
+  Constant *Reverse = ConstantVector::get({C3, C2, C1, CU});<br>
+  EXPECT_FALSE(<wbr>ShuffleVectorInst::<wbr>isIdentityMask(Reverse));<br>
+  EXPECT_FALSE(<wbr>ShuffleVectorInst::<wbr>isSelectMask(Reverse));<br>
+  EXPECT_TRUE(ShuffleVectorInst:<wbr>:isReverseMask(Reverse));<br>
+  EXPECT_TRUE(ShuffleVectorInst:<wbr>:isSingleSourceMask(Reverse)); // reverse is always single source<br>
+  EXPECT_FALSE(<wbr>ShuffleVectorInst::<wbr>isZeroEltSplatMask(Reverse));<br>
+  EXPECT_FALSE(<wbr>ShuffleVectorInst::<wbr>isTransposeMask(Reverse));<br>
+<br>
+  Constant *SingleSource = ConstantVector::get({C2, C2, C0, CU});<br>
+  EXPECT_FALSE(<wbr>ShuffleVectorInst::<wbr>isIdentityMask(SingleSource));<br>
+  EXPECT_FALSE(<wbr>ShuffleVectorInst::<wbr>isSelectMask(SingleSource));<br>
+  EXPECT_FALSE(<wbr>ShuffleVectorInst::<wbr>isReverseMask(SingleSource));<br>
+  EXPECT_TRUE(ShuffleVectorInst:<wbr>:isSingleSourceMask(<wbr>SingleSource));<br>
+  EXPECT_FALSE(<wbr>ShuffleVectorInst::<wbr>isZeroEltSplatMask(<wbr>SingleSource));<br>
+  EXPECT_FALSE(<wbr>ShuffleVectorInst::<wbr>isTransposeMask(SingleSource))<wbr>;<br>
+<br>
+  Constant *ZeroEltSplat = ConstantVector::get({C0, C0, CU, C0});<br>
+  EXPECT_FALSE(<wbr>ShuffleVectorInst::<wbr>isIdentityMask(ZeroEltSplat));<br>
+  EXPECT_FALSE(<wbr>ShuffleVectorInst::<wbr>isSelectMask(ZeroEltSplat));<br>
+  EXPECT_FALSE(<wbr>ShuffleVectorInst::<wbr>isReverseMask(ZeroEltSplat));<br>
+  EXPECT_TRUE(ShuffleVectorInst:<wbr>:isSingleSourceMask(<wbr>ZeroEltSplat)); // 0-splat is always single source<br>
+  EXPECT_TRUE(ShuffleVectorInst:<wbr>:isZeroEltSplatMask(<wbr>ZeroEltSplat));<br>
+  EXPECT_FALSE(<wbr>ShuffleVectorInst::<wbr>isTransposeMask(ZeroEltSplat))<wbr>;<br>
+<br>
+  Constant *Transpose = ConstantVector::get({C0, C4, C2, C6});<br>
+  EXPECT_FALSE(<wbr>ShuffleVectorInst::<wbr>isIdentityMask(Transpose));<br>
+  EXPECT_FALSE(<wbr>ShuffleVectorInst::<wbr>isSelectMask(Transpose));<br>
+  EXPECT_FALSE(<wbr>ShuffleVectorInst::<wbr>isReverseMask(Transpose));<br>
+  EXPECT_FALSE(<wbr>ShuffleVectorInst::<wbr>isSingleSourceMask(Transpose))<wbr>;<br>
+  EXPECT_FALSE(<wbr>ShuffleVectorInst::<wbr>isZeroEltSplatMask(Transpose))<wbr>;<br>
+  EXPECT_TRUE(ShuffleVectorInst:<wbr>:isTransposeMask(Transpose));<br>
+<br>
+  // More tests to make sure the logic is/stays correct...<br>
+  EXPECT_TRUE(ShuffleVectorInst:<wbr>:isIdentityMask(<wbr>ConstantVector::get({CU, C1, CU, C3})));<br>
+  EXPECT_TRUE(ShuffleVectorInst:<wbr>:isIdentityMask(<wbr>ConstantVector::get({C4, CU, C6, CU})));<br>
+<br>
+  EXPECT_TRUE(ShuffleVectorInst:<wbr>:isSelectMask(ConstantVector::<wbr>get({C4, C1, C6, CU})));<br>
+  EXPECT_TRUE(ShuffleVectorInst:<wbr>:isSelectMask(ConstantVector::<wbr>get({CU, C1, C6, C3})));<br>
+<br>
+  EXPECT_TRUE(ShuffleVectorInst:<wbr>:isReverseMask(ConstantVector:<wbr>:get({C7, C6, CU, C4})));<br>
+  EXPECT_TRUE(ShuffleVectorInst:<wbr>:isReverseMask(ConstantVector:<wbr>:get({C3, CU, C1, CU})));<br>
+<br>
+  EXPECT_TRUE(ShuffleVectorInst:<wbr>:isSingleSourceMask(<wbr>ConstantVector::get({C7, C5, CU, C7})));<br>
+  EXPECT_TRUE(ShuffleVectorInst:<wbr>:isSingleSourceMask(<wbr>ConstantVector::get({C3, C0, CU, C3})));<br>
+<br>
+  EXPECT_TRUE(ShuffleVectorInst:<wbr>:isZeroEltSplatMask(<wbr>ConstantVector::get({C4, CU, CU, C4})));<br>
+  EXPECT_TRUE(ShuffleVectorInst:<wbr>:isZeroEltSplatMask(<wbr>ConstantVector::get({CU, C0, CU, C0})));<br>
+<br>
+  EXPECT_TRUE(ShuffleVectorInst:<wbr>:isTransposeMask(<wbr>ConstantVector::get({C1, C5, C3, C7})));<br>
+  EXPECT_TRUE(ShuffleVectorInst:<wbr>:isTransposeMask(<wbr>ConstantVector::get({C1, C3})));<br>
+}<br>
+<br>
 } // end anonymous namespace<br>
 } // end namespace llvm<br>
<br>
<br>
______________________________<wbr>_________________<br>
llvm-commits mailing list<br>
<a href="mailto:llvm-commits@lists.llvm.org" target="_blank">llvm-commits@lists.llvm.org</a><br>
<a href="http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-commits" rel="noreferrer" target="_blank">http://lists.llvm.org/cgi-bin/<wbr>mailman/listinfo/llvm-commits</a><br>
</blockquote></div>
</div></div></blockquote></div><br></div>