8 changes: 3 additions & 5 deletions llvm/lib/Target/AArch64/AArch64ISelLowering.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11813,7 +11813,7 @@ SDValue AArch64TargetLowering::LowerVECTOR_SHUFFLE(SDValue Op,

if (((VT.getVectorNumElements() == 8 && VT.getScalarSizeInBits() == 16) ||
(VT.getVectorNumElements() == 16 && VT.getScalarSizeInBits() == 8)) &&
ShuffleVectorInst::isReverseMask(ShuffleMask, ShuffleMask.size())) {
ShuffleVectorInst::isReverseMask(ShuffleMask)) {
SDValue Rev = DAG.getNode(AArch64ISD::REV64, dl, VT, V1);
return DAG.getNode(AArch64ISD::EXT, dl, VT, Rev, Rev,
DAG.getConstant(8, dl, MVT::i32));
Expand Down Expand Up @@ -25837,8 +25837,7 @@ static SDValue GenerateFixedLengthSVETBL(SDValue Op, SDValue Op1, SDValue Op2,
SDLoc DL(Op);
unsigned MinSVESize = Subtarget.getMinSVEVectorSizeInBits();
unsigned MaxSVESize = Subtarget.getMaxSVEVectorSizeInBits();
bool IsSingleOp =
ShuffleVectorInst::isSingleSourceMask(ShuffleMask, ShuffleMask.size());
bool IsSingleOp = ShuffleVectorInst::isSingleSourceMask(ShuffleMask);

// Ignore two operands if no SVE2 or all index numbers couldn't
// be represented.
Expand Down Expand Up @@ -26022,8 +26021,7 @@ SDValue AArch64TargetLowering::LowerFixedLengthVECTOR_SHUFFLEToSVE(
unsigned MinSVESize = Subtarget->getMinSVEVectorSizeInBits();
unsigned MaxSVESize = Subtarget->getMaxSVEVectorSizeInBits();
if (MinSVESize == MaxSVESize && MaxSVESize == VT.getSizeInBits()) {
if (ShuffleVectorInst::isReverseMask(ShuffleMask, ShuffleMask.size()) &&
Op2.isUndef()) {
if (ShuffleVectorInst::isReverseMask(ShuffleMask) && Op2.isUndef()) {
Op = DAG.getNode(ISD::VECTOR_REVERSE, DL, ContainerVT, Op1);
return convertFromScalableVector(DAG, VT, Op);
}
Expand Down
2 changes: 1 addition & 1 deletion llvm/lib/Target/ARM/ARMISelLowering.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8375,7 +8375,7 @@ bool ARMTargetLowering::isShuffleMaskLegal(ArrayRef<int> M, EVT VT) const {
unsigned EltSize = VT.getScalarSizeInBits();
if (EltSize >= 32 ||
ShuffleVectorSDNode::isSplatMask(&M[0], VT) ||
ShuffleVectorInst::isIdentityMask(M, M.size()) ||
ShuffleVectorInst::isIdentityMask(M) ||
isVREVMask(M, VT, 64) ||
isVREVMask(M, VT, 32) ||
isVREVMask(M, VT, 16))
Expand Down
3 changes: 1 addition & 2 deletions llvm/lib/Target/RISCV/RISCVISelLowering.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4337,8 +4337,7 @@ static SDValue lowerBitreverseShuffle(ShuffleVectorSDNode *SVN,

assert(VT.getVectorElementType() == MVT::i1);

if (!ShuffleVectorInst::isReverseMask(SVN->getMask(),
SVN->getMask().size()) ||
if (!ShuffleVectorInst::isReverseMask(SVN->getMask()) ||
!SVN->getOperand(1).isUndef())
return SDValue();

Expand Down
7 changes: 2 additions & 5 deletions llvm/lib/Target/RISCV/RISCVTargetTransformInfo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -322,10 +322,7 @@ InstructionCost RISCVTTIImpl::getShuffleCost(TTI::ShuffleKind Kind,
LT.second.getVectorElementType().getSizeInBits() ==
Tp->getElementType()->getPrimitiveSizeInBits() &&
LT.second.getVectorNumElements() <
cast<FixedVectorType>(Tp)->getNumElements() &&
divideCeil(Mask.size(),
cast<FixedVectorType>(Tp)->getNumElements()) ==
static_cast<unsigned>(*LT.first.getValue())) {
cast<FixedVectorType>(Tp)->getNumElements()) {
unsigned NumRegs = *LT.first.getValue();
unsigned VF = cast<FixedVectorType>(Tp)->getNumElements();
unsigned SubVF = PowerOf2Ceil(VF / NumRegs);
Expand Down Expand Up @@ -501,7 +498,7 @@ InstructionCost RISCVTTIImpl::getInterleavedMemoryOpCost(
InstructionCost Cost = MemCost;
for (unsigned Index : Indices) {
FixedVectorType *SubVecTy =
FixedVectorType::get(FVTy->getElementType(), VF * Factor);
FixedVectorType::get(FVTy->getElementType(), VF);
auto Mask = createStrideMask(Index, Factor, VF);
InstructionCost ShuffleCost =
getShuffleCost(TTI::ShuffleKind::SK_PermuteSingleSrc, SubVecTy, Mask,
Expand Down
7 changes: 2 additions & 5 deletions llvm/lib/Target/X86/X86TargetTransformInfo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1596,6 +1596,7 @@ InstructionCost X86TTIImpl::getShuffleCost(TTI::ShuffleKind Kind,
BaseTp->getElementType()->getPrimitiveSizeInBits() &&
LegalVT.getVectorNumElements() <
cast<FixedVectorType>(BaseTp)->getNumElements()) {

unsigned VecTySize = DL.getTypeStoreSize(BaseTp);
unsigned LegalVTSize = LegalVT.getStoreSize();
// Number of source vectors after legalization:
Expand All @@ -1620,10 +1621,6 @@ InstructionCost X86TTIImpl::getShuffleCost(TTI::ShuffleKind Kind,
// copy of the previous destination register (the cost is
// TTI::TCC_Basic). If the source register is just reused, the cost for
// this operation is 0.
NumOfDests =
getTypeLegalizationCost(
FixedVectorType::get(BaseTp->getElementType(), Mask.size()))
.first;
unsigned E = *NumOfDests.getValue();
unsigned NormalizedVF =
LegalVT.getVectorNumElements() * std::max(NumOfSrcs, E);
Expand All @@ -1638,7 +1635,7 @@ InstructionCost X86TTIImpl::getShuffleCost(TTI::ShuffleKind Kind,
NormalizedMask, NumOfSrcRegs, NumOfDestRegs, NumOfDestRegs, []() {},
[this, SingleOpTy, CostKind, &PrevSrcReg, &PrevRegMask,
&Cost](ArrayRef<int> RegMask, unsigned SrcReg, unsigned DestReg) {
if (!ShuffleVectorInst::isIdentityMask(RegMask, RegMask.size())) {
if (!ShuffleVectorInst::isIdentityMask(RegMask)) {
// Check if the previous register can be just copied to the next
// one.
if (PrevRegMask.empty() || PrevSrcReg != SrcReg ||
Expand Down
4 changes: 2 additions & 2 deletions llvm/lib/Transforms/InstCombine/InstCombineVectorOps.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2122,8 +2122,8 @@ static Instruction *foldSelectShuffleOfSelectShuffle(ShuffleVectorInst &Shuf) {
NewMask[i] = Mask[i] < (signed)NumElts ? Mask[i] : Mask1[i];

// A select mask with undef elements might look like an identity mask.
assert((ShuffleVectorInst::isSelectMask(NewMask, NumElts) ||
ShuffleVectorInst::isIdentityMask(NewMask, NumElts)) &&
assert((ShuffleVectorInst::isSelectMask(NewMask) ||
ShuffleVectorInst::isIdentityMask(NewMask)) &&
"Unexpected shuffle mask");
return new ShuffleVectorInst(X, Y, NewMask);
}
Expand Down
290 changes: 96 additions & 194 deletions llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp

Large diffs are not rendered by default.

31 changes: 27 additions & 4 deletions llvm/test/Transforms/LoopVectorize/RISCV/interleaved-accesses.ll
Original file line number Diff line number Diff line change
Expand Up @@ -461,21 +461,44 @@ exit:
define void @combine_load_factor2_i64(ptr noalias %p, ptr noalias %q) {
; CHECK-LABEL: @combine_load_factor2_i64(
; CHECK-NEXT: entry:
; CHECK-NEXT: br i1 false, label [[SCALAR_PH:%.*]], label [[VECTOR_PH:%.*]]
; CHECK: vector.ph:
; CHECK-NEXT: br label [[VECTOR_BODY:%.*]]
; CHECK: vector.body:
; CHECK-NEXT: [[INDEX:%.*]] = phi i64 [ 0, [[VECTOR_PH]] ], [ [[INDEX_NEXT:%.*]], [[VECTOR_BODY]] ]
; CHECK-NEXT: [[TMP0:%.*]] = add i64 [[INDEX]], 0
; CHECK-NEXT: [[TMP1:%.*]] = shl i64 [[TMP0]], 1
; CHECK-NEXT: [[TMP2:%.*]] = getelementptr i64, ptr [[P:%.*]], i64 [[TMP1]]
; CHECK-NEXT: [[TMP3:%.*]] = getelementptr i64, ptr [[TMP2]], i32 0
; CHECK-NEXT: [[WIDE_VEC:%.*]] = load <8 x i64>, ptr [[TMP3]], align 4
; CHECK-NEXT: [[STRIDED_VEC:%.*]] = shufflevector <8 x i64> [[WIDE_VEC]], <8 x i64> poison, <4 x i32> <i32 0, i32 2, i32 4, i32 6>
; CHECK-NEXT: [[STRIDED_VEC1:%.*]] = shufflevector <8 x i64> [[WIDE_VEC]], <8 x i64> poison, <4 x i32> <i32 1, i32 3, i32 5, i32 7>
; CHECK-NEXT: [[TMP4:%.*]] = add <4 x i64> [[STRIDED_VEC]], [[STRIDED_VEC1]]
; CHECK-NEXT: [[TMP5:%.*]] = getelementptr i64, ptr [[Q:%.*]], i64 [[TMP0]]
; CHECK-NEXT: [[TMP6:%.*]] = getelementptr i64, ptr [[TMP5]], i32 0
; CHECK-NEXT: store <4 x i64> [[TMP4]], ptr [[TMP6]], align 4
; CHECK-NEXT: [[INDEX_NEXT]] = add nuw i64 [[INDEX]], 4
; CHECK-NEXT: [[TMP7:%.*]] = icmp eq i64 [[INDEX_NEXT]], 1024
; CHECK-NEXT: br i1 [[TMP7]], label [[MIDDLE_BLOCK:%.*]], label [[VECTOR_BODY]], !llvm.loop [[LOOP8:![0-9]+]]
; CHECK: middle.block:
; CHECK-NEXT: br i1 true, label [[EXIT:%.*]], label [[SCALAR_PH]]
; CHECK: scalar.ph:
; CHECK-NEXT: [[BC_RESUME_VAL:%.*]] = phi i64 [ 1024, [[MIDDLE_BLOCK]] ], [ 0, [[ENTRY:%.*]] ]
; CHECK-NEXT: br label [[LOOP:%.*]]
; CHECK: loop:
; CHECK-NEXT: [[I:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[NEXTI:%.*]], [[LOOP]] ]
; CHECK-NEXT: [[I:%.*]] = phi i64 [ [[BC_RESUME_VAL]], [[SCALAR_PH]] ], [ [[NEXTI:%.*]], [[LOOP]] ]
; CHECK-NEXT: [[OFFSET0:%.*]] = shl i64 [[I]], 1
; CHECK-NEXT: [[Q0:%.*]] = getelementptr i64, ptr [[P:%.*]], i64 [[OFFSET0]]
; CHECK-NEXT: [[Q0:%.*]] = getelementptr i64, ptr [[P]], i64 [[OFFSET0]]
; CHECK-NEXT: [[X0:%.*]] = load i64, ptr [[Q0]], align 4
; CHECK-NEXT: [[OFFSET1:%.*]] = add i64 [[OFFSET0]], 1
; CHECK-NEXT: [[Q1:%.*]] = getelementptr i64, ptr [[P]], i64 [[OFFSET1]]
; CHECK-NEXT: [[X1:%.*]] = load i64, ptr [[Q1]], align 4
; CHECK-NEXT: [[RES:%.*]] = add i64 [[X0]], [[X1]]
; CHECK-NEXT: [[DST:%.*]] = getelementptr i64, ptr [[Q:%.*]], i64 [[I]]
; CHECK-NEXT: [[DST:%.*]] = getelementptr i64, ptr [[Q]], i64 [[I]]
; CHECK-NEXT: store i64 [[RES]], ptr [[DST]], align 4
; CHECK-NEXT: [[NEXTI]] = add i64 [[I]], 1
; CHECK-NEXT: [[DONE:%.*]] = icmp eq i64 [[NEXTI]], 1024
; CHECK-NEXT: br i1 [[DONE]], label [[EXIT:%.*]], label [[LOOP]]
; CHECK-NEXT: br i1 [[DONE]], label [[EXIT]], label [[LOOP]], !llvm.loop [[LOOP9:![0-9]+]]
; CHECK: exit:
; CHECK-NEXT: ret void
;
Expand Down
19 changes: 15 additions & 4 deletions llvm/test/Transforms/SLPVectorizer/X86/tiny-tree.ll
Original file line number Diff line number Diff line change
Expand Up @@ -241,10 +241,21 @@ define void @tiny_vector_gather(ptr %a, ptr %v1, ptr %v2) {
; CHECK-LABEL: @tiny_vector_gather(
; CHECK-NEXT: [[TMP1:%.*]] = load i32, ptr [[V1:%.*]], align 4
; CHECK-NEXT: [[TMP2:%.*]] = load i32, ptr [[V2:%.*]], align 4
; CHECK-NEXT: [[TMP3:%.*]] = insertelement <8 x i32> poison, i32 [[TMP1]], i32 0
; CHECK-NEXT: [[TMP4:%.*]] = insertelement <8 x i32> [[TMP3]], i32 [[TMP2]], i32 1
; CHECK-NEXT: [[TMP5:%.*]] = shufflevector <8 x i32> [[TMP4]], <8 x i32> poison, <8 x i32> <i32 0, i32 1, i32 0, i32 1, i32 0, i32 1, i32 0, i32 1>
; CHECK-NEXT: store <8 x i32> [[TMP5]], ptr [[A:%.*]], align 16
; CHECK-NEXT: store i32 [[TMP1]], ptr [[A:%.*]], align 16
; CHECK-NEXT: [[PTR1:%.*]] = getelementptr inbounds i32, ptr [[A]], i64 1
; CHECK-NEXT: store i32 [[TMP2]], ptr [[PTR1]], align 4
; CHECK-NEXT: [[PTR2:%.*]] = getelementptr inbounds i32, ptr [[A]], i64 2
; CHECK-NEXT: store i32 [[TMP1]], ptr [[PTR2]], align 8
; CHECK-NEXT: [[PTR3:%.*]] = getelementptr inbounds i32, ptr [[A]], i64 3
; CHECK-NEXT: store i32 [[TMP2]], ptr [[PTR3]], align 4
; CHECK-NEXT: [[PTR4:%.*]] = getelementptr inbounds i32, ptr [[A]], i64 4
; CHECK-NEXT: store i32 [[TMP1]], ptr [[PTR4]], align 16
; CHECK-NEXT: [[PTR5:%.*]] = getelementptr inbounds i32, ptr [[A]], i64 5
; CHECK-NEXT: store i32 [[TMP2]], ptr [[PTR5]], align 4
; CHECK-NEXT: [[PTR6:%.*]] = getelementptr inbounds i32, ptr [[A]], i64 6
; CHECK-NEXT: store i32 [[TMP1]], ptr [[PTR6]], align 8
; CHECK-NEXT: [[PTR7:%.*]] = getelementptr inbounds i32, ptr [[A]], i64 7
; CHECK-NEXT: store i32 [[TMP2]], ptr [[PTR7]], align 4
; CHECK-NEXT: ret void
;
%1 = load i32, ptr %v1, align 4
Expand Down
178 changes: 54 additions & 124 deletions llvm/unittests/IR/InstructionsTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1024,141 +1024,71 @@ TEST(InstructionsTest, ShuffleMaskQueries) {
Constant *C7 = ConstantInt::get(Int32Ty, 7);

Constant *Identity = ConstantVector::get({C0, CU, C2, C3, C4});
EXPECT_TRUE(ShuffleVectorInst::isIdentityMask(
Identity, cast<FixedVectorType>(Identity->getType())->getNumElements()));
EXPECT_FALSE(ShuffleVectorInst::isSelectMask(
Identity,
cast<FixedVectorType>(Identity->getType())
->getNumElements())); // identity is distinguished from select
EXPECT_FALSE(ShuffleVectorInst::isReverseMask(
Identity, cast<FixedVectorType>(Identity->getType())->getNumElements()));
EXPECT_TRUE(ShuffleVectorInst::isSingleSourceMask(
Identity, cast<FixedVectorType>(Identity->getType())
->getNumElements())); // identity is always single source
EXPECT_FALSE(ShuffleVectorInst::isZeroEltSplatMask(
Identity, cast<FixedVectorType>(Identity->getType())->getNumElements()));
EXPECT_FALSE(ShuffleVectorInst::isTransposeMask(
Identity, cast<FixedVectorType>(Identity->getType())->getNumElements()));
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, cast<FixedVectorType>(Select->getType())->getNumElements()));
EXPECT_TRUE(ShuffleVectorInst::isSelectMask(
Select, cast<FixedVectorType>(Select->getType())->getNumElements()));
EXPECT_FALSE(ShuffleVectorInst::isReverseMask(
Select, cast<FixedVectorType>(Select->getType())->getNumElements()));
EXPECT_FALSE(ShuffleVectorInst::isSingleSourceMask(
Select, cast<FixedVectorType>(Select->getType())->getNumElements()));
EXPECT_FALSE(ShuffleVectorInst::isZeroEltSplatMask(
Select, cast<FixedVectorType>(Select->getType())->getNumElements()));
EXPECT_FALSE(ShuffleVectorInst::isTransposeMask(
Select, cast<FixedVectorType>(Select->getType())->getNumElements()));

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, cast<FixedVectorType>(Reverse->getType())->getNumElements()));
EXPECT_FALSE(ShuffleVectorInst::isSelectMask(
Reverse, cast<FixedVectorType>(Reverse->getType())->getNumElements()));
EXPECT_TRUE(ShuffleVectorInst::isReverseMask(
Reverse, cast<FixedVectorType>(Reverse->getType())->getNumElements()));
EXPECT_TRUE(ShuffleVectorInst::isSingleSourceMask(
Reverse, cast<FixedVectorType>(Reverse->getType())
->getNumElements())); // reverse is always single source
EXPECT_FALSE(ShuffleVectorInst::isZeroEltSplatMask(
Reverse, cast<FixedVectorType>(Reverse->getType())->getNumElements()));
EXPECT_FALSE(ShuffleVectorInst::isTransposeMask(
Reverse, cast<FixedVectorType>(Reverse->getType())->getNumElements()));
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,
cast<FixedVectorType>(SingleSource->getType())->getNumElements()));
EXPECT_FALSE(ShuffleVectorInst::isSelectMask(
SingleSource,
cast<FixedVectorType>(SingleSource->getType())->getNumElements()));
EXPECT_FALSE(ShuffleVectorInst::isReverseMask(
SingleSource,
cast<FixedVectorType>(SingleSource->getType())->getNumElements()));
EXPECT_TRUE(ShuffleVectorInst::isSingleSourceMask(
SingleSource,
cast<FixedVectorType>(SingleSource->getType())->getNumElements()));
EXPECT_FALSE(ShuffleVectorInst::isZeroEltSplatMask(
SingleSource,
cast<FixedVectorType>(SingleSource->getType())->getNumElements()));
EXPECT_FALSE(ShuffleVectorInst::isTransposeMask(
SingleSource,
cast<FixedVectorType>(SingleSource->getType())->getNumElements()));
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,
cast<FixedVectorType>(ZeroEltSplat->getType())->getNumElements()));
EXPECT_FALSE(ShuffleVectorInst::isSelectMask(
ZeroEltSplat,
cast<FixedVectorType>(ZeroEltSplat->getType())->getNumElements()));
EXPECT_FALSE(ShuffleVectorInst::isReverseMask(
ZeroEltSplat,
cast<FixedVectorType>(ZeroEltSplat->getType())->getNumElements()));
EXPECT_TRUE(ShuffleVectorInst::isSingleSourceMask(
ZeroEltSplat, cast<FixedVectorType>(ZeroEltSplat->getType())
->getNumElements())); // 0-splat is always single source
EXPECT_TRUE(ShuffleVectorInst::isZeroEltSplatMask(
ZeroEltSplat,
cast<FixedVectorType>(ZeroEltSplat->getType())->getNumElements()));
EXPECT_FALSE(ShuffleVectorInst::isTransposeMask(
ZeroEltSplat,
cast<FixedVectorType>(ZeroEltSplat->getType())->getNumElements()));
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,
cast<FixedVectorType>(Transpose->getType())->getNumElements()));
EXPECT_FALSE(ShuffleVectorInst::isSelectMask(
Transpose,
cast<FixedVectorType>(Transpose->getType())->getNumElements()));
EXPECT_FALSE(ShuffleVectorInst::isReverseMask(
Transpose,
cast<FixedVectorType>(Transpose->getType())->getNumElements()));
EXPECT_FALSE(ShuffleVectorInst::isSingleSourceMask(
Transpose,
cast<FixedVectorType>(Transpose->getType())->getNumElements()));
EXPECT_FALSE(ShuffleVectorInst::isZeroEltSplatMask(
Transpose,
cast<FixedVectorType>(Transpose->getType())->getNumElements()));
EXPECT_TRUE(ShuffleVectorInst::isTransposeMask(
Transpose,
cast<FixedVectorType>(Transpose->getType())->getNumElements()));
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}), 4));
EXPECT_TRUE(ShuffleVectorInst::isIdentityMask(
ConstantVector::get({C4, CU, C6, CU}), 4));

EXPECT_TRUE(ShuffleVectorInst::isSelectMask(
ConstantVector::get({C4, C1, C6, CU}), 4));
EXPECT_TRUE(ShuffleVectorInst::isSelectMask(
ConstantVector::get({CU, C1, C6, C3}), 4));

EXPECT_TRUE(ShuffleVectorInst::isReverseMask(
ConstantVector::get({C7, C6, CU, C4}), 4));
EXPECT_TRUE(ShuffleVectorInst::isReverseMask(
ConstantVector::get({C3, CU, C1, CU}), 4));

EXPECT_TRUE(ShuffleVectorInst::isSingleSourceMask(
ConstantVector::get({C7, C5, CU, C7}), 4));
EXPECT_TRUE(ShuffleVectorInst::isSingleSourceMask(
ConstantVector::get({C3, C0, CU, C3}), 4));

EXPECT_TRUE(ShuffleVectorInst::isZeroEltSplatMask(
ConstantVector::get({C4, CU, CU, C4}), 4));
EXPECT_TRUE(ShuffleVectorInst::isZeroEltSplatMask(
ConstantVector::get({CU, C0, CU, C0}), 4));

EXPECT_TRUE(ShuffleVectorInst::isTransposeMask(
ConstantVector::get({C1, C5, C3, C7}), 4));
EXPECT_TRUE(
ShuffleVectorInst::isTransposeMask(ConstantVector::get({C1, C3}), 2));
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})));

// Nothing special about the values here - just re-using inputs to reduce code.
Constant *V0 = ConstantVector::get({C0, C1, C2, C3});
Expand Down
71 changes: 19 additions & 52 deletions llvm/unittests/IR/ShuffleVectorInstTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,84 +14,51 @@ using namespace llvm;
namespace {

TEST(ShuffleVectorInst, isIdentityMask) {
ASSERT_TRUE(ShuffleVectorInst::isIdentityMask({0, 1, 2, 3}, 4));
ASSERT_TRUE(ShuffleVectorInst::isIdentityMask({0, 1, 2, 3, -1}, 5));
ASSERT_TRUE(ShuffleVectorInst::isIdentityMask({0, 1, -1, 3}, 4));
ASSERT_TRUE(ShuffleVectorInst::isIdentityMask({0, 1, 2, 3}));
ASSERT_TRUE(ShuffleVectorInst::isIdentityMask({0, 1, 2, 3, -1}));
ASSERT_TRUE(ShuffleVectorInst::isIdentityMask({0, 1, -1, 3}));

ASSERT_FALSE(ShuffleVectorInst::isIdentityMask({0, 1, 2, 3}, 3));
ASSERT_FALSE(ShuffleVectorInst::isIdentityMask({0, 1, 2, 3, -1}, 4));
ASSERT_FALSE(ShuffleVectorInst::isIdentityMask({0, 1, -1, 3}, 3));

ASSERT_FALSE(ShuffleVectorInst::isIdentityMask({0, 1, 2, 3}, 5));
ASSERT_FALSE(ShuffleVectorInst::isIdentityMask({0, 1, 2, 3, -1}, 6));
ASSERT_FALSE(ShuffleVectorInst::isIdentityMask({0, 1, -1, 3}, 5));

ASSERT_FALSE(ShuffleVectorInst::isIdentityMask({0, 1, 2, 4}, 4));
ASSERT_FALSE(ShuffleVectorInst::isIdentityMask({0, -1, 2, 4}, 4));
ASSERT_FALSE(ShuffleVectorInst::isIdentityMask({0, 1, 2, 4}));
ASSERT_FALSE(ShuffleVectorInst::isIdentityMask({0, -1, 2, 4}));
}

TEST(ShuffleVectorInst, isSelectMask) {
ASSERT_TRUE(ShuffleVectorInst::isSelectMask({0, 5, 6, 3}, 4));

ASSERT_FALSE(ShuffleVectorInst::isSelectMask({0, 5, 6, 3}, 3));
ASSERT_FALSE(ShuffleVectorInst::isSelectMask({0, 5, 6, 3}, 5));
ASSERT_TRUE(ShuffleVectorInst::isSelectMask({0, 5, 6, 3}));

ASSERT_FALSE(ShuffleVectorInst::isSelectMask({0, 1, 2, 3}, 4));
ASSERT_FALSE(ShuffleVectorInst::isSelectMask({0, 1, 2, 3}));
}

TEST(ShuffleVectorInst, isReverseMask) {
ASSERT_TRUE(ShuffleVectorInst::isReverseMask({3, 2, 1, 0}, 4));
ASSERT_TRUE(ShuffleVectorInst::isReverseMask({-1, -1, 1, 0}, 4));
ASSERT_TRUE(ShuffleVectorInst::isReverseMask({3, 2, 1, 0}));
ASSERT_TRUE(ShuffleVectorInst::isReverseMask({-1, -1, 1, 0}));

ASSERT_FALSE(ShuffleVectorInst::isReverseMask({3, 2, 1, 0}, 3));
ASSERT_FALSE(ShuffleVectorInst::isReverseMask({-1, -1, 1, 0}, 3));
ASSERT_FALSE(ShuffleVectorInst::isReverseMask({3, 2, 1, 0}, 5));
ASSERT_FALSE(ShuffleVectorInst::isReverseMask({-1, -1, 1, 0}, 5));

ASSERT_FALSE(ShuffleVectorInst::isReverseMask({4, 3, 2, 1}, 4));
ASSERT_FALSE(ShuffleVectorInst::isReverseMask({4, 3, 2, 1}));
}

TEST(ShuffleVectorInst, isZeroEltSplatMask) {
ASSERT_TRUE(ShuffleVectorInst::isZeroEltSplatMask({0, 0, 0, 0}, 4));
ASSERT_TRUE(ShuffleVectorInst::isZeroEltSplatMask({0, -1, 0, -1}, 4));

ASSERT_FALSE(ShuffleVectorInst::isZeroEltSplatMask({0, 0, 0, 0}, 3));
ASSERT_FALSE(ShuffleVectorInst::isZeroEltSplatMask({0, -1, 0, -1}, 3));
ASSERT_FALSE(ShuffleVectorInst::isZeroEltSplatMask({0, 0, 0, 0}, 5));
ASSERT_FALSE(ShuffleVectorInst::isZeroEltSplatMask({0, -1, 0, -1}, 5));
ASSERT_TRUE(ShuffleVectorInst::isZeroEltSplatMask({0, 0, 0, 0}));
ASSERT_TRUE(ShuffleVectorInst::isZeroEltSplatMask({0, -1, 0, -1}));

ASSERT_FALSE(ShuffleVectorInst::isZeroEltSplatMask({1, 1, 1, 1}, 4));
ASSERT_FALSE(ShuffleVectorInst::isZeroEltSplatMask({1, 1, 1, 1}));
}

TEST(ShuffleVectorInst, isTransposeMask) {
ASSERT_TRUE(ShuffleVectorInst::isTransposeMask({0, 4, 2, 6}, 4));
ASSERT_TRUE(ShuffleVectorInst::isTransposeMask({1, 5, 3, 7}, 4));
ASSERT_TRUE(ShuffleVectorInst::isTransposeMask({0, 4, 2, 6}));
ASSERT_TRUE(ShuffleVectorInst::isTransposeMask({1, 5, 3, 7}));

ASSERT_FALSE(ShuffleVectorInst::isTransposeMask({0, 4, 2, 6}, 3));
ASSERT_FALSE(ShuffleVectorInst::isTransposeMask({1, 5, 3, 7}, 3));
ASSERT_FALSE(ShuffleVectorInst::isTransposeMask({0, 4, 2, 6}, 5));
ASSERT_FALSE(ShuffleVectorInst::isTransposeMask({1, 5, 3, 7}, 5));

ASSERT_FALSE(ShuffleVectorInst::isTransposeMask({2, 6, 4, 8}, 4));
ASSERT_FALSE(ShuffleVectorInst::isTransposeMask({2, 6, 4, 8}));
}

TEST(ShuffleVectorInst, isSpliceMask) {
int Index;

ASSERT_TRUE(ShuffleVectorInst::isSpliceMask({0, 1, 2, 3}, 4, Index));
ASSERT_TRUE(ShuffleVectorInst::isSpliceMask({0, 1, 2, 3}, Index));
ASSERT_EQ(0, Index);

ASSERT_TRUE(ShuffleVectorInst::isSpliceMask({1, 2, 3, 4, 5, 6, 7}, 7, Index));
ASSERT_TRUE(ShuffleVectorInst::isSpliceMask({1, 2, 3, 4, 5, 6, 7}, Index));
ASSERT_EQ(1, Index);

ASSERT_FALSE(ShuffleVectorInst::isSpliceMask({0, 1, 2, 3}, 3, Index));
ASSERT_FALSE(
ShuffleVectorInst::isSpliceMask({1, 2, 3, 4, 5, 6, 7}, 6, Index));
ASSERT_FALSE(ShuffleVectorInst::isSpliceMask({0, 1, 2, 3}, 5, Index));
ASSERT_FALSE(
ShuffleVectorInst::isSpliceMask({1, 2, 3, 4, 5, 6, 7}, 8, Index));

ASSERT_FALSE(ShuffleVectorInst::isSpliceMask({4, 5, 6, 7}, 4, Index));
ASSERT_FALSE(ShuffleVectorInst::isSpliceMask({4, 5, 6, 7}, Index));
}

TEST(ShuffleVectorInst, isExtractSubvectorMask) {
Expand Down