llvm.org GIT mirror llvm / 14ea008
[IR] add shuffle queries for identity extend/extract This was one of the potential follow-ups suggested in D48236, and these will be used to make matching the patterns in PR38691 cleaner: https://bugs.llvm.org/show_bug.cgi?id=38691 About the vocabulary: in the DAG, these would be concat_vector with an undef operand or extract_subvector. Alternate names are discussed in the review, but I think these are familiar/good enough to proceed. Once we have uses of them in code, we might adjust if there are better options. https://reviews.llvm.org/D51392 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@341075 91177308-0d34-0410-b5e6-96231b3b80d8 Sanjay Patel 1 year, 1 month ago
3 changed file(s) with 130 addition(s) and 12 deletion(s). Raw diff Collapse all Expand all
24552455 }
24562456
24572457 /// Return true if this shuffle returns a vector with a different number of
2458 /// elements than its source elements.
2458 /// elements than its source vectors.
24592459 /// Example: shufflevector <4 x n> A, <4 x n> B, <1,2>
24602460 bool changesLength() const {
24612461 unsigned NumSourceElts = Op<0>()->getType()->getVectorNumElements();
24962496 return isIdentityMask(MaskAsInts);
24972497 }
24982498
2499 /// Return true if this shuffle mask chooses elements from exactly one source
2499 /// Return true if this shuffle chooses elements from exactly one source
25002500 /// vector without lane crossings and does not change the number of elements
25012501 /// from its input vectors.
25022502 /// Example: shufflevector <4 x n> A, <4 x n> B, <4,undef,6,undef>
2503 /// TODO: Optionally allow length-changing shuffles.
25042503 bool isIdentity() const {
25052504 return !changesLength() && isIdentityMask(getShuffleMask());
25062505 }
2506
2507 /// Return true if this shuffle lengthens exactly one source vector with
2508 /// undefs in the high elements.
2509 bool isIdentityWithPadding() const;
2510
2511 /// Return true if this shuffle extracts the first N elements of exactly one
2512 /// source vector.
2513 bool isIdentityWithExtract() const;
25072514
25082515 /// Return true if this shuffle mask chooses elements from its source vectors
25092516 /// without lane crossings. A shuffle using this mask would be
16591659 }
16601660 }
16611661
1662 bool ShuffleVectorInst::isSingleSourceMask(ArrayRef Mask) {
1662 static bool isSingleSourceMaskImpl(ArrayRef Mask, int NumOpElts) {
16631663 assert(!Mask.empty() && "Shuffle mask must contain elements");
16641664 bool UsesLHS = false;
16651665 bool UsesRHS = false;
1666 for (int i = 0, NumElts = Mask.size(); i < NumElts; ++i) {
1666 for (int i = 0, NumMaskElts = Mask.size(); i < NumMaskElts; ++i) {
16671667 if (Mask[i] == -1)
16681668 continue;
1669 assert(Mask[i] >= 0 && Mask[i] < (NumElts * 2) &&
1669 assert(Mask[i] >= 0 && Mask[i] < (NumOpElts * 2) &&
16701670 "Out-of-bounds shuffle mask element");
1671 UsesLHS |= (Mask[i] < NumElts);
1672 UsesRHS |= (Mask[i] >= NumElts);
1671 UsesLHS |= (Mask[i] < NumOpElts);
1672 UsesRHS |= (Mask[i] >= NumOpElts);
16731673 if (UsesLHS && UsesRHS)
16741674 return false;
16751675 }
16771677 return true;
16781678 }
16791679
1680 bool ShuffleVectorInst::isIdentityMask(ArrayRef Mask) {
1681 if (!isSingleSourceMask(Mask))
1680 bool ShuffleVectorInst::isSingleSourceMask(ArrayRef Mask) {
1681 // We don't have vector operand size information, so assume operands are the
1682 // same size as the mask.
1683 return isSingleSourceMaskImpl(Mask, Mask.size());
1684 }
1685
1686 static bool isIdentityMaskImpl(ArrayRef Mask, int NumOpElts) {
1687 if (!isSingleSourceMaskImpl(Mask, NumOpElts))
16821688 return false;
1683 for (int i = 0, NumElts = Mask.size(); i < NumElts; ++i) {
1689 for (int i = 0, NumMaskElts = Mask.size(); i < NumMaskElts; ++i) {
16841690 if (Mask[i] == -1)
16851691 continue;
1686 if (Mask[i] != i && Mask[i] != (NumElts + i))
1692 if (Mask[i] != i && Mask[i] != (NumOpElts + i))
16871693 return false;
16881694 }
16891695 return true;
1696 }
1697
1698 bool ShuffleVectorInst::isIdentityMask(ArrayRef Mask) {
1699 // We don't have vector operand size information, so assume operands are the
1700 // same size as the mask.
1701 return isIdentityMaskImpl(Mask, Mask.size());
16901702 }
16911703
16921704 bool ShuffleVectorInst::isReverseMask(ArrayRef Mask) {
17601772 return true;
17611773 }
17621774
1775 bool ShuffleVectorInst::isIdentityWithPadding() const {
1776 int NumOpElts = Op<0>()->getType()->getVectorNumElements();
1777 int NumMaskElts = getType()->getVectorNumElements();
1778 if (NumMaskElts <= NumOpElts)
1779 return false;
1780
1781 // The first part of the mask must choose elements from exactly 1 source op.
1782 ArrayRef Mask = getShuffleMask();
1783 if (!isIdentityMaskImpl(Mask, NumOpElts))
1784 return false;
1785
1786 // All extending must be with undef elements.
1787 for (int i = NumOpElts; i < NumMaskElts; ++i)
1788 if (Mask[i] != -1)
1789 return false;
1790
1791 return true;
1792 }
1793
1794 bool ShuffleVectorInst::isIdentityWithExtract() const {
1795 int NumOpElts = Op<0>()->getType()->getVectorNumElements();
1796 int NumMaskElts = getType()->getVectorNumElements();
1797 if (NumMaskElts >= NumOpElts)
1798 return false;
1799
1800 return isIdentityMaskImpl(getShuffleMask(), NumOpElts);
1801 }
17631802
17641803 //===----------------------------------------------------------------------===//
17651804 // InsertValueInst Class
836836
837837 EXPECT_TRUE(ShuffleVectorInst::isTransposeMask(ConstantVector::get({C1, C5, C3, C7})));
838838 EXPECT_TRUE(ShuffleVectorInst::isTransposeMask(ConstantVector::get({C1, C3})));
839
840 // Identity with undef elts.
841 ShuffleVectorInst *Id1 = new ShuffleVectorInst(ConstantVector::get({C0, C1, C3, C3}),
842 ConstantVector::get({C0, C1, C2, C3}),
843 ConstantVector::get({C0, C1, CU, CU}));
844 EXPECT_TRUE(Id1->isIdentity());
845 EXPECT_FALSE(Id1->isIdentityWithPadding());
846 EXPECT_FALSE(Id1->isIdentityWithExtract());
847 delete Id1;
848
849 // Result has less elements than operands.
850 ShuffleVectorInst *Id2 = new ShuffleVectorInst(ConstantVector::get({C0, C1, C2, C3}),
851 ConstantVector::get({C0, C1, C2, C3}),
852 ConstantVector::get({C0, C1, C2}));
853 EXPECT_FALSE(Id2->isIdentity());
854 EXPECT_FALSE(Id2->isIdentityWithPadding());
855 EXPECT_TRUE(Id2->isIdentityWithExtract());
856 delete Id2;
857
858 // Result has less elements than operands; choose from Op1.
859 ShuffleVectorInst *Id3 = new ShuffleVectorInst(ConstantVector::get({C0, C1, C2, C3}),
860 ConstantVector::get({C0, C1, C2, C3}),
861 ConstantVector::get({C4, CU, C6}));
862 EXPECT_FALSE(Id3->isIdentity());
863 EXPECT_FALSE(Id3->isIdentityWithPadding());
864 EXPECT_TRUE(Id3->isIdentityWithExtract());
865 delete Id3;
866
867 // Result has less elements than operands; choose from Op0 and Op1 is not identity.
868 ShuffleVectorInst *Id4 = new ShuffleVectorInst(ConstantVector::get({C0, C1, C2, C3}),
869 ConstantVector::get({C0, C1, C2, C3}),
870 ConstantVector::get({C4, C1, C6}));
871 EXPECT_FALSE(Id4->isIdentity());
872 EXPECT_FALSE(Id4->isIdentityWithPadding());
873 EXPECT_FALSE(Id4->isIdentityWithExtract());
874 delete Id4;
875
876 // Result has more elements than operands, and extra elements are undef.
877 ShuffleVectorInst *Id5 = new ShuffleVectorInst(ConstantVector::get({C0, C1, C2, C3}),
878 ConstantVector::get({C0, C1, C2, C3}),
879 ConstantVector::get({CU, C1, C2, C3, CU, CU}));
880 EXPECT_FALSE(Id5->isIdentity());
881 EXPECT_TRUE(Id5->isIdentityWithPadding());
882 EXPECT_FALSE(Id5->isIdentityWithExtract());
883 delete Id5;
884
885 // Result has more elements than operands, and extra elements are undef; choose from Op1.
886 ShuffleVectorInst *Id6 = new ShuffleVectorInst(ConstantVector::get({C0, C1, C2, C3}),
887 ConstantVector::get({C0, C1, C2, C3}),
888 ConstantVector::get({C4, C5, C6, CU, CU, CU}));
889 EXPECT_FALSE(Id6->isIdentity());
890 EXPECT_TRUE(Id6->isIdentityWithPadding());
891 EXPECT_FALSE(Id6->isIdentityWithExtract());
892 delete Id6;
893
894 // Result has more elements than operands, but extra elements are not undef.
895 ShuffleVectorInst *Id7 = new ShuffleVectorInst(ConstantVector::get({C0, C1, C2, C3}),
896 ConstantVector::get({C0, C1, C2, C3}),
897 ConstantVector::get({C0, C1, C2, C3, CU, C1}));
898 EXPECT_FALSE(Id7->isIdentity());
899 EXPECT_FALSE(Id7->isIdentityWithPadding());
900 EXPECT_FALSE(Id7->isIdentityWithExtract());
901 delete Id7;
902
903 // Result has more elements than operands; choose from Op0 and Op1 is not identity.
904 ShuffleVectorInst *Id8 = new ShuffleVectorInst(ConstantVector::get({C0, C1, C2, C3}),
905 ConstantVector::get({C0, C1, C2, C3}),
906 ConstantVector::get({C4, CU, C2, C3, CU, CU}));
907 EXPECT_FALSE(Id8->isIdentity());
908 EXPECT_FALSE(Id8->isIdentityWithPadding());
909 EXPECT_FALSE(Id8->isIdentityWithExtract());
910 delete Id8;
839911 }
840912
841913 TEST(InstructionsTest, SkipDebug) {