diff --git a/llvm/include/llvm/IR/Instructions.h b/llvm/include/llvm/IR/Instructions.h index 9a41971b63373..c770969efb40b 100644 --- a/llvm/include/llvm/IR/Instructions.h +++ b/llvm/include/llvm/IR/Instructions.h @@ -1886,6 +1886,20 @@ DEFINE_TRANSPARENT_OPERAND_ACCESSORS(InsertElementInst, Value) // ShuffleVectorInst Class //===----------------------------------------------------------------------===// +struct ShuffleMaskAttrs { + bool SingleSource : 1; + bool Identity : 1; + bool Reverse : 1; + bool ZeroEltSplat : 1; + bool Select : 1; + bool Transpose : 1; + bool Splice : 1; + int SpliceIndex; +}; + +static_assert(sizeof(ShuffleMaskAttrs) <= sizeof(uint64_t), + "ShuffleMaskAttrs is too large!"); + constexpr int PoisonMaskElem = -1; /// This instruction constructs a fixed permutation of two @@ -1903,6 +1917,27 @@ class ShuffleVectorInst : public Instruction { SmallVector ShuffleMask; Constant *ShuffleMaskForBitcode; + ShuffleMaskAttrs ShuffleAttrs; + + // (Re)compute the shuffle mask attributes. + void computeShuffleAttrs() { + ShuffleAttrs = {}; // reset + ShuffleAttrs.SingleSource = + !changesLength() && isSingleSourceMask(ShuffleMask, ShuffleMask.size()); + ShuffleAttrs.Identity = + !changesLength() && isIdentityMask(ShuffleMask, ShuffleMask.size()); + ShuffleAttrs.Select = + !changesLength() && isSelectMask(ShuffleMask, ShuffleMask.size()); + ShuffleAttrs.Reverse = + !changesLength() && isReverseMask(ShuffleMask, ShuffleMask.size()); + ShuffleAttrs.ZeroEltSplat = + !changesLength() && isZeroEltSplatMask(ShuffleMask, ShuffleMask.size()); + ShuffleAttrs.Transpose = + !changesLength() && isTransposeMask(ShuffleMask, ShuffleMask.size()); + ShuffleAttrs.Splice = + !changesLength() && + isSpliceMask(ShuffleMask, ShuffleMask.size(), ShuffleAttrs.SpliceIndex); + } protected: // Note: Instruction needs to be a friend here to call cloneImpl. @@ -2013,10 +2048,7 @@ class ShuffleVectorInst : public Instruction { /// 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(ShuffleMask, ShuffleMask.size()); - } + bool isSingleSource() const { return ShuffleAttrs.SingleSource; } /// Return true if this shuffle mask chooses elements from exactly one source /// vector without lane crossings. A shuffle using this mask is not @@ -2047,7 +2079,7 @@ class ShuffleVectorInst : public Instruction { if (isa(getType())) return false; - return !changesLength() && isIdentityMask(ShuffleMask, ShuffleMask.size()); + return ShuffleAttrs.Identity; } /// Return true if this shuffle lengthens exactly one source vector with @@ -2087,9 +2119,7 @@ class ShuffleVectorInst : public Instruction { /// 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(ShuffleMask, ShuffleMask.size()); - } + bool isSelect() const { return ShuffleAttrs.Select; } /// Return true if this shuffle mask swaps the order of elements from exactly /// one source vector. @@ -2108,9 +2138,7 @@ class ShuffleVectorInst : public Instruction { /// 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(ShuffleMask, ShuffleMask.size()); - } + bool isReverse() const { return ShuffleAttrs.Reverse; } /// Return true if this shuffle mask chooses all elements with the same value /// as the first element of exactly one source vector. @@ -2131,10 +2159,7 @@ class ShuffleVectorInst : public Instruction { /// Example: shufflevector <4 x n> A, <4 x n> B, /// TODO: Optionally allow length-changing shuffles. /// TODO: Optionally allow splats from other elements. - bool isZeroEltSplat() const { - return !changesLength() && - isZeroEltSplatMask(ShuffleMask, ShuffleMask.size()); - } + bool isZeroEltSplat() const { return ShuffleAttrs.ZeroEltSplat; } /// Return true if this shuffle mask is a transpose mask. /// Transpose vector masks transpose a 2xn matrix. They read corresponding @@ -2181,9 +2206,7 @@ class ShuffleVectorInst : public Instruction { /// 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(ShuffleMask, ShuffleMask.size()); - } + bool isTranspose() const { return ShuffleAttrs.Transpose; } /// Return true if this shuffle mask is a splice mask, concatenating the two /// inputs together and then extracts an original width vector starting from @@ -2204,8 +2227,9 @@ class ShuffleVectorInst : public Instruction { /// then extracts an original width vector starting from the splice index. /// Example: shufflevector <4 x n> A, <4 x n> B, <1,2,3,4> bool isSplice(int &Index) const { - return !changesLength() && - isSpliceMask(ShuffleMask, ShuffleMask.size(), Index); + if (ShuffleAttrs.Splice) + Index = ShuffleAttrs.SpliceIndex; + return ShuffleAttrs.Splice; } /// Return true if this shuffle mask is an extract subvector mask. diff --git a/llvm/lib/IR/Instructions.cpp b/llvm/lib/IR/Instructions.cpp index b585d8cfbf2e2..794307b81ea7d 100644 --- a/llvm/lib/IR/Instructions.cpp +++ b/llvm/lib/IR/Instructions.cpp @@ -1822,6 +1822,7 @@ void ShuffleVectorInst::getShuffleMask(const Constant *Mask, void ShuffleVectorInst::setShuffleMask(ArrayRef Mask) { ShuffleMask.assign(Mask.begin(), Mask.end()); ShuffleMaskForBitcode = convertShuffleMaskForBitcode(Mask, getType()); + computeShuffleAttrs(); } Constant *ShuffleVectorInst::convertShuffleMaskForBitcode(ArrayRef Mask,