19#include "llvm/IR/IntrinsicsRISCV.h"
28#define DEBUG_TYPE "riscvtti"
36 size_t NumInstr = OpCodes.size();
41 return LMULCost * NumInstr;
43 for (
auto Op : OpCodes) {
45 case RISCV::VRGATHER_VI:
48 case RISCV::VRGATHER_VV:
51 case RISCV::VSLIDEUP_VI:
52 case RISCV::VSLIDEDOWN_VI:
55 case RISCV::VSLIDEUP_VX:
56 case RISCV::VSLIDEDOWN_VX:
59 case RISCV::VREDMAX_VS:
60 case RISCV::VREDMIN_VS:
61 case RISCV::VREDMAXU_VS:
62 case RISCV::VREDMINU_VS:
63 case RISCV::VREDSUM_VS:
64 case RISCV::VREDAND_VS:
65 case RISCV::VREDOR_VS:
66 case RISCV::VREDXOR_VS:
67 case RISCV::VFREDMAX_VS:
68 case RISCV::VFREDMIN_VS:
69 case RISCV::VFREDUSUM_VS: {
76 case RISCV::VFREDOSUM_VS: {
93 case RISCV::VMANDN_MM:
94 case RISCV::VMNAND_MM:
115 assert(Ty->isIntegerTy() &&
116 "getIntImmCost can only estimate cost of materialising integers");
139 if (!BO || !BO->hasOneUse())
142 if (BO->getOpcode() != Instruction::Shl)
153 if (ShAmt == Trailing)
170 if (!Cmp || !Cmp->isEquality())
186 if ((CmpC & Mask) != CmpC)
193 return NewCmpC >= -2048 && NewCmpC <= 2048;
200 assert(Ty->isIntegerTy() &&
201 "getIntImmCost can only estimate cost of materialising integers");
209 bool Takes12BitImm =
false;
210 unsigned ImmArgIdx = ~0U;
213 case Instruction::GetElementPtr:
218 case Instruction::Store: {
223 if (Idx == 1 || !Inst)
228 if (!getTLI()->allowsMemoryAccessForAlignment(
229 Ty->getContext(),
DL, getTLI()->getValueType(
DL, Ty),
236 case Instruction::Load:
239 case Instruction::And:
241 if (
Imm == UINT64_C(0xffff) && ST->hasStdExtZbb())
244 if (
Imm == UINT64_C(0xffffffff) && (!ST->is64Bit() || ST->hasStdExtZba()))
247 if (ST->hasStdExtZbs() && (~
Imm).isPowerOf2())
249 if (Inst && Idx == 1 &&
Imm.getBitWidth() <= ST->getXLen() &&
252 if (Inst && Idx == 1 &&
Imm.getBitWidth() == 64 &&
255 Takes12BitImm =
true;
257 case Instruction::Add:
258 Takes12BitImm =
true;
260 case Instruction::Or:
261 case Instruction::Xor:
263 if (ST->hasStdExtZbs() &&
Imm.isPowerOf2())
265 Takes12BitImm =
true;
267 case Instruction::Mul:
269 if (
Imm.isPowerOf2() ||
Imm.isNegatedPowerOf2())
272 if ((
Imm + 1).isPowerOf2() || (
Imm - 1).isPowerOf2())
275 Takes12BitImm =
true;
277 case Instruction::Sub:
278 case Instruction::Shl:
279 case Instruction::LShr:
280 case Instruction::AShr:
281 Takes12BitImm =
true;
292 if (
Imm.getSignificantBits() <= 64 &&
315 return ST->hasVInstructions();
325 unsigned Opcode,
Type *InputTypeA,
Type *InputTypeB,
Type *AccumType,
329 if (Opcode == Instruction::FAdd)
338 if (!ST->hasStdExtZvdot4a8i() || ST->getELen() < 64 ||
339 Opcode != Instruction::Add || !BinOp || *BinOp != Instruction::Mul ||
340 InputTypeA != InputTypeB || !InputTypeA->
isIntegerTy(8) ||
356 getRISCVInstructionCost(RISCV::VDOT4A_VV, DotLT.second,
CostKind);
365 std::pair<InstructionCost, MVT> AccLT =
373 bool WidenFirst =
false;
374 if (VF.
isScalable() && AccLT.second.isScalableVector()) {
375 MVT NarrowMVT = AccLT.second.changeVectorElementType(MVT::i32);
388 WideLT.first * getRISCVInstructionCost(RISCV::VSEXT_VF2,
391 getRISCVInstructionCost(RISCV::VADD_VV, AccLT.second,
CostKind);
395 std::pair<InstructionCost, MVT> RedLT =
397 Cost += RedLT.first * getRISCVInstructionCost(RISCV::VADD_VV,
399 AccLT.first * getRISCVInstructionCost(RISCV::VWADD_WV,
403 Cost += DotLT.first * getRISCVInstructionCost(RISCV::VSLIDEDOWN_VI,
415 switch (
II->getIntrinsicID()) {
419 case Intrinsic::vector_reduce_mul:
420 case Intrinsic::vector_reduce_fmul:
426 if (ST->hasVInstructions())
427 if (
unsigned MinVLen = ST->getRealMinVLen();
436 std::clamp<unsigned>(ST->getCLOpts().v_register_bit_width_lmul, 1, 8));
442 ST->useRVVForFixedLengthVectors() ? LMUL * ST->getRealMinVLen() : 0);
445 (ST->hasVInstructions() &&
468 return (ST->hasAUIPCADDIFusion() && ST->hasLUIADDIFusion()) ? 1 : 2;
474RISCVTTIImpl::getConstantPoolLoadCost(
Type *Ty,
491 unsigned Size = Mask.size();
494 for (
unsigned I = 0;
I !=
Size; ++
I) {
495 if (
static_cast<unsigned>(Mask[
I]) ==
I)
501 for (
unsigned J =
I + 1; J !=
Size; ++J)
503 if (
static_cast<unsigned>(Mask[J]) != J %
I)
531 "Expected fixed vector type and non-empty mask");
534 unsigned NumOfDests =
divideCeil(Mask.size(), LegalNumElts);
538 if (NumOfDests <= 1 ||
540 Tp->getElementType()->getPrimitiveSizeInBits() ||
541 LegalNumElts >= Tp->getElementCount().getFixedValue())
544 unsigned VecTySize =
TTI.getDataLayout().getTypeStoreSize(Tp);
547 unsigned NumOfSrcs =
divideCeil(VecTySize, LegalVTSize);
551 unsigned NormalizedVF = LegalNumElts * std::max(NumOfSrcs, NumOfDests);
552 unsigned NumOfSrcRegs = NormalizedVF / LegalNumElts;
553 unsigned NumOfDestRegs = NormalizedVF / LegalNumElts;
555 assert(NormalizedVF >= Mask.size() &&
556 "Normalized mask expected to be not shorter than original mask.");
561 NormalizedMask, NumOfSrcRegs, NumOfDestRegs, NumOfDestRegs, []() {},
562 [&](
ArrayRef<int> RegMask,
unsigned SrcReg,
unsigned DestReg) {
565 if (!ReusedSingleSrcShuffles.
insert(std::make_pair(RegMask, SrcReg))
568 Cost +=
TTI.getShuffleCost(
571 SingleOpTy,
CostKind, RegMask, 0,
nullptr);
573 [&](
ArrayRef<int> RegMask,
unsigned Idx1,
unsigned Idx2,
bool NewReg) {
574 Cost +=
TTI.getShuffleCost(
577 SingleOpTy,
CostKind, RegMask, 0,
nullptr);
600 if (!VLen || Mask.empty())
604 LegalVT =
TTI.getTypeLegalizationCost(
610 if (NumOfDests <= 1 ||
612 Tp->getElementType()->getPrimitiveSizeInBits() ||
616 unsigned VecTySize =
TTI.getDataLayout().getTypeStoreSize(Tp);
619 unsigned NumOfSrcs =
divideCeil(VecTySize, LegalVTSize);
625 unsigned NormalizedVF =
630 assert(NormalizedVF >= Mask.size() &&
631 "Normalized mask expected to be not shorter than original mask.");
637 NormalizedMask, NumOfSrcRegs, NumOfDestRegs, NumOfDestRegs, []() {},
638 [&](
ArrayRef<int> RegMask,
unsigned SrcReg,
unsigned DestReg) {
641 if (!ReusedSingleSrcShuffles.
insert(std::make_pair(RegMask, SrcReg))
646 SingleOpTy,
CostKind, RegMask, 0,
nullptr);
648 [&](
ArrayRef<int> RegMask,
unsigned Idx1,
unsigned Idx2,
bool NewReg) {
650 SingleOpTy,
CostKind, RegMask, 0,
nullptr);
657 if ((NumOfDestRegs > 2 && NumShuffles <=
static_cast<int>(NumOfDestRegs)) ||
658 (NumOfDestRegs <= 2 && NumShuffles < 4))
673 if (!
LT.second.isFixedLengthVector())
681 auto GetSlideOpcode = [&](
int SlideAmt) {
683 bool IsVI =
isUInt<5>(std::abs(SlideAmt));
685 return IsVI ? RISCV::VSLIDEDOWN_VI : RISCV::VSLIDEDOWN_VX;
686 return IsVI ? RISCV::VSLIDEUP_VI : RISCV::VSLIDEUP_VX;
689 std::array<std::pair<int, int>, 2> SrcInfo;
693 if (SrcInfo[1].second == 0)
696 if (ST->hasStdExtZvzip() &&
LT.second.getScalarSizeInBits() != 1) {
698 if (
isPairEven(SrcInfo, Mask, Factor) && Factor == 1)
699 return getRISCVInstructionCost(RISCV::VPAIRE_VV,
LT.second,
CostKind);
700 if (
isPairOdd(SrcInfo, Mask, Factor) && Factor == 1)
701 return getRISCVInstructionCost(RISCV::VPAIRO_VV,
LT.second,
CostKind);
705 if (SrcInfo[0].second != 0) {
706 unsigned Opcode = GetSlideOpcode(SrcInfo[0].second);
707 FirstSlideCost = getRISCVInstructionCost(Opcode,
LT.second,
CostKind);
710 if (SrcInfo[1].first == -1)
711 return FirstSlideCost;
714 if (SrcInfo[1].second != 0) {
715 unsigned Opcode = GetSlideOpcode(SrcInfo[1].second);
716 SecondSlideCost = getRISCVInstructionCost(Opcode,
LT.second,
CostKind);
719 getRISCVInstructionCost(RISCV::VMERGE_VVM,
LT.second,
CostKind);
726 return FirstSlideCost + SecondSlideCost + MaskCost;
729MVT RISCVTTIImpl::getZvzipVZIPCostVT(
MVT InterleavedVT)
const {
733 MVT CostVT = InterleavedVT;
736 CostVT = TLI->getContainerForFixedLengthVector(SourceVT)
745 LMULOctuple * std::min(ST->getELen(), ST->getRealMinVLen()))
750MVT RISCVTTIImpl::getZvzipVUNZIPCostVT(
MVT InterleavedVT)
const {
754 MVT CostVT = InterleavedVT;
759 CostVT = TLI->getContainerForFixedLengthVector(InterleavedVT);
777 if (!ST->hasStdExtZvzip() ||
Mask.size() < 2 ||
778 DstTy->getScalarSizeInBits() == 1)
781 unsigned NumSrcElts = SrcTy->getElementCount().getKnownMinValue();
782 unsigned NumDstElts = DstTy->getElementCount().getKnownMinValue();
783 unsigned NumInputElts;
788 if (NumSrcElts != NumDstElts)
790 NumInputElts = NumSrcElts;
804 if (NumSrcElts != NumDstElts && NumSrcElts * 2 != NumDstElts)
806 NumInputElts = NumSrcElts * 2;
821 unsigned DeinterleaveIndex;
823 DeinterleaveIndex) &&
824 count_if(Mask, [](
int Idx) {
return Idx >= 0; }) > 1)
829 SmallVector<unsigned, 2> StartIndexes;
833 unsigned HalfNumElts =
Mask.size() / 2;
834 if ((StartIndexes[0] != 0 && StartIndexes[1] != 0) ||
835 StartIndexes[0] % HalfNumElts != 0 || StartIndexes[1] % HalfNumElts != 0)
839 MVT CostVT = getZvzipVZIPCostVT(DstLT.second);
844 DstLT.first * getRISCVInstructionCost(RISCV::VZIP_VV, CostVT,
CostKind);
851 if (NumSrcElts == NumDstElts) {
854 for (
unsigned Start : StartIndexes) {
855 unsigned ExtractIndex =
Start % NumSrcElts;
856 if (ExtractIndex != 0)
858 CostKind, {}, ExtractIndex, HalfSrcTy);
872 "Expected the Mask to match the return size if given");
874 "Expected the same scalar types");
877 if (VIC == TTI::VectorInstrContext::SplatOpFolded &&
893 FVTp && ST->hasVInstructions() && LT.second.isFixedLengthVector()) {
895 *
this, LT.second, ST->getRealVLen(),
897 if (VRegSplittingCost.
isValid())
898 return VRegSplittingCost;
903 if (Mask.size() >= 2) {
904 MVT EltTp = LT.second.getVectorElementType();
909 getVZIPCost(Kind, DstTy, SrcTy, Mask,
CostKind);
916 unsigned Opcode = Index == 0 ? RISCV::VUNZIPE_V : RISCV::VUNZIPO_V;
917 if (
MVT CostVT = getZvzipVUNZIPCostVT(LT.second); CostVT.
isValid())
918 return LT.first * getRISCVInstructionCost(Opcode, CostVT,
CostKind);
931 return 2 * LT.first * TLI->getLMULCost(LT.second);
933 if (Mask[0] == 0 || Mask[0] == 1) {
937 if (
equal(DeinterleaveMask, Mask))
938 return LT.first * getRISCVInstructionCost(RISCV::VNSRL_WI,
944 if (LT.second.getScalarSizeInBits() != 1 &&
947 unsigned NumSlides =
Log2_32(Mask.size() / SubVectorSize);
949 for (
unsigned I = 0;
I != NumSlides; ++
I) {
950 unsigned InsertIndex = SubVectorSize * (1 <<
I);
955 std::pair<InstructionCost, MVT> DestLT =
960 Cost += DestLT.first * TLI->getLMULCost(DestLT.second);
974 if (LT.first == 1 && (LT.second.getScalarSizeInBits() != 8 ||
975 LT.second.getVectorNumElements() <= 256)) {
980 getRISCVInstructionCost(RISCV::VRGATHER_VV, LT.second,
CostKind);
992 getVZIPCost(Kind, DstTy, SrcTy, Mask,
CostKind);
998 if (LT.first == 1 && (LT.second.getScalarSizeInBits() != 8 ||
999 LT.second.getVectorNumElements() <= 256)) {
1000 auto &
C = SrcTy->getContext();
1001 auto EC = SrcTy->getElementCount();
1006 return 2 * IndexCost +
1007 getRISCVInstructionCost({RISCV::VRGATHER_VV, RISCV::VRGATHER_VV},
1026 if (!Mask.empty() && LT.first.isValid() && LT.first != 1 &&
1054 SubLT.second.isValid() && SubLT.second.isFixedLengthVector()) {
1055 if (std::optional<unsigned> VLen = ST->getRealVLen();
1056 VLen && SubLT.second.getScalarSizeInBits() * Index % *VLen == 0 &&
1057 SubLT.second.getSizeInBits() <= *VLen)
1065 getRISCVInstructionCost(RISCV::VSLIDEDOWN_VI, LT.second,
CostKind);
1072 getRISCVInstructionCost(RISCV::VSLIDEUP_VI, LT.second,
CostKind);
1084 (1 + getRISCVInstructionCost({RISCV::VMV_S_X, RISCV::VMERGE_VVM},
1091 if (IsLoad && LT.second.isVector() &&
1093 LT.second.getVectorElementCount()))
1097 Instruction::InsertElement);
1098 if (LT.second.getScalarSizeInBits() == 1) {
1106 (1 + getRISCVInstructionCost({RISCV::VMV_V_X, RISCV::VMSNE_VI},
1119 (1 + getRISCVInstructionCost({RISCV::VMV_V_I, RISCV::VMERGE_VIM,
1120 RISCV::VMV_X_S, RISCV::VMV_V_X,
1129 getRISCVInstructionCost(RISCV::VMV_V_X, LT.second,
CostKind);
1135 getRISCVInstructionCost(RISCV::VRGATHER_VI, LT.second,
CostKind);
1141 unsigned Opcodes[2] = {RISCV::VSLIDEDOWN_VX, RISCV::VSLIDEUP_VX};
1142 if (Index >= 0 && Index < 32)
1143 Opcodes[0] = RISCV::VSLIDEDOWN_VI;
1144 else if (Index < 0 && Index > -32)
1145 Opcodes[1] = RISCV::VSLIDEUP_VI;
1146 return LT.first * getRISCVInstructionCost(Opcodes, LT.second,
CostKind);
1150 if (!LT.second.isVector())
1156 if (SrcTy->getElementType()->isIntegerTy(1)) {
1168 MVT ContainerVT = LT.second;
1169 if (LT.second.isFixedLengthVector())
1170 ContainerVT = TLI->getContainerForFixedLengthVector(LT.second);
1172 if (ContainerVT.
bitsLE(M1VT)) {
1182 if (LT.second.isFixedLengthVector())
1184 LenCost =
isInt<5>(LT.second.getVectorNumElements() - 1) ? 0 : 1;
1185 unsigned Opcodes[] = {RISCV::VID_V, RISCV::VRSUB_VX, RISCV::VRGATHER_VV};
1186 if (LT.second.isFixedLengthVector() &&
1187 isInt<5>(LT.second.getVectorNumElements() - 1))
1188 Opcodes[1] = RISCV::VRSUB_VI;
1190 getRISCVInstructionCost(Opcodes, LT.second,
CostKind);
1191 return LT.first * (LenCost + GatherCost);
1198 unsigned M1Opcodes[] = {RISCV::VID_V, RISCV::VRSUB_VX};
1200 getRISCVInstructionCost(M1Opcodes, M1VT,
CostKind) + 3;
1204 getRISCVInstructionCost({RISCV::VRGATHER_VV}, M1VT,
CostKind) * Ratio;
1206 getRISCVInstructionCost({RISCV::VSLIDEDOWN_VX}, LT.second,
CostKind);
1207 return FixedCost + LT.first * (GatherCost + SlideCost);
1241 Ty, DemandedElts, Insert, Extract,
CostKind);
1243 if (Insert && !Extract && LT.first.isValid() && LT.second.isVector()) {
1244 if (Ty->getScalarSizeInBits() == 1) {
1254 assert(LT.second.isFixedLengthVector());
1255 MVT ContainerVT = TLI->getContainerForFixedLengthVector(LT.second);
1259 getRISCVInstructionCost(RISCV::VSLIDE1DOWN_VX, LT.second,
CostKind);
1272 switch (MICA.
getID()) {
1273 case Intrinsic::vp_load_ff: {
1274 EVT DataTypeVT = TLI->getValueType(
DL, DataTy);
1275 if (!TLI->isLegalFirstFaultLoad(DataTypeVT, Alignment))
1282 case Intrinsic::experimental_vp_strided_load:
1283 case Intrinsic::experimental_vp_strided_store:
1285 case Intrinsic::masked_compressstore:
1286 case Intrinsic::masked_expandload:
1288 case Intrinsic::vp_scatter:
1289 case Intrinsic::vp_gather:
1290 case Intrinsic::masked_scatter:
1291 case Intrinsic::masked_gather:
1293 case Intrinsic::vp_load:
1294 case Intrinsic::vp_store:
1295 case Intrinsic::masked_load:
1296 case Intrinsic::masked_store:
1305 unsigned Opcode = MICA.
getID() == Intrinsic::masked_load ? Instruction::Load
1306 : Instruction::Store;
1317 if (MICA.
getID() == Intrinsic::vp_load ||
1318 MICA.
getID() == Intrinsic::vp_store) {
1330 bool UseMaskForCond,
bool UseMaskForGaps)
const {
1336 if (!UseMaskForGaps && Factor <= TLI->getMaxSupportedInterleaveFactor()) {
1340 if (LT.second.isVector()) {
1346 VTy->getElementCount().divideCoefficientBy(Factor));
1347 if (VTy->getElementCount().isKnownMultipleOf(Factor) &&
1348 TLI->isLegalInterleavedAccessType(SubVecTy, Factor, Alignment,
1353 if (ST->hasOptimizedSegmentLoadStore(Factor)) {
1354 unsigned VecSizeInBits =
1355 getEstimatedVLFor(VTy) * VTy->getScalarSizeInBits();
1356 unsigned VLENForTuning =
1358 unsigned DLENForTuning = VLENForTuning / ST->getDLenFactor();
1360 MVT SubVecVT = getTLI()->getValueType(
DL, SubVecTy).getSimpleVT();
1361 Cost += Factor * TLI->getLMULCost(SubVecVT);
1367 unsigned NumLoads = getEstimatedVLFor(VTy);
1383 if (UseMaskForGaps) {
1386 "Indices should not contain duplicate elements");
1387 unsigned NumOfFields = Indices.
size();
1388 bool IsTailGapOnly = NumOfFields > 1 && (NumOfFields == Indices.
back() + 1);
1389 if (IsTailGapOnly &&
1390 NumOfFields <= TLI->getMaxSupportedInterleaveFactor()) {
1392 if (LT.second.isVector() &&
1393 FVTy->getElementCount().isKnownMultipleOf(Factor)) {
1395 FVTy->getElementType(),
1396 FVTy->getElementCount().divideCoefficientBy(Factor));
1397 if (TLI->isLegalInterleavedAccessType(SubVecTy, NumOfFields, Alignment,
1400 unsigned NumAccesses = getEstimatedVLFor(FVTy);
1409 unsigned VF = FVTy->getNumElements() / Factor;
1416 if (Opcode == Instruction::Load) {
1418 for (
unsigned Index : Indices) {
1422 Mask.resize(VF * Factor, -1);
1426 Cost += ShuffleCost;
1444 UseMaskForCond, UseMaskForGaps);
1446 assert(Opcode == Instruction::Store &&
"Opcode must be a store");
1453 return MemCost + ShuffleCost;
1460 bool IsLoad = MICA.
getID() == Intrinsic::masked_gather ||
1461 MICA.
getID() == Intrinsic::vp_gather;
1462 unsigned Opcode = IsLoad ? Instruction::Load : Instruction::Store;
1470 if ((Opcode == Instruction::Load &&
1472 (Opcode == Instruction::Store &&
1478 if (MICA.
getID() == Intrinsic::vp_gather ||
1479 MICA.
getID() == Intrinsic::vp_scatter) {
1482 if (DataLT.first > 1)
1484 if (PtrLT.first > 1)
1492 unsigned NumLoads = getEstimatedVLFor(&VTy);
1499 unsigned Opcode = MICA.
getID() == Intrinsic::masked_expandload
1501 : Instruction::Store;
1505 bool IsLegal = (Opcode == Instruction::Store &&
1507 (Opcode == Instruction::Load &&
1531 if (Opcode == Instruction::Store)
1532 Opcodes.
append({RISCV::VCOMPRESS_VM});
1534 Opcodes.
append({RISCV::VSETIVLI, RISCV::VIOTA_M, RISCV::VRGATHER_VV});
1536 LT.first * getRISCVInstructionCost(Opcodes, LT.second,
CostKind);
1561 unsigned NumLoads = getEstimatedVLFor(&VTy);
1564 uint64_t CacheLineBytes = ST->getCacheLineSize();
1565 if (!CacheLineBytes)
1566 CacheLineBytes = 64;
1569 int64_t Stride = StrideCI->getSExtValue();
1571 if (Stride != std::numeric_limits<int64_t>::min() && Stride != 0) {
1572 uint64_t AbsStride = (uint64_t)std::abs(Stride);
1573 if (AbsStride < CacheLineBytes) {
1574 uint64_t MaxCombines = ST->getMaxVectorCoalesceElts();
1575 if ((CacheLineBytes / AbsStride) >= MaxCombines)
1576 NumLoads =
divideCeil(NumLoads, MaxCombines);
1580 NumLoads =
divideCeil((NumLoads * AbsStride), CacheLineBytes);
1594 for (
auto *Ty : Tys) {
1595 if (!Ty->isVectorTy())
1609 {Intrinsic::floor, MVT::f32, 9},
1610 {Intrinsic::floor, MVT::f64, 9},
1611 {Intrinsic::ceil, MVT::f32, 9},
1612 {Intrinsic::ceil, MVT::f64, 9},
1613 {Intrinsic::trunc, MVT::f32, 7},
1614 {Intrinsic::trunc, MVT::f64, 7},
1615 {Intrinsic::round, MVT::f32, 9},
1616 {Intrinsic::round, MVT::f64, 9},
1617 {Intrinsic::roundeven, MVT::f32, 9},
1618 {Intrinsic::roundeven, MVT::f64, 9},
1619 {Intrinsic::rint, MVT::f32, 7},
1620 {Intrinsic::rint, MVT::f64, 7},
1621 {Intrinsic::nearbyint, MVT::f32, 9},
1622 {Intrinsic::nearbyint, MVT::f64, 9},
1623 {Intrinsic::bswap, MVT::i16, 3},
1624 {Intrinsic::bswap, MVT::i32, 12},
1625 {Intrinsic::bswap, MVT::i64, 31},
1626 {Intrinsic::bitreverse, MVT::i8, 17},
1627 {Intrinsic::bitreverse, MVT::i16, 24},
1628 {Intrinsic::bitreverse, MVT::i32, 33},
1629 {Intrinsic::bitreverse, MVT::i64, 52},
1630 {Intrinsic::ctpop, MVT::i8, 12},
1631 {Intrinsic::ctpop, MVT::i16, 19},
1632 {Intrinsic::ctpop, MVT::i32, 20},
1633 {Intrinsic::ctpop, MVT::i64, 21},
1634 {Intrinsic::ctlz, MVT::i8, 19},
1635 {Intrinsic::ctlz, MVT::i16, 28},
1636 {Intrinsic::ctlz, MVT::i32, 31},
1637 {Intrinsic::ctlz, MVT::i64, 35},
1638 {Intrinsic::cttz, MVT::i8, 16},
1639 {Intrinsic::cttz, MVT::i16, 23},
1640 {Intrinsic::cttz, MVT::i32, 24},
1641 {Intrinsic::cttz, MVT::i64, 25},
1648 switch (ICA.
getID()) {
1649 case Intrinsic::lrint:
1650 case Intrinsic::llrint:
1651 case Intrinsic::lround:
1652 case Intrinsic::llround: {
1656 if (ST->hasVInstructions() && LT.second.isVector()) {
1658 unsigned SrcEltSz =
DL.getTypeSizeInBits(SrcTy->getScalarType());
1659 unsigned DstEltSz =
DL.getTypeSizeInBits(RetTy->getScalarType());
1660 if (LT.second.getVectorElementType() == MVT::bf16) {
1661 if (!ST->hasVInstructionsBF16Minimal())
1664 Ops = {RISCV::VFWCVTBF16_F_F_V, RISCV::VFCVT_X_F_V};
1666 Ops = {RISCV::VFWCVTBF16_F_F_V, RISCV::VFWCVT_X_F_V};
1667 }
else if (LT.second.getVectorElementType() == MVT::f16 &&
1668 !ST->hasVInstructionsF16()) {
1669 if (!ST->hasVInstructionsF16Minimal())
1672 Ops = {RISCV::VFWCVT_F_F_V, RISCV::VFCVT_X_F_V};
1674 Ops = {RISCV::VFWCVT_F_F_V, RISCV::VFWCVT_X_F_V};
1676 }
else if (SrcEltSz > DstEltSz) {
1677 Ops = {RISCV::VFNCVT_X_F_W};
1678 }
else if (SrcEltSz < DstEltSz) {
1679 Ops = {RISCV::VFWCVT_X_F_V};
1681 Ops = {RISCV::VFCVT_X_F_V};
1686 if (SrcEltSz > DstEltSz)
1687 return SrcLT.first *
1688 getRISCVInstructionCost(
Ops, SrcLT.second,
CostKind);
1689 return LT.first * getRISCVInstructionCost(
Ops, LT.second,
CostKind);
1693 case Intrinsic::ceil:
1694 case Intrinsic::floor:
1695 case Intrinsic::trunc:
1696 case Intrinsic::rint:
1697 case Intrinsic::round:
1698 case Intrinsic::roundeven: {
1701 if (!LT.second.isVector() && TLI->isOperationCustom(
ISD::FCEIL, LT.second))
1702 return LT.first * 8;
1705 case Intrinsic::umin:
1706 case Intrinsic::umax:
1707 case Intrinsic::smin:
1708 case Intrinsic::smax: {
1710 if (LT.second.isScalarInteger() && ST->hasStdExtZbb())
1713 if (ST->hasVInstructions() && LT.second.isVector()) {
1715 switch (ICA.
getID()) {
1716 case Intrinsic::umin:
1717 Op = RISCV::VMINU_VV;
1719 case Intrinsic::umax:
1720 Op = RISCV::VMAXU_VV;
1722 case Intrinsic::smin:
1723 Op = RISCV::VMIN_VV;
1725 case Intrinsic::smax:
1726 Op = RISCV::VMAX_VV;
1729 return LT.first * getRISCVInstructionCost(
Op, LT.second,
CostKind);
1733 case Intrinsic::sadd_sat:
1734 case Intrinsic::ssub_sat:
1735 case Intrinsic::uadd_sat:
1736 case Intrinsic::usub_sat: {
1738 if (ST->hasVInstructions() && LT.second.isVector()) {
1740 switch (ICA.
getID()) {
1741 case Intrinsic::sadd_sat:
1742 Op = RISCV::VSADD_VV;
1744 case Intrinsic::ssub_sat:
1745 Op = RISCV::VSSUB_VV;
1747 case Intrinsic::uadd_sat:
1748 Op = RISCV::VSADDU_VV;
1750 case Intrinsic::usub_sat:
1751 Op = RISCV::VSSUBU_VV;
1754 return LT.first * getRISCVInstructionCost(
Op, LT.second,
CostKind);
1758 case Intrinsic::fma:
1759 case Intrinsic::fmuladd: {
1762 if (ST->hasVInstructions() && LT.second.isVector())
1764 getRISCVInstructionCost(RISCV::VFMADD_VV, LT.second,
CostKind);
1767 case Intrinsic::fabs: {
1769 if (ST->hasVInstructions() && LT.second.isVector()) {
1775 if (LT.second.getVectorElementType() == MVT::bf16 ||
1776 (LT.second.getVectorElementType() == MVT::f16 &&
1777 !ST->hasVInstructionsF16()))
1778 return LT.first * getRISCVInstructionCost(RISCV::VAND_VX, LT.second,
1783 getRISCVInstructionCost(RISCV::VFSGNJX_VV, LT.second,
CostKind);
1787 case Intrinsic::sqrt: {
1789 if (ST->hasVInstructions() && LT.second.isVector()) {
1792 MVT ConvType = LT.second;
1793 MVT FsqrtType = LT.second;
1796 if (LT.second.getVectorElementType() == MVT::bf16) {
1797 if (LT.second == MVT::nxv32bf16) {
1798 ConvOp = {RISCV::VFWCVTBF16_F_F_V, RISCV::VFWCVTBF16_F_F_V,
1799 RISCV::VFNCVTBF16_F_F_W, RISCV::VFNCVTBF16_F_F_W};
1800 FsqrtOp = {RISCV::VFSQRT_V, RISCV::VFSQRT_V};
1801 ConvType = MVT::nxv16f16;
1802 FsqrtType = MVT::nxv16f32;
1804 ConvOp = {RISCV::VFWCVTBF16_F_F_V, RISCV::VFNCVTBF16_F_F_W};
1805 FsqrtOp = {RISCV::VFSQRT_V};
1806 FsqrtType = TLI->getTypeToPromoteTo(
ISD::FSQRT, FsqrtType);
1808 }
else if (LT.second.getVectorElementType() == MVT::f16 &&
1809 !ST->hasVInstructionsF16()) {
1810 if (LT.second == MVT::nxv32f16) {
1811 ConvOp = {RISCV::VFWCVT_F_F_V, RISCV::VFWCVT_F_F_V,
1812 RISCV::VFNCVT_F_F_W, RISCV::VFNCVT_F_F_W};
1813 FsqrtOp = {RISCV::VFSQRT_V, RISCV::VFSQRT_V};
1814 ConvType = MVT::nxv16f16;
1815 FsqrtType = MVT::nxv16f32;
1817 ConvOp = {RISCV::VFWCVT_F_F_V, RISCV::VFNCVT_F_F_W};
1818 FsqrtOp = {RISCV::VFSQRT_V};
1819 FsqrtType = TLI->getTypeToPromoteTo(
ISD::FSQRT, FsqrtType);
1822 FsqrtOp = {RISCV::VFSQRT_V};
1825 return LT.first * (getRISCVInstructionCost(FsqrtOp, FsqrtType,
CostKind) +
1826 getRISCVInstructionCost(ConvOp, ConvType,
CostKind));
1830 case Intrinsic::cttz:
1831 case Intrinsic::ctlz:
1832 case Intrinsic::ctpop: {
1834 if (ST->hasStdExtZvbb() && LT.second.isVector()) {
1836 switch (ICA.
getID()) {
1837 case Intrinsic::cttz:
1840 case Intrinsic::ctlz:
1843 case Intrinsic::ctpop:
1844 Op = RISCV::VCPOP_V;
1847 return LT.first * getRISCVInstructionCost(
Op, LT.second,
CostKind);
1851 case Intrinsic::abs: {
1853 if (ST->hasVInstructions() && LT.second.isVector()) {
1855 if (ST->hasStdExtZvabd())
1857 getRISCVInstructionCost({RISCV::VABD_VX}, LT.second,
CostKind);
1862 getRISCVInstructionCost({RISCV::VRSUB_VI, RISCV::VMAX_VV},
1867 case Intrinsic::fshl:
1868 case Intrinsic::fshr: {
1875 if ((ST->hasStdExtZbb() || ST->hasStdExtZbkb()) && RetTy->isIntegerTy() &&
1877 (RetTy->getIntegerBitWidth() == 32 ||
1878 RetTy->getIntegerBitWidth() == 64) &&
1879 RetTy->getIntegerBitWidth() <= ST->getXLen()) {
1884 case Intrinsic::clmul: {
1886 if (!LT.second.isVector() && ST->hasStdExtZvbc() && !ST->hasStdExtZbkc()) {
1889 if (!ST->is64Bit() || LT.second != MVT::i64)
1895 return LT.first * getRISCVInstructionCost(
1896 {RISCV::VMV_S_X, RISCV::VCLMUL_VX, RISCV::VMV_X_S},
1901 case Intrinsic::masked_udiv:
1904 case Intrinsic::masked_sdiv:
1907 case Intrinsic::masked_urem:
1910 case Intrinsic::masked_srem:
1913 case Intrinsic::get_active_lane_mask: {
1914 if (ST->hasVInstructions()) {
1923 getRISCVInstructionCost({RISCV::VSADDU_VX, RISCV::VMSLTU_VX},
1929 case Intrinsic::stepvector: {
1933 if (ST->hasVInstructions())
1934 return getRISCVInstructionCost(RISCV::VID_V, LT.second,
CostKind) +
1936 getRISCVInstructionCost(RISCV::VADD_VX, LT.second,
CostKind);
1937 return 1 + (LT.first - 1);
1939 case Intrinsic::vector_splice_left:
1940 case Intrinsic::vector_splice_right: {
1945 if (ST->hasVInstructions() && LT.second.isVector()) {
1947 getRISCVInstructionCost({RISCV::VSLIDEDOWN_VX, RISCV::VSLIDEUP_VX},
1952 case Intrinsic::experimental_cttz_elts: {
1953 if (!ST->hasVInstructions())
1958 if (!LT.second.isVector())
1962 if (LT.second.getVectorElementType() != MVT::i1)
1963 Cost += getRISCVInstructionCost(RISCV::VMSNE_VI, LT.second,
CostKind);
1965 Cost += getRISCVInstructionCost(RISCV::VFIRST_M, LT.second,
CostKind);
1977 return LT.first *
Cost;
1979 case Intrinsic::experimental_vp_splice: {
1987 case Intrinsic::vp_merge: {
1995 case Intrinsic::fptoui_sat:
1996 case Intrinsic::fptosi_sat: {
1998 bool IsSigned = ICA.
getID() == Intrinsic::fptosi_sat;
2003 if (!SrcTy->isVectorTy())
2006 if (!SrcLT.first.isValid() || !DstLT.first.isValid())
2023 case Intrinsic::experimental_vector_extract_last_active: {
2045 unsigned EltWidth = getTLI()->getBitWidthForCttzElements(
2046 TLI->getVectorIdxTy(
getDataLayout()), MaskTy->getElementCount(),
2047 true, &VScaleRange);
2048 EltWidth = std::max(EltWidth, MaskTy->getScalarSizeInBits());
2056 if (StepLT.first > 1)
2060 unsigned Opcodes[] = {RISCV::VID_V, RISCV::VREDMAXU_VS, RISCV::VMV_X_S};
2062 Cost += MaskLT.first *
2063 getRISCVInstructionCost(RISCV::VCPOP_M, MaskLT.second,
CostKind);
2065 Cost += StepLT.first *
2066 getRISCVInstructionCost(Opcodes, StepLT.second,
CostKind);
2070 Cost += ValLT.first *
2071 getRISCVInstructionCost({RISCV::VSLIDEDOWN_VI, RISCV::VMV_X_S},
2075 case Intrinsic::vector_interleave2:
2076 case Intrinsic::vector_deinterleave2: {
2077 if (!ST->hasStdExtZvzip())
2080 bool IsInterleave = ICA.
getID() == Intrinsic::vector_interleave2;
2081 Type *InterleavedTy = IsInterleave ? RetTy : ICA.
getArgTypes().front();
2085 [](
const Value *Arg) { return isa<UndefValue>(Arg); }))
2092 unsigned HalfVF = HalfFVT->getNumElements();
2097 for (
unsigned Start = 0; Start != 2; ++Start)
2104 if (!LT.second.isScalableVector())
2107 if (
MVT CostVT = getZvzipVZIPCostVT(LT.second); CostVT.
isValid())
2109 getRISCVInstructionCost(RISCV::VZIP_VV, CostVT,
CostKind);
2110 }
else if (
MVT CostVT = getZvzipVUNZIPCostVT(LT.second); CostVT.
isValid()) {
2112 getRISCVInstructionCost({RISCV::VUNZIPE_V, RISCV::VUNZIPO_V},
2119 if (ST->hasVInstructions() && RetTy->isVectorTy()) {
2121 LT.second.isVector()) {
2122 MVT EltTy = LT.second.getVectorElementType();
2124 ICA.
getID(), EltTy))
2125 return LT.first * Entry->Cost;
2138 if (ST->hasVInstructions() && PtrTy->
isVectorTy())
2156 if (ST->hasStdExtP() &&
2164 if (!ST->hasVInstructions() || Src->getScalarSizeInBits() > ST->getELen() ||
2165 Dst->getScalarSizeInBits() > ST->getELen())
2168 int ISD = TLI->InstructionOpcodeToISD(Opcode);
2183 if (Src->getScalarSizeInBits() == 1) {
2188 return getRISCVInstructionCost(RISCV::VMV_V_I, DstLT.second,
CostKind) +
2189 DstLT.first * getRISCVInstructionCost(RISCV::VMERGE_VIM,
2195 if (Dst->getScalarSizeInBits() == 1) {
2201 return SrcLT.first *
2202 getRISCVInstructionCost({RISCV::VAND_VI, RISCV::VMSNE_VI},
2214 if (!SrcLT.second.isVector() || !DstLT.second.isVector() ||
2215 !SrcLT.first.isValid() || !DstLT.first.isValid() ||
2217 SrcLT.second.getSizeInBits()) ||
2219 DstLT.second.getSizeInBits()) ||
2220 SrcLT.first > 1 || DstLT.first > 1)
2224 assert((SrcLT.first == 1) && (DstLT.first == 1) &&
"Illegal type");
2226 int PowDiff = (int)
Log2_32(DstLT.second.getScalarSizeInBits()) -
2227 (int)
Log2_32(SrcLT.second.getScalarSizeInBits());
2231 if ((PowDiff < 1) || (PowDiff > 3))
2233 unsigned SExtOp[] = {RISCV::VSEXT_VF2, RISCV::VSEXT_VF4, RISCV::VSEXT_VF8};
2234 unsigned ZExtOp[] = {RISCV::VZEXT_VF2, RISCV::VZEXT_VF4, RISCV::VZEXT_VF8};
2237 return getRISCVInstructionCost(
Op, DstLT.second,
CostKind);
2243 unsigned SrcEltSize = SrcLT.second.getScalarSizeInBits();
2244 unsigned DstEltSize = DstLT.second.getScalarSizeInBits();
2248 : RISCV::VFNCVT_F_F_W;
2250 for (; SrcEltSize != DstEltSize;) {
2254 MVT DstMVT = DstLT.second.changeVectorElementType(ElementMVT);
2256 (DstEltSize > SrcEltSize) ? DstEltSize >> 1 : DstEltSize << 1;
2264 unsigned FCVT = IsSigned ? RISCV::VFCVT_RTZ_X_F_V : RISCV::VFCVT_RTZ_XU_F_V;
2266 IsSigned ? RISCV::VFWCVT_RTZ_X_F_V : RISCV::VFWCVT_RTZ_XU_F_V;
2268 IsSigned ? RISCV::VFNCVT_RTZ_X_F_W : RISCV::VFNCVT_RTZ_XU_F_W;
2269 unsigned SrcEltSize = Src->getScalarSizeInBits();
2270 unsigned DstEltSize = Dst->getScalarSizeInBits();
2272 if ((SrcEltSize == 16) &&
2273 (!ST->hasVInstructionsF16() || ((DstEltSize / 2) > SrcEltSize))) {
2279 std::pair<InstructionCost, MVT> VecF32LT =
2282 VecF32LT.first * getRISCVInstructionCost(RISCV::VFWCVT_F_F_V,
2287 if (DstEltSize == SrcEltSize)
2288 Cost += getRISCVInstructionCost(FCVT, DstLT.second,
CostKind);
2289 else if (DstEltSize > SrcEltSize)
2290 Cost += getRISCVInstructionCost(FWCVT, DstLT.second,
CostKind);
2295 MVT VecVT = DstLT.second.changeVectorElementType(ElementVT);
2296 Cost += getRISCVInstructionCost(FNCVT, VecVT,
CostKind);
2297 if ((SrcEltSize / 2) > DstEltSize) {
2308 unsigned FCVT = IsSigned ? RISCV::VFCVT_F_X_V : RISCV::VFCVT_F_XU_V;
2309 unsigned FWCVT = IsSigned ? RISCV::VFWCVT_F_X_V : RISCV::VFWCVT_F_XU_V;
2310 unsigned FNCVT = IsSigned ? RISCV::VFNCVT_F_X_W : RISCV::VFNCVT_F_XU_W;
2311 unsigned SrcEltSize = Src->getScalarSizeInBits();
2312 unsigned DstEltSize = Dst->getScalarSizeInBits();
2315 if ((DstEltSize == 16) &&
2316 (!ST->hasVInstructionsF16() || ((SrcEltSize / 2) > DstEltSize))) {
2322 std::pair<InstructionCost, MVT> VecF32LT =
2325 Cost += VecF32LT.first * getRISCVInstructionCost(RISCV::VFNCVT_F_F_W,
2330 if (DstEltSize == SrcEltSize)
2331 Cost += getRISCVInstructionCost(FCVT, DstLT.second,
CostKind);
2332 else if (DstEltSize > SrcEltSize) {
2333 if ((DstEltSize / 2) > SrcEltSize) {
2337 unsigned Op = IsSigned ? Instruction::SExt : Instruction::ZExt;
2340 Cost += getRISCVInstructionCost(FWCVT, DstLT.second,
CostKind);
2342 Cost += getRISCVInstructionCost(FNCVT, DstLT.second,
CostKind);
2349unsigned RISCVTTIImpl::getEstimatedVLFor(
VectorType *Ty)
const {
2351 const unsigned EltSize =
DL.getTypeSizeInBits(Ty->getElementType());
2352 const unsigned MinSize =
DL.getTypeSizeInBits(Ty).getKnownMinValue();
2367 if (Ty->getScalarSizeInBits() > ST->getELen())
2371 if (Ty->getElementType()->isIntegerTy(1)) {
2375 if (IID == Intrinsic::umax || IID == Intrinsic::smin)
2381 if (IID == Intrinsic::maximum || IID == Intrinsic::minimum) {
2385 case Intrinsic::maximum:
2387 Opcodes = {RISCV::VFREDMAX_VS, RISCV::VFMV_F_S};
2389 Opcodes = {RISCV::VMFNE_VV, RISCV::VCPOP_M, RISCV::VFREDMAX_VS,
2394 Type *DstTy = Ty->getScalarType();
2404 case Intrinsic::minimum:
2406 Opcodes = {RISCV::VFREDMIN_VS, RISCV::VFMV_F_S};
2408 Opcodes = {RISCV::VMFNE_VV, RISCV::VCPOP_M, RISCV::VFREDMIN_VS,
2413 Type *DstTy = Ty->getScalarType();
2414 const unsigned EltTyBits =
DL.getTypeSizeInBits(DstTy);
2423 return ExtraCost + getRISCVInstructionCost(Opcodes, LT.second,
CostKind);
2432 case Intrinsic::smax:
2433 SplitOp = RISCV::VMAX_VV;
2434 Opcodes = {RISCV::VREDMAX_VS, RISCV::VMV_X_S};
2436 case Intrinsic::smin:
2437 SplitOp = RISCV::VMIN_VV;
2438 Opcodes = {RISCV::VREDMIN_VS, RISCV::VMV_X_S};
2440 case Intrinsic::umax:
2441 SplitOp = RISCV::VMAXU_VV;
2442 Opcodes = {RISCV::VREDMAXU_VS, RISCV::VMV_X_S};
2444 case Intrinsic::umin:
2445 SplitOp = RISCV::VMINU_VV;
2446 Opcodes = {RISCV::VREDMINU_VS, RISCV::VMV_X_S};
2448 case Intrinsic::maxnum:
2449 SplitOp = RISCV::VFMAX_VV;
2450 Opcodes = {RISCV::VFREDMAX_VS, RISCV::VFMV_F_S};
2452 case Intrinsic::minnum:
2453 SplitOp = RISCV::VFMIN_VV;
2454 Opcodes = {RISCV::VFREDMIN_VS, RISCV::VFMV_F_S};
2459 (LT.first > 1) ? (LT.first - 1) *
2460 getRISCVInstructionCost(SplitOp, LT.second,
CostKind)
2462 return SplitCost + getRISCVInstructionCost(Opcodes, LT.second,
CostKind);
2467 std::optional<FastMathFlags> FMF,
2473 if (Ty->getScalarSizeInBits() > ST->getELen())
2476 int ISD = TLI->InstructionOpcodeToISD(Opcode);
2484 Type *ElementTy = Ty->getElementType();
2489 if (LT.second == MVT::v1i1)
2490 return getRISCVInstructionCost(RISCV::VFIRST_M, LT.second,
CostKind) +
2508 return ((LT.first > 2) ? (LT.first - 2) : 0) *
2509 getRISCVInstructionCost(RISCV::VMAND_MM, LT.second,
CostKind) +
2510 getRISCVInstructionCost(RISCV::VMNAND_MM, LT.second,
CostKind) +
2511 getRISCVInstructionCost(RISCV::VCPOP_M, LT.second,
CostKind) +
2520 return (LT.first - 1) *
2521 getRISCVInstructionCost(RISCV::VMXOR_MM, LT.second,
CostKind) +
2522 getRISCVInstructionCost(RISCV::VCPOP_M, LT.second,
CostKind) + 1;
2530 return (LT.first - 1) *
2531 getRISCVInstructionCost(RISCV::VMOR_MM, LT.second,
CostKind) +
2532 getRISCVInstructionCost(RISCV::VCPOP_M, LT.second,
CostKind) +
2545 SplitOp = RISCV::VADD_VV;
2546 Opcodes = {RISCV::VMV_S_X, RISCV::VREDSUM_VS, RISCV::VMV_X_S};
2549 SplitOp = RISCV::VOR_VV;
2550 Opcodes = {RISCV::VREDOR_VS, RISCV::VMV_X_S};
2553 SplitOp = RISCV::VXOR_VV;
2554 Opcodes = {RISCV::VMV_S_X, RISCV::VREDXOR_VS, RISCV::VMV_X_S};
2557 SplitOp = RISCV::VAND_VV;
2558 Opcodes = {RISCV::VREDAND_VS, RISCV::VMV_X_S};
2562 if ((LT.second.getScalarType() == MVT::f16 && !ST->hasVInstructionsF16()) ||
2563 LT.second.getScalarType() == MVT::bf16)
2567 for (
unsigned i = 0; i < LT.first.getValue(); i++)
2570 return getRISCVInstructionCost(Opcodes, LT.second,
CostKind);
2572 SplitOp = RISCV::VFADD_VV;
2573 Opcodes = {RISCV::VFMV_S_F, RISCV::VFREDUSUM_VS, RISCV::VFMV_F_S};
2578 (LT.first > 1) ? (LT.first - 1) *
2579 getRISCVInstructionCost(SplitOp, LT.second,
CostKind)
2581 return SplitCost + getRISCVInstructionCost(Opcodes, LT.second,
CostKind);
2585 unsigned Opcode,
bool IsUnsigned,
Type *ResTy,
VectorType *ValTy,
2596 if (Opcode != Instruction::Add && Opcode != Instruction::FAdd)
2602 if (IsUnsigned && Opcode == Instruction::Add &&
2603 LT.second.isFixedLengthVectorOf(MVT::i1)) {
2607 getRISCVInstructionCost(RISCV::VCPOP_M, LT.second,
CostKind);
2614 return (LT.first - 1) +
2621 assert(OpInfo.isConstant() &&
"non constant operand?");
2628 if (OpInfo.isUniform())
2634 return getConstantPoolLoadCost(Ty,
CostKind);
2643 EVT VT = TLI->getValueType(
DL, Src,
true);
2645 if (VT == MVT::Other ||
2651 if (Opcode == Instruction::Store && OpInfo.isConstant())
2666 if (Src->
isVectorTy() && LT.second.isVector() &&
2668 LT.second.getSizeInBits()))
2678 if (ST->hasVInstructions() && LT.second.isVector() &&
2680 BaseCost *= TLI->getLMULCost(LT.second);
2681 return Cost + BaseCost;
2690 Op1Info, Op2Info,
I);
2694 Op1Info, Op2Info,
I);
2699 Op1Info, Op2Info,
I);
2701 auto GetConstantMatCost =
2703 if (OpInfo.isUniform())
2708 return getConstantPoolLoadCost(ValTy,
CostKind);
2713 ConstantMatCost += GetConstantMatCost(Op1Info);
2715 ConstantMatCost += GetConstantMatCost(Op2Info);
2718 if (Opcode == Instruction::Select && LT.second.isVector()) {
2719 if (CondTy->isVectorTy()) {
2724 return ConstantMatCost +
2726 getRISCVInstructionCost(
2727 {RISCV::VMANDN_MM, RISCV::VMAND_MM, RISCV::VMOR_MM},
2731 return ConstantMatCost +
2732 LT.first * getRISCVInstructionCost(RISCV::VMERGE_VVM, LT.second,
2742 MVT InterimVT = LT.second.changeVectorElementType(MVT::i8);
2743 return ConstantMatCost +
2745 getRISCVInstructionCost({RISCV::VMV_V_X, RISCV::VMSNE_VI},
2747 LT.first * getRISCVInstructionCost(
2748 {RISCV::VMANDN_MM, RISCV::VMAND_MM, RISCV::VMOR_MM},
2755 return ConstantMatCost +
2756 LT.first * getRISCVInstructionCost(
2757 {RISCV::VMV_V_X, RISCV::VMSNE_VI, RISCV::VMERGE_VVM},
2761 if ((Opcode == Instruction::ICmp) && ValTy->
isVectorTy() &&
2765 return ConstantMatCost + LT.first * getRISCVInstructionCost(RISCV::VMSLT_VV,
2770 if ((Opcode == Instruction::FCmp) && ValTy->
isVectorTy() &&
2775 return ConstantMatCost +
2776 getRISCVInstructionCost(RISCV::VMXOR_MM, LT.second,
CostKind);
2786 Op1Info, Op2Info,
I);
2795 return ConstantMatCost +
2796 LT.first * getRISCVInstructionCost(
2797 {RISCV::VMFLT_VV, RISCV::VMFLT_VV, RISCV::VMOR_MM},
2804 return ConstantMatCost +
2806 getRISCVInstructionCost({RISCV::VMFLT_VV, RISCV::VMNAND_MM},
2815 return ConstantMatCost +
2817 getRISCVInstructionCost(RISCV::VMFLT_VV, LT.second,
CostKind);
2830 return match(U, m_Select(m_Specific(I), m_Value(), m_Value())) &&
2831 U->getType()->isIntegerTy() &&
2832 !isa<ConstantData>(U->getOperand(1)) &&
2833 !isa<ConstantData>(U->getOperand(2));
2841 Op1Info, Op2Info,
I);
2848 return Opcode == Instruction::PHI ? 0 : 1;
2865 if (Opcode != Instruction::ExtractElement &&
2866 Opcode != Instruction::InsertElement)
2872 if (Opcode == Instruction::InsertElement &&
2873 VIC == TTI::VectorInstrContext::SplatOpFolded &&
2874 ST->sinkSplatOperands() && Index == 0)
2881 if (!LT.second.isVector()) {
2891 auto NumElems = FixedVecTy->getNumElements();
2897 return Opcode == Instruction::ExtractElement
2898 ? StoreCost * NumElems + LoadCost
2899 : (StoreCost + LoadCost) * NumElems + StoreCost;
2903 if (LT.second.isScalableVector() && !LT.first.isValid())
2911 if (Opcode == Instruction::ExtractElement) {
2917 return ExtendCost + ExtractCost;
2927 return ExtendCost + InsertCost + TruncCost;
2934 if (LT.second.isFloatingPoint())
2935 MoveOpc = Opcode == Instruction::InsertElement ? RISCV::VFMV_S_F
2939 Opcode == Instruction::InsertElement ? RISCV::VMV_S_X : RISCV::VMV_X_S;
2941 getRISCVInstructionCost(MoveOpc, LT.second,
CostKind);
2943 InstructionCost SlideCost = Opcode == Instruction::InsertElement ? 2 : 1;
2948 if (LT.second.isFixedLengthVector()) {
2949 unsigned Width = LT.second.getVectorNumElements();
2950 Index = Index % Width;
2955 if (
auto VLEN = ST->getRealVLen()) {
2956 unsigned EltSize = LT.second.getScalarSizeInBits();
2957 unsigned M1Max = *VLEN / EltSize;
2958 Index = Index % M1Max;
2964 else if (Opcode == Instruction::InsertElement)
2972 ((Index == -1U) || (Index >= LT.second.getVectorMinNumElements() &&
2973 LT.second.isScalableVector()))) {
2975 Align VecAlign =
DL.getPrefTypeAlign(Val);
2976 Align SclAlign =
DL.getPrefTypeAlign(ScalarType);
2981 if (Opcode == Instruction::ExtractElement)
3017 Opcode == Instruction::InsertElement
3018 ? getRISCVInstructionCost({RISCV::VSLIDE1DOWN_VX,
3019 RISCV::VSLIDE1DOWN_VX,
3020 RISCV::VSLIDEUP_VX},
3022 : getRISCVInstructionCost({RISCV::VSLIDEDOWN_VX, RISCV::VMV_X_S,
3023 RISCV::VSRL_VX, RISCV::VMV_X_S},
3026 return BaseCost + SlideCost;
3032 unsigned Index)
const {
3041 assert(Index < EC.getKnownMinValue() &&
"Unexpected reverse index");
3043 EC.getKnownMinValue() - 1 - Index,
nullptr,
3052std::optional<InstructionCost>
3058 if ((Opcode == Instruction::UDiv || Opcode == Instruction::URem) &&
3060 if (Opcode == Instruction::UDiv)
3067 return std::nullopt;
3089 if (std::optional<InstructionCost> CombinedCost =
3091 Op2Info, Args, CtxI))
3092 return *CombinedCost;
3096 unsigned ISDOpcode = TLI->InstructionOpcodeToISD(Opcode);
3099 if (!LT.second.isVector()) {
3109 if (TLI->isOperationLegalOrPromote(ISDOpcode, LT.second))
3110 if (
const auto *Entry =
CostTableLookup(DivTbl, ISDOpcode, LT.second))
3111 return Entry->Cost * LT.first;
3120 if ((LT.second.getVectorElementType() == MVT::f16 ||
3121 LT.second.getVectorElementType() == MVT::bf16) &&
3122 TLI->getOperationAction(ISDOpcode, LT.second) ==
3124 MVT PromotedVT = TLI->getTypeToPromoteTo(ISDOpcode, LT.second);
3128 CastCost += LT.first * Args.size() *
3136 LT.second = PromotedVT;
3139 auto getConstantMatCost =
3141 if (OpInfo.isUniform() &&
3150 return getConstantPoolLoadCost(Ty,
CostKind);
3156 ConstantMatCost += getConstantMatCost(0, Op1Info);
3158 ConstantMatCost += getConstantMatCost(1, Op2Info);
3161 switch (ISDOpcode) {
3164 Op = RISCV::VADD_VV;
3169 Op = RISCV::VSLL_VV;
3174 Op = (Ty->getScalarSizeInBits() == 1) ? RISCV::VMAND_MM : RISCV::VAND_VV;
3179 Op = RISCV::VMUL_VV;
3183 Op = RISCV::VDIV_VV;
3187 Op = RISCV::VREM_VV;
3191 Op = RISCV::VFADD_VV;
3194 Op = RISCV::VFMUL_VV;
3197 Op = RISCV::VFDIV_VV;
3200 Op = RISCV::VFSGNJN_VV;
3205 return CastCost + ConstantMatCost +
3214 if (Ty->isFPOrFPVectorTy())
3216 return CastCost + ConstantMatCost + LT.first *
InstrCost;
3239 if (Info.isSameBase() && V !=
Base) {
3240 if (
GEP->hasAllConstantIndices())
3246 unsigned Stride =
DL.getTypeStoreSize(AccessTy);
3247 if (Info.isUnitStride() &&
3253 GEP->getType()->getPointerAddressSpace()))
3256 {TTI::OK_AnyValue, TTI::OP_None},
3257 {TTI::OK_AnyValue, TTI::OP_None}, {});
3274 if (ST->enableDefaultUnroll())
3284 if (L->getHeader()->getParent()->hasOptSize())
3288 L->getExitingBlocks(ExitingBlocks);
3290 <<
"Blocks: " << L->getNumBlocks() <<
"\n"
3291 <<
"Exit blocks: " << ExitingBlocks.
size() <<
"\n");
3295 if (ExitingBlocks.
size() > 2)
3300 if (L->getNumBlocks() > 4)
3308 for (
auto *BB : L->getBlocks()) {
3309 for (
auto &
I : *BB) {
3313 if (IsVectorized && (
I.getType()->isVectorTy() ||
3315 return V->getType()->isVectorTy();
3354 bool HasMask =
false;
3357 bool IsWrite) -> int64_t {
3358 if (
auto *TarExtTy =
3360 return TarExtTy->getIntParameter(0);
3366 case Intrinsic::riscv_vle_mask:
3367 case Intrinsic::riscv_vse_mask:
3368 case Intrinsic::riscv_vlseg2_mask:
3369 case Intrinsic::riscv_vlseg3_mask:
3370 case Intrinsic::riscv_vlseg4_mask:
3371 case Intrinsic::riscv_vlseg5_mask:
3372 case Intrinsic::riscv_vlseg6_mask:
3373 case Intrinsic::riscv_vlseg7_mask:
3374 case Intrinsic::riscv_vlseg8_mask:
3375 case Intrinsic::riscv_vsseg2_mask:
3376 case Intrinsic::riscv_vsseg3_mask:
3377 case Intrinsic::riscv_vsseg4_mask:
3378 case Intrinsic::riscv_vsseg5_mask:
3379 case Intrinsic::riscv_vsseg6_mask:
3380 case Intrinsic::riscv_vsseg7_mask:
3381 case Intrinsic::riscv_vsseg8_mask:
3384 case Intrinsic::riscv_vle:
3385 case Intrinsic::riscv_vse:
3386 case Intrinsic::riscv_vlseg2:
3387 case Intrinsic::riscv_vlseg3:
3388 case Intrinsic::riscv_vlseg4:
3389 case Intrinsic::riscv_vlseg5:
3390 case Intrinsic::riscv_vlseg6:
3391 case Intrinsic::riscv_vlseg7:
3392 case Intrinsic::riscv_vlseg8:
3393 case Intrinsic::riscv_vsseg2:
3394 case Intrinsic::riscv_vsseg3:
3395 case Intrinsic::riscv_vsseg4:
3396 case Intrinsic::riscv_vsseg5:
3397 case Intrinsic::riscv_vsseg6:
3398 case Intrinsic::riscv_vsseg7:
3399 case Intrinsic::riscv_vsseg8: {
3416 Ty = TarExtTy->getTypeParameter(0U);
3421 const auto *RVVIInfo = RISCVVIntrinsicsTable::getRISCVVIntrinsicInfo(IID);
3422 unsigned VLIndex = RVVIInfo->VLOperand;
3423 unsigned PtrOperandNo = VLIndex - 1 - HasMask;
3431 unsigned SegNum = getSegNum(Inst, PtrOperandNo, IsWrite);
3434 unsigned ElemSize = Ty->getScalarSizeInBits();
3438 Info.InterestingOperands.emplace_back(Inst, PtrOperandNo, IsWrite, Ty,
3439 Alignment, Mask, EVL);
3442 case Intrinsic::riscv_vlse_mask:
3443 case Intrinsic::riscv_vsse_mask:
3444 case Intrinsic::riscv_vlsseg2_mask:
3445 case Intrinsic::riscv_vlsseg3_mask:
3446 case Intrinsic::riscv_vlsseg4_mask:
3447 case Intrinsic::riscv_vlsseg5_mask:
3448 case Intrinsic::riscv_vlsseg6_mask:
3449 case Intrinsic::riscv_vlsseg7_mask:
3450 case Intrinsic::riscv_vlsseg8_mask:
3451 case Intrinsic::riscv_vssseg2_mask:
3452 case Intrinsic::riscv_vssseg3_mask:
3453 case Intrinsic::riscv_vssseg4_mask:
3454 case Intrinsic::riscv_vssseg5_mask:
3455 case Intrinsic::riscv_vssseg6_mask:
3456 case Intrinsic::riscv_vssseg7_mask:
3457 case Intrinsic::riscv_vssseg8_mask:
3460 case Intrinsic::riscv_vlse:
3461 case Intrinsic::riscv_vsse:
3462 case Intrinsic::riscv_vlsseg2:
3463 case Intrinsic::riscv_vlsseg3:
3464 case Intrinsic::riscv_vlsseg4:
3465 case Intrinsic::riscv_vlsseg5:
3466 case Intrinsic::riscv_vlsseg6:
3467 case Intrinsic::riscv_vlsseg7:
3468 case Intrinsic::riscv_vlsseg8:
3469 case Intrinsic::riscv_vssseg2:
3470 case Intrinsic::riscv_vssseg3:
3471 case Intrinsic::riscv_vssseg4:
3472 case Intrinsic::riscv_vssseg5:
3473 case Intrinsic::riscv_vssseg6:
3474 case Intrinsic::riscv_vssseg7:
3475 case Intrinsic::riscv_vssseg8: {
3492 Ty = TarExtTy->getTypeParameter(0U);
3497 const auto *RVVIInfo = RISCVVIntrinsicsTable::getRISCVVIntrinsicInfo(IID);
3498 unsigned VLIndex = RVVIInfo->VLOperand;
3499 unsigned PtrOperandNo = VLIndex - 2 - HasMask;
3508 unsigned PointerAlign = Alignment.valueOrOne().value();
3511 Alignment =
Align(1);
3518 unsigned SegNum = getSegNum(Inst, PtrOperandNo, IsWrite);
3521 unsigned ElemSize = Ty->getScalarSizeInBits();
3525 Info.InterestingOperands.emplace_back(Inst, PtrOperandNo, IsWrite, Ty,
3526 Alignment, Mask, EVL, Stride);
3529 case Intrinsic::riscv_vloxei_mask:
3530 case Intrinsic::riscv_vluxei_mask:
3531 case Intrinsic::riscv_vsoxei_mask:
3532 case Intrinsic::riscv_vsuxei_mask:
3533 case Intrinsic::riscv_vloxseg2_mask:
3534 case Intrinsic::riscv_vloxseg3_mask:
3535 case Intrinsic::riscv_vloxseg4_mask:
3536 case Intrinsic::riscv_vloxseg5_mask:
3537 case Intrinsic::riscv_vloxseg6_mask:
3538 case Intrinsic::riscv_vloxseg7_mask:
3539 case Intrinsic::riscv_vloxseg8_mask:
3540 case Intrinsic::riscv_vluxseg2_mask:
3541 case Intrinsic::riscv_vluxseg3_mask:
3542 case Intrinsic::riscv_vluxseg4_mask:
3543 case Intrinsic::riscv_vluxseg5_mask:
3544 case Intrinsic::riscv_vluxseg6_mask:
3545 case Intrinsic::riscv_vluxseg7_mask:
3546 case Intrinsic::riscv_vluxseg8_mask:
3547 case Intrinsic::riscv_vsoxseg2_mask:
3548 case Intrinsic::riscv_vsoxseg3_mask:
3549 case Intrinsic::riscv_vsoxseg4_mask:
3550 case Intrinsic::riscv_vsoxseg5_mask:
3551 case Intrinsic::riscv_vsoxseg6_mask:
3552 case Intrinsic::riscv_vsoxseg7_mask:
3553 case Intrinsic::riscv_vsoxseg8_mask:
3554 case Intrinsic::riscv_vsuxseg2_mask:
3555 case Intrinsic::riscv_vsuxseg3_mask:
3556 case Intrinsic::riscv_vsuxseg4_mask:
3557 case Intrinsic::riscv_vsuxseg5_mask:
3558 case Intrinsic::riscv_vsuxseg6_mask:
3559 case Intrinsic::riscv_vsuxseg7_mask:
3560 case Intrinsic::riscv_vsuxseg8_mask:
3563 case Intrinsic::riscv_vloxei:
3564 case Intrinsic::riscv_vluxei:
3565 case Intrinsic::riscv_vsoxei:
3566 case Intrinsic::riscv_vsuxei:
3567 case Intrinsic::riscv_vloxseg2:
3568 case Intrinsic::riscv_vloxseg3:
3569 case Intrinsic::riscv_vloxseg4:
3570 case Intrinsic::riscv_vloxseg5:
3571 case Intrinsic::riscv_vloxseg6:
3572 case Intrinsic::riscv_vloxseg7:
3573 case Intrinsic::riscv_vloxseg8:
3574 case Intrinsic::riscv_vluxseg2:
3575 case Intrinsic::riscv_vluxseg3:
3576 case Intrinsic::riscv_vluxseg4:
3577 case Intrinsic::riscv_vluxseg5:
3578 case Intrinsic::riscv_vluxseg6:
3579 case Intrinsic::riscv_vluxseg7:
3580 case Intrinsic::riscv_vluxseg8:
3581 case Intrinsic::riscv_vsoxseg2:
3582 case Intrinsic::riscv_vsoxseg3:
3583 case Intrinsic::riscv_vsoxseg4:
3584 case Intrinsic::riscv_vsoxseg5:
3585 case Intrinsic::riscv_vsoxseg6:
3586 case Intrinsic::riscv_vsoxseg7:
3587 case Intrinsic::riscv_vsoxseg8:
3588 case Intrinsic::riscv_vsuxseg2:
3589 case Intrinsic::riscv_vsuxseg3:
3590 case Intrinsic::riscv_vsuxseg4:
3591 case Intrinsic::riscv_vsuxseg5:
3592 case Intrinsic::riscv_vsuxseg6:
3593 case Intrinsic::riscv_vsuxseg7:
3594 case Intrinsic::riscv_vsuxseg8: {
3611 Ty = TarExtTy->getTypeParameter(0U);
3616 const auto *RVVIInfo = RISCVVIntrinsicsTable::getRISCVVIntrinsicInfo(IID);
3617 unsigned VLIndex = RVVIInfo->VLOperand;
3618 unsigned PtrOperandNo = VLIndex - 2 - HasMask;
3631 unsigned SegNum = getSegNum(Inst, PtrOperandNo, IsWrite);
3634 unsigned ElemSize = Ty->getScalarSizeInBits();
3639 Info.InterestingOperands.emplace_back(Inst, PtrOperandNo, IsWrite, Ty,
3640 Align(1), Mask, EVL,
3649 if (Ty->isVectorTy()) {
3652 if ((EltTy->
isHalfTy() && !ST->hasVInstructionsF16()) ||
3658 if (
Size.isScalable() && ST->hasVInstructions())
3661 if (ST->useRVVForFixedLengthVectors())
3669 if (std::optional<unsigned> MaxVF = ST->getCLOpts().v_slp_max_vf)
3681 return std::max<unsigned>(1U, RegWidth.
getFixedValue() / ElemWidth);
3685 return ST->getCLOpts().v_min_trip_count;
3689 return ST->enableUnalignedVectorMem();
3695 if (ST->hasVendorXCVmem() && !ST->is64Bit())
3717 Align Alignment)
const {
3727 if (VTy->getElementType()->isIntegerTy(8)) {
3728 uint64_t MaxEltCount = VTy->getElementCount().getKnownMinValue();
3729 if (VTy->isScalableTy())
3732 if (MaxEltCount > 256)
3741 Align Alignment)
const {
3748 if (!ST->hasVInstructions() || !ST->hasOptimizedZeroStrideLoad())
3751 return TLI->isLegalElementTypeForRVV(TLI->getValueType(
DL, ElementTy));
3760 const Instruction &
I,
bool &AllowPromotionWithoutCommonHeader)
const {
3761 bool Considerable =
false;
3762 AllowPromotionWithoutCommonHeader =
false;
3765 Type *ConsideredSExtType =
3767 if (
I.getType() != ConsideredSExtType)
3771 for (
const User *U :
I.users()) {
3773 Considerable =
true;
3777 if (GEPInst->getNumOperands() > 2) {
3778 AllowPromotionWithoutCommonHeader =
true;
3783 return Considerable;
3789 case Instruction::Add:
3790 case Instruction::Sub:
3791 case Instruction::Mul:
3792 case Instruction::And:
3793 case Instruction::Or:
3794 case Instruction::Xor:
3795 case Instruction::FAdd:
3796 case Instruction::FSub:
3797 case Instruction::FMul:
3798 case Instruction::FDiv:
3799 case Instruction::ICmp:
3800 case Instruction::FCmp:
3802 case Instruction::Shl:
3803 case Instruction::LShr:
3804 case Instruction::AShr:
3805 case Instruction::UDiv:
3806 case Instruction::SDiv:
3807 case Instruction::URem:
3808 case Instruction::SRem:
3809 case Instruction::Select:
3810 return Operand == 1;
3811 case Instruction::Call:
3812 switch (IntrinsicID) {
3813 case Intrinsic::fma:
3814 case Intrinsic::fmuladd:
3815 return Operand == 0 || Operand == 1;
3816 case Intrinsic::vp_udiv:
3817 case Intrinsic::vp_sdiv:
3818 case Intrinsic::vp_urem:
3819 case Intrinsic::vp_srem:
3820 case Intrinsic::ssub_sat:
3821 case Intrinsic::usub_sat:
3822 return Operand == 1;
3824 case Intrinsic::smin:
3825 case Intrinsic::umin:
3826 case Intrinsic::smax:
3827 case Intrinsic::umax:
3828 case Intrinsic::sadd_sat:
3829 case Intrinsic::uadd_sat:
3830 return Operand == 0 || Operand == 1;
3840 if (!
I->getType()->isVectorTy() || !ST->hasVInstructions())
3846 IntrinsicID =
II->getIntrinsicID();
3854 GatherUseOps)
const {
3855 if (Scalars.
empty() || !ST->hasVInstructions() || !ST->sinkSplatOperands() ||
3860 if (SplatIt == Scalars.
end() || (*SplatIt)->getType()->isIntegerTy(1) ||
3866 if (!GatherUseOps(UserOps) || UserOps.
empty())
3886 if (
I->isBitwiseLogicOp()) {
3887 if (!
I->getType()->isVectorTy()) {
3888 if (ST->hasStdExtZbb() || ST->hasStdExtZbkb()) {
3889 for (
auto &
Op :
I->operands()) {
3897 }
else if (
I->getOpcode() == Instruction::And && ST->hasStdExtZvkb()) {
3898 for (
auto &
Op :
I->operands()) {
3910 Ops.push_back(&Not);
3911 Ops.push_back(&InsertElt);
3919 if (!
I->getType()->isVectorTy() || !ST->hasVInstructions())
3927 if (!ST->sinkSplatOperands())
3930 for (
auto OpIdx :
enumerate(
I->operands())) {
3950 for (
Use &U :
Op->uses()) {
3957 Use *InsertEltUse = &
Op->getOperandUse(0);
3960 Ops.push_back(&InsertElt->getOperandUse(1));
3961 Ops.push_back(InsertEltUse);
3962 Ops.push_back(&OpIdx.value());
3971 if (!ST->hasStdExtZbb() && !ST->hasStdExtZbkb() && !IsZeroCmp)
3974 Options.AllowOverlappingLoads =
true;
3975 Options.MaxNumLoads = TLI->getMaxExpandSizeMemcmp(OptSize);
3977 if (ST->is64Bit()) {
3978 Options.LoadSizes = {8, 4, 2, 1};
3979 Options.AllowedTailExpansions = {3, 5, 6};
3981 Options.LoadSizes = {4, 2, 1};
3982 Options.AllowedTailExpansions = {3};
3985 if (IsZeroCmp && ST->hasVInstructions()) {
3986 unsigned VLenB = ST->getRealMinVLen() / 8;
3989 unsigned MinSize = ST->getXLen() / 8 + 1;
3990 unsigned MaxSize = VLenB * 8;
3999 if (ST->getCLOpts().or_like_select) {
4004 if (
I->getOpcode() == Instruction::Or &&
4008 if (
I->getOpcode() == Instruction::Add ||
4009 I->getOpcode() == Instruction::Sub)
4027std::optional<Instruction *>
4033 if (
is_contained({Intrinsic::riscv_vsetvli, Intrinsic::riscv_vsetvlimax},
4034 II.getIntrinsicID())) {
4037 if (!ST->hasVInstructions())
4040 bool HasAVL =
II.getIntrinsicID() == Intrinsic::riscv_vsetvli;
4041 unsigned Offset = HasAVL ? 1 : 0;
4042 unsigned BitWidth =
II.getType()->getIntegerBitWidth();
4067 Value *AVL =
II.getArgOperand(0);
4096 II.getRange().value_or(ConstantRange::getFull(
BitWidth));
4098 if (NewRange != OldRange) {
4099 II.addRangeRetAttr(NewRange);
4109 if (
II.user_empty())
4114 const APInt *Scalar;
4119 return U->getType() == TargetVecTy && match(U, m_BitCast(m_Value()));
4123 unsigned TargetEltBW =
DL.getTypeSizeInBits(TargetVecTy->getElementType());
4124 unsigned SourceEltBW =
DL.getTypeSizeInBits(SourceVecTy->getElementType());
4125 if (TargetEltBW % SourceEltBW)
4127 unsigned TargetScale = TargetEltBW / SourceEltBW;
4128 if (VL % TargetScale || TargetScale == 1)
4130 Type *VLTy =
II.getOperand(2)->getType();
4131 ElementCount SourceEC = SourceVecTy->getElementCount();
4132 unsigned NewEltBW = SourceEltBW * TargetScale;
4134 !
DL.fitsInLegalInteger(NewEltBW))
4137 if (!TLI->isLegalElementTypeForRVV(TLI->getValueType(
DL, NewEltTy)))
4141 assert(SourceVecTy->canLosslesslyBitCastTo(RetTy) &&
4142 "Lossless bitcast between types expected");
4148 RetTy, Intrinsic::riscv_vmv_v_x,
4149 {PoisonValue::get(RetTy), ConstantInt::get(NewEltTy, NewScalar),
4150 ConstantInt::get(VLTy, VL / TargetScale)}),
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
This file provides a helper that implements much of the TTI interface in terms of the target-independ...
static GCRegistry::Add< ShadowStackGC > C("shadow-stack", "Very portable GC for uncooperative code generators")
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
static bool shouldSplit(Instruction *InsertPoint, DenseSet< Value * > &PrevConditionValues, DenseSet< Value * > &ConditionValues, DominatorTree &DT, DenseSet< Instruction * > &Unhoistables)
static cl::opt< OutputCostKind > CostKind("cost-kind", cl::desc("Target cost kind"), cl::init(OutputCostKind::RecipThroughput), cl::values(clEnumValN(OutputCostKind::RecipThroughput, "throughput", "Reciprocal throughput"), clEnumValN(OutputCostKind::Latency, "latency", "Instruction latency"), clEnumValN(OutputCostKind::CodeSize, "code-size", "Code size"), clEnumValN(OutputCostKind::SizeAndLatency, "size-latency", "Code size and latency"), clEnumValN(OutputCostKind::All, "all", "Print all cost kinds")))
Cost tables and simple lookup functions.
static cl::opt< int > InstrCost("inline-instr-cost", cl::Hidden, cl::init(5), cl::desc("Cost of a single instruction when inlining"))
std::pair< Instruction::BinaryOps, Value * > OffsetOp
Find all possible pairs (BinOp, RHS) that BinOp V, RHS can be simplified.
This file provides the interface for the instcombine pass implementation.
const AbstractManglingParser< Derived, Alloc >::OperatorInfo AbstractManglingParser< Derived, Alloc >::Ops[]
uint64_t IntrinsicInst * II
This file describes how to lower LLVM code to machine code.
Class for arbitrary precision integers.
static LLVM_ABI APInt getSplat(unsigned NewLen, const APInt &V)
Return a value containing V broadcasted over NewLen bits.
static APInt getZero(unsigned numBits)
Get the '0' value for the specified bit-width.
Represent a constant reference to an array (0 or more elements consecutively in memory),...
const T & back() const
Get the last element.
size_t size() const
Get the array size.
bool empty() const
Check if the array is empty.
Functions, function parameters, and return types can have attributes to indicate how they should be t...
LLVM_ABI bool isStringAttribute() const
Return true if the attribute is a string (target-dependent) attribute.
LLVM_ABI StringRef getKindAsString() const
Return the attribute's kind as a string.
InstructionCost getInterleavedMemoryOpCost(unsigned Opcode, Type *VecTy, unsigned Factor, ArrayRef< unsigned > Indices, Align Alignment, unsigned AddressSpace, TTI::TargetCostKind CostKind, bool UseMaskForCond=false, bool UseMaskForGaps=false) const override
InstructionCost getMinMaxReductionCost(Intrinsic::ID IID, VectorType *Ty, FastMathFlags FMF, TTI::TargetCostKind CostKind) const override
TTI::ShuffleKind improveShuffleKindFromMask(TTI::ShuffleKind Kind, ArrayRef< int > Mask, VectorType *SrcTy, int &Index, VectorType *&SubTy) const
bool isLegalAddressingMode(Type *Ty, GlobalValue *BaseGV, int64_t BaseOffset, bool HasBaseReg, int64_t Scale, unsigned AddrSpace, Instruction *I=nullptr, int64_t ScalableOffset=0) const override
InstructionCost getScalarizationOverhead(VectorType *InTy, const APInt &DemandedElts, bool Insert, bool Extract, TTI::TargetCostKind CostKind, bool ForPoisonSrc=true, ArrayRef< Value * > VL={}, TTI::VectorInstrContext VIC=TTI::VectorInstrContext::None) const override
InstructionCost getArithmeticReductionCost(unsigned Opcode, VectorType *Ty, std::optional< FastMathFlags > FMF, TTI::TargetCostKind CostKind) const override
InstructionCost getCmpSelInstrCost(unsigned Opcode, Type *ValTy, Type *CondTy, CmpInst::Predicate VecPred, TTI::TargetCostKind CostKind, TTI::OperandValueInfo Op1Info={TTI::OK_AnyValue, TTI::OP_None}, TTI::OperandValueInfo Op2Info={TTI::OK_AnyValue, TTI::OP_None}, const Instruction *I=nullptr) const override
InstructionCost getArithmeticInstrCost(unsigned Opcode, Type *Ty, TTI::TargetCostKind CostKind, TTI::OperandValueInfo Opd1Info={TTI::OK_AnyValue, TTI::OP_None}, TTI::OperandValueInfo Opd2Info={TTI::OK_AnyValue, TTI::OP_None}, ArrayRef< const Value * > Args={}, const Instruction *CtxI=nullptr) const override
void getUnrollingPreferences(Loop *L, ScalarEvolution &SE, TTI::UnrollingPreferences &UP, OptimizationRemarkEmitter *ORE) const override
void getPeelingPreferences(Loop *L, ScalarEvolution &SE, TTI::PeelingPreferences &PP) const override
InstructionCost getShuffleCost(TTI::ShuffleKind Kind, VectorType *DstTy, VectorType *SrcTy, TTI::TargetCostKind CostKind, ArrayRef< int > Mask, int Index, VectorType *SubTp, ArrayRef< const Value * > Args={}, const Instruction *CtxI=nullptr, TTI::VectorInstrContext VIC=TTI::VectorInstrContext::None) const override
InstructionCost getIndexedVectorInstrCostFromEnd(unsigned Opcode, Type *Val, TTI::TargetCostKind CostKind, unsigned Index) const override
InstructionCost getCastInstrCost(unsigned Opcode, Type *Dst, Type *Src, TTI::CastContextHint CCH, TTI::TargetCostKind CostKind, const Instruction *I=nullptr) const override
std::pair< InstructionCost, MVT > getTypeLegalizationCost(Type *Ty) const
bool isLegalAddImmediate(int64_t imm) const override
InstructionCost getVectorInstrCost(unsigned Opcode, Type *Val, TTI::TargetCostKind CostKind, unsigned Index, const Value *Op0, const Value *Op1, TTI::VectorInstrContext VIC=TTI::VectorInstrContext::None) const override
std::optional< unsigned > getVScaleForTuning() const override
InstructionCost getExtendedReductionCost(unsigned Opcode, bool IsUnsigned, Type *ResTy, VectorType *Ty, std::optional< FastMathFlags > FMF, TTI::TargetCostKind CostKind) const override
InstructionCost getIntrinsicInstrCost(const IntrinsicCostAttributes &ICA, TTI::TargetCostKind CostKind) const override
InstructionCost getAddressComputationCost(Type *PtrTy, ScalarEvolution *, const SCEV *, TTI::TargetCostKind) const override
InstructionCost getGEPCost(Type *PointeeType, const Value *Ptr, ArrayRef< const Value * > Operands, TTI::TargetCostKind CostKind, Type *AccessType) const override
unsigned getRegUsageForType(Type *Ty) const override
InstructionCost getMemIntrinsicInstrCost(const MemIntrinsicCostAttributes &MICA, TTI::TargetCostKind CostKind) const override
InstructionCost getMemoryOpCost(unsigned Opcode, Type *Src, Align Alignment, unsigned AddressSpace, TTI::TargetCostKind CostKind, TTI::OperandValueInfo OpInfo={TTI::OK_AnyValue, TTI::OP_None}, const Instruction *I=nullptr) const override
Value * getArgOperand(unsigned i) const
unsigned arg_size() const
Predicate
This enumeration lists the possible predicates for CmpInst subclasses.
@ FCMP_OEQ
0 0 0 1 True if ordered and equal
@ FCMP_TRUE
1 1 1 1 Always true (always folded)
@ ICMP_SLT
signed less than
@ FCMP_OLT
0 1 0 0 True if ordered and less than
@ FCMP_ULE
1 1 0 1 True if unordered, less than, or equal
@ FCMP_OGT
0 0 1 0 True if ordered and greater than
@ FCMP_OGE
0 0 1 1 True if ordered and greater than or equal
@ ICMP_UGE
unsigned greater or equal
@ ICMP_UGT
unsigned greater than
@ FCMP_ULT
1 1 0 0 True if unordered or less than
@ FCMP_ONE
0 1 1 0 True if ordered and operands are unequal
@ FCMP_UEQ
1 0 0 1 True if unordered or equal
@ ICMP_ULT
unsigned less than
@ FCMP_UGT
1 0 1 0 True if unordered or greater than
@ FCMP_OLE
0 1 0 1 True if ordered and less than or equal
@ FCMP_ORD
0 1 1 1 True if ordered (no nans)
@ FCMP_UNE
1 1 1 0 True if unordered or not equal
@ ICMP_ULE
unsigned less or equal
@ FCMP_UGE
1 0 1 1 True if unordered, greater than, or equal
@ FCMP_FALSE
0 0 0 0 Always false (always folded)
@ FCMP_UNO
1 0 0 0 True if unordered: isnan(X) | isnan(Y)
static bool isFPPredicate(Predicate P)
static bool isIntPredicate(Predicate P)
This is the shared class of boolean and integer constants.
static LLVM_ABI ConstantInt * getTrue(LLVMContext &Context)
This class represents a range of values.
LLVM_ABI ConstantRange umin(const ConstantRange &Other) const
Return a new range representing the possible values resulting from an unsigned minimum of a value in ...
LLVM_ABI APInt getUnsignedMin() const
Return the smallest unsigned value contained in the ConstantRange.
LLVM_ABI bool icmp(CmpInst::Predicate Pred, const ConstantRange &Other) const
Does the predicate Pred hold between ranges this and Other?
LLVM_ABI ConstantRange umax(const ConstantRange &Other) const
Return a new range representing the possible values resulting from an unsigned maximum of a value in ...
static LLVM_ABI ConstantRange makeAllowedICmpRegion(CmpInst::Predicate Pred, const ConstantRange &Other)
Produce the smallest range such that all values that may satisfy the given predicate with any value c...
LLVM_ABI ConstantRange multiply(const ConstantRange &Other, unsigned NoWrapKind=0) const
Return a new range representing the possible values resulting from a multiplication of a value in thi...
LLVM_ABI APInt getUnsignedMax() const
Return the largest unsigned value contained in the ConstantRange.
LLVM_ABI ConstantRange intersectWith(const ConstantRange &CR, PreferredRangeType Type=Smallest) const
Return the range that results from the intersection of this range with another range.
LLVM_ABI ConstantRange udiv(const ConstantRange &Other) const
Return a new range representing the possible values resulting from an unsigned division of a value in...
A parsed version of the target data layout string in and methods for querying it.
Convenience struct for specifying and reasoning about fast-math flags.
Class to represent fixed width SIMD vectors.
unsigned getNumElements() const
static FixedVectorType * getDoubleElementsVectorType(FixedVectorType *VTy)
static LLVM_ABI FixedVectorType * get(Type *ElementType, unsigned NumElts)
static FixedVectorType * getHalfElementsVectorType(FixedVectorType *VTy)
an instruction for type-safe pointer arithmetic to access elements of arrays and structs
Value * CreateBitCast(Value *V, Type *DestTy, const Twine &Name="")
LLVM_ABI Value * CreateIntrinsic(Intrinsic::ID ID, ArrayRef< Type * > OverloadTypes, ArrayRef< Value * > Args, FMFSource FMFSource={}, const Twine &Name="", ArrayRef< OperandBundleDef > OpBundles={}, function_ref< void(CallInst *)> SetFn=[](CallInst *) {})
Variant to create a possibly constant-folded intrinsic.
The core instruction combiner logic.
const DataLayout & getDataLayout() const
Instruction * replaceInstUsesWith(Instruction &I, Value *V)
A combiner-aware RAUW-like routine.
const SimplifyQuery & getSimplifyQuery() const
static InstructionCost getInvalid(CostType Val=0)
CostType getValue() const
This function is intended to be used as sparingly as possible, since the class provides the full rang...
LLVM_ABI bool isCommutative() const LLVM_READONLY
Return true if the instruction is commutative:
user_iterator user_begin()
static LLVM_ABI IntegerType * get(LLVMContext &C, unsigned NumBits)
This static method is the primary way of constructing an IntegerType.
const SmallVectorImpl< Type * > & getArgTypes() const
Type * getReturnType() const
const SmallVectorImpl< const Value * > & getArgs() const
VectorInstrContext getVectorInstrContext() const
Intrinsic::ID getID() const
bool isTypeBasedOnly() const
A wrapper class for inspecting calls to intrinsic functions.
Intrinsic::ID getIntrinsicID() const
Return the intrinsic ID of this intrinsic.
This is an important class for using LLVM in a threaded context.
Represents a single loop in the control flow graph.
static MVT getFloatingPointVT(unsigned BitWidth)
@ INVALID_SIMPLE_VALUE_TYPE
unsigned getVectorMinNumElements() const
Given a vector type, return the minimum number of elements it contains.
uint64_t getScalarSizeInBits() const
MVT changeVectorElementType(MVT EltVT) const
Return a VT for a vector type whose attributes match ourselves with the exception of the element type...
bool bitsLE(MVT VT) const
Return true if this has no more bits than VT.
unsigned getVectorNumElements() const
bool isVector() const
Return true if this is a vector value type.
static MVT getScalableVectorVT(MVT VT, unsigned NumElements)
MVT changeTypeToInteger()
Return the type converted to an equivalently sized integer or vector with integer element type.
TypeSize getSizeInBits() const
Returns the size of the specified MVT in bits.
uint64_t getFixedSizeInBits() const
Return the size of the specified fixed width value type in bits.
bool bitsGT(MVT VT) const
Return true if this has more bits than VT.
bool isFixedLengthVector() const
ElementCount getVectorElementCount() const
TypeSize getStoreSize() const
Return the number of bytes overwritten by a store of the specified value type.
MVT getVectorElementType() const
bool isValid() const
Return true if this is a valid simple valuetype.
static MVT getIntegerVT(unsigned BitWidth)
MVT getDoubleNumVectorElementsVT() const
MVT getHalfNumVectorElementsVT() const
Return a VT for a vector type with the same element type but half the number of elements.
MVT getScalarType() const
If this is a vector, return the element type, otherwise return this.
Information for memory intrinsic cost model.
Align getAlignment() const
unsigned getAddressSpace() const
Type * getDataType() const
bool getVariableMask() const
const Value * getStrideVal() const
Intrinsic::ID getID() const
unsigned getOpcode() const
Return the opcode for this Instruction or ConstantExpr.
InstructionCost getExtendedReductionCost(unsigned Opcode, bool IsUnsigned, Type *ResTy, VectorType *ValTy, std::optional< FastMathFlags > FMF, TTI::TargetCostKind CostKind) const override
InstructionCost getCFInstrCost(unsigned Opcode, TTI::TargetCostKind CostKind, const Instruction *I=nullptr) const override
bool shouldCopyAttributeWhenOutliningFrom(const Function *Caller, const Attribute &Attr) const override
InstructionCost getVectorInstrCost(unsigned Opcode, Type *Val, TTI::TargetCostKind CostKind, unsigned Index, const Value *Op0, const Value *Op1, TTI::VectorInstrContext VIC=TTI::VectorInstrContext::None) const override
bool isLegalMaskedExpandLoad(Type *DataType, Align Alignment) const override
InstructionCost getStridedMemoryOpCost(const MemIntrinsicCostAttributes &MICA, TTI::TargetCostKind CostKind) const
bool isLegalMaskedLoadStore(Type *DataType, Align Alignment) const
TargetTransformInfo::VectorInstrContext getBuildVectorContextHint(ArrayRef< int > Mask, ArrayRef< Value * > Scalars, function_ref< bool(SmallVectorImpl< TargetTransformInfo::BuildVectorUseOp > &)> GatherUseOps) const override
InstructionCost getIntImmCostIntrin(Intrinsic::ID IID, unsigned Idx, const APInt &Imm, Type *Ty, TTI::TargetCostKind CostKind) const override
unsigned getMinTripCountTailFoldingThreshold() const override
TTI::AddressingModeKind getPreferredAddressingMode(const Loop *L, ScalarEvolution *SE) const override
InstructionCost getAddressComputationCost(Type *PTy, ScalarEvolution *SE, const SCEV *Ptr, TTI::TargetCostKind CostKind) const override
InstructionCost getShuffleCost(TTI::ShuffleKind Kind, VectorType *DstTy, VectorType *SrcTy, TTI::TargetCostKind CostKind, ArrayRef< int > Mask, int Index, VectorType *SubTp, ArrayRef< const Value * > Args={}, const Instruction *CtxI=nullptr, TTI::VectorInstrContext VIC=TTI::VectorInstrContext::None) const override
InstructionCost getStoreImmCost(Type *VecTy, TTI::OperandValueInfo OpInfo, TTI::TargetCostKind CostKind) const
Return the cost of materializing an immediate for a value operand of a store instruction.
bool getTgtMemIntrinsic(IntrinsicInst *Inst, MemIntrinsicInfo &Info) const override
InstructionCost getCostOfKeepingLiveOverCall(ArrayRef< Type * > Tys) const override
bool hasActiveVectorLength() const override
InstructionCost getCastInstrCost(unsigned Opcode, Type *Dst, Type *Src, TTI::CastContextHint CCH, TTI::TargetCostKind CostKind, const Instruction *I=nullptr) const override
InstructionCost getCmpSelInstrCost(unsigned Opcode, Type *ValTy, Type *CondTy, CmpInst::Predicate VecPred, TTI::TargetCostKind CostKind, TTI::OperandValueInfo Op1Info={TTI::OK_AnyValue, TTI::OP_None}, TTI::OperandValueInfo Op2Info={TTI::OK_AnyValue, TTI::OP_None}, const Instruction *I=nullptr) const override
InstructionCost getIndexedVectorInstrCostFromEnd(unsigned Opcode, Type *Val, TTI::TargetCostKind CostKind, unsigned Index) const override
void getUnrollingPreferences(Loop *L, ScalarEvolution &SE, TTI::UnrollingPreferences &UP, OptimizationRemarkEmitter *ORE) const override
bool isLegalBroadcastLoad(Type *ElementTy, ElementCount NumElements) const override
InstructionCost getIntImmCostInst(unsigned Opcode, unsigned Idx, const APInt &Imm, Type *Ty, TTI::TargetCostKind CostKind, Instruction *Inst=nullptr) const override
InstructionCost getMinMaxReductionCost(Intrinsic::ID IID, VectorType *Ty, FastMathFlags FMF, TTI::TargetCostKind CostKind) const override
Try to calculate op costs for min/max reduction operations.
bool canSplatOperand(Instruction *I, int Operand) const
Return true if the (vector) instruction I will be lowered to an instruction with a scalar splat opera...
bool isLSRCostLess(const TargetTransformInfo::LSRCost &C1, const TargetTransformInfo::LSRCost &C2) const override
bool isLegalStridedLoadStore(Type *DataType, Align Alignment) const override
unsigned getRegUsageForType(Type *Ty) const override
InstructionCost getInterleavedMemoryOpCost(unsigned Opcode, Type *VecTy, unsigned Factor, ArrayRef< unsigned > Indices, Align Alignment, unsigned AddressSpace, TTI::TargetCostKind CostKind, bool UseMaskForCond=false, bool UseMaskForGaps=false) const override
bool isLegalMaskedScatter(Type *DataType, Align Alignment) const override
bool isLegalMaskedCompressStore(Type *DataTy, Align Alignment) const override
InstructionCost getGatherScatterOpCost(const MemIntrinsicCostAttributes &MICA, TTI::TargetCostKind CostKind) const
InstructionCost getPartialReductionCost(unsigned Opcode, Type *InputTypeA, Type *InputTypeB, Type *AccumType, ElementCount VF, TTI::PartialReductionExtendKind OpAExtend, TTI::PartialReductionExtendKind OpBExtend, std::optional< unsigned > BinOp, TTI::TargetCostKind CostKind, std::optional< FastMathFlags > FMF) const override
bool shouldTreatInstructionLikeSelect(const Instruction *I) const override
InstructionCost getExpandCompressMemoryOpCost(const MemIntrinsicCostAttributes &MICA, TTI::TargetCostKind CostKind) const
bool preferAlternateOpcodeVectorization() const override
bool isProfitableToSinkOperands(Instruction *I, SmallVectorImpl< Use * > &Ops) const override
Check if sinking I's operands to I's basic block is profitable, because the operands can be folded in...
bool shouldExpandReduction(const IntrinsicInst *II) const override
std::optional< unsigned > getVScaleForTuning() const override
std::optional< InstructionCost > getCombinedArithmeticInstructionCost(unsigned ISDOpcode, Type *Ty, TTI::TargetCostKind CostKind, TTI::OperandValueInfo Opd1Info, TTI::OperandValueInfo Opd2Info, ArrayRef< const Value * > Args, const Instruction *CtxI) const
Check to see if this instruction is expected to be combined to a simpler operation during/before lowe...
InstructionCost getMemIntrinsicInstrCost(const MemIntrinsicCostAttributes &MICA, TTI::TargetCostKind CostKind) const override
Get memory intrinsic cost based on arguments.
InstructionCost getArithmeticInstrCost(unsigned Opcode, Type *Ty, TTI::TargetCostKind CostKind, TTI::OperandValueInfo Op1Info={TTI::OK_AnyValue, TTI::OP_None}, TTI::OperandValueInfo Op2Info={TTI::OK_AnyValue, TTI::OP_None}, ArrayRef< const Value * > Args={}, const Instruction *CtxI=nullptr) const override
bool isLegalMaskedGather(Type *DataType, Align Alignment) const override
InstructionCost getPointersChainCost(ArrayRef< const Value * > Ptrs, const Value *Base, const TTI::PointersChainInfo &Info, Type *AccessTy, const TTI::TargetCostKind CostKind) const override
unsigned getMaximumVF(unsigned ElemWidth, unsigned Opcode) const override
TTI::MemCmpExpansionOptions enableMemCmpExpansion(bool OptSize, bool IsZeroCmp) const override
InstructionCost getScalarizationOverhead(VectorType *Ty, const APInt &DemandedElts, bool Insert, bool Extract, TTI::TargetCostKind CostKind, bool ForPoisonSrc=true, ArrayRef< Value * > VL={}, TTI::VectorInstrContext VIC=TTI::VectorInstrContext::None) const override
Estimate the overhead of scalarizing an instruction.
InstructionCost getMemoryOpCost(unsigned Opcode, Type *Src, Align Alignment, unsigned AddressSpace, TTI::TargetCostKind CostKind, TTI::OperandValueInfo OpdInfo={TTI::OK_AnyValue, TTI::OP_None}, const Instruction *I=nullptr) const override
InstructionCost getIntrinsicInstrCost(const IntrinsicCostAttributes &ICA, TTI::TargetCostKind CostKind) const override
Get intrinsic cost based on arguments.
InstructionCost getMaskedMemoryOpCost(const MemIntrinsicCostAttributes &MICA, TTI::TargetCostKind CostKind) const
InstructionCost getArithmeticReductionCost(unsigned Opcode, VectorType *Ty, std::optional< FastMathFlags > FMF, TTI::TargetCostKind CostKind) const override
TypeSize getRegisterBitWidth(TargetTransformInfo::RegisterKind K) const override
void getPeelingPreferences(Loop *L, ScalarEvolution &SE, TTI::PeelingPreferences &PP) const override
std::optional< Instruction * > instCombineIntrinsic(InstCombiner &IC, IntrinsicInst &II) const override
bool shouldConsiderAddressTypePromotion(const Instruction &I, bool &AllowPromotionWithoutCommonHeader) const override
See if I should be considered for address type promotion.
InstructionCost getIntImmCost(const APInt &Imm, Type *Ty, TTI::TargetCostKind CostKind) const override
TargetTransformInfo::PopcntSupportKind getPopcntSupport(unsigned TyWidth) const override
static MVT getM1VT(MVT VT)
Given a vector (either fixed or scalable), return the scalable vector corresponding to a vector regis...
InstructionCost getVRGatherVVCost(MVT VT) const
Return the cost of a vrgather.vv instruction for the type VT.
InstructionCost getVRGatherVICost(MVT VT) const
Return the cost of a vrgather.vi (or vx) instruction for the type VT.
static unsigned computeVLMAX(unsigned VectorBits, unsigned EltSize, unsigned MinSize)
InstructionCost getLMULCost(MVT VT) const
Return the cost of LMUL for linear operations.
InstructionCost getVSlideVICost(MVT VT) const
Return the cost of a vslidedown.vi or vslideup.vi instruction for the type VT.
InstructionCost getVSlideVXCost(MVT VT) const
Return the cost of a vslidedown.vx or vslideup.vx instruction for the type VT.
static RISCVVType::VLMUL getLMUL(MVT VT)
This class represents an analyzed expression in the program.
static LLVM_ABI ScalableVectorType * get(Type *ElementType, unsigned MinNumElts)
The main scalar evolution driver.
static LLVM_ABI bool isZeroEltSplatMask(ArrayRef< int > Mask, int NumSrcElts)
Return true if this shuffle mask chooses all elements with the same value as the first element of exa...
static LLVM_ABI bool isSingleSourceMask(ArrayRef< int > Mask, int NumSrcElts)
Return true if this shuffle mask chooses elements from exactly one source vector.
static LLVM_ABI bool isDeInterleaveMaskOfFactor(ArrayRef< int > Mask, unsigned Factor, unsigned &Index)
Check if the mask is a DE-interleave mask of the given factor Factor like: <Index,...
static LLVM_ABI bool isIdentityMask(ArrayRef< int > Mask, int NumSrcElts)
Return true if this shuffle mask chooses elements from exactly one source vector without lane crossin...
static LLVM_ABI bool isInterleaveMask(ArrayRef< int > Mask, unsigned Factor, unsigned NumInputElts, SmallVectorImpl< unsigned > &StartIndexes)
Return true if the mask interleaves one or more input vectors together.
Implements a dense probed hash-table based set with some number of buckets stored inline.
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
void append(ItTy in_start, ItTy in_end)
Add the specified range to the end of the SmallVector.
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
An instruction for storing to memory.
static constexpr TypeSize getFixed(ScalarTy ExactSize)
static constexpr TypeSize getScalable(ScalarTy MinimumSize)
The instances of the Type class are immutable: once they are created, they are never changed.
static LLVM_ABI IntegerType * getInt64Ty(LLVMContext &C)
bool isVectorTy() const
True if this is an instance of VectorType.
static LLVM_ABI IntegerType * getInt32Ty(LLVMContext &C)
bool isBFloatTy() const
Return true if this is 'bfloat', a 16-bit bfloat type.
LLVM_ABI unsigned getPointerAddressSpace() const
Get the address space of this pointer or pointer vector type.
Type * getScalarType() const
If this is a vector type, return the element type, otherwise return 'this'.
LLVM_ABI Type * getWithNewBitWidth(unsigned NewBitWidth) const
Given an integer or vector type, change the lane bitwidth to NewBitwidth, whilst keeping the old numb...
static LLVM_ABI IntegerType * getInt16Ty(LLVMContext &C)
bool isHalfTy() const
Return true if this is 'half', a 16-bit IEEE fp type.
LLVM_ABI Type * getWithNewType(Type *EltTy) const
Given vector type, change the element type, whilst keeping the old number of elements.
LLVMContext & getContext() const
Return the LLVMContext in which this type was uniqued.
LLVM_ABI unsigned getScalarSizeInBits() const LLVM_READONLY
If this is a vector type, return the getPrimitiveSizeInBits value for the element type.
static LLVM_ABI IntegerType * getInt1Ty(LLVMContext &C)
LLVM_ABI bool isScalableTy() const
Return true if this is a type whose size is a known multiple of vscale.
bool isIntegerTy() const
True if this is an instance of IntegerType.
static LLVM_ABI IntegerType * getIntNTy(LLVMContext &C, unsigned N)
static LLVM_ABI Type * getFloatTy(LLVMContext &C)
bool isVoidTy() const
Return true if this is 'void'.
A Use represents the edge between a Value definition and its users.
Value * getOperand(unsigned i) const
LLVM Value Representation.
Type * getType() const
All values are typed, get the type of this value.
bool hasOneUse() const
Return true if there is exactly one use of this value.
LLVMContext & getContext() const
All values hold a context through their type.
LLVM_ABI Align getPointerAlignment(const DataLayout &DL) const
Returns an alignment of the pointer value.
Base class of all SIMD vector types.
ElementCount getElementCount() const
Return an ElementCount instance to represent the (possibly scalable) number of elements in the vector...
static LLVM_ABI VectorType * get(Type *ElementType, ElementCount EC)
This static method is the primary way to construct an VectorType.
std::pair< iterator, bool > insert(const ValueT &V)
constexpr bool isKnownMultipleOf(ScalarTy RHS) const
This function tells the caller whether the element count is known at compile time to be a multiple of...
constexpr ScalarTy getFixedValue() const
static constexpr bool isKnownLE(const FixedOrScalableQuantity &LHS, const FixedOrScalableQuantity &RHS)
static constexpr bool isKnownLT(const FixedOrScalableQuantity &LHS, const FixedOrScalableQuantity &RHS)
constexpr bool isScalable() const
Returns whether the quantity is scaled by a runtime quantity (vscale).
constexpr bool isKnownEven() const
A return value of true indicates we know at compile time that the number of elements (vscale * Min) i...
constexpr bool isFixed() const
Returns true if the quantity is not scaled by vscale.
constexpr ScalarTy getKnownMinValue() const
Returns the minimum value this quantity can represent.
constexpr LeafTy divideCoefficientBy(ScalarTy RHS) const
We do not provide the '/' operator here because division for polynomial types does not work in the sa...
An efficient, type-erasing, non-owning reference to a callable.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
LLVM_ABI APInt RoundingUDiv(const APInt &A, const APInt &B, APInt::Rounding RM)
Return A unsign-divided by B, rounded by the given rounding mode.
constexpr std::underlying_type_t< E > Mask()
Get a bitmask with 1s in all places up to the high-order bit of E's largest value.
ISD namespace - This namespace contains an enum which represents all of the SelectionDAG node types a...
@ ADD
Simple integer binary arithmetic operators.
@ SINT_TO_FP
[SU]INT_TO_FP - These operators convert integers (whose interpreted sign depends on the first letter)...
@ FADD
Simple binary floating point operators.
@ SIGN_EXTEND
Conversion operators.
@ FNEG
Perform various unary floating-point operations inspired by libm.
@ MULHU
MULHU/MULHS - Multiply high - Multiply two integers of type iN, producing an unsigned/signed value of...
@ SHL
Shift and rotation operations.
@ ZERO_EXTEND
ZERO_EXTEND - Used for integer types, zeroing the new bits.
@ FP_EXTEND
X = FP_EXTEND(Y) - Extend a smaller FP type into a larger FP type.
@ FP_TO_SINT
FP_TO_[US]INT - Convert a floating point value to a signed or unsigned integer.
@ AND
Bitwise operators - logical and, logical or, logical xor.
@ FP_ROUND
X = FP_ROUND(Y, TRUNC) - Rounding 'Y' from a larger floating point type down to the precision of the ...
@ TRUNCATE
TRUNCATE - Completely drop the high bits.
SpecificConstantMatch m_ZeroInt()
Convenience matchers for specific integer values.
BinaryOp_match< SrcTy, SpecificConstantMatch, TargetOpcode::G_XOR, true > m_Not(const SrcTy &&Src)
Matches a register not-ed by a G_XOR.
auto m_Poison()
Match an arbitrary poison constant.
ap_match< APInt > m_APInt(const APInt *&Res)
Match a ConstantInt or splatted ConstantVector, binding the specified pointer to the contained APInt.
bool match(Val *V, const Pattern &P)
auto m_Value()
Match an arbitrary value and ignore it.
TwoOps_match< V1_t, V2_t, Instruction::ShuffleVector > m_Shuffle(const V1_t &v1, const V2_t &v2)
Matches ShuffleVectorInst independently of mask value.
auto m_Intrinsic(const Ts &...Ops)
Match intrinsic calls like this: m_Intrinsic<Intrinsic::fabs>(m_Value(X))
ThreeOps_match< Val_t, Elt_t, Idx_t, Instruction::InsertElement > m_InsertElt(const Val_t &Val, const Elt_t &Elt, const Idx_t &Idx)
Matches InsertElementInst.
auto m_ConstantInt()
Match an arbitrary ConstantInt and ignore it.
int getIntMatCost(const APInt &Val, unsigned Size, const MCSubtargetInfo &STI, bool CompressionCost, bool FreeZeroes)
static unsigned decodeVSEW(unsigned VSEW)
LLVM_ABI std::pair< unsigned, bool > decodeVLMUL(VLMUL VLMul)
LLVM_ABI unsigned getSEWLMULRatio(unsigned SEW, VLMUL VLMul)
static constexpr unsigned RVVBitsPerBlock
This is an optimization pass for GlobalISel generic memory operations.
unsigned Log2_32_Ceil(uint32_t Value)
Return the ceil log base 2 of the specified value, 32 if the value is zero.
bool all_of(R &&range, UnaryPredicate P)
Provide wrappers to std::all_of which take ranges instead of having to pass begin/end explicitly.
const CostTblEntryT< CostType > * CostTableLookup(ArrayRef< CostTblEntryT< CostType > > Tbl, int ISD, MVT Ty)
Find in cost table.
LLVM_ABI bool getBooleanLoopAttribute(const Loop *TheLoop, StringRef Name)
Returns true if Name is applied to TheLoop and enabled.
constexpr bool isInt(int64_t x)
Checks if an integer fits into the given bit width.
auto enumerate(FirstRange &&First, RestRanges &&...Rest)
Given two or more input ranges, returns a new range whose values are tuples (A, B,...
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
@ None
The instruction is not folded.
@ BinaryOp
One of the operands is a binary op.
@ SplatOpFolded
All of the value's users support splatting the value.
auto adjacent_find(R &&Range)
Provide wrappers to std::adjacent_find which finds the first pair of adjacent elements that are equal...
bool isPairEven(const std::array< std::pair< int, int >, 2 > &SrcInfo, ArrayRef< int > Mask, unsigned &Factor)
Given a shuffle which can be represented as a pair of two slides, see if it is a pair-even idiom.
bool isPairOdd(const std::array< std::pair< int, int >, 2 > &SrcInfo, ArrayRef< int > Mask, unsigned &Factor)
Given a shuffle which can be represented as a pair of two slides, see if it is a pair-odd idiom.
int countr_zero(T Val)
Count number of 0's from the least significant bit to the most stopping at the first 1.
constexpr bool isShiftedMask_64(uint64_t Value)
Return true if the argument contains a non-empty sequence of ones with the remainder zero (64 bit ver...
auto dyn_cast_or_null(const Y &Val)
bool any_of(R &&range, UnaryPredicate P)
Provide wrappers to std::any_of which take ranges instead of having to pass begin/end explicitly.
unsigned Log2_32(uint32_t Value)
Return the floor log base 2 of the specified value, -1 if the value is zero.
LLVM_ABI llvm::SmallVector< int, 16 > createStrideMask(unsigned Start, unsigned Stride, unsigned VF)
Create a stride shuffle mask.
constexpr bool isPowerOf2_32(uint32_t Value)
Return true if the argument is a power of two > 0.
auto find_if_not(R &&Range, UnaryPredicate P)
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
bool is_sorted(R &&Range, Compare C)
Wrapper function around std::is_sorted to check if elements in a range R are sorted with respect to a...
constexpr bool isUInt(uint64_t x)
Checks if an unsigned integer fits into the given bit width.
bool isa(const From &Val)
isa<X> - Return true if the parameter to the template is an instance of one of the template type argu...
constexpr int PoisonMaskElem
constexpr T divideCeil(U Numerator, V Denominator)
Returns the integer ceil(Numerator / Denominator).
LLVM_ABI bool isMaskedSlidePair(ArrayRef< int > Mask, int NumElts, std::array< std::pair< int, int >, 2 > &SrcInfo)
Does this shuffle mask represent either one slide shuffle or a pair of two slide shuffles,...
LLVM_ABI llvm::SmallVector< int, 16 > createInterleaveMask(unsigned VF, unsigned NumVecs)
Create an interleave shuffle mask.
LLVM_ABI ConstantRange computeConstantRangeIncludingKnownBits(const WithCache< const Value * > &V, bool ForSigned, const SimplifyQuery &SQ)
Combine constant ranges from computeConstantRange() and computeKnownBits().
DWARFExpression::Operation Op
OutputIt copy(R &&Range, OutputIt Out)
constexpr unsigned BitWidth
CostTblEntryT< uint16_t > CostTblEntry
auto count_if(R &&Range, UnaryPredicate P)
Wrapper function around std::count_if to count the number of times an element satisfying a given pred...
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
bool is_contained(R &&Range, const E &Element)
Returns true if Element is found in Range.
constexpr int64_t SignExtend64(uint64_t x)
Sign-extend the number in the bottom B bits of X to a 64-bit integer.
LLVM_ABI void processShuffleMasks(ArrayRef< int > Mask, unsigned NumOfSrcRegs, unsigned NumOfDestRegs, unsigned NumOfUsedRegs, function_ref< void()> NoInputAction, function_ref< void(ArrayRef< int >, unsigned, unsigned)> SingleInputAction, function_ref< void(ArrayRef< int >, unsigned, unsigned, bool)> ManyInputsAction)
Splits and processes shuffle mask depending on the number of input and output registers.
bool equal(L &&LRange, R &&RRange)
Wrapper function around std::equal to detect if pair-wise elements between two ranges are the same.
T bit_floor(T Value)
Returns the largest integral power of two no greater than Value if Value is nonzero.
constexpr detail::IsaCheckPredicate< Types... > IsaPred
Function object wrapper for the llvm::isa type check.
void swap(llvm::BitVector &LHS, llvm::BitVector &RHS)
Implement std::swap in terms of BitVector swap.
This struct is a compact representation of a valid (non-zero power of two) alignment.
LLVM_ABI Type * getTypeForEVT(LLVMContext &Context) const
This method returns an LLVM type corresponding to the specified EVT.
This struct is a compact representation of a valid (power of two) or undefined (0) alignment.
Information about a load/store intrinsic defined by the target.
SimplifyQuery getWithInstruction(const Instruction *I) const