diff --git a/llvm/lib/Target/RISCV/RISCVTargetTransformInfo.cpp b/llvm/lib/Target/RISCV/RISCVTargetTransformInfo.cpp index 8d18fd63e4a2e..b5b6aa8148d62 100644 --- a/llvm/lib/Target/RISCV/RISCVTargetTransformInfo.cpp +++ b/llvm/lib/Target/RISCV/RISCVTargetTransformInfo.cpp @@ -343,6 +343,28 @@ RISCVTTIImpl::getConstantPoolLoadCost(Type *Ty, TTI::TargetCostKind CostKind) { /*AddressSpace=*/0, CostKind); } +static bool isRepeatedConcatMask(ArrayRef Mask, int &SubVectorSize) { + unsigned Size = Mask.size(); + if (!isPowerOf2_32(Size)) + return false; + for (unsigned I = 0; I != Size; ++I) { + if (static_cast(Mask[I]) == I) + continue; + if (Mask[I] != 0) + return false; + if (Size % I != 0) + return false; + for (unsigned J = I + 1; J != Size; ++J) + // Check the pattern is repeated. + if (static_cast(Mask[J]) != J % I) + return false; + SubVectorSize = I; + return true; + } + // That means Mask is <0, 1, 2, 3>. This is not a concatenation. + return false; +} + static VectorType *getVRGatherIndexType(MVT DataVT, const RISCVSubtarget &ST, LLVMContext &C) { assert((DataVT.getScalarSizeInBits() != 8 || @@ -394,6 +416,29 @@ InstructionCost RISCVTTIImpl::getShuffleCost(TTI::ShuffleKind Kind, LT.second, CostKind); } } + int SubVectorSize; + if (LT.second.getScalarSizeInBits() != 1 && + isRepeatedConcatMask(Mask, SubVectorSize)) { + InstructionCost Cost = 0; + unsigned NumSlides = Log2_32(Mask.size() / SubVectorSize); + // The cost of extraction from a subvector is 0 if the index is 0. + for (unsigned I = 0; I != NumSlides; ++I) { + unsigned InsertIndex = SubVectorSize * (1 << I); + FixedVectorType *SubTp = + FixedVectorType::get(Tp->getElementType(), InsertIndex); + FixedVectorType *DestTp = + FixedVectorType::getDoubleElementsVectorType(SubTp); + std::pair DestLT = + getTypeLegalizationCost(DestTp); + // Add the cost of whole vector register move because the + // destination vector register group for vslideup cannot overlap the + // source. + Cost += DestLT.first * TLI->getLMULCost(DestLT.second); + Cost += getShuffleCost(TTI::SK_InsertSubvector, DestTp, {}, + CostKind, InsertIndex, SubTp); + } + return Cost; + } } // vrgather + cost of generating the mask constant. // We model this for an unknown mask with a single vrgather. diff --git a/llvm/test/Analysis/CostModel/RISCV/fixed-vector-insert-subvector.ll b/llvm/test/Analysis/CostModel/RISCV/fixed-vector-insert-subvector.ll new file mode 100644 index 0000000000000..47a2af92aee95 --- /dev/null +++ b/llvm/test/Analysis/CostModel/RISCV/fixed-vector-insert-subvector.ll @@ -0,0 +1,18 @@ +; NOTE: Assertions have been autogenerated by utils/update_analyze_test_checks.py +; RUN: opt < %s -passes="print" 2>&1 -disable-output -S -mtriple=riscv64 -mattr=+v | FileCheck %s + +define void @test() { +; CHECK-LABEL: 'test' +; CHECK-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %0 = shufflevector <8 x float> poison, <8 x float> poison, <16 x i32> +; CHECK-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %1 = shufflevector <4 x i16> poison, <4 x i16> poison, <16 x i32> +; CHECK-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %2 = shufflevector <4 x float> poison, <4 x float> poison, <8 x i32> +; CHECK-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %3 = shufflevector <2 x i1> poison, <2 x i1> poison, <4 x i32> +; CHECK-NEXT: Cost Model: Found an estimated cost of 0 for instruction: ret void +; +entry: + %0 = shufflevector <8 x float> poison, <8 x float> poison, <16 x i32> + %1 = shufflevector <4 x i16> poison, <4 x i16> poison, <16 x i32> + %2 = shufflevector <4 x float> poison, <4 x float> poison, <8 x i32> + %3 = shufflevector <2 x i1> poison, <2 x i1> poison, <4 x i32> + ret void +} diff --git a/llvm/test/Transforms/SLPVectorizer/RISCV/remarks-insert-into-small-vector.ll b/llvm/test/Transforms/SLPVectorizer/RISCV/remarks-insert-into-small-vector.ll index 09612444afd20..4788e1ef71559 100644 --- a/llvm/test/Transforms/SLPVectorizer/RISCV/remarks-insert-into-small-vector.ll +++ b/llvm/test/Transforms/SLPVectorizer/RISCV/remarks-insert-into-small-vector.ll @@ -8,7 +8,7 @@ ; YAML-NEXT: Function: test ; YAML-NEXT: Args: ; YAML-NEXT: - String: 'Stores SLP vectorized with cost ' -; YAML-NEXT: - Cost: '0' +; YAML-NEXT: - Cost: '-2' ; YAML-NEXT: - String: ' and with tree size ' ; YAML-NEXT: - TreeSize: '9' diff --git a/llvm/test/Transforms/SLPVectorizer/RISCV/revec-getGatherCost.ll b/llvm/test/Transforms/SLPVectorizer/RISCV/revec-getGatherCost.ll index 995cd7cfbc880..a0cb52a853b7e 100644 --- a/llvm/test/Transforms/SLPVectorizer/RISCV/revec-getGatherCost.ll +++ b/llvm/test/Transforms/SLPVectorizer/RISCV/revec-getGatherCost.ll @@ -8,7 +8,7 @@ ; YAML: Function: test1 ; YAML: Args: ; YAML: - String: 'Stores SLP vectorized with cost ' -; YAML: - Cost: '6' +; YAML: - Cost: '4' ; YAML: - String: ' and with tree size ' ; YAML: - TreeSize: '5' @@ -47,7 +47,7 @@ declare <4 x float> @llvm.fmuladd.v4f32(<4 x float>, <4 x float>, <4 x float>) ; YAML: Function: test2 ; YAML: Args: ; YAML: - String: 'Stores SLP vectorized with cost ' -; YAML: - Cost: '16' +; YAML: - Cost: '12' ; YAML: - String: ' and with tree size ' ; YAML: - TreeSize: '5'