diff options
Diffstat (limited to 'llvm/lib')
-rw-r--r-- | llvm/lib/Analysis/TargetTransformInfo.cpp | 186 | ||||
-rw-r--r-- | llvm/lib/IR/Instructions.cpp | 106 |
2 files changed, 122 insertions, 170 deletions
diff --git a/llvm/lib/Analysis/TargetTransformInfo.cpp b/llvm/lib/Analysis/TargetTransformInfo.cpp index fea6db458c7..2bbc074186a 100644 --- a/llvm/lib/Analysis/TargetTransformInfo.cpp +++ b/llvm/lib/Analysis/TargetTransformInfo.cpp @@ -630,147 +630,6 @@ int TargetTransformInfo::getInstructionLatency(const Instruction *I) const { 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::getInstructionThroughput(const Instruction *I) const { } 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(); - - if (NumVecElems == Mask.size()) { - if (isIdentityVectorMask(Mask)) - return 0; + // TODO: Identify and add costs for insert/extract subvector, etc. + if (Shuffle->changesLength()) + return -1; + + if (Shuffle->isIdentity()) + return 0; - if (isReverseVectorMask(Mask)) - return TTIImpl->getShuffleCost(TargetTransformInfo::SK_Reverse, - VecTypOp0, 0, nullptr); + Type *Ty = Shuffle->getType(); + if (Shuffle->isReverse()) + return TTIImpl->getShuffleCost(SK_Reverse, Ty, 0, nullptr); - if (isSelectVectorMask(Mask)) - return TTIImpl->getShuffleCost(TargetTransformInfo::SK_Select, - VecTypOp0, 0, nullptr); + if (Shuffle->isSelect()) + return TTIImpl->getShuffleCost(SK_Select, Ty, 0, nullptr); - if (isTransposeVectorMask(Mask)) - return TTIImpl->getShuffleCost(TargetTransformInfo::SK_Transpose, - VecTypOp0, 0, nullptr); + if (Shuffle->isTranspose()) + return TTIImpl->getShuffleCost(SK_Transpose, Ty, 0, nullptr); - if (isZeroEltBroadcastVectorMask(Mask)) - return TTIImpl->getShuffleCost(TargetTransformInfo::SK_Broadcast, - VecTypOp0, 0, nullptr); + if (Shuffle->isZeroEltSplat()) + return TTIImpl->getShuffleCost(SK_Broadcast, Ty, 0, nullptr); - if (isSingleSourceVectorMask(Mask)) - return TTIImpl->getShuffleCost(TargetTransformInfo::SK_PermuteSingleSrc, - VecTypOp0, 0, nullptr); + if (Shuffle->isSingleSource()) + return TTIImpl->getShuffleCost(SK_PermuteSingleSrc, Ty, 0, nullptr); - return TTIImpl->getShuffleCost(TargetTransformInfo::SK_PermuteTwoSrc, - VecTypOp0, 0, nullptr); - } - - return -1; + return TTIImpl->getShuffleCost(SK_PermuteTwoSrc, Ty, 0, nullptr); } case Instruction::Call: if (const IntrinsicInst *II = dyn_cast<IntrinsicInst>(I)) { diff --git a/llvm/lib/IR/Instructions.cpp b/llvm/lib/IR/Instructions.cpp index e486890e616..58d377c47f6 100644 --- a/llvm/lib/IR/Instructions.cpp +++ b/llvm/lib/IR/Instructions.cpp @@ -1658,7 +1658,7 @@ bool ShuffleVectorInst::isValidOperands(const Value *V1, const Value *V2, 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(Constant *Mask, unsigned i) { 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(Constant *Mask, } } +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 //===----------------------------------------------------------------------===// |