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 &&
308 if (!ST->hasStdExtZibi())
313 const auto Pred =
Cond.getPredicate();
315 if (
C && (
C->isZero() ||
324 return Imm == -1 || (
Imm >= 1 &&
Imm <= 31);
336 return ST->hasVInstructions();
346 unsigned Opcode,
Type *InputTypeA,
Type *InputTypeB,
Type *AccumType,
350 if (Opcode == Instruction::FAdd)
359 if (!ST->hasStdExtZvdot4a8i() || ST->getELen() < 64 ||
360 Opcode != Instruction::Add || !BinOp || *BinOp != Instruction::Mul ||
361 InputTypeA != InputTypeB || !InputTypeA->
isIntegerTy(8) ||
377 getRISCVInstructionCost(RISCV::VDOT4A_VV, DotLT.second, CostKind);
386 std::pair<InstructionCost, MVT> AccLT =
394 bool WidenFirst =
false;
395 if (VF.
isScalable() && AccLT.second.isScalableVector()) {
396 MVT NarrowMVT = AccLT.second.changeVectorElementType(MVT::i32);
409 WideLT.first * getRISCVInstructionCost(RISCV::VSEXT_VF2,
410 WideLT.second, CostKind) +
412 getRISCVInstructionCost(RISCV::VADD_VV, AccLT.second, CostKind);
416 std::pair<InstructionCost, MVT> RedLT =
418 Cost += RedLT.first * getRISCVInstructionCost(RISCV::VADD_VV,
419 RedLT.second, CostKind) +
420 AccLT.first * getRISCVInstructionCost(RISCV::VWADD_WV,
421 AccLT.second, CostKind);
424 Cost += DotLT.first * getRISCVInstructionCost(RISCV::VSLIDEDOWN_VI,
425 DotLT.second, CostKind);
436 switch (
II->getIntrinsicID()) {
440 case Intrinsic::vector_reduce_mul:
441 case Intrinsic::vector_reduce_fmul:
447 if (ST->hasVInstructions())
448 if (
unsigned MinVLen = ST->getRealMinVLen();
457 std::clamp<unsigned>(ST->getCLOpts().v_register_bit_width_lmul, 1, 8));
463 ST->useRVVForFixedLengthVectors() ? LMUL * ST->getRealMinVLen() : 0);
466 (ST->hasVInstructions() &&
489 return (ST->hasAUIPCADDIFusion() && ST->hasLUIADDIFusion()) ? 1 : 2;
495RISCVTTIImpl::getConstantPoolLoadCost(
Type *Ty,
501 Cost = getStaticDataAddrGenerationCost(CostKind) +
512 unsigned Size = Mask.size();
515 for (
unsigned I = 0;
I !=
Size; ++
I) {
516 if (
static_cast<unsigned>(Mask[
I]) ==
I)
522 for (
unsigned J =
I + 1; J !=
Size; ++J)
524 if (
static_cast<unsigned>(Mask[J]) != J %
I)
552 "Expected fixed vector type and non-empty mask");
555 unsigned NumOfDests =
divideCeil(Mask.size(), LegalNumElts);
559 if (NumOfDests <= 1 ||
561 Tp->getElementType()->getPrimitiveSizeInBits() ||
562 LegalNumElts >= Tp->getElementCount().getFixedValue())
565 unsigned VecTySize =
TTI.getDataLayout().getTypeStoreSize(Tp);
568 unsigned NumOfSrcs =
divideCeil(VecTySize, LegalVTSize);
572 unsigned NormalizedVF = LegalNumElts * std::max(NumOfSrcs, NumOfDests);
573 unsigned NumOfSrcRegs = NormalizedVF / LegalNumElts;
574 unsigned NumOfDestRegs = NormalizedVF / LegalNumElts;
576 assert(NormalizedVF >= Mask.size() &&
577 "Normalized mask expected to be not shorter than original mask.");
582 NormalizedMask, NumOfSrcRegs, NumOfDestRegs, NumOfDestRegs, []() {},
583 [&](
ArrayRef<int> RegMask,
unsigned SrcReg,
unsigned DestReg) {
586 if (!ReusedSingleSrcShuffles.
insert(std::make_pair(RegMask, SrcReg))
589 Cost +=
TTI.getShuffleCost(
592 SingleOpTy, CostKind, RegMask, 0,
nullptr);
594 [&](
ArrayRef<int> RegMask,
unsigned Idx1,
unsigned Idx2,
bool NewReg) {
595 Cost +=
TTI.getShuffleCost(
598 SingleOpTy, CostKind, RegMask, 0,
nullptr);
621 if (!VLen || Mask.empty())
625 LegalVT =
TTI.getTypeLegalizationCost(
631 if (NumOfDests <= 1 ||
633 Tp->getElementType()->getPrimitiveSizeInBits() ||
637 unsigned VecTySize =
TTI.getDataLayout().getTypeStoreSize(Tp);
640 unsigned NumOfSrcs =
divideCeil(VecTySize, LegalVTSize);
646 unsigned NormalizedVF =
651 assert(NormalizedVF >= Mask.size() &&
652 "Normalized mask expected to be not shorter than original mask.");
658 NormalizedMask, NumOfSrcRegs, NumOfDestRegs, NumOfDestRegs, []() {},
659 [&](
ArrayRef<int> RegMask,
unsigned SrcReg,
unsigned DestReg) {
662 if (!ReusedSingleSrcShuffles.
insert(std::make_pair(RegMask, SrcReg))
667 SingleOpTy, CostKind, RegMask, 0,
nullptr);
669 [&](
ArrayRef<int> RegMask,
unsigned Idx1,
unsigned Idx2,
bool NewReg) {
671 SingleOpTy, CostKind, RegMask, 0,
nullptr);
678 if ((NumOfDestRegs > 2 && NumShuffles <=
static_cast<int>(NumOfDestRegs)) ||
679 (NumOfDestRegs <= 2 && NumShuffles < 4))
694 if (!
LT.second.isFixedLengthVector())
702 auto GetSlideOpcode = [&](
int SlideAmt) {
704 bool IsVI =
isUInt<5>(std::abs(SlideAmt));
706 return IsVI ? RISCV::VSLIDEDOWN_VI : RISCV::VSLIDEDOWN_VX;
707 return IsVI ? RISCV::VSLIDEUP_VI : RISCV::VSLIDEUP_VX;
710 std::array<std::pair<int, int>, 2> SrcInfo;
714 if (SrcInfo[1].second == 0)
717 if (ST->hasStdExtZvzip() &&
LT.second.getScalarSizeInBits() != 1) {
719 if (
isPairEven(SrcInfo, Mask, Factor) && Factor == 1)
720 return getRISCVInstructionCost(RISCV::VPAIRE_VV,
LT.second, CostKind);
721 if (
isPairOdd(SrcInfo, Mask, Factor) && Factor == 1)
722 return getRISCVInstructionCost(RISCV::VPAIRO_VV,
LT.second, CostKind);
726 if (SrcInfo[0].second != 0) {
727 unsigned Opcode = GetSlideOpcode(SrcInfo[0].second);
728 FirstSlideCost = getRISCVInstructionCost(Opcode,
LT.second, CostKind);
731 if (SrcInfo[1].first == -1)
732 return FirstSlideCost;
735 if (SrcInfo[1].second != 0) {
736 unsigned Opcode = GetSlideOpcode(SrcInfo[1].second);
737 SecondSlideCost = getRISCVInstructionCost(Opcode,
LT.second, CostKind);
740 getRISCVInstructionCost(RISCV::VMERGE_VVM,
LT.second, CostKind);
747 return FirstSlideCost + SecondSlideCost + MaskCost;
750MVT RISCVTTIImpl::getZvzipVZIPCostVT(
MVT InterleavedVT)
const {
754 MVT CostVT = InterleavedVT;
757 CostVT = TLI->getContainerForFixedLengthVector(SourceVT)
766 LMULOctuple * std::min(ST->getELen(), ST->getRealMinVLen()))
771MVT RISCVTTIImpl::getZvzipVUNZIPCostVT(
MVT InterleavedVT)
const {
775 MVT CostVT = InterleavedVT;
780 CostVT = TLI->getContainerForFixedLengthVector(InterleavedVT);
798 if (!ST->hasStdExtZvzip() ||
Mask.size() < 2 ||
799 DstTy->getScalarSizeInBits() == 1)
802 unsigned NumSrcElts = SrcTy->getElementCount().getKnownMinValue();
803 unsigned NumDstElts = DstTy->getElementCount().getKnownMinValue();
804 unsigned NumInputElts;
809 if (NumSrcElts != NumDstElts)
811 NumInputElts = NumSrcElts;
825 if (NumSrcElts != NumDstElts && NumSrcElts * 2 != NumDstElts)
827 NumInputElts = NumSrcElts * 2;
842 unsigned DeinterleaveIndex;
844 DeinterleaveIndex) &&
845 count_if(Mask, [](
int Idx) {
return Idx >= 0; }) > 1)
850 SmallVector<unsigned, 2> StartIndexes;
854 unsigned HalfNumElts =
Mask.size() / 2;
855 if ((StartIndexes[0] != 0 && StartIndexes[1] != 0) ||
856 StartIndexes[0] % HalfNumElts != 0 || StartIndexes[1] % HalfNumElts != 0)
860 MVT CostVT = getZvzipVZIPCostVT(DstLT.second);
865 DstLT.first * getRISCVInstructionCost(RISCV::VZIP_VV, CostVT, CostKind);
872 if (NumSrcElts == NumDstElts) {
875 for (
unsigned Start : StartIndexes) {
876 unsigned ExtractIndex =
Start % NumSrcElts;
877 if (ExtractIndex != 0)
879 CostKind, {}, ExtractIndex, HalfSrcTy);
893 "Expected the Mask to match the return size if given");
895 "Expected the same scalar types");
898 if (VIC == TTI::VectorInstrContext::SplatOpFolded &&
914 FVTp && ST->hasVInstructions() && LT.second.isFixedLengthVector()) {
916 *
this, LT.second, ST->getRealVLen(),
918 if (VRegSplittingCost.
isValid())
919 return VRegSplittingCost;
924 if (Mask.size() >= 2) {
925 MVT EltTp = LT.second.getVectorElementType();
930 getVZIPCost(Kind, DstTy, SrcTy, Mask, CostKind);
937 unsigned Opcode = Index == 0 ? RISCV::VUNZIPE_V : RISCV::VUNZIPO_V;
938 if (
MVT CostVT = getZvzipVUNZIPCostVT(LT.second); CostVT.
isValid())
939 return LT.first * getRISCVInstructionCost(Opcode, CostVT, CostKind);
952 return 2 * LT.first * TLI->getLMULCost(LT.second);
954 if (Mask[0] == 0 || Mask[0] == 1) {
958 if (
equal(DeinterleaveMask, Mask))
959 return LT.first * getRISCVInstructionCost(RISCV::VNSRL_WI,
960 LT.second, CostKind);
965 if (LT.second.getScalarSizeInBits() != 1 &&
968 unsigned NumSlides =
Log2_32(Mask.size() / SubVectorSize);
970 for (
unsigned I = 0;
I != NumSlides; ++
I) {
971 unsigned InsertIndex = SubVectorSize * (1 <<
I);
976 std::pair<InstructionCost, MVT> DestLT =
981 Cost += DestLT.first * TLI->getLMULCost(DestLT.second);
983 CostKind, {}, InsertIndex, SubTp);
995 if (LT.first == 1 && (LT.second.getScalarSizeInBits() != 8 ||
996 LT.second.getVectorNumElements() <= 256)) {
1001 getRISCVInstructionCost(RISCV::VRGATHER_VV, LT.second, CostKind);
1013 getVZIPCost(Kind, DstTy, SrcTy, Mask, CostKind);
1019 if (LT.first == 1 && (LT.second.getScalarSizeInBits() != 8 ||
1020 LT.second.getVectorNumElements() <= 256)) {
1021 auto &
C = SrcTy->getContext();
1022 auto EC = SrcTy->getElementCount();
1027 return 2 * IndexCost +
1028 getRISCVInstructionCost({RISCV::VRGATHER_VV, RISCV::VRGATHER_VV},
1029 LT.second, CostKind) +
1047 if (!Mask.empty() && LT.first.isValid() && LT.first != 1 &&
1075 SubLT.second.isValid() && SubLT.second.isFixedLengthVector()) {
1076 if (std::optional<unsigned> VLen = ST->getRealVLen();
1077 VLen && SubLT.second.getScalarSizeInBits() * Index % *VLen == 0 &&
1078 SubLT.second.getSizeInBits() <= *VLen)
1086 getRISCVInstructionCost(RISCV::VSLIDEDOWN_VI, LT.second, CostKind);
1093 getRISCVInstructionCost(RISCV::VSLIDEUP_VI, LT.second, CostKind);
1105 (1 + getRISCVInstructionCost({RISCV::VMV_S_X, RISCV::VMERGE_VVM},
1106 LT.second, CostKind));
1112 if (IsLoad && LT.second.isVector() &&
1114 LT.second.getVectorElementCount()))
1118 Instruction::InsertElement);
1119 if (LT.second.getScalarSizeInBits() == 1) {
1127 (1 + getRISCVInstructionCost({RISCV::VMV_V_X, RISCV::VMSNE_VI},
1128 LT.second, CostKind));
1140 (1 + getRISCVInstructionCost({RISCV::VMV_V_I, RISCV::VMERGE_VIM,
1141 RISCV::VMV_X_S, RISCV::VMV_V_X,
1143 LT.second, CostKind));
1150 getRISCVInstructionCost(RISCV::VMV_V_X, LT.second, CostKind);
1156 getRISCVInstructionCost(RISCV::VRGATHER_VI, LT.second, CostKind);
1162 unsigned Opcodes[2] = {RISCV::VSLIDEDOWN_VX, RISCV::VSLIDEUP_VX};
1163 if (Index >= 0 && Index < 32)
1164 Opcodes[0] = RISCV::VSLIDEDOWN_VI;
1165 else if (Index < 0 && Index > -32)
1166 Opcodes[1] = RISCV::VSLIDEUP_VI;
1167 return LT.first * getRISCVInstructionCost(Opcodes, LT.second, CostKind);
1171 if (!LT.second.isVector())
1177 if (SrcTy->getElementType()->isIntegerTy(1)) {
1189 MVT ContainerVT = LT.second;
1190 if (LT.second.isFixedLengthVector())
1191 ContainerVT = TLI->getContainerForFixedLengthVector(LT.second);
1193 if (ContainerVT.
bitsLE(M1VT)) {
1203 if (LT.second.isFixedLengthVector())
1205 LenCost =
isInt<5>(LT.second.getVectorNumElements() - 1) ? 0 : 1;
1206 unsigned Opcodes[] = {RISCV::VID_V, RISCV::VRSUB_VX, RISCV::VRGATHER_VV};
1207 if (LT.second.isFixedLengthVector() &&
1208 isInt<5>(LT.second.getVectorNumElements() - 1))
1209 Opcodes[1] = RISCV::VRSUB_VI;
1211 getRISCVInstructionCost(Opcodes, LT.second, CostKind);
1212 return LT.first * (LenCost + GatherCost);
1219 unsigned M1Opcodes[] = {RISCV::VID_V, RISCV::VRSUB_VX};
1221 getRISCVInstructionCost(M1Opcodes, M1VT, CostKind) + 3;
1225 getRISCVInstructionCost({RISCV::VRGATHER_VV}, M1VT, CostKind) * Ratio;
1227 getRISCVInstructionCost({RISCV::VSLIDEDOWN_VX}, LT.second, CostKind);
1228 return FixedCost + LT.first * (GatherCost + SlideCost);
1262 Ty, DemandedElts, Insert, Extract, CostKind);
1264 if (Insert && !Extract && LT.first.isValid() && LT.second.isVector()) {
1265 if (Ty->getScalarSizeInBits() == 1) {
1275 assert(LT.second.isFixedLengthVector());
1276 MVT ContainerVT = TLI->getContainerForFixedLengthVector(LT.second);
1280 getRISCVInstructionCost(RISCV::VSLIDE1DOWN_VX, LT.second, CostKind);
1293 switch (MICA.
getID()) {
1294 case Intrinsic::vp_load_ff: {
1295 EVT DataTypeVT = TLI->getValueType(
DL, DataTy);
1296 if (!TLI->isLegalFirstFaultLoad(DataTypeVT, Alignment))
1300 return getMemoryOpCost(Instruction::Load, DataTy, Alignment, AS, CostKind,
1303 case Intrinsic::experimental_vp_strided_load:
1304 case Intrinsic::experimental_vp_strided_store:
1306 case Intrinsic::masked_compressstore:
1307 case Intrinsic::masked_expandload:
1309 case Intrinsic::vp_scatter:
1310 case Intrinsic::vp_gather:
1311 case Intrinsic::masked_scatter:
1312 case Intrinsic::masked_gather:
1314 case Intrinsic::vp_load:
1315 case Intrinsic::vp_store:
1316 case Intrinsic::masked_load:
1317 case Intrinsic::masked_store:
1326 unsigned Opcode = MICA.
getID() == Intrinsic::masked_load ? Instruction::Load
1327 : Instruction::Store;
1338 if (MICA.
getID() == Intrinsic::vp_load ||
1339 MICA.
getID() == Intrinsic::vp_store) {
1351 bool UseMaskForCond,
bool UseMaskForGaps)
const {
1357 if (!UseMaskForGaps && Factor <= TLI->getMaxSupportedInterleaveFactor()) {
1361 if (LT.second.isVector()) {
1367 VTy->getElementCount().divideCoefficientBy(Factor));
1368 if (VTy->getElementCount().isKnownMultipleOf(Factor) &&
1369 TLI->isLegalInterleavedAccessType(SubVecTy, Factor, Alignment,
1374 if (ST->hasOptimizedSegmentLoadStore(Factor)) {
1375 unsigned VecSizeInBits =
1376 getEstimatedVLFor(VTy) * VTy->getScalarSizeInBits();
1377 unsigned VLENForTuning =
1379 unsigned DLENForTuning = VLENForTuning / ST->getDLenFactor();
1381 MVT SubVecVT = getTLI()->getValueType(
DL, SubVecTy).getSimpleVT();
1382 Cost += Factor * TLI->getLMULCost(SubVecVT);
1388 unsigned NumLoads = getEstimatedVLFor(VTy);
1404 if (UseMaskForGaps) {
1407 "Indices should not contain duplicate elements");
1408 unsigned NumOfFields = Indices.
size();
1409 bool IsTailGapOnly = NumOfFields > 1 && (NumOfFields == Indices.
back() + 1);
1410 if (IsTailGapOnly &&
1411 NumOfFields <= TLI->getMaxSupportedInterleaveFactor()) {
1413 if (LT.second.isVector() &&
1414 FVTy->getElementCount().isKnownMultipleOf(Factor)) {
1416 FVTy->getElementType(),
1417 FVTy->getElementCount().divideCoefficientBy(Factor));
1418 if (TLI->isLegalInterleavedAccessType(SubVecTy, NumOfFields, Alignment,
1421 unsigned NumAccesses = getEstimatedVLFor(FVTy);
1430 unsigned VF = FVTy->getNumElements() / Factor;
1437 if (Opcode == Instruction::Load) {
1439 for (
unsigned Index : Indices) {
1443 Mask.resize(VF * Factor, -1);
1446 CostKind, Mask, 0,
nullptr, {});
1447 Cost += ShuffleCost;
1465 UseMaskForCond, UseMaskForGaps);
1467 assert(Opcode == Instruction::Store &&
"Opcode must be a store");
1473 CostKind, Mask, 0,
nullptr, {});
1474 return MemCost + ShuffleCost;
1481 bool IsLoad = MICA.
getID() == Intrinsic::masked_gather ||
1482 MICA.
getID() == Intrinsic::vp_gather;
1483 unsigned Opcode = IsLoad ? Instruction::Load : Instruction::Store;
1491 if ((Opcode == Instruction::Load &&
1493 (Opcode == Instruction::Store &&
1499 if (MICA.
getID() == Intrinsic::vp_gather ||
1500 MICA.
getID() == Intrinsic::vp_scatter) {
1503 if (DataLT.first > 1)
1505 if (PtrLT.first > 1)
1513 unsigned NumLoads = getEstimatedVLFor(&VTy);
1520 unsigned Opcode = MICA.
getID() == Intrinsic::masked_expandload
1522 : Instruction::Store;
1526 bool IsLegal = (Opcode == Instruction::Store &&
1528 (Opcode == Instruction::Load &&
1552 if (Opcode == Instruction::Store)
1553 Opcodes.
append({RISCV::VCOMPRESS_VM});
1555 Opcodes.
append({RISCV::VSETIVLI, RISCV::VIOTA_M, RISCV::VRGATHER_VV});
1557 LT.first * getRISCVInstructionCost(Opcodes, LT.second, CostKind);
1582 unsigned NumLoads = getEstimatedVLFor(&VTy);
1585 uint64_t CacheLineBytes = ST->getCacheLineSize();
1586 if (!CacheLineBytes)
1587 CacheLineBytes = 64;
1590 int64_t Stride = StrideCI->getSExtValue();
1592 if (Stride != std::numeric_limits<int64_t>::min() && Stride != 0) {
1593 uint64_t AbsStride = (uint64_t)std::abs(Stride);
1594 if (AbsStride < CacheLineBytes) {
1595 uint64_t MaxCombines = ST->getMaxVectorCoalesceElts();
1596 if ((CacheLineBytes / AbsStride) >= MaxCombines)
1597 NumLoads =
divideCeil(NumLoads, MaxCombines);
1601 NumLoads =
divideCeil((NumLoads * AbsStride), CacheLineBytes);
1615 for (
auto *Ty : Tys) {
1616 if (!Ty->isVectorTy())
1630 {Intrinsic::floor, MVT::f32, 9},
1631 {Intrinsic::floor, MVT::f64, 9},
1632 {Intrinsic::ceil, MVT::f32, 9},
1633 {Intrinsic::ceil, MVT::f64, 9},
1634 {Intrinsic::trunc, MVT::f32, 7},
1635 {Intrinsic::trunc, MVT::f64, 7},
1636 {Intrinsic::round, MVT::f32, 9},
1637 {Intrinsic::round, MVT::f64, 9},
1638 {Intrinsic::roundeven, MVT::f32, 9},
1639 {Intrinsic::roundeven, MVT::f64, 9},
1640 {Intrinsic::rint, MVT::f32, 7},
1641 {Intrinsic::rint, MVT::f64, 7},
1642 {Intrinsic::nearbyint, MVT::f32, 9},
1643 {Intrinsic::nearbyint, MVT::f64, 9},
1644 {Intrinsic::bswap, MVT::i16, 3},
1645 {Intrinsic::bswap, MVT::i32, 12},
1646 {Intrinsic::bswap, MVT::i64, 31},
1647 {Intrinsic::bitreverse, MVT::i8, 17},
1648 {Intrinsic::bitreverse, MVT::i16, 24},
1649 {Intrinsic::bitreverse, MVT::i32, 33},
1650 {Intrinsic::bitreverse, MVT::i64, 52},
1651 {Intrinsic::ctpop, MVT::i8, 12},
1652 {Intrinsic::ctpop, MVT::i16, 19},
1653 {Intrinsic::ctpop, MVT::i32, 20},
1654 {Intrinsic::ctpop, MVT::i64, 21},
1655 {Intrinsic::ctlz, MVT::i8, 19},
1656 {Intrinsic::ctlz, MVT::i16, 28},
1657 {Intrinsic::ctlz, MVT::i32, 31},
1658 {Intrinsic::ctlz, MVT::i64, 35},
1659 {Intrinsic::cttz, MVT::i8, 16},
1660 {Intrinsic::cttz, MVT::i16, 23},
1661 {Intrinsic::cttz, MVT::i32, 24},
1662 {Intrinsic::cttz, MVT::i64, 25},
1669 switch (ICA.
getID()) {
1670 case Intrinsic::lrint:
1671 case Intrinsic::llrint:
1672 case Intrinsic::lround:
1673 case Intrinsic::llround: {
1677 if (ST->hasVInstructions() && LT.second.isVector()) {
1679 unsigned SrcEltSz =
DL.getTypeSizeInBits(SrcTy->getScalarType());
1680 unsigned DstEltSz =
DL.getTypeSizeInBits(RetTy->getScalarType());
1681 if (LT.second.getVectorElementType() == MVT::bf16) {
1682 if (!ST->hasVInstructionsBF16Minimal())
1685 Ops = {RISCV::VFWCVTBF16_F_F_V, RISCV::VFCVT_X_F_V};
1687 Ops = {RISCV::VFWCVTBF16_F_F_V, RISCV::VFWCVT_X_F_V};
1688 }
else if (LT.second.getVectorElementType() == MVT::f16 &&
1689 !ST->hasVInstructionsF16()) {
1690 if (!ST->hasVInstructionsF16Minimal())
1693 Ops = {RISCV::VFWCVT_F_F_V, RISCV::VFCVT_X_F_V};
1695 Ops = {RISCV::VFWCVT_F_F_V, RISCV::VFWCVT_X_F_V};
1697 }
else if (SrcEltSz > DstEltSz) {
1698 Ops = {RISCV::VFNCVT_X_F_W};
1699 }
else if (SrcEltSz < DstEltSz) {
1700 Ops = {RISCV::VFWCVT_X_F_V};
1702 Ops = {RISCV::VFCVT_X_F_V};
1707 if (SrcEltSz > DstEltSz)
1708 return SrcLT.first *
1709 getRISCVInstructionCost(
Ops, SrcLT.second, CostKind);
1710 return LT.first * getRISCVInstructionCost(
Ops, LT.second, CostKind);
1714 case Intrinsic::ceil:
1715 case Intrinsic::floor:
1716 case Intrinsic::trunc:
1717 case Intrinsic::rint:
1718 case Intrinsic::round:
1719 case Intrinsic::roundeven: {
1722 if (!LT.second.isVector() && TLI->isOperationCustom(
ISD::FCEIL, LT.second))
1723 return LT.first * 8;
1726 case Intrinsic::umin:
1727 case Intrinsic::umax:
1728 case Intrinsic::smin:
1729 case Intrinsic::smax: {
1731 if (LT.second.isScalarInteger() && ST->hasStdExtZbb())
1734 if (ST->hasVInstructions() && LT.second.isVector()) {
1736 switch (ICA.
getID()) {
1737 case Intrinsic::umin:
1738 Op = RISCV::VMINU_VV;
1740 case Intrinsic::umax:
1741 Op = RISCV::VMAXU_VV;
1743 case Intrinsic::smin:
1744 Op = RISCV::VMIN_VV;
1746 case Intrinsic::smax:
1747 Op = RISCV::VMAX_VV;
1750 return LT.first * getRISCVInstructionCost(
Op, LT.second, CostKind);
1754 case Intrinsic::sadd_sat:
1755 case Intrinsic::ssub_sat:
1756 case Intrinsic::uadd_sat:
1757 case Intrinsic::usub_sat: {
1759 if (ST->hasVInstructions() && LT.second.isVector()) {
1761 switch (ICA.
getID()) {
1762 case Intrinsic::sadd_sat:
1763 Op = RISCV::VSADD_VV;
1765 case Intrinsic::ssub_sat:
1766 Op = RISCV::VSSUB_VV;
1768 case Intrinsic::uadd_sat:
1769 Op = RISCV::VSADDU_VV;
1771 case Intrinsic::usub_sat:
1772 Op = RISCV::VSSUBU_VV;
1775 return LT.first * getRISCVInstructionCost(
Op, LT.second, CostKind);
1779 case Intrinsic::fma:
1780 case Intrinsic::fmuladd: {
1783 if (ST->hasVInstructions() && LT.second.isVector())
1785 getRISCVInstructionCost(RISCV::VFMADD_VV, LT.second, CostKind);
1788 case Intrinsic::fabs: {
1790 if (ST->hasVInstructions() && LT.second.isVector()) {
1796 if (LT.second.getVectorElementType() == MVT::bf16 ||
1797 (LT.second.getVectorElementType() == MVT::f16 &&
1798 !ST->hasVInstructionsF16()))
1799 return LT.first * getRISCVInstructionCost(RISCV::VAND_VX, LT.second,
1804 getRISCVInstructionCost(RISCV::VFSGNJX_VV, LT.second, CostKind);
1808 case Intrinsic::sqrt: {
1810 if (ST->hasVInstructions() && LT.second.isVector()) {
1813 MVT ConvType = LT.second;
1814 MVT FsqrtType = LT.second;
1817 if (LT.second.getVectorElementType() == MVT::bf16) {
1818 if (LT.second == MVT::nxv32bf16) {
1819 ConvOp = {RISCV::VFWCVTBF16_F_F_V, RISCV::VFWCVTBF16_F_F_V,
1820 RISCV::VFNCVTBF16_F_F_W, RISCV::VFNCVTBF16_F_F_W};
1821 FsqrtOp = {RISCV::VFSQRT_V, RISCV::VFSQRT_V};
1822 ConvType = MVT::nxv16f16;
1823 FsqrtType = MVT::nxv16f32;
1825 ConvOp = {RISCV::VFWCVTBF16_F_F_V, RISCV::VFNCVTBF16_F_F_W};
1826 FsqrtOp = {RISCV::VFSQRT_V};
1827 FsqrtType = TLI->getTypeToPromoteTo(
ISD::FSQRT, FsqrtType);
1829 }
else if (LT.second.getVectorElementType() == MVT::f16 &&
1830 !ST->hasVInstructionsF16()) {
1831 if (LT.second == MVT::nxv32f16) {
1832 ConvOp = {RISCV::VFWCVT_F_F_V, RISCV::VFWCVT_F_F_V,
1833 RISCV::VFNCVT_F_F_W, RISCV::VFNCVT_F_F_W};
1834 FsqrtOp = {RISCV::VFSQRT_V, RISCV::VFSQRT_V};
1835 ConvType = MVT::nxv16f16;
1836 FsqrtType = MVT::nxv16f32;
1838 ConvOp = {RISCV::VFWCVT_F_F_V, RISCV::VFNCVT_F_F_W};
1839 FsqrtOp = {RISCV::VFSQRT_V};
1840 FsqrtType = TLI->getTypeToPromoteTo(
ISD::FSQRT, FsqrtType);
1843 FsqrtOp = {RISCV::VFSQRT_V};
1846 return LT.first * (getRISCVInstructionCost(FsqrtOp, FsqrtType, CostKind) +
1847 getRISCVInstructionCost(ConvOp, ConvType, CostKind));
1851 case Intrinsic::cttz:
1852 case Intrinsic::ctlz:
1853 case Intrinsic::ctpop: {
1855 if (ST->hasStdExtZvbb() && LT.second.isVector()) {
1857 switch (ICA.
getID()) {
1858 case Intrinsic::cttz:
1861 case Intrinsic::ctlz:
1864 case Intrinsic::ctpop:
1865 Op = RISCV::VCPOP_V;
1868 return LT.first * getRISCVInstructionCost(
Op, LT.second, CostKind);
1872 case Intrinsic::abs: {
1874 if (ST->hasVInstructions() && LT.second.isVector()) {
1876 if (ST->hasStdExtZvabd())
1878 getRISCVInstructionCost({RISCV::VABD_VX}, LT.second, CostKind);
1883 getRISCVInstructionCost({RISCV::VRSUB_VI, RISCV::VMAX_VV},
1884 LT.second, CostKind);
1888 case Intrinsic::fshl:
1889 case Intrinsic::fshr: {
1896 if ((ST->hasStdExtZbb() || ST->hasStdExtZbkb()) && RetTy->isIntegerTy() &&
1898 (RetTy->getIntegerBitWidth() == 32 ||
1899 RetTy->getIntegerBitWidth() == 64) &&
1900 RetTy->getIntegerBitWidth() <= ST->getXLen()) {
1905 case Intrinsic::clmul: {
1907 if (!LT.second.isVector() && ST->hasStdExtZvbc() && !ST->hasStdExtZbkc()) {
1910 if (!ST->is64Bit() || LT.second != MVT::i64)
1916 return LT.first * getRISCVInstructionCost(
1917 {RISCV::VMV_S_X, RISCV::VCLMUL_VX, RISCV::VMV_X_S},
1922 case Intrinsic::masked_udiv:
1925 case Intrinsic::masked_sdiv:
1928 case Intrinsic::masked_urem:
1931 case Intrinsic::masked_srem:
1934 case Intrinsic::get_active_lane_mask: {
1935 if (ST->hasVInstructions()) {
1944 getRISCVInstructionCost({RISCV::VSADDU_VX, RISCV::VMSLTU_VX},
1945 LT.second, CostKind);
1950 case Intrinsic::stepvector: {
1954 if (ST->hasVInstructions())
1955 return getRISCVInstructionCost(RISCV::VID_V, LT.second, CostKind) +
1957 getRISCVInstructionCost(RISCV::VADD_VX, LT.second, CostKind);
1958 return 1 + (LT.first - 1);
1960 case Intrinsic::vector_splice_left:
1961 case Intrinsic::vector_splice_right: {
1966 if (ST->hasVInstructions() && LT.second.isVector()) {
1968 getRISCVInstructionCost({RISCV::VSLIDEDOWN_VX, RISCV::VSLIDEUP_VX},
1969 LT.second, CostKind);
1973 case Intrinsic::experimental_cttz_elts: {
1974 if (!ST->hasVInstructions())
1979 if (!LT.second.isVector())
1983 if (LT.second.getVectorElementType() != MVT::i1)
1984 Cost += getRISCVInstructionCost(RISCV::VMSNE_VI, LT.second, CostKind);
1986 Cost += getRISCVInstructionCost(RISCV::VFIRST_M, LT.second, CostKind);
1998 return LT.first *
Cost;
2000 case Intrinsic::experimental_vp_splice: {
2008 case Intrinsic::vp_merge: {
2016 case Intrinsic::fptoui_sat:
2017 case Intrinsic::fptosi_sat: {
2019 bool IsSigned = ICA.
getID() == Intrinsic::fptosi_sat;
2024 if (!SrcTy->isVectorTy())
2027 if (!SrcLT.first.isValid() || !DstLT.first.isValid())
2044 case Intrinsic::experimental_vector_extract_last_active: {
2066 unsigned EltWidth = getTLI()->getBitWidthForCttzElements(
2067 TLI->getVectorIdxTy(
getDataLayout()), MaskTy->getElementCount(),
2068 true, &VScaleRange);
2069 EltWidth = std::max(EltWidth, MaskTy->getScalarSizeInBits());
2077 if (StepLT.first > 1)
2081 unsigned Opcodes[] = {RISCV::VID_V, RISCV::VREDMAXU_VS, RISCV::VMV_X_S};
2083 Cost += MaskLT.first *
2084 getRISCVInstructionCost(RISCV::VCPOP_M, MaskLT.second, CostKind);
2086 Cost += StepLT.first *
2087 getRISCVInstructionCost(Opcodes, StepLT.second, CostKind);
2091 Cost += ValLT.first *
2092 getRISCVInstructionCost({RISCV::VSLIDEDOWN_VI, RISCV::VMV_X_S},
2093 ValLT.second, CostKind);
2096 case Intrinsic::vector_interleave2:
2097 case Intrinsic::vector_deinterleave2: {
2098 if (!ST->hasStdExtZvzip())
2101 bool IsInterleave = ICA.
getID() == Intrinsic::vector_interleave2;
2102 Type *InterleavedTy = IsInterleave ? RetTy : ICA.
getArgTypes().front();
2106 [](
const Value *Arg) { return isa<UndefValue>(Arg); }))
2113 unsigned HalfVF = HalfFVT->getNumElements();
2118 for (
unsigned Start = 0; Start != 2; ++Start)
2125 if (!LT.second.isScalableVector())
2128 if (
MVT CostVT = getZvzipVZIPCostVT(LT.second); CostVT.
isValid())
2130 getRISCVInstructionCost(RISCV::VZIP_VV, CostVT, CostKind);
2131 }
else if (
MVT CostVT = getZvzipVUNZIPCostVT(LT.second); CostVT.
isValid()) {
2133 getRISCVInstructionCost({RISCV::VUNZIPE_V, RISCV::VUNZIPO_V},
2140 if (ST->hasVInstructions() && RetTy->isVectorTy()) {
2142 LT.second.isVector()) {
2143 MVT EltTy = LT.second.getVectorElementType();
2145 ICA.
getID(), EltTy))
2146 return LT.first * Entry->Cost;
2159 if (ST->hasVInstructions() && PtrTy->
isVectorTy())
2177 if (ST->hasStdExtP() &&
2185 if (!ST->hasVInstructions() || Src->getScalarSizeInBits() > ST->getELen() ||
2186 Dst->getScalarSizeInBits() > ST->getELen())
2189 int ISD = TLI->InstructionOpcodeToISD(Opcode);
2204 if (Src->getScalarSizeInBits() == 1) {
2209 return getRISCVInstructionCost(RISCV::VMV_V_I, DstLT.second, CostKind) +
2210 DstLT.first * getRISCVInstructionCost(RISCV::VMERGE_VIM,
2211 DstLT.second, CostKind) +
2216 if (Dst->getScalarSizeInBits() == 1) {
2222 return SrcLT.first *
2223 getRISCVInstructionCost({RISCV::VAND_VI, RISCV::VMSNE_VI},
2224 SrcLT.second, CostKind) +
2235 if (!SrcLT.second.isVector() || !DstLT.second.isVector() ||
2236 !SrcLT.first.isValid() || !DstLT.first.isValid() ||
2238 SrcLT.second.getSizeInBits()) ||
2240 DstLT.second.getSizeInBits()) ||
2241 SrcLT.first > 1 || DstLT.first > 1)
2245 assert((SrcLT.first == 1) && (DstLT.first == 1) &&
"Illegal type");
2247 int PowDiff = (int)
Log2_32(DstLT.second.getScalarSizeInBits()) -
2248 (int)
Log2_32(SrcLT.second.getScalarSizeInBits());
2252 if ((PowDiff < 1) || (PowDiff > 3))
2254 unsigned SExtOp[] = {RISCV::VSEXT_VF2, RISCV::VSEXT_VF4, RISCV::VSEXT_VF8};
2255 unsigned ZExtOp[] = {RISCV::VZEXT_VF2, RISCV::VZEXT_VF4, RISCV::VZEXT_VF8};
2258 return getRISCVInstructionCost(
Op, DstLT.second, CostKind);
2264 unsigned SrcEltSize = SrcLT.second.getScalarSizeInBits();
2265 unsigned DstEltSize = DstLT.second.getScalarSizeInBits();
2269 : RISCV::VFNCVT_F_F_W;
2271 for (; SrcEltSize != DstEltSize;) {
2275 MVT DstMVT = DstLT.second.changeVectorElementType(ElementMVT);
2277 (DstEltSize > SrcEltSize) ? DstEltSize >> 1 : DstEltSize << 1;
2278 Cost += getRISCVInstructionCost(
Op, DstMVT, CostKind);
2285 unsigned FCVT = IsSigned ? RISCV::VFCVT_RTZ_X_F_V : RISCV::VFCVT_RTZ_XU_F_V;
2287 IsSigned ? RISCV::VFWCVT_RTZ_X_F_V : RISCV::VFWCVT_RTZ_XU_F_V;
2289 IsSigned ? RISCV::VFNCVT_RTZ_X_F_W : RISCV::VFNCVT_RTZ_XU_F_W;
2290 unsigned SrcEltSize = Src->getScalarSizeInBits();
2291 unsigned DstEltSize = Dst->getScalarSizeInBits();
2293 if ((SrcEltSize == 16) &&
2294 (!ST->hasVInstructionsF16() || ((DstEltSize / 2) > SrcEltSize))) {
2300 std::pair<InstructionCost, MVT> VecF32LT =
2303 VecF32LT.first * getRISCVInstructionCost(RISCV::VFWCVT_F_F_V,
2304 VecF32LT.second, CostKind);
2308 if (DstEltSize == SrcEltSize)
2309 Cost += getRISCVInstructionCost(FCVT, DstLT.second, CostKind);
2310 else if (DstEltSize > SrcEltSize)
2311 Cost += getRISCVInstructionCost(FWCVT, DstLT.second, CostKind);
2316 MVT VecVT = DstLT.second.changeVectorElementType(ElementVT);
2317 Cost += getRISCVInstructionCost(FNCVT, VecVT, CostKind);
2318 if ((SrcEltSize / 2) > DstEltSize) {
2329 unsigned FCVT = IsSigned ? RISCV::VFCVT_F_X_V : RISCV::VFCVT_F_XU_V;
2330 unsigned FWCVT = IsSigned ? RISCV::VFWCVT_F_X_V : RISCV::VFWCVT_F_XU_V;
2331 unsigned FNCVT = IsSigned ? RISCV::VFNCVT_F_X_W : RISCV::VFNCVT_F_XU_W;
2332 unsigned SrcEltSize = Src->getScalarSizeInBits();
2333 unsigned DstEltSize = Dst->getScalarSizeInBits();
2336 if ((DstEltSize == 16) &&
2337 (!ST->hasVInstructionsF16() || ((SrcEltSize / 2) > DstEltSize))) {
2343 std::pair<InstructionCost, MVT> VecF32LT =
2346 Cost += VecF32LT.first * getRISCVInstructionCost(RISCV::VFNCVT_F_F_W,
2347 DstLT.second, CostKind);
2351 if (DstEltSize == SrcEltSize)
2352 Cost += getRISCVInstructionCost(FCVT, DstLT.second, CostKind);
2353 else if (DstEltSize > SrcEltSize) {
2354 if ((DstEltSize / 2) > SrcEltSize) {
2358 unsigned Op = IsSigned ? Instruction::SExt : Instruction::ZExt;
2361 Cost += getRISCVInstructionCost(FWCVT, DstLT.second, CostKind);
2363 Cost += getRISCVInstructionCost(FNCVT, DstLT.second, CostKind);
2370unsigned RISCVTTIImpl::getEstimatedVLFor(
VectorType *Ty)
const {
2372 const unsigned EltSize =
DL.getTypeSizeInBits(Ty->getElementType());
2373 const unsigned MinSize =
DL.getTypeSizeInBits(Ty).getKnownMinValue();
2388 if (Ty->getScalarSizeInBits() > ST->getELen())
2392 if (Ty->getElementType()->isIntegerTy(1)) {
2396 if (IID == Intrinsic::umax || IID == Intrinsic::smin)
2402 if (IID == Intrinsic::maximum || IID == Intrinsic::minimum) {
2406 case Intrinsic::maximum:
2408 Opcodes = {RISCV::VFREDMAX_VS, RISCV::VFMV_F_S};
2410 Opcodes = {RISCV::VMFNE_VV, RISCV::VCPOP_M, RISCV::VFREDMAX_VS,
2415 Type *DstTy = Ty->getScalarType();
2425 case Intrinsic::minimum:
2427 Opcodes = {RISCV::VFREDMIN_VS, RISCV::VFMV_F_S};
2429 Opcodes = {RISCV::VMFNE_VV, RISCV::VCPOP_M, RISCV::VFREDMIN_VS,
2434 Type *DstTy = Ty->getScalarType();
2435 const unsigned EltTyBits =
DL.getTypeSizeInBits(DstTy);
2444 return ExtraCost + getRISCVInstructionCost(Opcodes, LT.second, CostKind);
2453 case Intrinsic::smax:
2454 SplitOp = RISCV::VMAX_VV;
2455 Opcodes = {RISCV::VREDMAX_VS, RISCV::VMV_X_S};
2457 case Intrinsic::smin:
2458 SplitOp = RISCV::VMIN_VV;
2459 Opcodes = {RISCV::VREDMIN_VS, RISCV::VMV_X_S};
2461 case Intrinsic::umax:
2462 SplitOp = RISCV::VMAXU_VV;
2463 Opcodes = {RISCV::VREDMAXU_VS, RISCV::VMV_X_S};
2465 case Intrinsic::umin:
2466 SplitOp = RISCV::VMINU_VV;
2467 Opcodes = {RISCV::VREDMINU_VS, RISCV::VMV_X_S};
2469 case Intrinsic::maxnum:
2470 SplitOp = RISCV::VFMAX_VV;
2471 Opcodes = {RISCV::VFREDMAX_VS, RISCV::VFMV_F_S};
2473 case Intrinsic::minnum:
2474 SplitOp = RISCV::VFMIN_VV;
2475 Opcodes = {RISCV::VFREDMIN_VS, RISCV::VFMV_F_S};
2480 (LT.first > 1) ? (LT.first - 1) *
2481 getRISCVInstructionCost(SplitOp, LT.second, CostKind)
2483 return SplitCost + getRISCVInstructionCost(Opcodes, LT.second, CostKind);
2488 std::optional<FastMathFlags> FMF,
2494 if (Ty->getScalarSizeInBits() > ST->getELen())
2497 int ISD = TLI->InstructionOpcodeToISD(Opcode);
2505 Type *ElementTy = Ty->getElementType();
2510 if (LT.second == MVT::v1i1)
2511 return getRISCVInstructionCost(RISCV::VFIRST_M, LT.second, CostKind) +
2529 return ((LT.first > 2) ? (LT.first - 2) : 0) *
2530 getRISCVInstructionCost(RISCV::VMAND_MM, LT.second, CostKind) +
2531 getRISCVInstructionCost(RISCV::VMNAND_MM, LT.second, CostKind) +
2532 getRISCVInstructionCost(RISCV::VCPOP_M, LT.second, CostKind) +
2541 return (LT.first - 1) *
2542 getRISCVInstructionCost(RISCV::VMXOR_MM, LT.second, CostKind) +
2543 getRISCVInstructionCost(RISCV::VCPOP_M, LT.second, CostKind) + 1;
2551 return (LT.first - 1) *
2552 getRISCVInstructionCost(RISCV::VMOR_MM, LT.second, CostKind) +
2553 getRISCVInstructionCost(RISCV::VCPOP_M, LT.second, CostKind) +
2566 SplitOp = RISCV::VADD_VV;
2567 Opcodes = {RISCV::VMV_S_X, RISCV::VREDSUM_VS, RISCV::VMV_X_S};
2570 SplitOp = RISCV::VOR_VV;
2571 Opcodes = {RISCV::VREDOR_VS, RISCV::VMV_X_S};
2574 SplitOp = RISCV::VXOR_VV;
2575 Opcodes = {RISCV::VMV_S_X, RISCV::VREDXOR_VS, RISCV::VMV_X_S};
2578 SplitOp = RISCV::VAND_VV;
2579 Opcodes = {RISCV::VREDAND_VS, RISCV::VMV_X_S};
2583 if ((LT.second.getScalarType() == MVT::f16 && !ST->hasVInstructionsF16()) ||
2584 LT.second.getScalarType() == MVT::bf16)
2588 for (
unsigned i = 0; i < LT.first.getValue(); i++)
2591 return getRISCVInstructionCost(Opcodes, LT.second, CostKind);
2593 SplitOp = RISCV::VFADD_VV;
2594 Opcodes = {RISCV::VFMV_S_F, RISCV::VFREDUSUM_VS, RISCV::VFMV_F_S};
2599 (LT.first > 1) ? (LT.first - 1) *
2600 getRISCVInstructionCost(SplitOp, LT.second, CostKind)
2602 return SplitCost + getRISCVInstructionCost(Opcodes, LT.second, CostKind);
2606 unsigned Opcode,
bool IsUnsigned,
Type *ResTy,
VectorType *ValTy,
2617 if (Opcode != Instruction::Add && Opcode != Instruction::FAdd)
2623 if (IsUnsigned && Opcode == Instruction::Add &&
2624 LT.second.isFixedLengthVectorOf(MVT::i1)) {
2628 getRISCVInstructionCost(RISCV::VCPOP_M, LT.second, CostKind);
2635 return (LT.first - 1) +
2642 assert(OpInfo.isConstant() &&
"non constant operand?");
2649 if (OpInfo.isUniform())
2655 return getConstantPoolLoadCost(Ty, CostKind);
2664 EVT VT = TLI->getValueType(
DL, Src,
true);
2666 if (VT == MVT::Other ||
2669 CostKind, OpInfo,
I);
2672 if (Opcode == Instruction::Store && OpInfo.isConstant())
2687 if (Src->
isVectorTy() && LT.second.isVector() &&
2689 LT.second.getSizeInBits()))
2693 CostKind, OpInfo,
I);
2699 if (ST->hasVInstructions() && LT.second.isVector() &&
2701 BaseCost *= TLI->getLMULCost(LT.second);
2702 return Cost + BaseCost;
2711 Op1Info, Op2Info,
I);
2715 Op1Info, Op2Info,
I);
2720 Op1Info, Op2Info,
I);
2722 auto GetConstantMatCost =
2724 if (OpInfo.isUniform())
2729 return getConstantPoolLoadCost(ValTy, CostKind);
2734 ConstantMatCost += GetConstantMatCost(Op1Info);
2736 ConstantMatCost += GetConstantMatCost(Op2Info);
2739 if (Opcode == Instruction::Select && LT.second.isVector()) {
2740 if (CondTy->isVectorTy()) {
2745 return ConstantMatCost +
2747 getRISCVInstructionCost(
2748 {RISCV::VMANDN_MM, RISCV::VMAND_MM, RISCV::VMOR_MM},
2749 LT.second, CostKind);
2752 return ConstantMatCost +
2753 LT.first * getRISCVInstructionCost(RISCV::VMERGE_VVM, LT.second,
2763 MVT InterimVT = LT.second.changeVectorElementType(MVT::i8);
2764 return ConstantMatCost +
2766 getRISCVInstructionCost({RISCV::VMV_V_X, RISCV::VMSNE_VI},
2767 InterimVT, CostKind) +
2768 LT.first * getRISCVInstructionCost(
2769 {RISCV::VMANDN_MM, RISCV::VMAND_MM, RISCV::VMOR_MM},
2770 LT.second, CostKind);
2776 return ConstantMatCost +
2777 LT.first * getRISCVInstructionCost(
2778 {RISCV::VMV_V_X, RISCV::VMSNE_VI, RISCV::VMERGE_VVM},
2779 LT.second, CostKind);
2782 if ((Opcode == Instruction::ICmp) && ValTy->
isVectorTy() &&
2786 return ConstantMatCost + LT.first * getRISCVInstructionCost(RISCV::VMSLT_VV,
2791 if ((Opcode == Instruction::FCmp) && ValTy->
isVectorTy() &&
2796 return ConstantMatCost +
2797 getRISCVInstructionCost(RISCV::VMXOR_MM, LT.second, CostKind);
2807 Op1Info, Op2Info,
I);
2816 return ConstantMatCost +
2817 LT.first * getRISCVInstructionCost(
2818 {RISCV::VMFLT_VV, RISCV::VMFLT_VV, RISCV::VMOR_MM},
2819 LT.second, CostKind);
2825 return ConstantMatCost +
2827 getRISCVInstructionCost({RISCV::VMFLT_VV, RISCV::VMNAND_MM},
2828 LT.second, CostKind);
2836 return ConstantMatCost +
2838 getRISCVInstructionCost(RISCV::VMFLT_VV, LT.second, CostKind);
2851 return match(U, m_Select(m_Specific(I), m_Value(), m_Value())) &&
2852 U->getType()->isIntegerTy() &&
2853 !isa<ConstantData>(U->getOperand(1)) &&
2854 !isa<ConstantData>(U->getOperand(2));
2862 Op1Info, Op2Info,
I);
2869 return Opcode == Instruction::PHI ? 0 : 1;
2886 if (Opcode != Instruction::ExtractElement &&
2887 Opcode != Instruction::InsertElement)
2893 if (Opcode == Instruction::InsertElement &&
2894 VIC == TTI::VectorInstrContext::SplatOpFolded &&
2895 ST->sinkSplatOperands() && Index == 0)
2902 if (!LT.second.isVector()) {
2912 auto NumElems = FixedVecTy->getNumElements();
2918 return Opcode == Instruction::ExtractElement
2919 ? StoreCost * NumElems + LoadCost
2920 : (StoreCost + LoadCost) * NumElems + StoreCost;
2924 if (LT.second.isScalableVector() && !LT.first.isValid())
2932 if (Opcode == Instruction::ExtractElement) {
2938 return ExtendCost + ExtractCost;
2948 return ExtendCost + InsertCost + TruncCost;
2955 if (LT.second.isFloatingPoint())
2956 MoveOpc = Opcode == Instruction::InsertElement ? RISCV::VFMV_S_F
2960 Opcode == Instruction::InsertElement ? RISCV::VMV_S_X : RISCV::VMV_X_S;
2962 getRISCVInstructionCost(MoveOpc, LT.second, CostKind);
2964 InstructionCost SlideCost = Opcode == Instruction::InsertElement ? 2 : 1;
2969 if (LT.second.isFixedLengthVector()) {
2970 unsigned Width = LT.second.getVectorNumElements();
2971 Index = Index % Width;
2976 if (
auto VLEN = ST->getRealVLen()) {
2977 unsigned EltSize = LT.second.getScalarSizeInBits();
2978 unsigned M1Max = *VLEN / EltSize;
2979 Index = Index % M1Max;
2985 else if (Opcode == Instruction::InsertElement)
2993 ((Index == -1U) || (Index >= LT.second.getVectorMinNumElements() &&
2994 LT.second.isScalableVector()))) {
2996 Align VecAlign =
DL.getPrefTypeAlign(Val);
2997 Align SclAlign =
DL.getPrefTypeAlign(ScalarType);
3002 if (Opcode == Instruction::ExtractElement)
3003 return getMemoryOpCost(Instruction::Store, Val, VecAlign, 0, CostKind) +
3010 return getMemoryOpCost(Instruction::Store, Val, VecAlign, 0, CostKind) +
3038 Opcode == Instruction::InsertElement
3039 ? getRISCVInstructionCost({RISCV::VSLIDE1DOWN_VX,
3040 RISCV::VSLIDE1DOWN_VX,
3041 RISCV::VSLIDEUP_VX},
3042 LT.second, CostKind)
3043 : getRISCVInstructionCost({RISCV::VSLIDEDOWN_VX, RISCV::VMV_X_S,
3044 RISCV::VSRL_VX, RISCV::VMV_X_S},
3045 LT.second, CostKind);
3047 return BaseCost + SlideCost;
3053 unsigned Index)
const {
3062 assert(Index < EC.getKnownMinValue() &&
"Unexpected reverse index");
3064 EC.getKnownMinValue() - 1 - Index,
nullptr,
3073std::optional<InstructionCost>
3079 if ((Opcode == Instruction::UDiv || Opcode == Instruction::URem) &&
3081 if (Opcode == Instruction::UDiv)
3088 return std::nullopt;
3110 if (std::optional<InstructionCost> CombinedCost =
3112 Op2Info, Args, CtxI))
3113 return *CombinedCost;
3117 unsigned ISDOpcode = TLI->InstructionOpcodeToISD(Opcode);
3120 if (!LT.second.isVector()) {
3121 if (ISDOpcode ==
ISD::MUL && !ST->hasStdExtZmmul())
3133 if (TLI->isOperationLegalOrPromote(ISDOpcode, LT.second))
3134 if (
const auto *Entry =
CostTableLookup(DivTbl, ISDOpcode, LT.second))
3135 return Entry->Cost * LT.first;
3144 if ((LT.second.getVectorElementType() == MVT::f16 ||
3145 LT.second.getVectorElementType() == MVT::bf16) &&
3146 TLI->getOperationAction(ISDOpcode, LT.second) ==
3148 MVT PromotedVT = TLI->getTypeToPromoteTo(ISDOpcode, LT.second);
3152 CastCost += LT.first * Args.size() *
3160 LT.second = PromotedVT;
3163 auto getConstantMatCost =
3165 if (OpInfo.isUniform() &&
3174 return getConstantPoolLoadCost(Ty, CostKind);
3180 ConstantMatCost += getConstantMatCost(0, Op1Info);
3182 ConstantMatCost += getConstantMatCost(1, Op2Info);
3185 switch (ISDOpcode) {
3188 Op = RISCV::VADD_VV;
3193 Op = RISCV::VSLL_VV;
3198 Op = (Ty->getScalarSizeInBits() == 1) ? RISCV::VMAND_MM : RISCV::VAND_VV;
3203 Op = RISCV::VMUL_VV;
3207 Op = RISCV::VDIV_VV;
3211 Op = RISCV::VREM_VV;
3215 Op = RISCV::VFADD_VV;
3218 Op = RISCV::VFMUL_VV;
3221 Op = RISCV::VFDIV_VV;
3224 Op = RISCV::VFSGNJN_VV;
3229 return CastCost + ConstantMatCost +
3238 if (Ty->isFPOrFPVectorTy())
3240 return CastCost + ConstantMatCost + LT.first *
InstrCost;
3263 if (Info.isSameBase() && V !=
Base) {
3264 if (
GEP->hasAllConstantIndices())
3270 unsigned Stride =
DL.getTypeStoreSize(AccessTy);
3271 if (Info.isUnitStride() &&
3277 GEP->getType()->getPointerAddressSpace()))
3280 {TTI::OK_AnyValue, TTI::OP_None},
3281 {TTI::OK_AnyValue, TTI::OP_None}, {});
3285 Indices, CostKind, AccessTy);
3298 if (ST->enableDefaultUnroll())
3308 if (L->getHeader()->getParent()->hasOptSize())
3312 L->getExitingBlocks(ExitingBlocks);
3314 <<
"Blocks: " << L->getNumBlocks() <<
"\n"
3315 <<
"Exit blocks: " << ExitingBlocks.
size() <<
"\n");
3319 if (ExitingBlocks.
size() > 2)
3324 if (L->getNumBlocks() > 4)
3332 for (
auto *BB : L->getBlocks()) {
3333 for (
auto &
I : *BB) {
3337 if (IsVectorized && (
I.getType()->isVectorTy() ||
3339 return V->getType()->isVectorTy();
3378 bool HasMask =
false;
3381 bool IsWrite) -> int64_t {
3382 if (
auto *TarExtTy =
3384 return TarExtTy->getIntParameter(0);
3390 case Intrinsic::riscv_vle_mask:
3391 case Intrinsic::riscv_vse_mask:
3392 case Intrinsic::riscv_vlseg2_mask:
3393 case Intrinsic::riscv_vlseg3_mask:
3394 case Intrinsic::riscv_vlseg4_mask:
3395 case Intrinsic::riscv_vlseg5_mask:
3396 case Intrinsic::riscv_vlseg6_mask:
3397 case Intrinsic::riscv_vlseg7_mask:
3398 case Intrinsic::riscv_vlseg8_mask:
3399 case Intrinsic::riscv_vsseg2_mask:
3400 case Intrinsic::riscv_vsseg3_mask:
3401 case Intrinsic::riscv_vsseg4_mask:
3402 case Intrinsic::riscv_vsseg5_mask:
3403 case Intrinsic::riscv_vsseg6_mask:
3404 case Intrinsic::riscv_vsseg7_mask:
3405 case Intrinsic::riscv_vsseg8_mask:
3408 case Intrinsic::riscv_vle:
3409 case Intrinsic::riscv_vse:
3410 case Intrinsic::riscv_vlseg2:
3411 case Intrinsic::riscv_vlseg3:
3412 case Intrinsic::riscv_vlseg4:
3413 case Intrinsic::riscv_vlseg5:
3414 case Intrinsic::riscv_vlseg6:
3415 case Intrinsic::riscv_vlseg7:
3416 case Intrinsic::riscv_vlseg8:
3417 case Intrinsic::riscv_vsseg2:
3418 case Intrinsic::riscv_vsseg3:
3419 case Intrinsic::riscv_vsseg4:
3420 case Intrinsic::riscv_vsseg5:
3421 case Intrinsic::riscv_vsseg6:
3422 case Intrinsic::riscv_vsseg7:
3423 case Intrinsic::riscv_vsseg8: {
3440 Ty = TarExtTy->getTypeParameter(0U);
3445 const auto *RVVIInfo = RISCVVIntrinsicsTable::getRISCVVIntrinsicInfo(IID);
3446 unsigned VLIndex = RVVIInfo->VLOperand;
3447 unsigned PtrOperandNo = VLIndex - 1 - HasMask;
3455 unsigned SegNum = getSegNum(Inst, PtrOperandNo, IsWrite);
3458 unsigned ElemSize = Ty->getScalarSizeInBits();
3462 Info.InterestingOperands.emplace_back(Inst, PtrOperandNo, IsWrite, Ty,
3463 Alignment, Mask, EVL);
3466 case Intrinsic::riscv_vlse_mask:
3467 case Intrinsic::riscv_vsse_mask:
3468 case Intrinsic::riscv_vlsseg2_mask:
3469 case Intrinsic::riscv_vlsseg3_mask:
3470 case Intrinsic::riscv_vlsseg4_mask:
3471 case Intrinsic::riscv_vlsseg5_mask:
3472 case Intrinsic::riscv_vlsseg6_mask:
3473 case Intrinsic::riscv_vlsseg7_mask:
3474 case Intrinsic::riscv_vlsseg8_mask:
3475 case Intrinsic::riscv_vssseg2_mask:
3476 case Intrinsic::riscv_vssseg3_mask:
3477 case Intrinsic::riscv_vssseg4_mask:
3478 case Intrinsic::riscv_vssseg5_mask:
3479 case Intrinsic::riscv_vssseg6_mask:
3480 case Intrinsic::riscv_vssseg7_mask:
3481 case Intrinsic::riscv_vssseg8_mask:
3484 case Intrinsic::riscv_vlse:
3485 case Intrinsic::riscv_vsse:
3486 case Intrinsic::riscv_vlsseg2:
3487 case Intrinsic::riscv_vlsseg3:
3488 case Intrinsic::riscv_vlsseg4:
3489 case Intrinsic::riscv_vlsseg5:
3490 case Intrinsic::riscv_vlsseg6:
3491 case Intrinsic::riscv_vlsseg7:
3492 case Intrinsic::riscv_vlsseg8:
3493 case Intrinsic::riscv_vssseg2:
3494 case Intrinsic::riscv_vssseg3:
3495 case Intrinsic::riscv_vssseg4:
3496 case Intrinsic::riscv_vssseg5:
3497 case Intrinsic::riscv_vssseg6:
3498 case Intrinsic::riscv_vssseg7:
3499 case Intrinsic::riscv_vssseg8: {
3516 Ty = TarExtTy->getTypeParameter(0U);
3521 const auto *RVVIInfo = RISCVVIntrinsicsTable::getRISCVVIntrinsicInfo(IID);
3522 unsigned VLIndex = RVVIInfo->VLOperand;
3523 unsigned PtrOperandNo = VLIndex - 2 - HasMask;
3532 unsigned PointerAlign = Alignment.valueOrOne().value();
3535 Alignment =
Align(1);
3542 unsigned SegNum = getSegNum(Inst, PtrOperandNo, IsWrite);
3545 unsigned ElemSize = Ty->getScalarSizeInBits();
3549 Info.InterestingOperands.emplace_back(Inst, PtrOperandNo, IsWrite, Ty,
3550 Alignment, Mask, EVL, Stride);
3553 case Intrinsic::riscv_vloxei_mask:
3554 case Intrinsic::riscv_vluxei_mask:
3555 case Intrinsic::riscv_vsoxei_mask:
3556 case Intrinsic::riscv_vsuxei_mask:
3557 case Intrinsic::riscv_vloxseg2_mask:
3558 case Intrinsic::riscv_vloxseg3_mask:
3559 case Intrinsic::riscv_vloxseg4_mask:
3560 case Intrinsic::riscv_vloxseg5_mask:
3561 case Intrinsic::riscv_vloxseg6_mask:
3562 case Intrinsic::riscv_vloxseg7_mask:
3563 case Intrinsic::riscv_vloxseg8_mask:
3564 case Intrinsic::riscv_vluxseg2_mask:
3565 case Intrinsic::riscv_vluxseg3_mask:
3566 case Intrinsic::riscv_vluxseg4_mask:
3567 case Intrinsic::riscv_vluxseg5_mask:
3568 case Intrinsic::riscv_vluxseg6_mask:
3569 case Intrinsic::riscv_vluxseg7_mask:
3570 case Intrinsic::riscv_vluxseg8_mask:
3571 case Intrinsic::riscv_vsoxseg2_mask:
3572 case Intrinsic::riscv_vsoxseg3_mask:
3573 case Intrinsic::riscv_vsoxseg4_mask:
3574 case Intrinsic::riscv_vsoxseg5_mask:
3575 case Intrinsic::riscv_vsoxseg6_mask:
3576 case Intrinsic::riscv_vsoxseg7_mask:
3577 case Intrinsic::riscv_vsoxseg8_mask:
3578 case Intrinsic::riscv_vsuxseg2_mask:
3579 case Intrinsic::riscv_vsuxseg3_mask:
3580 case Intrinsic::riscv_vsuxseg4_mask:
3581 case Intrinsic::riscv_vsuxseg5_mask:
3582 case Intrinsic::riscv_vsuxseg6_mask:
3583 case Intrinsic::riscv_vsuxseg7_mask:
3584 case Intrinsic::riscv_vsuxseg8_mask:
3587 case Intrinsic::riscv_vloxei:
3588 case Intrinsic::riscv_vluxei:
3589 case Intrinsic::riscv_vsoxei:
3590 case Intrinsic::riscv_vsuxei:
3591 case Intrinsic::riscv_vloxseg2:
3592 case Intrinsic::riscv_vloxseg3:
3593 case Intrinsic::riscv_vloxseg4:
3594 case Intrinsic::riscv_vloxseg5:
3595 case Intrinsic::riscv_vloxseg6:
3596 case Intrinsic::riscv_vloxseg7:
3597 case Intrinsic::riscv_vloxseg8:
3598 case Intrinsic::riscv_vluxseg2:
3599 case Intrinsic::riscv_vluxseg3:
3600 case Intrinsic::riscv_vluxseg4:
3601 case Intrinsic::riscv_vluxseg5:
3602 case Intrinsic::riscv_vluxseg6:
3603 case Intrinsic::riscv_vluxseg7:
3604 case Intrinsic::riscv_vluxseg8:
3605 case Intrinsic::riscv_vsoxseg2:
3606 case Intrinsic::riscv_vsoxseg3:
3607 case Intrinsic::riscv_vsoxseg4:
3608 case Intrinsic::riscv_vsoxseg5:
3609 case Intrinsic::riscv_vsoxseg6:
3610 case Intrinsic::riscv_vsoxseg7:
3611 case Intrinsic::riscv_vsoxseg8:
3612 case Intrinsic::riscv_vsuxseg2:
3613 case Intrinsic::riscv_vsuxseg3:
3614 case Intrinsic::riscv_vsuxseg4:
3615 case Intrinsic::riscv_vsuxseg5:
3616 case Intrinsic::riscv_vsuxseg6:
3617 case Intrinsic::riscv_vsuxseg7:
3618 case Intrinsic::riscv_vsuxseg8: {
3635 Ty = TarExtTy->getTypeParameter(0U);
3640 const auto *RVVIInfo = RISCVVIntrinsicsTable::getRISCVVIntrinsicInfo(IID);
3641 unsigned VLIndex = RVVIInfo->VLOperand;
3642 unsigned PtrOperandNo = VLIndex - 2 - HasMask;
3655 unsigned SegNum = getSegNum(Inst, PtrOperandNo, IsWrite);
3658 unsigned ElemSize = Ty->getScalarSizeInBits();
3663 Info.InterestingOperands.emplace_back(Inst, PtrOperandNo, IsWrite, Ty,
3664 Align(1), Mask, EVL,
3673 if (Ty->isVectorTy()) {
3676 if ((EltTy->
isHalfTy() && !ST->hasVInstructionsF16()) ||
3682 if (
Size.isScalable() && ST->hasVInstructions())
3685 if (ST->useRVVForFixedLengthVectors())
3693 if (std::optional<unsigned> MaxVF = ST->getCLOpts().v_slp_max_vf)
3705 return std::max<unsigned>(1U, RegWidth.
getFixedValue() / ElemWidth);
3709 return ST->getCLOpts().v_min_trip_count;
3713 return ST->enableUnalignedVectorMem();
3719 if (ST->hasVendorXCVmem() && !ST->is64Bit())
3730 unsigned C1NumRegs =
C1.NumRegs + (
C1.NumBaseAdds != 0);
3732 return std::tie(
C1.Insns, C1NumRegs,
C1.AddRecCost,
3733 C1.NumIVMuls,
C1.NumBaseAdds,
3734 C1.ScaleCost,
C1.ImmCost,
C1.SetupCost) <
3741 Align Alignment)
const {
3751 if (VTy->getElementType()->isIntegerTy(8)) {
3752 uint64_t MaxEltCount = VTy->getElementCount().getKnownMinValue();
3753 if (VTy->isScalableTy())
3756 if (MaxEltCount > 256)
3765 Align Alignment)
const {
3772 if (!ST->hasVInstructions() || !ST->hasOptimizedZeroStrideLoad())
3775 return TLI->isLegalElementTypeForRVV(TLI->getValueType(
DL, ElementTy));
3784 const Instruction &
I,
bool &AllowPromotionWithoutCommonHeader)
const {
3785 bool Considerable =
false;
3786 AllowPromotionWithoutCommonHeader =
false;
3789 Type *ConsideredSExtType =
3791 if (
I.getType() != ConsideredSExtType)
3795 for (
const User *U :
I.users()) {
3797 Considerable =
true;
3801 if (GEPInst->getNumOperands() > 2) {
3802 AllowPromotionWithoutCommonHeader =
true;
3807 return Considerable;
3813 case Instruction::Add:
3814 case Instruction::Sub:
3815 case Instruction::Mul:
3816 case Instruction::And:
3817 case Instruction::Or:
3818 case Instruction::Xor:
3819 case Instruction::FAdd:
3820 case Instruction::FSub:
3821 case Instruction::FMul:
3822 case Instruction::FDiv:
3823 case Instruction::ICmp:
3824 case Instruction::FCmp:
3826 case Instruction::Shl:
3827 case Instruction::LShr:
3828 case Instruction::AShr:
3829 case Instruction::UDiv:
3830 case Instruction::SDiv:
3831 case Instruction::URem:
3832 case Instruction::SRem:
3833 case Instruction::Select:
3834 return Operand == 1;
3835 case Instruction::Call:
3836 switch (IntrinsicID) {
3837 case Intrinsic::fma:
3838 case Intrinsic::fmuladd:
3839 return Operand == 0 || Operand == 1;
3840 case Intrinsic::vp_udiv:
3841 case Intrinsic::vp_sdiv:
3842 case Intrinsic::vp_urem:
3843 case Intrinsic::vp_srem:
3844 case Intrinsic::ssub_sat:
3845 case Intrinsic::usub_sat:
3846 return Operand == 1;
3848 case Intrinsic::smin:
3849 case Intrinsic::umin:
3850 case Intrinsic::smax:
3851 case Intrinsic::umax:
3852 case Intrinsic::sadd_sat:
3853 case Intrinsic::uadd_sat:
3854 return Operand == 0 || Operand == 1;
3864 if (!
I->getType()->isVectorTy() || !ST->hasVInstructions())
3870 IntrinsicID =
II->getIntrinsicID();
3878 GatherUseOps)
const {
3879 if (Scalars.
empty() || !ST->hasVInstructions() || !ST->sinkSplatOperands() ||
3884 if (SplatIt == Scalars.
end() || (*SplatIt)->getType()->isIntegerTy(1) ||
3890 if (!GatherUseOps(UserOps) || UserOps.
empty())
3910 if (
I->isBitwiseLogicOp()) {
3911 if (!
I->getType()->isVectorTy()) {
3912 if (ST->hasStdExtZbb() || ST->hasStdExtZbkb()) {
3913 for (
auto &
Op :
I->operands()) {
3921 }
else if (
I->getOpcode() == Instruction::And && ST->hasStdExtZvkb()) {
3922 for (
auto &
Op :
I->operands()) {
3934 Ops.push_back(&Not);
3935 Ops.push_back(&InsertElt);
3943 if (!
I->getType()->isVectorTy() || !ST->hasVInstructions())
3951 if (!ST->sinkSplatOperands())
3954 for (
auto OpIdx :
enumerate(
I->operands())) {
3974 for (
Use &U :
Op->uses()) {
3981 Use *InsertEltUse = &
Op->getOperandUse(0);
3984 Ops.push_back(&InsertElt->getOperandUse(1));
3985 Ops.push_back(InsertEltUse);
3986 Ops.push_back(&OpIdx.value());
3995 if (!ST->hasStdExtZbb() && !ST->hasStdExtZbkb() && !IsZeroCmp)
3998 Options.AllowOverlappingLoads =
true;
3999 Options.MaxNumLoads = TLI->getMaxExpandSizeMemcmp(OptSize);
4001 if (ST->is64Bit()) {
4002 Options.LoadSizes = {8, 4, 2, 1};
4003 Options.AllowedTailExpansions = {3, 5, 6};
4005 Options.LoadSizes = {4, 2, 1};
4006 Options.AllowedTailExpansions = {3};
4009 if (IsZeroCmp && ST->hasVInstructions()) {
4010 unsigned VLenB = ST->getRealMinVLen() / 8;
4013 unsigned MinSize = ST->getXLen() / 8 + 1;
4014 unsigned MaxSize = VLenB * 8;
4023 if (ST->getCLOpts().or_like_select) {
4028 if (
I->getOpcode() == Instruction::Or &&
4032 if (
I->getOpcode() == Instruction::Add ||
4033 I->getOpcode() == Instruction::Sub)
4051std::optional<Instruction *>
4057 if (
is_contained({Intrinsic::riscv_vsetvli, Intrinsic::riscv_vsetvlimax},
4058 II.getIntrinsicID())) {
4061 if (!ST->hasVInstructions())
4064 bool HasAVL =
II.getIntrinsicID() == Intrinsic::riscv_vsetvli;
4065 unsigned Offset = HasAVL ? 1 : 0;
4066 unsigned BitWidth =
II.getType()->getIntegerBitWidth();
4091 Value *AVL =
II.getArgOperand(0);
4120 II.getRange().value_or(ConstantRange::getFull(
BitWidth));
4122 if (NewRange != OldRange) {
4123 II.addRangeRetAttr(NewRange);
4133 if (
II.user_empty())
4138 const APInt *Scalar;
4143 return U->getType() == TargetVecTy && match(U, m_BitCast(m_Value()));
4147 unsigned TargetEltBW =
DL.getTypeSizeInBits(TargetVecTy->getElementType());
4148 unsigned SourceEltBW =
DL.getTypeSizeInBits(SourceVecTy->getElementType());
4149 if (TargetEltBW % SourceEltBW)
4151 unsigned TargetScale = TargetEltBW / SourceEltBW;
4152 if (VL % TargetScale || TargetScale == 1)
4154 Type *VLTy =
II.getOperand(2)->getType();
4155 ElementCount SourceEC = SourceVecTy->getElementCount();
4156 unsigned NewEltBW = SourceEltBW * TargetScale;
4158 !
DL.fitsInLegalInteger(NewEltBW))
4161 if (!TLI->isLegalElementTypeForRVV(TLI->getValueType(
DL, NewEltTy)))
4165 assert(SourceVecTy->canLosslesslyBitCastTo(RetTy) &&
4166 "Lossless bitcast between types expected");
4172 RetTy, Intrinsic::riscv_vmv_v_x,
4173 {PoisonValue::get(RetTy), ConstantInt::get(NewEltTy, NewScalar),
4174 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)
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
SmallVector< MachineOperand, 4 > Cond
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.
int64_t getSExtValue() const
Get sign extended value.
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
@ ICMP_SLE
signed less or equal
@ 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
@ ICMP_SGT
signed 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)
@ ICMP_SGE
signed greater or equal
@ 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
This instruction compares its operands according to the predicate given to the constructor.
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
bool preferLoopExitWithEqualityComparison(const ICmpInst &Cond, const APInt &PostIncExitValue) 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