[llvm] r335067 - [IR] move shuffle mask queries from TTI to ShuffleVectorInst

Sanjay Patel via llvm-commits llvm-commits at lists.llvm.org
Mon Jun 25 06:46:49 PDT 2018


Sure - sorry I didn't notice the problem:
https://reviews.llvm.org/rL335468

On Sun, Jun 24, 2018 at 10:52 PM, Zachary Turner <zturner at google.com> wrote:

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


More information about the llvm-commits mailing list