[llvm] r335067 - [IR] move shuffle mask queries from TTI to ShuffleVectorInst
Zachary Turner via llvm-commits
llvm-commits at lists.llvm.org
Sun Jun 24 21:52:40 PDT 2018
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/20180624/b8f39b46/attachment.html>
More information about the llvm-commits
mailing list