LLVM 24.0.0git
RISCVTargetTransformInfo.cpp
Go to the documentation of this file.
1//===-- RISCVTargetTransformInfo.cpp - RISC-V specific TTI ----------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8
11#include "llvm/ADT/STLExtras.h"
18#include "llvm/IR/IntrinsicsRISCV.h"
21#include <cmath>
22#include <optional>
23using namespace llvm;
24using namespace llvm::PatternMatch;
25
26#define DEBUG_TYPE "riscvtti"
27
29 "riscv-v-register-bit-width-lmul",
31 "The LMUL to use for getRegisterBitWidth queries. Affects LMUL used "
32 "by autovectorized code. Fractional LMULs are not supported."),
34
36 "riscv-v-slp-max-vf",
38 "Overrides result used for getMaximumVF query which is used "
39 "exclusively by SLP vectorizer."),
41
43 RVVMinTripCount("riscv-v-min-trip-count",
44 cl::desc("Set the lower bound of a trip count to decide on "
45 "vectorization while tail-folding."),
47
48static cl::opt<bool> EnableOrLikeSelectOpt("enable-riscv-or-like-select",
49 cl::init(true), cl::Hidden);
50
52RISCVTTIImpl::getRISCVInstructionCost(ArrayRef<unsigned> OpCodes, MVT VT,
54 // Check if the type is valid for all CostKind
55 if (!VT.isVector())
57 size_t NumInstr = OpCodes.size();
59 return NumInstr;
60 InstructionCost LMULCost = TLI->getLMULCost(VT);
62 return LMULCost * NumInstr;
63 InstructionCost Cost = 0;
64 for (auto Op : OpCodes) {
65 switch (Op) {
66 case RISCV::VRGATHER_VI:
67 Cost += TLI->getVRGatherVICost(VT);
68 break;
69 case RISCV::VRGATHER_VV:
70 Cost += TLI->getVRGatherVVCost(VT);
71 break;
72 case RISCV::VSLIDEUP_VI:
73 case RISCV::VSLIDEDOWN_VI:
74 Cost += TLI->getVSlideVICost(VT);
75 break;
76 case RISCV::VSLIDEUP_VX:
77 case RISCV::VSLIDEDOWN_VX:
78 Cost += TLI->getVSlideVXCost(VT);
79 break;
80 case RISCV::VREDMAX_VS:
81 case RISCV::VREDMIN_VS:
82 case RISCV::VREDMAXU_VS:
83 case RISCV::VREDMINU_VS:
84 case RISCV::VREDSUM_VS:
85 case RISCV::VREDAND_VS:
86 case RISCV::VREDOR_VS:
87 case RISCV::VREDXOR_VS:
88 case RISCV::VFREDMAX_VS:
89 case RISCV::VFREDMIN_VS:
90 case RISCV::VFREDUSUM_VS: {
91 unsigned VL = VT.getVectorMinNumElements();
92 if (!VT.isFixedLengthVector())
93 VL *= *getVScaleForTuning();
94 Cost += Log2_32_Ceil(VL);
95 break;
96 }
97 case RISCV::VFREDOSUM_VS: {
98 unsigned VL = VT.getVectorMinNumElements();
99 if (!VT.isFixedLengthVector())
100 VL *= *getVScaleForTuning();
101 Cost += VL;
102 break;
103 }
104 case RISCV::VMV_X_S:
105 case RISCV::VFMV_F_S:
106 // Domain crossings from vector -> scalar are usually more expensive.
107 Cost += 2;
108 break;
109 case RISCV::VMV_S_X:
110 case RISCV::VFMV_S_F:
111 case RISCV::VMOR_MM:
112 case RISCV::VMXOR_MM:
113 case RISCV::VMAND_MM:
114 case RISCV::VMANDN_MM:
115 case RISCV::VMNAND_MM:
116 case RISCV::VCPOP_M:
117 case RISCV::VFIRST_M:
118 Cost += 1;
119 break;
120 case RISCV::VDIV_VV:
121 case RISCV::VREM_VV:
122 Cost += LMULCost * TTI::TCC_Expensive;
123 break;
124 default:
125 Cost += LMULCost;
126 }
127 }
128 return Cost;
129}
130
132 const RISCVSubtarget *ST,
133 const APInt &Imm, Type *Ty,
135 bool FreeZeroes) {
136 assert(Ty->isIntegerTy() &&
137 "getIntImmCost can only estimate cost of materialising integers");
138
139 // We have a Zero register, so 0 is always free.
140 if (Imm == 0)
141 return TTI::TCC_Free;
142
143 // Otherwise, we check how many instructions it will take to materialise.
144 return RISCVMatInt::getIntMatCost(Imm, DL.getTypeSizeInBits(Ty), *ST,
145 /*CompressionCost=*/false, FreeZeroes);
146}
147
151 return getIntImmCostImpl(getDataLayout(), getST(), Imm, Ty, CostKind, false);
152}
153
154// Look for patterns of shift followed by AND that can be turned into a pair of
155// shifts. We won't need to materialize an immediate for the AND so these can
156// be considered free.
157static bool canUseShiftPair(Instruction *Inst, const APInt &Imm) {
158 uint64_t Mask = Imm.getZExtValue();
159 auto *BO = dyn_cast<BinaryOperator>(Inst->getOperand(0));
160 if (!BO || !BO->hasOneUse())
161 return false;
162
163 if (BO->getOpcode() != Instruction::Shl)
164 return false;
165
166 if (!isa<ConstantInt>(BO->getOperand(1)))
167 return false;
168
169 unsigned ShAmt = cast<ConstantInt>(BO->getOperand(1))->getZExtValue();
170 // (and (shl x, c2), c1) will be matched to (srli (slli x, c2+c3), c3) if c1
171 // is a mask shifted by c2 bits with c3 leading zeros.
172 if (isShiftedMask_64(Mask)) {
173 unsigned Trailing = llvm::countr_zero(Mask);
174 if (ShAmt == Trailing)
175 return true;
176 }
177
178 return false;
179}
180
181// If this is i64 AND is part of (X & -(1 << C1) & 0xffffffff) == C2 << C1),
182// DAGCombiner can convert this to (sraiw X, C1) == sext(C2) for RV64. On RV32,
183// the type will be split so only the lower 32 bits need to be compared using
184// (srai/srli X, C) == C2.
185static bool canUseShiftCmp(Instruction *Inst, const APInt &Imm) {
186 if (!Inst->hasOneUse())
187 return false;
188
189 // Look for equality comparison.
190 auto *Cmp = dyn_cast<ICmpInst>(*Inst->user_begin());
191 if (!Cmp || !Cmp->isEquality())
192 return false;
193
194 // Right hand side of comparison should be a constant.
195 auto *C = dyn_cast<ConstantInt>(Cmp->getOperand(1));
196 if (!C)
197 return false;
198
199 uint64_t Mask = Imm.getZExtValue();
200
201 // Mask should be of the form -(1 << C) in the lower 32 bits.
202 if (!isUInt<32>(Mask) || !isPowerOf2_32(-uint32_t(Mask)))
203 return false;
204
205 // Comparison constant should be a subset of Mask.
206 uint64_t CmpC = C->getZExtValue();
207 if ((CmpC & Mask) != CmpC)
208 return false;
209
210 // We'll need to sign extend the comparison constant and shift it right. Make
211 // sure the new constant can use addi/xori+seqz/snez.
212 unsigned ShiftBits = llvm::countr_zero(Mask);
213 int64_t NewCmpC = SignExtend64<32>(CmpC) >> ShiftBits;
214 return NewCmpC >= -2048 && NewCmpC <= 2048;
215}
216
218 const APInt &Imm, Type *Ty,
220 Instruction *Inst) const {
221 assert(Ty->isIntegerTy() &&
222 "getIntImmCost can only estimate cost of materialising integers");
223
224 // We have a Zero register, so 0 is always free.
225 if (Imm == 0)
226 return TTI::TCC_Free;
227
228 // Some instructions in RISC-V can take a 12-bit immediate. Some of these are
229 // commutative, in others the immediate comes from a specific argument index.
230 bool Takes12BitImm = false;
231 unsigned ImmArgIdx = ~0U;
232
233 switch (Opcode) {
234 case Instruction::GetElementPtr:
235 // Never hoist any arguments to a GetElementPtr. CodeGenPrepare will
236 // split up large offsets in GEP into better parts than ConstantHoisting
237 // can.
238 return TTI::TCC_Free;
239 case Instruction::Store: {
240 // Use the materialization cost regardless of if it's the address or the
241 // value that is constant, except for if the store is misaligned and
242 // misaligned accesses are not legal (experience shows constant hoisting
243 // can sometimes be harmful in such cases).
244 if (Idx == 1 || !Inst)
245 return getIntImmCostImpl(getDataLayout(), getST(), Imm, Ty, CostKind,
246 /*FreeZeroes=*/true);
247
248 StoreInst *ST = cast<StoreInst>(Inst);
249 if (!getTLI()->allowsMemoryAccessForAlignment(
250 Ty->getContext(), DL, getTLI()->getValueType(DL, Ty),
251 ST->getPointerAddressSpace(), ST->getAlign()))
252 return TTI::TCC_Free;
253
254 return getIntImmCostImpl(getDataLayout(), getST(), Imm, Ty, CostKind,
255 /*FreeZeroes=*/true);
256 }
257 case Instruction::Load:
258 // If the address is a constant, use the materialization cost.
259 return getIntImmCost(Imm, Ty, CostKind);
260 case Instruction::And:
261 // zext.h
262 if (Imm == UINT64_C(0xffff) && ST->hasStdExtZbb())
263 return TTI::TCC_Free;
264 // zext.w
265 if (Imm == UINT64_C(0xffffffff) &&
266 ((ST->hasStdExtZba() && ST->isRV64()) || ST->isRV32()))
267 return TTI::TCC_Free;
268 // bclri
269 if (ST->hasStdExtZbs() && (~Imm).isPowerOf2())
270 return TTI::TCC_Free;
271 if (Inst && Idx == 1 && Imm.getBitWidth() <= ST->getXLen() &&
272 canUseShiftPair(Inst, Imm))
273 return TTI::TCC_Free;
274 if (Inst && Idx == 1 && Imm.getBitWidth() == 64 &&
275 canUseShiftCmp(Inst, Imm))
276 return TTI::TCC_Free;
277 Takes12BitImm = true;
278 break;
279 case Instruction::Add:
280 Takes12BitImm = true;
281 break;
282 case Instruction::Or:
283 case Instruction::Xor:
284 // bseti/binvi
285 if (ST->hasStdExtZbs() && Imm.isPowerOf2())
286 return TTI::TCC_Free;
287 Takes12BitImm = true;
288 break;
289 case Instruction::Mul:
290 // Power of 2 is a shift. Negated power of 2 is a shift and a negate.
291 if (Imm.isPowerOf2() || Imm.isNegatedPowerOf2())
292 return TTI::TCC_Free;
293 // One more or less than a power of 2 can use SLLI+ADD/SUB.
294 if ((Imm + 1).isPowerOf2() || (Imm - 1).isPowerOf2())
295 return TTI::TCC_Free;
296 // FIXME: There is no MULI instruction.
297 Takes12BitImm = true;
298 break;
299 case Instruction::Sub:
300 case Instruction::Shl:
301 case Instruction::LShr:
302 case Instruction::AShr:
303 Takes12BitImm = true;
304 ImmArgIdx = 1;
305 break;
306 default:
307 break;
308 }
309
310 if (Takes12BitImm) {
311 // Check immediate is the correct argument...
312 if (Instruction::isCommutative(Opcode) || Idx == ImmArgIdx) {
313 // ... and fits into the 12-bit immediate.
314 if (Imm.getSignificantBits() <= 64 &&
315 getTLI()->isLegalAddImmediate(Imm.getSExtValue())) {
316 return TTI::TCC_Free;
317 }
318 }
319
320 // Otherwise, use the full materialisation cost.
321 return getIntImmCost(Imm, Ty, CostKind);
322 }
323
324 // By default, prevent hoisting.
325 return TTI::TCC_Free;
326}
327
330 const APInt &Imm, Type *Ty,
332 // Prevent hoisting in unknown cases.
333 return TTI::TCC_Free;
334}
335
337 return ST->hasVInstructions();
338}
339
341RISCVTTIImpl::getPopcntSupport(unsigned TyWidth) const {
342 assert(isPowerOf2_32(TyWidth) && "Ty width must be power of 2");
343 return ST->hasCPOPLike() ? TTI::PSK_FastHardware : TTI::PSK_Software;
344}
345
347 unsigned Opcode, Type *InputTypeA, Type *InputTypeB, Type *AccumType,
349 TTI::PartialReductionExtendKind OpBExtend, std::optional<unsigned> BinOp,
350 TTI::TargetCostKind CostKind, std::optional<FastMathFlags> FMF) const {
351 if (Opcode == Instruction::FAdd)
353
354 // zve32x is broken for partial_reduce_umla, but let's make sure we
355 // don't generate them.
356 if (!ST->hasStdExtZvdot4a8i() || ST->getELen() < 64 ||
357 Opcode != Instruction::Add || !BinOp || *BinOp != Instruction::Mul ||
358 InputTypeA != InputTypeB || !InputTypeA->isIntegerTy(8) ||
359 !AccumType->isIntegerTy(32) || !VF.isKnownMultipleOf(4))
361
362 Type *Tp = VectorType::get(AccumType, VF.divideCoefficientBy(4));
363 std::pair<InstructionCost, MVT> LT = getTypeLegalizationCost(Tp);
364 // Note: Asuming all vdot4a* variants are equal cost
365 return LT.first *
366 getRISCVInstructionCost(RISCV::VDOT4A_VV, LT.second, CostKind);
367}
368
370 // Currently, the ExpandReductions pass can't expand scalable-vector
371 // reductions, but we still request expansion as RVV doesn't support certain
372 // reductions and the SelectionDAG can't legalize them either.
373 switch (II->getIntrinsicID()) {
374 default:
375 return false;
376 // These reductions have no equivalent in RVV
377 case Intrinsic::vector_reduce_mul:
378 case Intrinsic::vector_reduce_fmul:
379 return true;
380 }
381}
382
383std::optional<unsigned> RISCVTTIImpl::getMaxVScale() const {
384 if (ST->hasVInstructions())
385 return ST->getRealMaxVLen() / RISCV::RVVBitsPerBlock;
386 return BaseT::getMaxVScale();
387}
388
389std::optional<unsigned> RISCVTTIImpl::getVScaleForTuning() const {
390 if (ST->hasVInstructions())
391 if (unsigned MinVLen = ST->getRealMinVLen();
392 MinVLen >= RISCV::RVVBitsPerBlock)
393 return MinVLen / RISCV::RVVBitsPerBlock;
395}
396
399 unsigned LMUL =
400 llvm::bit_floor(std::clamp<unsigned>(RVVRegisterWidthLMUL, 1, 8));
401 switch (K) {
403 return TypeSize::getFixed(ST->getXLen());
405 return TypeSize::getFixed(
406 ST->useRVVForFixedLengthVectors() ? LMUL * ST->getRealMinVLen() : 0);
409 (ST->hasVInstructions() &&
410 ST->getRealMinVLen() >= RISCV::RVVBitsPerBlock)
412 : 0);
413 }
414
415 llvm_unreachable("Unsupported register kind");
416}
417
418InstructionCost RISCVTTIImpl::getStaticDataAddrGenerationCost(
419 const TTI::TargetCostKind CostKind) const {
420 switch (CostKind) {
423 // Always 2 instructions
424 return 2;
425 case TTI::TCK_Latency:
427 // Depending on the memory model the address generation will
428 // require AUIPC + ADDI (medany) or LUI + ADDI (medlow). Don't
429 // have a way of getting this information here, so conservatively
430 // require both.
431 // In practice, these are generally implemented together.
432 return (ST->hasAUIPCADDIFusion() && ST->hasLUIADDIFusion()) ? 1 : 2;
433 }
434 llvm_unreachable("Unsupported cost kind");
435}
436
438RISCVTTIImpl::getConstantPoolLoadCost(Type *Ty,
440 // Add a cost of address generation + the cost of the load. The address
441 // is expected to be a PC relative offset to a constant pool entry
442 // using auipc/addi.
443 return getStaticDataAddrGenerationCost(CostKind) +
444 getMemoryOpCost(Instruction::Load, Ty, DL.getABITypeAlign(Ty),
445 /*AddressSpace=*/0, CostKind);
446}
447
448static bool isRepeatedConcatMask(ArrayRef<int> Mask, int &SubVectorSize) {
449 unsigned Size = Mask.size();
450 if (!isPowerOf2_32(Size))
451 return false;
452 for (unsigned I = 0; I != Size; ++I) {
453 if (static_cast<unsigned>(Mask[I]) == I)
454 continue;
455 if (Mask[I] != 0)
456 return false;
457 if (Size % I != 0)
458 return false;
459 for (unsigned J = I + 1; J != Size; ++J)
460 // Check the pattern is repeated.
461 if (static_cast<unsigned>(Mask[J]) != J % I)
462 return false;
463 SubVectorSize = I;
464 return true;
465 }
466 // That means Mask is <0, 1, 2, 3>. This is not a concatenation.
467 return false;
468}
469
471 LLVMContext &C) {
472 assert((DataVT.getScalarSizeInBits() != 8 ||
473 DataVT.getVectorNumElements() <= 256) && "unhandled case in lowering");
474 MVT IndexVT = DataVT.changeTypeToInteger();
475 if (IndexVT.getScalarType().bitsGT(ST.getXLenVT()))
476 IndexVT = IndexVT.changeVectorElementType(MVT::i16);
477 return cast<VectorType>(EVT(IndexVT).getTypeForEVT(C));
478}
479
480/// Attempt to approximate the cost of a shuffle which will require splitting
481/// during legalization. Note that processShuffleMasks is not an exact proxy
482/// for the algorithm used in LegalizeVectorTypes, but hopefully it's a
483/// reasonably close upperbound.
485 MVT LegalVT, VectorType *Tp,
486 ArrayRef<int> Mask,
488 assert(LegalVT.isFixedLengthVector() && !Mask.empty() &&
489 "Expected fixed vector type and non-empty mask");
490 unsigned LegalNumElts = LegalVT.getVectorNumElements();
491 // Number of destination vectors after legalization:
492 unsigned NumOfDests = divideCeil(Mask.size(), LegalNumElts);
493 // We are going to permute multiple sources and the result will be in
494 // multiple destinations. Providing an accurate cost only for splits where
495 // the element type remains the same.
496 if (NumOfDests <= 1 ||
498 Tp->getElementType()->getPrimitiveSizeInBits() ||
499 LegalNumElts >= Tp->getElementCount().getFixedValue())
501
502 unsigned VecTySize = TTI.getDataLayout().getTypeStoreSize(Tp);
503 unsigned LegalVTSize = LegalVT.getStoreSize();
504 // Number of source vectors after legalization:
505 unsigned NumOfSrcs = divideCeil(VecTySize, LegalVTSize);
506
507 auto *SingleOpTy = FixedVectorType::get(Tp->getElementType(), LegalNumElts);
508
509 unsigned NormalizedVF = LegalNumElts * std::max(NumOfSrcs, NumOfDests);
510 unsigned NumOfSrcRegs = NormalizedVF / LegalNumElts;
511 unsigned NumOfDestRegs = NormalizedVF / LegalNumElts;
512 SmallVector<int> NormalizedMask(NormalizedVF, PoisonMaskElem);
513 assert(NormalizedVF >= Mask.size() &&
514 "Normalized mask expected to be not shorter than original mask.");
515 copy(Mask, NormalizedMask.begin());
516 InstructionCost Cost = 0;
517 SmallDenseSet<std::pair<ArrayRef<int>, unsigned>> ReusedSingleSrcShuffles;
519 NormalizedMask, NumOfSrcRegs, NumOfDestRegs, NumOfDestRegs, []() {},
520 [&](ArrayRef<int> RegMask, unsigned SrcReg, unsigned DestReg) {
521 if (ShuffleVectorInst::isIdentityMask(RegMask, RegMask.size()))
522 return;
523 if (!ReusedSingleSrcShuffles.insert(std::make_pair(RegMask, SrcReg))
524 .second)
525 return;
526 Cost += TTI.getShuffleCost(
528 FixedVectorType::get(SingleOpTy->getElementType(), RegMask.size()),
529 SingleOpTy, RegMask, CostKind, 0, nullptr);
530 },
531 [&](ArrayRef<int> RegMask, unsigned Idx1, unsigned Idx2, bool NewReg) {
532 Cost += TTI.getShuffleCost(
534 FixedVectorType::get(SingleOpTy->getElementType(), RegMask.size()),
535 SingleOpTy, RegMask, CostKind, 0, nullptr);
536 });
537 return Cost;
538}
539
540/// Try to perform better estimation of the permutation.
541/// 1. Split the source/destination vectors into real registers.
542/// 2. Do the mask analysis to identify which real registers are
543/// permuted. If more than 1 source registers are used for the
544/// destination register building, the cost for this destination register
545/// is (Number_of_source_register - 1) * Cost_PermuteTwoSrc. If only one
546/// source register is used, build mask and calculate the cost as a cost
547/// of PermuteSingleSrc.
548/// Also, for the single register permute we try to identify if the
549/// destination register is just a copy of the source register or the
550/// copy of the previous destination register (the cost is
551/// TTI::TCC_Basic). If the source register is just reused, the cost for
552/// this operation is 0.
553static InstructionCost
555 std::optional<unsigned> VLen, VectorType *Tp,
557 assert(LegalVT.isFixedLengthVector());
558 if (!VLen || Mask.empty())
560 MVT ElemVT = LegalVT.getVectorElementType();
561 unsigned ElemsPerVReg = *VLen / ElemVT.getFixedSizeInBits();
562 LegalVT = TTI.getTypeLegalizationCost(
563 FixedVectorType::get(Tp->getElementType(), ElemsPerVReg))
564 .second;
565 // Number of destination vectors after legalization:
566 InstructionCost NumOfDests =
567 divideCeil(Mask.size(), LegalVT.getVectorNumElements());
568 if (NumOfDests <= 1 ||
570 Tp->getElementType()->getPrimitiveSizeInBits() ||
571 LegalVT.getVectorNumElements() >= Tp->getElementCount().getFixedValue())
573
574 unsigned VecTySize = TTI.getDataLayout().getTypeStoreSize(Tp);
575 unsigned LegalVTSize = LegalVT.getStoreSize();
576 // Number of source vectors after legalization:
577 unsigned NumOfSrcs = divideCeil(VecTySize, LegalVTSize);
578
579 auto *SingleOpTy = FixedVectorType::get(Tp->getElementType(),
580 LegalVT.getVectorNumElements());
581
582 unsigned E = NumOfDests.getValue();
583 unsigned NormalizedVF =
584 LegalVT.getVectorNumElements() * std::max(NumOfSrcs, E);
585 unsigned NumOfSrcRegs = NormalizedVF / LegalVT.getVectorNumElements();
586 unsigned NumOfDestRegs = NormalizedVF / LegalVT.getVectorNumElements();
587 SmallVector<int> NormalizedMask(NormalizedVF, PoisonMaskElem);
588 assert(NormalizedVF >= Mask.size() &&
589 "Normalized mask expected to be not shorter than original mask.");
590 copy(Mask, NormalizedMask.begin());
591 InstructionCost Cost = 0;
592 int NumShuffles = 0;
593 SmallDenseSet<std::pair<ArrayRef<int>, unsigned>> ReusedSingleSrcShuffles;
595 NormalizedMask, NumOfSrcRegs, NumOfDestRegs, NumOfDestRegs, []() {},
596 [&](ArrayRef<int> RegMask, unsigned SrcReg, unsigned DestReg) {
597 if (ShuffleVectorInst::isIdentityMask(RegMask, RegMask.size()))
598 return;
599 if (!ReusedSingleSrcShuffles.insert(std::make_pair(RegMask, SrcReg))
600 .second)
601 return;
602 ++NumShuffles;
603 Cost += TTI.getShuffleCost(TTI::SK_PermuteSingleSrc, SingleOpTy,
604 SingleOpTy, RegMask, CostKind, 0, nullptr);
605 },
606 [&](ArrayRef<int> RegMask, unsigned Idx1, unsigned Idx2, bool NewReg) {
607 Cost += TTI.getShuffleCost(TTI::SK_PermuteTwoSrc, SingleOpTy,
608 SingleOpTy, RegMask, CostKind, 0, nullptr);
609 NumShuffles += 2;
610 });
611 // Note: check that we do not emit too many shuffles here to prevent code
612 // size explosion.
613 // TODO: investigate, if it can be improved by extra analysis of the masks
614 // to check if the code is more profitable.
615 if ((NumOfDestRegs > 2 && NumShuffles <= static_cast<int>(NumOfDestRegs)) ||
616 (NumOfDestRegs <= 2 && NumShuffles < 4))
617 return Cost;
619}
620
621InstructionCost RISCVTTIImpl::getSlideCost(FixedVectorType *Tp,
622 ArrayRef<int> Mask,
624 // Avoid missing masks and length changing shuffles
625 if (Mask.size() <= 2 || Mask.size() != Tp->getNumElements())
627
628 int NumElts = Tp->getNumElements();
629 std::pair<InstructionCost, MVT> LT = getTypeLegalizationCost(Tp);
630 // Avoid scalarization cases
631 if (!LT.second.isFixedLengthVector())
633
634 // Requires moving elements between parts, which requires additional
635 // unmodeled instructions.
636 if (LT.first != 1)
638
639 auto GetSlideOpcode = [&](int SlideAmt) {
640 assert(SlideAmt != 0);
641 bool IsVI = isUInt<5>(std::abs(SlideAmt));
642 if (SlideAmt < 0)
643 return IsVI ? RISCV::VSLIDEDOWN_VI : RISCV::VSLIDEDOWN_VX;
644 return IsVI ? RISCV::VSLIDEUP_VI : RISCV::VSLIDEUP_VX;
645 };
646
647 std::array<std::pair<int, int>, 2> SrcInfo;
648 if (!isMaskedSlidePair(Mask, NumElts, SrcInfo))
650
651 if (SrcInfo[1].second == 0)
652 std::swap(SrcInfo[0], SrcInfo[1]);
653
654 InstructionCost FirstSlideCost = 0;
655 if (SrcInfo[0].second != 0) {
656 unsigned Opcode = GetSlideOpcode(SrcInfo[0].second);
657 FirstSlideCost = getRISCVInstructionCost(Opcode, LT.second, CostKind);
658 }
659
660 if (SrcInfo[1].first == -1)
661 return FirstSlideCost;
662
663 InstructionCost SecondSlideCost = 0;
664 if (SrcInfo[1].second != 0) {
665 unsigned Opcode = GetSlideOpcode(SrcInfo[1].second);
666 SecondSlideCost = getRISCVInstructionCost(Opcode, LT.second, CostKind);
667 } else {
668 SecondSlideCost =
669 getRISCVInstructionCost(RISCV::VMERGE_VVM, LT.second, CostKind);
670 }
671
672 auto EC = Tp->getElementCount();
673 VectorType *MaskTy =
675 InstructionCost MaskCost = getConstantPoolLoadCost(MaskTy, CostKind);
676 return FirstSlideCost + SecondSlideCost + MaskCost;
677}
678
681 VectorType *SrcTy, ArrayRef<int> Mask,
682 TTI::TargetCostKind CostKind, int Index,
684 const Instruction *CxtI) const {
685 assert((Mask.empty() || DstTy->isScalableTy() ||
686 Mask.size() == DstTy->getElementCount().getKnownMinValue()) &&
687 "Expected the Mask to match the return size if given");
688 assert(SrcTy->getScalarType() == DstTy->getScalarType() &&
689 "Expected the same scalar types");
690
691 Kind = improveShuffleKindFromMask(Kind, Mask, SrcTy, Index, SubTp);
692
693 // TODO: Add proper cost model for P extension fixed vectors (e.g., v4i16)
694 // For now, skip all fixed vector cost analysis when P extension is available
695 // to avoid crashes in getMinRVVVectorSizeInBits()
696 if (ST->hasStdExtP() && isa<FixedVectorType>(SrcTy))
697 return 1;
698
699 std::pair<InstructionCost, MVT> LT = getTypeLegalizationCost(SrcTy);
700
701 // First, handle cases where having a fixed length vector enables us to
702 // give a more accurate cost than falling back to generic scalable codegen.
703 // TODO: Each of these cases hints at a modeling gap around scalable vectors.
704 if (auto *FVTp = dyn_cast<FixedVectorType>(SrcTy);
705 FVTp && ST->hasVInstructions() && LT.second.isFixedLengthVector()) {
707 *this, LT.second, ST->getRealVLen(),
708 Kind == TTI::SK_InsertSubvector ? DstTy : SrcTy, Mask, CostKind);
709 if (VRegSplittingCost.isValid())
710 return VRegSplittingCost;
711 switch (Kind) {
712 default:
713 break;
715 if (Mask.size() >= 2) {
716 MVT EltTp = LT.second.getVectorElementType();
717 // If the size of the element is < ELEN then shuffles of interleaves and
718 // deinterleaves of 2 vectors can be lowered into the following
719 // sequences
720 if (EltTp.getScalarSizeInBits() < ST->getELen()) {
721 // Example sequence:
722 // vsetivli zero, 4, e8, mf4, ta, ma (ignored)
723 // vwaddu.vv v10, v8, v9
724 // li a0, -1 (ignored)
725 // vwmaccu.vx v10, a0, v9
726 if (ShuffleVectorInst::isInterleaveMask(Mask, 2, Mask.size()))
727 return 2 * LT.first * TLI->getLMULCost(LT.second);
728
729 if (Mask[0] == 0 || Mask[0] == 1) {
730 auto DeinterleaveMask = createStrideMask(Mask[0], 2, Mask.size());
731 // Example sequence:
732 // vnsrl.wi v10, v8, 0
733 if (equal(DeinterleaveMask, Mask))
734 return LT.first * getRISCVInstructionCost(RISCV::VNSRL_WI,
735 LT.second, CostKind);
736 }
737 }
738 int SubVectorSize;
739 if (LT.second.getScalarSizeInBits() != 1 &&
740 isRepeatedConcatMask(Mask, SubVectorSize)) {
742 unsigned NumSlides = Log2_32(Mask.size() / SubVectorSize);
743 // The cost of extraction from a subvector is 0 if the index is 0.
744 for (unsigned I = 0; I != NumSlides; ++I) {
745 unsigned InsertIndex = SubVectorSize * (1 << I);
746 FixedVectorType *SubTp =
747 FixedVectorType::get(SrcTy->getElementType(), InsertIndex);
748 FixedVectorType *DestTp =
750 std::pair<InstructionCost, MVT> DestLT =
752 // Add the cost of whole vector register move because the
753 // destination vector register group for vslideup cannot overlap the
754 // source.
755 Cost += DestLT.first * TLI->getLMULCost(DestLT.second);
756 Cost += getShuffleCost(TTI::SK_InsertSubvector, DestTp, DestTp, {},
757 CostKind, InsertIndex, SubTp);
758 }
759 return Cost;
760 }
761 }
762
763 if (InstructionCost SlideCost = getSlideCost(FVTp, Mask, CostKind);
764 SlideCost.isValid())
765 return SlideCost;
766
767 // vrgather + cost of generating the mask constant.
768 // We model this for an unknown mask with a single vrgather.
769 if (LT.first == 1 && (LT.second.getScalarSizeInBits() != 8 ||
770 LT.second.getVectorNumElements() <= 256)) {
771 VectorType *IdxTy =
772 getVRGatherIndexType(LT.second, *ST, SrcTy->getContext());
773 InstructionCost IndexCost = getConstantPoolLoadCost(IdxTy, CostKind);
774 return IndexCost +
775 getRISCVInstructionCost(RISCV::VRGATHER_VV, LT.second, CostKind);
776 }
777 break;
778 }
781
782 if (InstructionCost SlideCost = getSlideCost(FVTp, Mask, CostKind);
783 SlideCost.isValid())
784 return SlideCost;
785
786 // 2 x (vrgather + cost of generating the mask constant) + cost of mask
787 // register for the second vrgather. We model this for an unknown
788 // (shuffle) mask.
789 if (LT.first == 1 && (LT.second.getScalarSizeInBits() != 8 ||
790 LT.second.getVectorNumElements() <= 256)) {
791 auto &C = SrcTy->getContext();
792 auto EC = SrcTy->getElementCount();
793 VectorType *IdxTy = getVRGatherIndexType(LT.second, *ST, C);
795 InstructionCost IndexCost = getConstantPoolLoadCost(IdxTy, CostKind);
796 InstructionCost MaskCost = getConstantPoolLoadCost(MaskTy, CostKind);
797 return 2 * IndexCost +
798 getRISCVInstructionCost({RISCV::VRGATHER_VV, RISCV::VRGATHER_VV},
799 LT.second, CostKind) +
800 MaskCost;
801 }
802 break;
803 }
804 }
805
806 auto shouldSplit = [](TTI::ShuffleKind Kind) {
807 switch (Kind) {
808 default:
809 return false;
813 return true;
814 }
815 };
816
817 if (!Mask.empty() && LT.first.isValid() && LT.first != 1 &&
818 shouldSplit(Kind)) {
819 InstructionCost SplitCost =
820 costShuffleViaSplitting(*this, LT.second, FVTp, Mask, CostKind);
821 if (SplitCost.isValid())
822 return SplitCost;
823 }
824 }
825
826 // Handle scalable vectors (and fixed vectors legalized to scalable vectors).
827 switch (Kind) {
828 default:
829 // Fallthrough to generic handling.
830 // TODO: Most of these cases will return getInvalid in generic code, and
831 // must be implemented here.
832 break;
834 // Extract at zero is always a subregister extract
835 if (Index == 0)
836 return TTI::TCC_Free;
837
838 // If we're extracting a subvector of at most m1 size at a sub-register
839 // boundary - which unfortunately we need exact vlen to identify - this is
840 // a subregister extract at worst and thus won't require a vslidedown.
841 // TODO: Extend for aligned m2, m4 subvector extracts
842 // TODO: Extend for misalgined (but contained) extracts
843 // TODO: Extend for scalable subvector types
844 if (std::pair<InstructionCost, MVT> SubLT = getTypeLegalizationCost(SubTp);
845 SubLT.second.isValid() && SubLT.second.isFixedLengthVector()) {
846 if (std::optional<unsigned> VLen = ST->getRealVLen();
847 VLen && SubLT.second.getScalarSizeInBits() * Index % *VLen == 0 &&
848 SubLT.second.getSizeInBits() <= *VLen)
849 return TTI::TCC_Free;
850 }
851
852 // Example sequence:
853 // vsetivli zero, 4, e8, mf2, tu, ma (ignored)
854 // vslidedown.vi v8, v9, 2
855 return LT.first *
856 getRISCVInstructionCost(RISCV::VSLIDEDOWN_VI, LT.second, CostKind);
858 // Example sequence:
859 // vsetivli zero, 4, e8, mf2, tu, ma (ignored)
860 // vslideup.vi v8, v9, 2
861 LT = getTypeLegalizationCost(DstTy);
862 return LT.first *
863 getRISCVInstructionCost(RISCV::VSLIDEUP_VI, LT.second, CostKind);
864 case TTI::SK_Select: {
865 // Example sequence:
866 // li a0, 90
867 // vsetivli zero, 8, e8, mf2, ta, ma (ignored)
868 // vmv.s.x v0, a0
869 // vmerge.vvm v8, v9, v8, v0
870 // We use 2 for the cost of the mask materialization as this is the true
871 // cost for small masks and most shuffles are small. At worst, this cost
872 // should be a very small constant for the constant pool load. As such,
873 // we may bias towards large selects slightly more than truly warranted.
874 return LT.first *
875 (1 + getRISCVInstructionCost({RISCV::VMV_S_X, RISCV::VMERGE_VVM},
876 LT.second, CostKind));
877 }
878 case TTI::SK_Broadcast: {
879 // Check for broadcast loads, which are synthesized by optimized zero-stride
880 // loads (this is checked in RISCVTTIImpl::isLegalBroadcastLoad).
881 bool IsLoad = !Args.empty() && isa<LoadInst>(Args[0]);
882 if (IsLoad && LT.second.isVector() &&
883 isLegalBroadcastLoad(SrcTy->getElementType(),
884 LT.second.getVectorElementCount()))
885 return 0;
886
887 bool HasScalar = (Args.size() > 0) && (Operator::getOpcode(Args[0]) ==
888 Instruction::InsertElement);
889 if (LT.second.getScalarSizeInBits() == 1) {
890 if (HasScalar) {
891 // Example sequence:
892 // andi a0, a0, 1
893 // vsetivli zero, 2, e8, mf8, ta, ma (ignored)
894 // vmv.v.x v8, a0
895 // vmsne.vi v0, v8, 0
896 return LT.first *
897 (1 + getRISCVInstructionCost({RISCV::VMV_V_X, RISCV::VMSNE_VI},
898 LT.second, CostKind));
899 }
900 // Example sequence:
901 // vsetivli zero, 2, e8, mf8, ta, mu (ignored)
902 // vmv.v.i v8, 0
903 // vmerge.vim v8, v8, 1, v0
904 // vmv.x.s a0, v8
905 // andi a0, a0, 1
906 // vmv.v.x v8, a0
907 // vmsne.vi v0, v8, 0
908
909 return LT.first *
910 (1 + getRISCVInstructionCost({RISCV::VMV_V_I, RISCV::VMERGE_VIM,
911 RISCV::VMV_X_S, RISCV::VMV_V_X,
912 RISCV::VMSNE_VI},
913 LT.second, CostKind));
914 }
915
916 if (HasScalar) {
917 // Example sequence:
918 // vmv.v.x v8, a0
919 return LT.first *
920 getRISCVInstructionCost(RISCV::VMV_V_X, LT.second, CostKind);
921 }
922
923 // Example sequence:
924 // vrgather.vi v9, v8, 0
925 return LT.first *
926 getRISCVInstructionCost(RISCV::VRGATHER_VI, LT.second, CostKind);
927 }
928 case TTI::SK_Splice: {
929 // vslidedown+vslideup.
930 // TODO: Multiplying by LT.first implies this legalizes into multiple copies
931 // of similar code, but I think we expand through memory.
932 unsigned Opcodes[2] = {RISCV::VSLIDEDOWN_VX, RISCV::VSLIDEUP_VX};
933 if (Index >= 0 && Index < 32)
934 Opcodes[0] = RISCV::VSLIDEDOWN_VI;
935 else if (Index < 0 && Index > -32)
936 Opcodes[1] = RISCV::VSLIDEUP_VI;
937 return LT.first * getRISCVInstructionCost(Opcodes, LT.second, CostKind);
938 }
939 case TTI::SK_Reverse: {
940
941 if (!LT.second.isVector())
943
944 // TODO: Cases to improve here:
945 // * Illegal vector types
946 // * i64 on RV32
947 if (SrcTy->getElementType()->isIntegerTy(1)) {
948 VectorType *WideTy =
949 VectorType::get(IntegerType::get(SrcTy->getContext(), 8),
950 cast<VectorType>(SrcTy)->getElementCount());
951 return getCastInstrCost(Instruction::ZExt, WideTy, SrcTy,
953 getShuffleCost(TTI::SK_Reverse, WideTy, WideTy, {}, CostKind, 0,
954 nullptr) +
955 getCastInstrCost(Instruction::Trunc, SrcTy, WideTy,
957 }
958
959 MVT ContainerVT = LT.second;
960 if (LT.second.isFixedLengthVector())
961 ContainerVT = TLI->getContainerForFixedLengthVector(LT.second);
962 MVT M1VT = RISCVTargetLowering::getM1VT(ContainerVT);
963 if (ContainerVT.bitsLE(M1VT)) {
964 // Example sequence:
965 // csrr a0, vlenb
966 // srli a0, a0, 3
967 // addi a0, a0, -1
968 // vsetvli a1, zero, e8, mf8, ta, mu (ignored)
969 // vid.v v9
970 // vrsub.vx v10, v9, a0
971 // vrgather.vv v9, v8, v10
972 InstructionCost LenCost = 3;
973 if (LT.second.isFixedLengthVector())
974 // vrsub.vi has a 5 bit immediate field, otherwise an li suffices
975 LenCost = isInt<5>(LT.second.getVectorNumElements() - 1) ? 0 : 1;
976 unsigned Opcodes[] = {RISCV::VID_V, RISCV::VRSUB_VX, RISCV::VRGATHER_VV};
977 if (LT.second.isFixedLengthVector() &&
978 isInt<5>(LT.second.getVectorNumElements() - 1))
979 Opcodes[1] = RISCV::VRSUB_VI;
980 InstructionCost GatherCost =
981 getRISCVInstructionCost(Opcodes, LT.second, CostKind);
982 return LT.first * (LenCost + GatherCost);
983 }
984
985 // At high LMUL, we split into a series of M1 reverses (see
986 // lowerVECTOR_REVERSE) and then do a single slide at the end to eliminate
987 // the resulting gap at the bottom (for fixed vectors only). The important
988 // bit is that the cost scales linearly, not quadratically with LMUL.
989 unsigned M1Opcodes[] = {RISCV::VID_V, RISCV::VRSUB_VX};
990 InstructionCost FixedCost =
991 getRISCVInstructionCost(M1Opcodes, M1VT, CostKind) + 3;
992 unsigned Ratio =
994 InstructionCost GatherCost =
995 getRISCVInstructionCost({RISCV::VRGATHER_VV}, M1VT, CostKind) * Ratio;
996 InstructionCost SlideCost = !LT.second.isFixedLengthVector() ? 0 :
997 getRISCVInstructionCost({RISCV::VSLIDEDOWN_VX}, LT.second, CostKind);
998 return FixedCost + LT.first * (GatherCost + SlideCost);
999 }
1000 }
1001 return BaseT::getShuffleCost(Kind, DstTy, SrcTy, Mask, CostKind, Index,
1002 SubTp);
1003}
1004
1005static unsigned isM1OrSmaller(MVT VT) {
1007 return (LMUL == RISCVVType::VLMUL::LMUL_F8 ||
1011}
1012
1014 VectorType *Ty, const APInt &DemandedElts, bool Insert, bool Extract,
1015 TTI::TargetCostKind CostKind, bool ForPoisonSrc, ArrayRef<Value *> VL,
1016 TTI::VectorInstrContext VIC) const {
1019
1020 // TODO: Add proper cost model for P extension fixed vectors (e.g., v4i16)
1021 // For now, skip all fixed vector cost analysis when P extension is available
1022 // to avoid crashes in getMinRVVVectorSizeInBits()
1023 if (ST->hasStdExtP() && isa<FixedVectorType>(Ty)) {
1024 return 1; // Treat as single instruction cost for now
1025 }
1026
1027 // A build_vector (which is m1 sized or smaller) can be done in no
1028 // worse than one vslide1down.vx per element in the type. We could
1029 // in theory do an explode_vector in the inverse manner, but our
1030 // lowering today does not have a first class node for this pattern.
1032 Ty, DemandedElts, Insert, Extract, CostKind);
1033 std::pair<InstructionCost, MVT> LT = getTypeLegalizationCost(Ty);
1034 if (Insert && !Extract && LT.first.isValid() && LT.second.isVector()) {
1035 if (Ty->getScalarSizeInBits() == 1) {
1036 auto *WideVecTy = cast<VectorType>(Ty->getWithNewBitWidth(8));
1037 // Note: Implicit scalar anyextend is assumed to be free since the i1
1038 // must be stored in a GPR.
1039 return getScalarizationOverhead(WideVecTy, DemandedElts, Insert, Extract,
1040 CostKind) +
1041 getCastInstrCost(Instruction::Trunc, Ty, WideVecTy,
1043 }
1044
1045 assert(LT.second.isFixedLengthVector());
1046 MVT ContainerVT = TLI->getContainerForFixedLengthVector(LT.second);
1047 if (isM1OrSmaller(ContainerVT)) {
1048 InstructionCost BV =
1049 cast<FixedVectorType>(Ty)->getNumElements() *
1050 getRISCVInstructionCost(RISCV::VSLIDE1DOWN_VX, LT.second, CostKind);
1051 if (BV < Cost)
1052 Cost = BV;
1053 }
1054 }
1055 return Cost;
1056}
1057
1061 Type *DataTy = MICA.getDataType();
1062 Align Alignment = MICA.getAlignment();
1063 switch (MICA.getID()) {
1064 case Intrinsic::vp_load_ff: {
1065 EVT DataTypeVT = TLI->getValueType(DL, DataTy);
1066 if (!TLI->isLegalFirstFaultLoad(DataTypeVT, Alignment))
1068
1069 unsigned AS = MICA.getAddressSpace();
1070 return getMemoryOpCost(Instruction::Load, DataTy, Alignment, AS, CostKind,
1071 {TTI::OK_AnyValue, TTI::OP_None}, nullptr);
1072 }
1073 case Intrinsic::experimental_vp_strided_load:
1074 case Intrinsic::experimental_vp_strided_store:
1075 return getStridedMemoryOpCost(MICA, CostKind);
1076 case Intrinsic::masked_compressstore:
1077 case Intrinsic::masked_expandload:
1079 case Intrinsic::vp_scatter:
1080 case Intrinsic::vp_gather:
1081 case Intrinsic::masked_scatter:
1082 case Intrinsic::masked_gather:
1083 return getGatherScatterOpCost(MICA, CostKind);
1084 case Intrinsic::vp_load:
1085 case Intrinsic::vp_store:
1086 case Intrinsic::masked_load:
1087 case Intrinsic::masked_store:
1088 return getMaskedMemoryOpCost(MICA, CostKind);
1089 }
1091}
1092
1096 unsigned Opcode = MICA.getID() == Intrinsic::masked_load ? Instruction::Load
1097 : Instruction::Store;
1098 Type *Src = MICA.getDataType();
1099 Align Alignment = MICA.getAlignment();
1100 unsigned AddressSpace = MICA.getAddressSpace();
1101
1102 if (!isLegalMaskedLoadStore(Src, Alignment) ||
1105
1106 return getMemoryOpCost(Opcode, Src, Alignment, AddressSpace, CostKind);
1107}
1108
1110 unsigned Opcode, Type *VecTy, unsigned Factor, ArrayRef<unsigned> Indices,
1111 Align Alignment, unsigned AddressSpace, TTI::TargetCostKind CostKind,
1112 bool UseMaskForCond, bool UseMaskForGaps) const {
1113
1114 // The interleaved memory access pass will lower (de)interleave ops combined
1115 // with an adjacent appropriate memory to vlseg/vsseg intrinsics. vlseg/vsseg
1116 // only support masking per-iteration (i.e. condition), not per-segment (i.e.
1117 // gap).
1118 if (!UseMaskForGaps && Factor <= TLI->getMaxSupportedInterleaveFactor()) {
1119 auto *VTy = cast<VectorType>(VecTy);
1120 std::pair<InstructionCost, MVT> LT = getTypeLegalizationCost(VTy);
1121 // Need to make sure type has't been scalarized
1122 if (LT.second.isVector()) {
1124 return LT.first * TTI::TCC_Basic;
1125
1126 auto *SubVecTy =
1127 VectorType::get(VTy->getElementType(),
1128 VTy->getElementCount().divideCoefficientBy(Factor));
1129 if (VTy->getElementCount().isKnownMultipleOf(Factor) &&
1130 TLI->isLegalInterleavedAccessType(SubVecTy, Factor, Alignment,
1131 AddressSpace, DL)) {
1132
1133 // Some processors optimize segment loads/stores as one wide memory op +
1134 // Factor * LMUL shuffle ops.
1135 if (ST->hasOptimizedSegmentLoadStore(Factor)) {
1137 getMemoryOpCost(Opcode, VTy, Alignment, AddressSpace, CostKind);
1138 MVT SubVecVT = getTLI()->getValueType(DL, SubVecTy).getSimpleVT();
1139 Cost += Factor * TLI->getLMULCost(SubVecVT);
1140 return LT.first * Cost;
1141 }
1142
1143 // Otherwise, the cost is proportional to the number of elements (VL *
1144 // Factor ops).
1145 unsigned NumLoads = getEstimatedVLFor(VTy);
1146 return NumLoads * TTI::TCC_Basic;
1147 }
1148 }
1149 }
1150
1151 // TODO: Return the cost of interleaved accesses for scalable vector when
1152 // unable to convert to segment accesses instructions.
1153 if (isa<ScalableVectorType>(VecTy))
1155
1156 auto *FVTy = cast<FixedVectorType>(VecTy);
1157 // When gaps are only at the tail, for interleaved load, we can emit a wide
1158 // masked load and shufflevectors. For interleaved store, we can emit
1159 // shufflevectors and a wide masked store. The interleaved memory access pass
1160 // will lower them into vlsseg/vssseg intrinsics.
1161 if (UseMaskForGaps) {
1162 assert(llvm::is_sorted(Indices) && "Indices must be sorted");
1163 assert(llvm::adjacent_find(Indices) == Indices.end() &&
1164 "Indices should not contain duplicate elements");
1165 unsigned NumOfFields = Indices.size();
1166 bool IsTailGapOnly = NumOfFields > 1 && (NumOfFields == Indices.back() + 1);
1167 if (IsTailGapOnly &&
1168 NumOfFields <= TLI->getMaxSupportedInterleaveFactor()) {
1169 std::pair<InstructionCost, MVT> LT = getTypeLegalizationCost(FVTy);
1170 if (LT.second.isVector() &&
1171 FVTy->getElementCount().isKnownMultipleOf(Factor)) {
1172 auto *SubVecTy = VectorType::get(
1173 FVTy->getElementType(),
1174 FVTy->getElementCount().divideCoefficientBy(Factor));
1175 if (TLI->isLegalInterleavedAccessType(SubVecTy, NumOfFields, Alignment,
1176 AddressSpace, DL)) {
1177 // The cost is proportional to the total number of element accesses.
1178 unsigned NumAccesses = getEstimatedVLFor(FVTy);
1179 return NumAccesses * TTI::TCC_Basic;
1180 }
1181 }
1182 }
1183 }
1184
1185 InstructionCost MemCost =
1186 getMemoryOpCost(Opcode, VecTy, Alignment, AddressSpace, CostKind);
1187 unsigned VF = FVTy->getNumElements() / Factor;
1188
1189 // An interleaved load will look like this for Factor=3:
1190 // %wide.vec = load <12 x i32>, ptr %3, align 4
1191 // %strided.vec = shufflevector %wide.vec, poison, <4 x i32> <stride mask>
1192 // %strided.vec1 = shufflevector %wide.vec, poison, <4 x i32> <stride mask>
1193 // %strided.vec2 = shufflevector %wide.vec, poison, <4 x i32> <stride mask>
1194 if (Opcode == Instruction::Load) {
1195 InstructionCost Cost = MemCost;
1196 for (unsigned Index : Indices) {
1197 FixedVectorType *VecTy =
1198 FixedVectorType::get(FVTy->getElementType(), VF * Factor);
1199 auto Mask = createStrideMask(Index, Factor, VF);
1200 Mask.resize(VF * Factor, -1);
1201 InstructionCost ShuffleCost =
1203 Mask, CostKind, 0, nullptr, {});
1204 Cost += ShuffleCost;
1205 }
1206 return Cost;
1207 }
1208
1209 // TODO: Model for NF > 2
1210 // We'll need to enhance getShuffleCost to model shuffles that are just
1211 // inserts and extracts into subvectors, since they won't have the full cost
1212 // of a vrgather.
1213 // An interleaved store for 3 vectors of 4 lanes will look like
1214 // %11 = shufflevector <4 x i32> %4, <4 x i32> %6, <8 x i32> <0...7>
1215 // %12 = shufflevector <4 x i32> %9, <4 x i32> poison, <8 x i32> <0...3>
1216 // %13 = shufflevector <8 x i32> %11, <8 x i32> %12, <12 x i32> <0...11>
1217 // %interleaved.vec = shufflevector %13, poison, <12 x i32> <interleave mask>
1218 // store <12 x i32> %interleaved.vec, ptr %10, align 4
1219 if (Factor != 2)
1220 return BaseT::getInterleavedMemoryOpCost(Opcode, VecTy, Factor, Indices,
1221 Alignment, AddressSpace, CostKind,
1222 UseMaskForCond, UseMaskForGaps);
1223
1224 assert(Opcode == Instruction::Store && "Opcode must be a store");
1225 // For an interleaving store of 2 vectors, we perform one large interleaving
1226 // shuffle that goes into the wide store
1227 auto Mask = createInterleaveMask(VF, Factor);
1228 InstructionCost ShuffleCost =
1230 CostKind, 0, nullptr, {});
1231 return MemCost + ShuffleCost;
1232}
1233
1237
1238 bool IsLoad = MICA.getID() == Intrinsic::masked_gather ||
1239 MICA.getID() == Intrinsic::vp_gather;
1240 unsigned Opcode = IsLoad ? Instruction::Load : Instruction::Store;
1241 Type *DataTy = MICA.getDataType();
1242 Align Alignment = MICA.getAlignment();
1245
1246 if ((Opcode == Instruction::Load &&
1247 !isLegalMaskedGather(DataTy, Align(Alignment))) ||
1248 (Opcode == Instruction::Store &&
1249 !isLegalMaskedScatter(DataTy, Align(Alignment))))
1251
1252 // Cost is proportional to the number of memory operations implied. For
1253 // scalable vectors, we use an estimate on that number since we don't
1254 // know exactly what VL will be.
1255 auto &VTy = *cast<VectorType>(DataTy);
1256 unsigned NumLoads = getEstimatedVLFor(&VTy);
1257 return NumLoads * TTI::TCC_Basic;
1258}
1259
1261 const MemIntrinsicCostAttributes &MICA,
1263 unsigned Opcode = MICA.getID() == Intrinsic::masked_expandload
1264 ? Instruction::Load
1265 : Instruction::Store;
1266 Type *DataTy = MICA.getDataType();
1267 bool VariableMask = MICA.getVariableMask();
1268 Align Alignment = MICA.getAlignment();
1269 bool IsLegal = (Opcode == Instruction::Store &&
1270 isLegalMaskedCompressStore(DataTy, Alignment)) ||
1271 (Opcode == Instruction::Load &&
1272 isLegalMaskedExpandLoad(DataTy, Alignment));
1273 if (!IsLegal || CostKind != TTI::TCK_RecipThroughput)
1275 // Example compressstore sequence:
1276 // vsetivli zero, 8, e32, m2, ta, ma (ignored)
1277 // vcompress.vm v10, v8, v0
1278 // vcpop.m a1, v0
1279 // vsetvli zero, a1, e32, m2, ta, ma
1280 // vse32.v v10, (a0)
1281 // Example expandload sequence:
1282 // vsetivli zero, 8, e8, mf2, ta, ma (ignored)
1283 // vcpop.m a1, v0
1284 // vsetvli zero, a1, e32, m2, ta, ma
1285 // vle32.v v10, (a0)
1286 // vsetivli zero, 8, e32, m2, ta, ma
1287 // viota.m v12, v0
1288 // vrgather.vv v8, v10, v12, v0.t
1289 auto MemOpCost =
1290 getMemoryOpCost(Opcode, DataTy, Alignment, /*AddressSpace*/ 0, CostKind);
1291 auto LT = getTypeLegalizationCost(DataTy);
1292 SmallVector<unsigned, 4> Opcodes{RISCV::VSETVLI};
1293 if (VariableMask)
1294 Opcodes.push_back(RISCV::VCPOP_M);
1295 if (Opcode == Instruction::Store)
1296 Opcodes.append({RISCV::VCOMPRESS_VM});
1297 else
1298 Opcodes.append({RISCV::VSETIVLI, RISCV::VIOTA_M, RISCV::VRGATHER_VV});
1299 return MemOpCost +
1300 LT.first * getRISCVInstructionCost(Opcodes, LT.second, CostKind);
1301}
1302
1306 Type *DataTy = MICA.getDataType();
1307 Align Alignment = MICA.getAlignment();
1308
1309 if (!isLegalStridedLoadStore(DataTy, Alignment))
1311
1313 return TTI::TCC_Basic;
1314
1315 // Cost is proportional to the number of memory operations implied. For
1316 // scalable vectors, we use an estimate on that number since we don't
1317 // know exactly what VL will be.
1318 auto &VTy = *cast<VectorType>(DataTy);
1319 unsigned NumLoads = getEstimatedVLFor(&VTy);
1320 return NumLoads * TTI::TCC_Basic;
1321}
1322
1325 // FIXME: This is a property of the default vector convention, not
1326 // all possible calling conventions. Fixing that will require
1327 // some TTI API and SLP rework.
1330 for (auto *Ty : Tys) {
1331 if (!Ty->isVectorTy())
1332 continue;
1333 Align A = DL.getPrefTypeAlign(Ty);
1334 Cost += getMemoryOpCost(Instruction::Store, Ty, A, 0, CostKind) +
1335 getMemoryOpCost(Instruction::Load, Ty, A, 0, CostKind);
1336 }
1337 return Cost;
1338}
1339
1340// Currently, these represent both throughput and codesize costs
1341// for the respective intrinsics. The costs in this table are simply
1342// instruction counts with the following adjustments made:
1343// * One vsetvli is considered free.
1345 {Intrinsic::floor, MVT::f32, 9},
1346 {Intrinsic::floor, MVT::f64, 9},
1347 {Intrinsic::ceil, MVT::f32, 9},
1348 {Intrinsic::ceil, MVT::f64, 9},
1349 {Intrinsic::trunc, MVT::f32, 7},
1350 {Intrinsic::trunc, MVT::f64, 7},
1351 {Intrinsic::round, MVT::f32, 9},
1352 {Intrinsic::round, MVT::f64, 9},
1353 {Intrinsic::roundeven, MVT::f32, 9},
1354 {Intrinsic::roundeven, MVT::f64, 9},
1355 {Intrinsic::rint, MVT::f32, 7},
1356 {Intrinsic::rint, MVT::f64, 7},
1357 {Intrinsic::nearbyint, MVT::f32, 9},
1358 {Intrinsic::nearbyint, MVT::f64, 9},
1359 {Intrinsic::bswap, MVT::i16, 3},
1360 {Intrinsic::bswap, MVT::i32, 12},
1361 {Intrinsic::bswap, MVT::i64, 31},
1362 {Intrinsic::vp_bswap, MVT::i16, 3},
1363 {Intrinsic::vp_bswap, MVT::i32, 12},
1364 {Intrinsic::vp_bswap, MVT::i64, 31},
1365 {Intrinsic::vp_fshl, MVT::i8, 7},
1366 {Intrinsic::vp_fshl, MVT::i16, 7},
1367 {Intrinsic::vp_fshl, MVT::i32, 7},
1368 {Intrinsic::vp_fshl, MVT::i64, 7},
1369 {Intrinsic::vp_fshr, MVT::i8, 7},
1370 {Intrinsic::vp_fshr, MVT::i16, 7},
1371 {Intrinsic::vp_fshr, MVT::i32, 7},
1372 {Intrinsic::vp_fshr, MVT::i64, 7},
1373 {Intrinsic::bitreverse, MVT::i8, 17},
1374 {Intrinsic::bitreverse, MVT::i16, 24},
1375 {Intrinsic::bitreverse, MVT::i32, 33},
1376 {Intrinsic::bitreverse, MVT::i64, 52},
1377 {Intrinsic::vp_bitreverse, MVT::i8, 17},
1378 {Intrinsic::vp_bitreverse, MVT::i16, 24},
1379 {Intrinsic::vp_bitreverse, MVT::i32, 33},
1380 {Intrinsic::vp_bitreverse, MVT::i64, 52},
1381 {Intrinsic::ctpop, MVT::i8, 12},
1382 {Intrinsic::ctpop, MVT::i16, 19},
1383 {Intrinsic::ctpop, MVT::i32, 20},
1384 {Intrinsic::ctpop, MVT::i64, 21},
1385 {Intrinsic::ctlz, MVT::i8, 19},
1386 {Intrinsic::ctlz, MVT::i16, 28},
1387 {Intrinsic::ctlz, MVT::i32, 31},
1388 {Intrinsic::ctlz, MVT::i64, 35},
1389 {Intrinsic::cttz, MVT::i8, 16},
1390 {Intrinsic::cttz, MVT::i16, 23},
1391 {Intrinsic::cttz, MVT::i32, 24},
1392 {Intrinsic::cttz, MVT::i64, 25},
1393 {Intrinsic::vp_ctpop, MVT::i8, 12},
1394 {Intrinsic::vp_ctpop, MVT::i16, 19},
1395 {Intrinsic::vp_ctpop, MVT::i32, 20},
1396 {Intrinsic::vp_ctpop, MVT::i64, 21},
1397 {Intrinsic::vp_ctlz, MVT::i8, 19},
1398 {Intrinsic::vp_ctlz, MVT::i16, 28},
1399 {Intrinsic::vp_ctlz, MVT::i32, 31},
1400 {Intrinsic::vp_ctlz, MVT::i64, 35},
1401 {Intrinsic::vp_cttz, MVT::i8, 16},
1402 {Intrinsic::vp_cttz, MVT::i16, 23},
1403 {Intrinsic::vp_cttz, MVT::i32, 24},
1404 {Intrinsic::vp_cttz, MVT::i64, 25},
1405};
1406
1410 auto *RetTy = ICA.getReturnType();
1411 switch (ICA.getID()) {
1412 case Intrinsic::lrint:
1413 case Intrinsic::llrint:
1414 case Intrinsic::lround:
1415 case Intrinsic::llround: {
1416 auto LT = getTypeLegalizationCost(RetTy);
1417 Type *SrcTy = ICA.getArgTypes().front();
1418 auto SrcLT = getTypeLegalizationCost(SrcTy);
1419 if (ST->hasVInstructions() && LT.second.isVector()) {
1421 unsigned SrcEltSz = DL.getTypeSizeInBits(SrcTy->getScalarType());
1422 unsigned DstEltSz = DL.getTypeSizeInBits(RetTy->getScalarType());
1423 if (LT.second.getVectorElementType() == MVT::bf16) {
1424 if (!ST->hasVInstructionsBF16Minimal())
1426 if (DstEltSz == 32)
1427 Ops = {RISCV::VFWCVTBF16_F_F_V, RISCV::VFCVT_X_F_V};
1428 else
1429 Ops = {RISCV::VFWCVTBF16_F_F_V, RISCV::VFWCVT_X_F_V};
1430 } else if (LT.second.getVectorElementType() == MVT::f16 &&
1431 !ST->hasVInstructionsF16()) {
1432 if (!ST->hasVInstructionsF16Minimal())
1434 if (DstEltSz == 32)
1435 Ops = {RISCV::VFWCVT_F_F_V, RISCV::VFCVT_X_F_V};
1436 else
1437 Ops = {RISCV::VFWCVT_F_F_V, RISCV::VFWCVT_X_F_V};
1438
1439 } else if (SrcEltSz > DstEltSz) {
1440 Ops = {RISCV::VFNCVT_X_F_W};
1441 } else if (SrcEltSz < DstEltSz) {
1442 Ops = {RISCV::VFWCVT_X_F_V};
1443 } else {
1444 Ops = {RISCV::VFCVT_X_F_V};
1445 }
1446
1447 // We need to use the source LMUL in the case of a narrowing op, and the
1448 // destination LMUL otherwise.
1449 if (SrcEltSz > DstEltSz)
1450 return SrcLT.first *
1451 getRISCVInstructionCost(Ops, SrcLT.second, CostKind);
1452 return LT.first * getRISCVInstructionCost(Ops, LT.second, CostKind);
1453 }
1454 break;
1455 }
1456 case Intrinsic::ceil:
1457 case Intrinsic::floor:
1458 case Intrinsic::trunc:
1459 case Intrinsic::rint:
1460 case Intrinsic::round:
1461 case Intrinsic::roundeven: {
1462 // These all use the same code.
1463 auto LT = getTypeLegalizationCost(RetTy);
1464 if (!LT.second.isVector() && TLI->isOperationCustom(ISD::FCEIL, LT.second))
1465 return LT.first * 8;
1466 break;
1467 }
1468 case Intrinsic::umin:
1469 case Intrinsic::umax:
1470 case Intrinsic::smin:
1471 case Intrinsic::smax: {
1472 auto LT = getTypeLegalizationCost(RetTy);
1473 if (LT.second.isScalarInteger() && ST->hasStdExtZbb())
1474 return LT.first;
1475
1476 if (ST->hasVInstructions() && LT.second.isVector()) {
1477 unsigned Op;
1478 switch (ICA.getID()) {
1479 case Intrinsic::umin:
1480 Op = RISCV::VMINU_VV;
1481 break;
1482 case Intrinsic::umax:
1483 Op = RISCV::VMAXU_VV;
1484 break;
1485 case Intrinsic::smin:
1486 Op = RISCV::VMIN_VV;
1487 break;
1488 case Intrinsic::smax:
1489 Op = RISCV::VMAX_VV;
1490 break;
1491 }
1492 return LT.first * getRISCVInstructionCost(Op, LT.second, CostKind);
1493 }
1494 break;
1495 }
1496 case Intrinsic::sadd_sat:
1497 case Intrinsic::ssub_sat:
1498 case Intrinsic::uadd_sat:
1499 case Intrinsic::usub_sat: {
1500 auto LT = getTypeLegalizationCost(RetTy);
1501 if (ST->hasVInstructions() && LT.second.isVector()) {
1502 unsigned Op;
1503 switch (ICA.getID()) {
1504 case Intrinsic::sadd_sat:
1505 Op = RISCV::VSADD_VV;
1506 break;
1507 case Intrinsic::ssub_sat:
1508 Op = RISCV::VSSUB_VV;
1509 break;
1510 case Intrinsic::uadd_sat:
1511 Op = RISCV::VSADDU_VV;
1512 break;
1513 case Intrinsic::usub_sat:
1514 Op = RISCV::VSSUBU_VV;
1515 break;
1516 }
1517 return LT.first * getRISCVInstructionCost(Op, LT.second, CostKind);
1518 }
1519 break;
1520 }
1521 case Intrinsic::fma:
1522 case Intrinsic::fmuladd: {
1523 // TODO: handle promotion with f16/bf16 with zvfhmin/zvfbfmin
1524 auto LT = getTypeLegalizationCost(RetTy);
1525 if (ST->hasVInstructions() && LT.second.isVector())
1526 return LT.first *
1527 getRISCVInstructionCost(RISCV::VFMADD_VV, LT.second, CostKind);
1528 break;
1529 }
1530 case Intrinsic::fabs: {
1531 auto LT = getTypeLegalizationCost(RetTy);
1532 if (ST->hasVInstructions() && LT.second.isVector()) {
1533 // lui a0, 8
1534 // addi a0, a0, -1
1535 // vsetvli a1, zero, e16, m1, ta, ma
1536 // vand.vx v8, v8, a0
1537 // f16 with zvfhmin and bf16 with zvfhbmin
1538 if (LT.second.getVectorElementType() == MVT::bf16 ||
1539 (LT.second.getVectorElementType() == MVT::f16 &&
1540 !ST->hasVInstructionsF16()))
1541 return LT.first * getRISCVInstructionCost(RISCV::VAND_VX, LT.second,
1542 CostKind) +
1543 2;
1544 else
1545 return LT.first *
1546 getRISCVInstructionCost(RISCV::VFSGNJX_VV, LT.second, CostKind);
1547 }
1548 break;
1549 }
1550 case Intrinsic::sqrt: {
1551 auto LT = getTypeLegalizationCost(RetTy);
1552 if (ST->hasVInstructions() && LT.second.isVector()) {
1555 MVT ConvType = LT.second;
1556 MVT FsqrtType = LT.second;
1557 // f16 with zvfhmin and bf16 with zvfbfmin and the type of nxv32[b]f16
1558 // will be spilt.
1559 if (LT.second.getVectorElementType() == MVT::bf16) {
1560 if (LT.second == MVT::nxv32bf16) {
1561 ConvOp = {RISCV::VFWCVTBF16_F_F_V, RISCV::VFWCVTBF16_F_F_V,
1562 RISCV::VFNCVTBF16_F_F_W, RISCV::VFNCVTBF16_F_F_W};
1563 FsqrtOp = {RISCV::VFSQRT_V, RISCV::VFSQRT_V};
1564 ConvType = MVT::nxv16f16;
1565 FsqrtType = MVT::nxv16f32;
1566 } else {
1567 ConvOp = {RISCV::VFWCVTBF16_F_F_V, RISCV::VFNCVTBF16_F_F_W};
1568 FsqrtOp = {RISCV::VFSQRT_V};
1569 FsqrtType = TLI->getTypeToPromoteTo(ISD::FSQRT, FsqrtType);
1570 }
1571 } else if (LT.second.getVectorElementType() == MVT::f16 &&
1572 !ST->hasVInstructionsF16()) {
1573 if (LT.second == MVT::nxv32f16) {
1574 ConvOp = {RISCV::VFWCVT_F_F_V, RISCV::VFWCVT_F_F_V,
1575 RISCV::VFNCVT_F_F_W, RISCV::VFNCVT_F_F_W};
1576 FsqrtOp = {RISCV::VFSQRT_V, RISCV::VFSQRT_V};
1577 ConvType = MVT::nxv16f16;
1578 FsqrtType = MVT::nxv16f32;
1579 } else {
1580 ConvOp = {RISCV::VFWCVT_F_F_V, RISCV::VFNCVT_F_F_W};
1581 FsqrtOp = {RISCV::VFSQRT_V};
1582 FsqrtType = TLI->getTypeToPromoteTo(ISD::FSQRT, FsqrtType);
1583 }
1584 } else {
1585 FsqrtOp = {RISCV::VFSQRT_V};
1586 }
1587
1588 return LT.first * (getRISCVInstructionCost(FsqrtOp, FsqrtType, CostKind) +
1589 getRISCVInstructionCost(ConvOp, ConvType, CostKind));
1590 }
1591 break;
1592 }
1593 case Intrinsic::cttz:
1594 case Intrinsic::ctlz:
1595 case Intrinsic::ctpop: {
1596 auto LT = getTypeLegalizationCost(RetTy);
1597 if (ST->hasStdExtZvbb() && LT.second.isVector()) {
1598 unsigned Op;
1599 switch (ICA.getID()) {
1600 case Intrinsic::cttz:
1601 Op = RISCV::VCTZ_V;
1602 break;
1603 case Intrinsic::ctlz:
1604 Op = RISCV::VCLZ_V;
1605 break;
1606 case Intrinsic::ctpop:
1607 Op = RISCV::VCPOP_V;
1608 break;
1609 }
1610 return LT.first * getRISCVInstructionCost(Op, LT.second, CostKind);
1611 }
1612 break;
1613 }
1614 case Intrinsic::abs: {
1615 auto LT = getTypeLegalizationCost(RetTy);
1616 if (ST->hasVInstructions() && LT.second.isVector()) {
1617 // vabs.v v10, v8
1618 if (ST->hasStdExtZvabd())
1619 return LT.first *
1620 getRISCVInstructionCost({RISCV::VABS_V}, LT.second, CostKind);
1621
1622 // vrsub.vi v10, v8, 0
1623 // vmax.vv v8, v8, v10
1624 return LT.first *
1625 getRISCVInstructionCost({RISCV::VRSUB_VI, RISCV::VMAX_VV},
1626 LT.second, CostKind);
1627 }
1628 break;
1629 }
1630 case Intrinsic::fshl:
1631 case Intrinsic::fshr: {
1632 if (ICA.getArgs().empty())
1633 break;
1634
1635 // Funnel-shifts are ROTL/ROTR when the first and second operand are equal.
1636 // When Zbb/Zbkb is enabled we can use a single ROL(W)/ROR(I)(W)
1637 // instruction.
1638 if ((ST->hasStdExtZbb() || ST->hasStdExtZbkb()) && RetTy->isIntegerTy() &&
1639 ICA.getArgs()[0] == ICA.getArgs()[1] &&
1640 (RetTy->getIntegerBitWidth() == 32 ||
1641 RetTy->getIntegerBitWidth() == 64) &&
1642 RetTy->getIntegerBitWidth() <= ST->getXLen()) {
1643 return 1;
1644 }
1645 break;
1646 }
1647 case Intrinsic::clmul: {
1648 auto LT = getTypeLegalizationCost(RetTy);
1649 if (!LT.second.isVector() && ST->hasStdExtZvbc() && !ST->hasStdExtZbc() &&
1650 !ST->hasStdExtZbkc()) {
1651 // TODO: Once custom lowering in this case for RV32 is added, this guard
1652 // should be removed and the cost model should be updated.
1653 if (!ST->is64Bit() || LT.second != MVT::i64)
1654 break;
1655 // vmv.s.x v8, a0
1656 // vclmul.vx v8, v8, a1
1657 // vmv.x.s a0, v8
1658 MVT VecVT = MVT::getScalableVectorVT(LT.second, 1);
1659 return LT.first * getRISCVInstructionCost(
1660 {RISCV::VMV_S_X, RISCV::VCLMUL_VX, RISCV::VMV_X_S},
1661 VecVT, CostKind);
1662 }
1663 break;
1664 }
1665 case Intrinsic::masked_udiv:
1666 return getArithmeticInstrCost(Instruction::UDiv, ICA.getReturnType(),
1667 CostKind);
1668 case Intrinsic::masked_sdiv:
1669 return getArithmeticInstrCost(Instruction::SDiv, ICA.getReturnType(),
1670 CostKind);
1671 case Intrinsic::masked_urem:
1672 return getArithmeticInstrCost(Instruction::URem, ICA.getReturnType(),
1673 CostKind);
1674 case Intrinsic::masked_srem:
1675 return getArithmeticInstrCost(Instruction::SRem, ICA.getReturnType(),
1676 CostKind);
1677 case Intrinsic::get_active_lane_mask: {
1678 if (ST->hasVInstructions()) {
1679 Type *ExpRetTy = VectorType::get(
1680 ICA.getArgTypes()[0], cast<VectorType>(RetTy)->getElementCount());
1681 auto LT = getTypeLegalizationCost(ExpRetTy);
1682
1683 // vid.v v8 // considered hoisted
1684 // vsaddu.vx v8, v8, a0
1685 // vmsltu.vx v0, v8, a1
1686 return LT.first *
1687 getRISCVInstructionCost({RISCV::VSADDU_VX, RISCV::VMSLTU_VX},
1688 LT.second, CostKind);
1689 }
1690 break;
1691 }
1692 // TODO: add more intrinsic
1693 case Intrinsic::stepvector: {
1694 auto LT = getTypeLegalizationCost(RetTy);
1695 // Legalisation of illegal types involves an `index' instruction plus
1696 // (LT.first - 1) vector adds.
1697 if (ST->hasVInstructions())
1698 return getRISCVInstructionCost(RISCV::VID_V, LT.second, CostKind) +
1699 (LT.first - 1) *
1700 getRISCVInstructionCost(RISCV::VADD_VX, LT.second, CostKind);
1701 return 1 + (LT.first - 1);
1702 }
1703 case Intrinsic::vector_splice_left:
1704 case Intrinsic::vector_splice_right: {
1705 auto LT = getTypeLegalizationCost(RetTy);
1706 // Constant offsets fall through to getShuffleCost.
1707 if (!ICA.isTypeBasedOnly() && isa<ConstantInt>(ICA.getArgs()[2]))
1708 break;
1709 if (ST->hasVInstructions() && LT.second.isVector()) {
1710 return LT.first *
1711 getRISCVInstructionCost({RISCV::VSLIDEDOWN_VX, RISCV::VSLIDEUP_VX},
1712 LT.second, CostKind);
1713 }
1714 break;
1715 }
1716 case Intrinsic::experimental_cttz_elts: {
1717 if (getTLI()->shouldExpandCttzElements({}))
1718 break;
1720 Type *ArgTy = ICA.getArgTypes()[0];
1721 auto LT = getTypeLegalizationCost(ArgTy);
1722
1723 // If the element type is not i1, do a comparison with all-zeros.
1724 if (LT.second.getVectorElementType() != MVT::i1)
1725 Cost += getRISCVInstructionCost(RISCV::VMSNE_VI, LT.second, CostKind);
1726
1727 Cost += getRISCVInstructionCost(RISCV::VFIRST_M, LT.second, CostKind);
1728
1729 // If zero_is_poison is false, then we will generate additional
1730 // cmp + select instructions to convert -1 to EVL.
1731 Type *BoolTy = Type::getInt1Ty(RetTy->getContext());
1732 if (ICA.getArgs().size() > 1 &&
1733 cast<ConstantInt>(ICA.getArgs()[1])->isZero())
1734 Cost += getCmpSelInstrCost(Instruction::ICmp, BoolTy, RetTy,
1736 getCmpSelInstrCost(Instruction::Select, RetTy, BoolTy,
1738
1739 return LT.first * Cost;
1740 }
1741 case Intrinsic::experimental_vp_splice: {
1742 // To support type-based query from vectorizer, set the index to 0.
1743 // Note that index only change the cost from vslide.vx to vslide.vi and in
1744 // current implementations they have same costs.
1746 cast<VectorType>(ICA.getArgTypes()[0]), {}, CostKind,
1748 }
1749 case Intrinsic::vp_merge: {
1750 // If an operand is a binary op and the type is legal, RISCVVectorPeephole
1751 // will likely fold the resulting vmerge.vvm away.
1753 getTypeLegalizationCost(RetTy).first == 1)
1754 return TTI::TCC_Free;
1755 break;
1756 }
1757 case Intrinsic::fptoui_sat:
1758 case Intrinsic::fptosi_sat: {
1760 bool IsSigned = ICA.getID() == Intrinsic::fptosi_sat;
1761 Type *SrcTy = ICA.getArgTypes()[0];
1762
1763 auto SrcLT = getTypeLegalizationCost(SrcTy);
1764 auto DstLT = getTypeLegalizationCost(RetTy);
1765 if (!SrcTy->isVectorTy())
1766 break;
1767
1768 if (!SrcLT.first.isValid() || !DstLT.first.isValid())
1770
1771 Cost +=
1772 getCastInstrCost(IsSigned ? Instruction::FPToSI : Instruction::FPToUI,
1773 RetTy, SrcTy, TTI::CastContextHint::None, CostKind);
1774
1775 // Handle NaN.
1776 // vmfne v0, v8, v8 # If v8[i] is NaN set v0[i] to 1.
1777 // vmerge.vim v8, v8, 0, v0 # Convert NaN to 0.
1778 Type *CondTy = RetTy->getWithNewBitWidth(1);
1779 Cost += getCmpSelInstrCost(BinaryOperator::FCmp, SrcTy, CondTy,
1781 Cost += getCmpSelInstrCost(BinaryOperator::Select, RetTy, CondTy,
1783 return Cost;
1784 }
1785 case Intrinsic::experimental_vector_extract_last_active: {
1786 auto *ValTy = cast<VectorType>(ICA.getArgTypes()[0]);
1787 auto *MaskTy = cast<VectorType>(ICA.getArgTypes()[1]);
1788
1789 auto ValLT = getTypeLegalizationCost(ValTy);
1790 auto MaskLT = getTypeLegalizationCost(MaskTy);
1791
1792 // TODO: Return cheaper cost when the entire lane is inactive.
1793 // The expected asm sequence is:
1794 // vcpop.m a0, v0
1795 // beqz a0, exit # Return passthru when the entire lane is inactive.
1796 // vid v10, v0.t
1797 // vredmaxu.vs v10, v10, v10
1798 // vmv.x.s a0, v10
1799 // zext.b a0, a0
1800 // vslidedown.vx v8, v8, a0
1801 // vmv.x.s a0, v8
1802 // exit:
1803 // ...
1804
1805 // Find a suitable type for a stepvector.
1806 ConstantRange VScaleRange(APInt(64, 1), APInt::getZero(64));
1807 unsigned EltWidth = getTLI()->getBitWidthForCttzElements(
1808 TLI->getVectorIdxTy(getDataLayout()), MaskTy->getElementCount(),
1809 /*ZeroIsPoison=*/true, &VScaleRange);
1810 EltWidth = std::max(EltWidth, MaskTy->getScalarSizeInBits());
1811 Type *StepTy = Type::getIntNTy(MaskTy->getContext(), EltWidth);
1812 auto *StepVecTy = VectorType::get(StepTy, ValTy->getElementCount());
1813 auto StepLT = getTypeLegalizationCost(StepVecTy);
1814
1815 // Currently expandVectorFindLastActive cannot handle step vector split.
1816 // So return invalid when the type needs split.
1817 // FIXME: Remove this if expandVectorFindLastActive supports split vector.
1818 if (StepLT.first > 1)
1820
1822 unsigned Opcodes[] = {RISCV::VID_V, RISCV::VREDMAXU_VS, RISCV::VMV_X_S};
1823
1824 Cost += MaskLT.first *
1825 getRISCVInstructionCost(RISCV::VCPOP_M, MaskLT.second, CostKind);
1826 Cost += getCFInstrCost(Instruction::CondBr, CostKind, nullptr);
1827 Cost += StepLT.first *
1828 getRISCVInstructionCost(Opcodes, StepLT.second, CostKind);
1829 Cost += getCastInstrCost(Instruction::ZExt,
1830 Type::getInt64Ty(ValTy->getContext()), StepTy,
1832 Cost += ValLT.first *
1833 getRISCVInstructionCost({RISCV::VSLIDEDOWN_VI, RISCV::VMV_X_S},
1834 ValLT.second, CostKind);
1835 return Cost;
1836 }
1837 }
1838
1839 if (ST->hasVInstructions() && RetTy->isVectorTy()) {
1840 if (auto LT = getTypeLegalizationCost(RetTy);
1841 LT.second.isVector()) {
1842 MVT EltTy = LT.second.getVectorElementType();
1843 if (const auto *Entry = CostTableLookup(VectorIntrinsicCostTable,
1844 ICA.getID(), EltTy))
1845 return LT.first * Entry->Cost;
1846 }
1847 }
1848
1850}
1851
1854 const SCEV *Ptr,
1856 // Address computations for vector indexed load/store likely require an offset
1857 // and/or scaling.
1858 if (ST->hasVInstructions() && PtrTy->isVectorTy())
1859 return getArithmeticInstrCost(Instruction::Add, PtrTy, CostKind);
1860
1861 return BaseT::getAddressComputationCost(PtrTy, SE, Ptr, CostKind);
1862}
1863
1865 Type *Src,
1868 const Instruction *I) const {
1869 bool IsVectorType = isa<VectorType>(Dst) && isa<VectorType>(Src);
1870 if (!IsVectorType)
1871 return BaseT::getCastInstrCost(Opcode, Dst, Src, CCH, CostKind, I);
1872
1873 // TODO: Add proper cost model for P extension fixed vectors (e.g., v4i16)
1874 // For now, skip all fixed vector cost analysis when P extension is available
1875 // to avoid crashes in getMinRVVVectorSizeInBits()
1876 if (ST->hasStdExtP() &&
1878 return 1; // Treat as single instruction cost for now
1879 }
1880
1881 // FIXME: Need to compute legalizing cost for illegal types. The current
1882 // code handles only legal types and those which can be trivially
1883 // promoted to legal.
1884 if (!ST->hasVInstructions() || Src->getScalarSizeInBits() > ST->getELen() ||
1885 Dst->getScalarSizeInBits() > ST->getELen())
1886 return BaseT::getCastInstrCost(Opcode, Dst, Src, CCH, CostKind, I);
1887
1888 int ISD = TLI->InstructionOpcodeToISD(Opcode);
1889 assert(ISD && "Invalid opcode");
1890 std::pair<InstructionCost, MVT> SrcLT = getTypeLegalizationCost(Src);
1891 std::pair<InstructionCost, MVT> DstLT = getTypeLegalizationCost(Dst);
1892
1893 // Handle i1 source and dest cases *before* calling logic in BasicTTI.
1894 // The shared implementation doesn't model vector widening during legalization
1895 // and instead assumes scalarization. In order to scalarize an <N x i1>
1896 // vector, we need to extend/trunc to/from i8. If we don't special case
1897 // this, we can get an infinite recursion cycle.
1898 switch (ISD) {
1899 default:
1900 break;
1901 case ISD::SIGN_EXTEND:
1902 case ISD::ZERO_EXTEND:
1903 if (Src->getScalarSizeInBits() == 1) {
1904 // We do not use vsext/vzext to extend from mask vector.
1905 // Instead we use the following instructions to extend from mask vector:
1906 // vmv.v.i v8, 0
1907 // vmerge.vim v8, v8, -1, v0 (repeated per split)
1908 return getRISCVInstructionCost(RISCV::VMV_V_I, DstLT.second, CostKind) +
1909 DstLT.first * getRISCVInstructionCost(RISCV::VMERGE_VIM,
1910 DstLT.second, CostKind) +
1911 DstLT.first - 1;
1912 }
1913 break;
1914 case ISD::TRUNCATE:
1915 if (Dst->getScalarSizeInBits() == 1) {
1916 // We do not use several vncvt to truncate to mask vector. So we could
1917 // not use PowDiff to calculate it.
1918 // Instead we use the following instructions to truncate to mask vector:
1919 // vand.vi v8, v8, 1
1920 // vmsne.vi v0, v8, 0
1921 return SrcLT.first *
1922 getRISCVInstructionCost({RISCV::VAND_VI, RISCV::VMSNE_VI},
1923 SrcLT.second, CostKind) +
1924 SrcLT.first - 1;
1925 }
1926 break;
1927 };
1928
1929 // Our actual lowering for the case where a wider legal type is available
1930 // uses promotion to the wider type. This is reflected in the result of
1931 // getTypeLegalizationCost, but BasicTTI assumes the widened cases are
1932 // scalarized if the legalized Src and Dst are not equal sized.
1933 const DataLayout &DL = this->getDataLayout();
1934 if (!SrcLT.second.isVector() || !DstLT.second.isVector() ||
1935 !SrcLT.first.isValid() || !DstLT.first.isValid() ||
1936 !TypeSize::isKnownLE(DL.getTypeSizeInBits(Src),
1937 SrcLT.second.getSizeInBits()) ||
1938 !TypeSize::isKnownLE(DL.getTypeSizeInBits(Dst),
1939 DstLT.second.getSizeInBits()) ||
1940 SrcLT.first > 1 || DstLT.first > 1)
1941 return BaseT::getCastInstrCost(Opcode, Dst, Src, CCH, CostKind, I);
1942
1943 // The split cost is handled by the base getCastInstrCost
1944 assert((SrcLT.first == 1) && (DstLT.first == 1) && "Illegal type");
1945
1946 int PowDiff = (int)Log2_32(DstLT.second.getScalarSizeInBits()) -
1947 (int)Log2_32(SrcLT.second.getScalarSizeInBits());
1948 switch (ISD) {
1949 case ISD::SIGN_EXTEND:
1950 case ISD::ZERO_EXTEND: {
1951 if ((PowDiff < 1) || (PowDiff > 3))
1952 return BaseT::getCastInstrCost(Opcode, Dst, Src, CCH, CostKind, I);
1953 unsigned SExtOp[] = {RISCV::VSEXT_VF2, RISCV::VSEXT_VF4, RISCV::VSEXT_VF8};
1954 unsigned ZExtOp[] = {RISCV::VZEXT_VF2, RISCV::VZEXT_VF4, RISCV::VZEXT_VF8};
1955 unsigned Op =
1956 (ISD == ISD::SIGN_EXTEND) ? SExtOp[PowDiff - 1] : ZExtOp[PowDiff - 1];
1957 return getRISCVInstructionCost(Op, DstLT.second, CostKind);
1958 }
1959 case ISD::TRUNCATE:
1960 case ISD::FP_EXTEND:
1961 case ISD::FP_ROUND: {
1962 // Counts of narrow/widen instructions.
1963 unsigned SrcEltSize = SrcLT.second.getScalarSizeInBits();
1964 unsigned DstEltSize = DstLT.second.getScalarSizeInBits();
1965
1966 unsigned Op = (ISD == ISD::TRUNCATE) ? RISCV::VNSRL_WI
1967 : (ISD == ISD::FP_EXTEND) ? RISCV::VFWCVT_F_F_V
1968 : RISCV::VFNCVT_F_F_W;
1970 for (; SrcEltSize != DstEltSize;) {
1971 MVT ElementMVT = (ISD == ISD::TRUNCATE)
1972 ? MVT::getIntegerVT(DstEltSize)
1973 : MVT::getFloatingPointVT(DstEltSize);
1974 MVT DstMVT = DstLT.second.changeVectorElementType(ElementMVT);
1975 DstEltSize =
1976 (DstEltSize > SrcEltSize) ? DstEltSize >> 1 : DstEltSize << 1;
1977 Cost += getRISCVInstructionCost(Op, DstMVT, CostKind);
1978 }
1979 return Cost;
1980 }
1981 case ISD::FP_TO_SINT:
1982 case ISD::FP_TO_UINT: {
1983 unsigned IsSigned = ISD == ISD::FP_TO_SINT;
1984 unsigned FCVT = IsSigned ? RISCV::VFCVT_RTZ_X_F_V : RISCV::VFCVT_RTZ_XU_F_V;
1985 unsigned FWCVT =
1986 IsSigned ? RISCV::VFWCVT_RTZ_X_F_V : RISCV::VFWCVT_RTZ_XU_F_V;
1987 unsigned FNCVT =
1988 IsSigned ? RISCV::VFNCVT_RTZ_X_F_W : RISCV::VFNCVT_RTZ_XU_F_W;
1989 unsigned SrcEltSize = Src->getScalarSizeInBits();
1990 unsigned DstEltSize = Dst->getScalarSizeInBits();
1992 if ((SrcEltSize == 16) &&
1993 (!ST->hasVInstructionsF16() || ((DstEltSize / 2) > SrcEltSize))) {
1994 // If the target only supports zvfhmin or it is fp16-to-i64 conversion
1995 // pre-widening to f32 and then convert f32 to integer
1996 VectorType *VecF32Ty =
1997 VectorType::get(Type::getFloatTy(Dst->getContext()),
1998 cast<VectorType>(Dst)->getElementCount());
1999 std::pair<InstructionCost, MVT> VecF32LT =
2000 getTypeLegalizationCost(VecF32Ty);
2001 Cost +=
2002 VecF32LT.first * getRISCVInstructionCost(RISCV::VFWCVT_F_F_V,
2003 VecF32LT.second, CostKind);
2004 Cost += getCastInstrCost(Opcode, Dst, VecF32Ty, CCH, CostKind, I);
2005 return Cost;
2006 }
2007 if (DstEltSize == SrcEltSize)
2008 Cost += getRISCVInstructionCost(FCVT, DstLT.second, CostKind);
2009 else if (DstEltSize > SrcEltSize)
2010 Cost += getRISCVInstructionCost(FWCVT, DstLT.second, CostKind);
2011 else { // (SrcEltSize > DstEltSize)
2012 // First do a narrowing conversion to an integer half the size, then
2013 // truncate if needed.
2014 MVT ElementVT = MVT::getIntegerVT(SrcEltSize / 2);
2015 MVT VecVT = DstLT.second.changeVectorElementType(ElementVT);
2016 Cost += getRISCVInstructionCost(FNCVT, VecVT, CostKind);
2017 if ((SrcEltSize / 2) > DstEltSize) {
2018 Type *VecTy = EVT(VecVT).getTypeForEVT(Dst->getContext());
2019 Cost +=
2020 getCastInstrCost(Instruction::Trunc, Dst, VecTy, CCH, CostKind, I);
2021 }
2022 }
2023 return Cost;
2024 }
2025 case ISD::SINT_TO_FP:
2026 case ISD::UINT_TO_FP: {
2027 unsigned IsSigned = ISD == ISD::SINT_TO_FP;
2028 unsigned FCVT = IsSigned ? RISCV::VFCVT_F_X_V : RISCV::VFCVT_F_XU_V;
2029 unsigned FWCVT = IsSigned ? RISCV::VFWCVT_F_X_V : RISCV::VFWCVT_F_XU_V;
2030 unsigned FNCVT = IsSigned ? RISCV::VFNCVT_F_X_W : RISCV::VFNCVT_F_XU_W;
2031 unsigned SrcEltSize = Src->getScalarSizeInBits();
2032 unsigned DstEltSize = Dst->getScalarSizeInBits();
2033
2035 if ((DstEltSize == 16) &&
2036 (!ST->hasVInstructionsF16() || ((SrcEltSize / 2) > DstEltSize))) {
2037 // If the target only supports zvfhmin or it is i64-to-fp16 conversion
2038 // it is converted to f32 and then converted to f16
2039 VectorType *VecF32Ty =
2040 VectorType::get(Type::getFloatTy(Dst->getContext()),
2041 cast<VectorType>(Dst)->getElementCount());
2042 std::pair<InstructionCost, MVT> VecF32LT =
2043 getTypeLegalizationCost(VecF32Ty);
2044 Cost += getCastInstrCost(Opcode, VecF32Ty, Src, CCH, CostKind, I);
2045 Cost += VecF32LT.first * getRISCVInstructionCost(RISCV::VFNCVT_F_F_W,
2046 DstLT.second, CostKind);
2047 return Cost;
2048 }
2049
2050 if (DstEltSize == SrcEltSize)
2051 Cost += getRISCVInstructionCost(FCVT, DstLT.second, CostKind);
2052 else if (DstEltSize > SrcEltSize) {
2053 if ((DstEltSize / 2) > SrcEltSize) {
2054 VectorType *VecTy =
2055 VectorType::get(IntegerType::get(Dst->getContext(), DstEltSize / 2),
2056 cast<VectorType>(Dst)->getElementCount());
2057 unsigned Op = IsSigned ? Instruction::SExt : Instruction::ZExt;
2058 Cost += getCastInstrCost(Op, VecTy, Src, CCH, CostKind, I);
2059 }
2060 Cost += getRISCVInstructionCost(FWCVT, DstLT.second, CostKind);
2061 } else
2062 Cost += getRISCVInstructionCost(FNCVT, DstLT.second, CostKind);
2063 return Cost;
2064 }
2065 }
2066 return BaseT::getCastInstrCost(Opcode, Dst, Src, CCH, CostKind, I);
2067}
2068
2069unsigned RISCVTTIImpl::getEstimatedVLFor(VectorType *Ty) const {
2070 if (isa<ScalableVectorType>(Ty)) {
2071 const unsigned EltSize = DL.getTypeSizeInBits(Ty->getElementType());
2072 const unsigned MinSize = DL.getTypeSizeInBits(Ty).getKnownMinValue();
2073 const unsigned VectorBits = *getVScaleForTuning() * RISCV::RVVBitsPerBlock;
2074 return RISCVTargetLowering::computeVLMAX(VectorBits, EltSize, MinSize);
2075 }
2076 return cast<FixedVectorType>(Ty)->getNumElements();
2077}
2078
2081 FastMathFlags FMF,
2083 if (isa<FixedVectorType>(Ty) && !ST->useRVVForFixedLengthVectors())
2084 return BaseT::getMinMaxReductionCost(IID, Ty, FMF, CostKind);
2085
2086 // Skip if scalar size of Ty is bigger than ELEN.
2087 if (Ty->getScalarSizeInBits() > ST->getELen())
2088 return BaseT::getMinMaxReductionCost(IID, Ty, FMF, CostKind);
2089
2090 std::pair<InstructionCost, MVT> LT = getTypeLegalizationCost(Ty);
2091 if (Ty->getElementType()->isIntegerTy(1)) {
2092 // SelectionDAGBuilder does following transforms:
2093 // vector_reduce_{smin,umax}(<n x i1>) --> vector_reduce_or(<n x i1>)
2094 // vector_reduce_{smax,umin}(<n x i1>) --> vector_reduce_and(<n x i1>)
2095 if (IID == Intrinsic::umax || IID == Intrinsic::smin)
2096 return getArithmeticReductionCost(Instruction::Or, Ty, FMF, CostKind);
2097 else
2098 return getArithmeticReductionCost(Instruction::And, Ty, FMF, CostKind);
2099 }
2100
2101 if (IID == Intrinsic::maximum || IID == Intrinsic::minimum) {
2103 InstructionCost ExtraCost = 0;
2104 switch (IID) {
2105 case Intrinsic::maximum:
2106 if (FMF.noNaNs()) {
2107 Opcodes = {RISCV::VFREDMAX_VS, RISCV::VFMV_F_S};
2108 } else {
2109 Opcodes = {RISCV::VMFNE_VV, RISCV::VCPOP_M, RISCV::VFREDMAX_VS,
2110 RISCV::VFMV_F_S};
2111 // Cost of Canonical Nan + branch
2112 // lui a0, 523264
2113 // fmv.w.x fa0, a0
2114 Type *DstTy = Ty->getScalarType();
2115 const unsigned EltTyBits = DstTy->getScalarSizeInBits();
2116 Type *SrcTy = IntegerType::getIntNTy(DstTy->getContext(), EltTyBits);
2117 ExtraCost = 1 +
2118 getCastInstrCost(Instruction::UIToFP, DstTy, SrcTy,
2120 getCFInstrCost(Instruction::CondBr, CostKind);
2121 }
2122 break;
2123
2124 case Intrinsic::minimum:
2125 if (FMF.noNaNs()) {
2126 Opcodes = {RISCV::VFREDMIN_VS, RISCV::VFMV_F_S};
2127 } else {
2128 Opcodes = {RISCV::VMFNE_VV, RISCV::VCPOP_M, RISCV::VFREDMIN_VS,
2129 RISCV::VFMV_F_S};
2130 // Cost of Canonical Nan + branch
2131 // lui a0, 523264
2132 // fmv.w.x fa0, a0
2133 Type *DstTy = Ty->getScalarType();
2134 const unsigned EltTyBits = DL.getTypeSizeInBits(DstTy);
2135 Type *SrcTy = IntegerType::getIntNTy(DstTy->getContext(), EltTyBits);
2136 ExtraCost = 1 +
2137 getCastInstrCost(Instruction::UIToFP, DstTy, SrcTy,
2139 getCFInstrCost(Instruction::CondBr, CostKind);
2140 }
2141 break;
2142 }
2143 return ExtraCost + getRISCVInstructionCost(Opcodes, LT.second, CostKind);
2144 }
2145
2146 // IR Reduction is composed by one rvv reduction instruction and vmv
2147 unsigned SplitOp;
2149 switch (IID) {
2150 default:
2151 llvm_unreachable("Unsupported intrinsic");
2152 case Intrinsic::smax:
2153 SplitOp = RISCV::VMAX_VV;
2154 Opcodes = {RISCV::VREDMAX_VS, RISCV::VMV_X_S};
2155 break;
2156 case Intrinsic::smin:
2157 SplitOp = RISCV::VMIN_VV;
2158 Opcodes = {RISCV::VREDMIN_VS, RISCV::VMV_X_S};
2159 break;
2160 case Intrinsic::umax:
2161 SplitOp = RISCV::VMAXU_VV;
2162 Opcodes = {RISCV::VREDMAXU_VS, RISCV::VMV_X_S};
2163 break;
2164 case Intrinsic::umin:
2165 SplitOp = RISCV::VMINU_VV;
2166 Opcodes = {RISCV::VREDMINU_VS, RISCV::VMV_X_S};
2167 break;
2168 case Intrinsic::maxnum:
2169 SplitOp = RISCV::VFMAX_VV;
2170 Opcodes = {RISCV::VFREDMAX_VS, RISCV::VFMV_F_S};
2171 break;
2172 case Intrinsic::minnum:
2173 SplitOp = RISCV::VFMIN_VV;
2174 Opcodes = {RISCV::VFREDMIN_VS, RISCV::VFMV_F_S};
2175 break;
2176 }
2177 // Add a cost for data larger than LMUL8
2178 InstructionCost SplitCost =
2179 (LT.first > 1) ? (LT.first - 1) *
2180 getRISCVInstructionCost(SplitOp, LT.second, CostKind)
2181 : 0;
2182 return SplitCost + getRISCVInstructionCost(Opcodes, LT.second, CostKind);
2183}
2184
2187 std::optional<FastMathFlags> FMF,
2189 if (isa<FixedVectorType>(Ty) && !ST->useRVVForFixedLengthVectors())
2190 return BaseT::getArithmeticReductionCost(Opcode, Ty, FMF, CostKind);
2191
2192 // Skip if scalar size of Ty is bigger than ELEN.
2193 if (Ty->getScalarSizeInBits() > ST->getELen())
2194 return BaseT::getArithmeticReductionCost(Opcode, Ty, FMF, CostKind);
2195
2196 int ISD = TLI->InstructionOpcodeToISD(Opcode);
2197 assert(ISD && "Invalid opcode");
2198
2199 if (ISD != ISD::ADD && ISD != ISD::OR && ISD != ISD::XOR && ISD != ISD::AND &&
2200 ISD != ISD::FADD)
2201 return BaseT::getArithmeticReductionCost(Opcode, Ty, FMF, CostKind);
2202
2203 std::pair<InstructionCost, MVT> LT = getTypeLegalizationCost(Ty);
2204 Type *ElementTy = Ty->getElementType();
2205 if (ElementTy->isIntegerTy(1)) {
2206 // Example sequences:
2207 // vfirst.m a0, v0
2208 // seqz a0, a0
2209 if (LT.second == MVT::v1i1)
2210 return getRISCVInstructionCost(RISCV::VFIRST_M, LT.second, CostKind) +
2211 getCmpSelInstrCost(Instruction::ICmp, ElementTy, ElementTy,
2213
2214 if (ISD == ISD::AND) {
2215 // Example sequences:
2216 // vmand.mm v8, v9, v8 ; needed every time type is split
2217 // vmnot.m v8, v0 ; alias for vmnand
2218 // vcpop.m a0, v8
2219 // seqz a0, a0
2220
2221 // See the discussion: https://github.com/llvm/llvm-project/pull/119160
2222 // For LMUL <= 8, there is no splitting,
2223 // the sequences are vmnot, vcpop and seqz.
2224 // When LMUL > 8 and split = 1,
2225 // the sequences are vmnand, vcpop and seqz.
2226 // When LMUL > 8 and split > 1,
2227 // the sequences are (LT.first-2) * vmand, vmnand, vcpop and seqz.
2228 return ((LT.first > 2) ? (LT.first - 2) : 0) *
2229 getRISCVInstructionCost(RISCV::VMAND_MM, LT.second, CostKind) +
2230 getRISCVInstructionCost(RISCV::VMNAND_MM, LT.second, CostKind) +
2231 getRISCVInstructionCost(RISCV::VCPOP_M, LT.second, CostKind) +
2232 getCmpSelInstrCost(Instruction::ICmp, ElementTy, ElementTy,
2234 } else if (ISD == ISD::XOR || ISD == ISD::ADD) {
2235 // Example sequences:
2236 // vsetvli a0, zero, e8, mf8, ta, ma
2237 // vmxor.mm v8, v0, v8 ; needed every time type is split
2238 // vcpop.m a0, v8
2239 // andi a0, a0, 1
2240 return (LT.first - 1) *
2241 getRISCVInstructionCost(RISCV::VMXOR_MM, LT.second, CostKind) +
2242 getRISCVInstructionCost(RISCV::VCPOP_M, LT.second, CostKind) + 1;
2243 } else {
2244 assert(ISD == ISD::OR);
2245 // Example sequences:
2246 // vsetvli a0, zero, e8, mf8, ta, ma
2247 // vmor.mm v8, v9, v8 ; needed every time type is split
2248 // vcpop.m a0, v0
2249 // snez a0, a0
2250 return (LT.first - 1) *
2251 getRISCVInstructionCost(RISCV::VMOR_MM, LT.second, CostKind) +
2252 getRISCVInstructionCost(RISCV::VCPOP_M, LT.second, CostKind) +
2253 getCmpSelInstrCost(Instruction::ICmp, ElementTy, ElementTy,
2255 }
2256 }
2257
2258 // IR Reduction of or/and is composed by one vmv and one rvv reduction
2259 // instruction, and others is composed by two vmv and one rvv reduction
2260 // instruction
2261 unsigned SplitOp;
2263 switch (ISD) {
2264 case ISD::ADD:
2265 SplitOp = RISCV::VADD_VV;
2266 Opcodes = {RISCV::VMV_S_X, RISCV::VREDSUM_VS, RISCV::VMV_X_S};
2267 break;
2268 case ISD::OR:
2269 SplitOp = RISCV::VOR_VV;
2270 Opcodes = {RISCV::VREDOR_VS, RISCV::VMV_X_S};
2271 break;
2272 case ISD::XOR:
2273 SplitOp = RISCV::VXOR_VV;
2274 Opcodes = {RISCV::VMV_S_X, RISCV::VREDXOR_VS, RISCV::VMV_X_S};
2275 break;
2276 case ISD::AND:
2277 SplitOp = RISCV::VAND_VV;
2278 Opcodes = {RISCV::VREDAND_VS, RISCV::VMV_X_S};
2279 break;
2280 case ISD::FADD:
2281 // We can't promote f16/bf16 fadd reductions.
2282 if ((LT.second.getScalarType() == MVT::f16 && !ST->hasVInstructionsF16()) ||
2283 LT.second.getScalarType() == MVT::bf16)
2284 return BaseT::getArithmeticReductionCost(Opcode, Ty, FMF, CostKind);
2286 Opcodes.push_back(RISCV::VFMV_S_F);
2287 for (unsigned i = 0; i < LT.first.getValue(); i++)
2288 Opcodes.push_back(RISCV::VFREDOSUM_VS);
2289 Opcodes.push_back(RISCV::VFMV_F_S);
2290 return getRISCVInstructionCost(Opcodes, LT.second, CostKind);
2291 }
2292 SplitOp = RISCV::VFADD_VV;
2293 Opcodes = {RISCV::VFMV_S_F, RISCV::VFREDUSUM_VS, RISCV::VFMV_F_S};
2294 break;
2295 }
2296 // Add a cost for data larger than LMUL8
2297 InstructionCost SplitCost =
2298 (LT.first > 1) ? (LT.first - 1) *
2299 getRISCVInstructionCost(SplitOp, LT.second, CostKind)
2300 : 0;
2301 return SplitCost + getRISCVInstructionCost(Opcodes, LT.second, CostKind);
2302}
2303
2305 unsigned Opcode, bool IsUnsigned, Type *ResTy, VectorType *ValTy,
2306 std::optional<FastMathFlags> FMF, TTI::TargetCostKind CostKind) const {
2307 if (isa<FixedVectorType>(ValTy) && !ST->useRVVForFixedLengthVectors())
2308 return BaseT::getExtendedReductionCost(Opcode, IsUnsigned, ResTy, ValTy,
2309 FMF, CostKind);
2310
2311 // Skip if scalar size of ResTy is bigger than ELEN.
2312 if (ResTy->getScalarSizeInBits() > ST->getELen())
2313 return BaseT::getExtendedReductionCost(Opcode, IsUnsigned, ResTy, ValTy,
2314 FMF, CostKind);
2315
2316 if (Opcode != Instruction::Add && Opcode != Instruction::FAdd)
2317 return BaseT::getExtendedReductionCost(Opcode, IsUnsigned, ResTy, ValTy,
2318 FMF, CostKind);
2319
2320 std::pair<InstructionCost, MVT> LT = getTypeLegalizationCost(ValTy);
2321
2322 if (IsUnsigned && Opcode == Instruction::Add &&
2323 LT.second.isFixedLengthVectorOf(MVT::i1)) {
2324 // Represent vector_reduce_add(ZExt(<n x i1>)) as
2325 // ZExtOrTrunc(ctpop(bitcast <n x i1> to in)).
2326 return LT.first *
2327 getRISCVInstructionCost(RISCV::VCPOP_M, LT.second, CostKind);
2328 }
2329
2330 if (ResTy->getScalarSizeInBits() != 2 * LT.second.getScalarSizeInBits())
2331 return BaseT::getExtendedReductionCost(Opcode, IsUnsigned, ResTy, ValTy,
2332 FMF, CostKind);
2333
2334 return (LT.first - 1) +
2335 getArithmeticReductionCost(Opcode, ValTy, FMF, CostKind);
2336}
2337
2341 assert(OpInfo.isConstant() && "non constant operand?");
2342 if (!isa<VectorType>(Ty))
2343 // FIXME: We need to account for immediate materialization here, but doing
2344 // a decent job requires more knowledge about the immediate than we
2345 // currently have here.
2346 return 0;
2347
2348 if (OpInfo.isUniform())
2349 // vmv.v.i, vmv.v.x, or vfmv.v.f
2350 // We ignore the cost of the scalar constant materialization to be consistent
2351 // with how we treat scalar constants themselves just above.
2352 return 1;
2353
2354 return getConstantPoolLoadCost(Ty, CostKind);
2355}
2356
2358 Align Alignment,
2359 unsigned AddressSpace,
2361 TTI::OperandValueInfo OpInfo,
2362 const Instruction *I) const {
2363 EVT VT = TLI->getValueType(DL, Src, true);
2364 // Type legalization can't handle structs, and load latency isn't handled here
2365 if (VT == MVT::Other ||
2366 (Opcode == Instruction::Load && CostKind == TTI::TCK_Latency))
2367 return BaseT::getMemoryOpCost(Opcode, Src, Alignment, AddressSpace,
2368 CostKind, OpInfo, I);
2369
2371 if (Opcode == Instruction::Store && OpInfo.isConstant())
2372 Cost += getStoreImmCost(Src, OpInfo, CostKind);
2373
2374 std::pair<InstructionCost, MVT> LT = getTypeLegalizationCost(Src);
2375
2376 InstructionCost BaseCost = [&]() {
2377 InstructionCost Cost = LT.first;
2379 return Cost;
2380
2381 // Our actual lowering for the case where a wider legal type is available
2382 // uses the a VL predicated load on the wider type. This is reflected in
2383 // the result of getTypeLegalizationCost, but BasicTTI assumes the
2384 // widened cases are scalarized.
2385 const DataLayout &DL = this->getDataLayout();
2386 if (Src->isVectorTy() && LT.second.isVector() &&
2387 TypeSize::isKnownLT(DL.getTypeStoreSizeInBits(Src),
2388 LT.second.getSizeInBits()))
2389 return Cost;
2390
2391 return BaseT::getMemoryOpCost(Opcode, Src, Alignment, AddressSpace,
2392 CostKind, OpInfo, I);
2393 }();
2394
2395 // Assume memory ops cost scale with the number of vector registers
2396 // possible accessed by the instruction. Note that BasicTTI already
2397 // handles the LT.first term for us.
2398 if (ST->hasVInstructions() && LT.second.isVector() &&
2400 BaseCost *= TLI->getLMULCost(LT.second);
2401 return Cost + BaseCost;
2402}
2403
2405 unsigned Opcode, Type *ValTy, Type *CondTy, CmpInst::Predicate VecPred,
2407 TTI::OperandValueInfo Op2Info, const Instruction *I) const {
2409 return BaseT::getCmpSelInstrCost(Opcode, ValTy, CondTy, VecPred, CostKind,
2410 Op1Info, Op2Info, I);
2411
2412 if (isa<FixedVectorType>(ValTy) && !ST->useRVVForFixedLengthVectors())
2413 return BaseT::getCmpSelInstrCost(Opcode, ValTy, CondTy, VecPred, CostKind,
2414 Op1Info, Op2Info, I);
2415
2416 // Skip if scalar size of ValTy is bigger than ELEN.
2417 if (ValTy->isVectorTy() && ValTy->getScalarSizeInBits() > ST->getELen())
2418 return BaseT::getCmpSelInstrCost(Opcode, ValTy, CondTy, VecPred, CostKind,
2419 Op1Info, Op2Info, I);
2420
2421 auto GetConstantMatCost =
2422 [&](TTI::OperandValueInfo OpInfo) -> InstructionCost {
2423 if (OpInfo.isUniform())
2424 // We return 0 we currently ignore the cost of materializing scalar
2425 // constants in GPRs.
2426 return 0;
2427
2428 return getConstantPoolLoadCost(ValTy, CostKind);
2429 };
2430
2431 InstructionCost ConstantMatCost;
2432 if (Op1Info.isConstant())
2433 ConstantMatCost += GetConstantMatCost(Op1Info);
2434 if (Op2Info.isConstant())
2435 ConstantMatCost += GetConstantMatCost(Op2Info);
2436
2437 std::pair<InstructionCost, MVT> LT = getTypeLegalizationCost(ValTy);
2438 if (Opcode == Instruction::Select && LT.second.isVector()) {
2439 if (CondTy->isVectorTy()) {
2440 if (ValTy->getScalarSizeInBits() == 1) {
2441 // vmandn.mm v8, v8, v9
2442 // vmand.mm v9, v0, v9
2443 // vmor.mm v0, v9, v8
2444 return ConstantMatCost +
2445 LT.first *
2446 getRISCVInstructionCost(
2447 {RISCV::VMANDN_MM, RISCV::VMAND_MM, RISCV::VMOR_MM},
2448 LT.second, CostKind);
2449 }
2450 // vselect and max/min are supported natively.
2451 return ConstantMatCost +
2452 LT.first * getRISCVInstructionCost(RISCV::VMERGE_VVM, LT.second,
2453 CostKind);
2454 }
2455
2456 if (ValTy->getScalarSizeInBits() == 1) {
2457 // vmv.v.x v9, a0
2458 // vmsne.vi v9, v9, 0
2459 // vmandn.mm v8, v8, v9
2460 // vmand.mm v9, v0, v9
2461 // vmor.mm v0, v9, v8
2462 MVT InterimVT = LT.second.changeVectorElementType(MVT::i8);
2463 return ConstantMatCost +
2464 LT.first *
2465 getRISCVInstructionCost({RISCV::VMV_V_X, RISCV::VMSNE_VI},
2466 InterimVT, CostKind) +
2467 LT.first * getRISCVInstructionCost(
2468 {RISCV::VMANDN_MM, RISCV::VMAND_MM, RISCV::VMOR_MM},
2469 LT.second, CostKind);
2470 }
2471
2472 // vmv.v.x v10, a0
2473 // vmsne.vi v0, v10, 0
2474 // vmerge.vvm v8, v9, v8, v0
2475 return ConstantMatCost +
2476 LT.first * getRISCVInstructionCost(
2477 {RISCV::VMV_V_X, RISCV::VMSNE_VI, RISCV::VMERGE_VVM},
2478 LT.second, CostKind);
2479 }
2480
2481 if ((Opcode == Instruction::ICmp) && ValTy->isVectorTy() &&
2482 CmpInst::isIntPredicate(VecPred)) {
2483 // Use VMSLT_VV to represent VMSEQ, VMSNE, VMSLTU, VMSLEU, VMSLT, VMSLE
2484 // provided they incur the same cost across all implementations
2485 return ConstantMatCost + LT.first * getRISCVInstructionCost(RISCV::VMSLT_VV,
2486 LT.second,
2487 CostKind);
2488 }
2489
2490 if ((Opcode == Instruction::FCmp) && ValTy->isVectorTy() &&
2491 CmpInst::isFPPredicate(VecPred)) {
2492
2493 // Use VMXOR_MM and VMXNOR_MM to generate all true/false mask
2494 if ((VecPred == CmpInst::FCMP_FALSE) || (VecPred == CmpInst::FCMP_TRUE))
2495 return ConstantMatCost +
2496 getRISCVInstructionCost(RISCV::VMXOR_MM, LT.second, CostKind);
2497
2498 // If we do not support the input floating point vector type, use the base
2499 // one which will calculate as:
2500 // ScalarizeCost + Num * Cost for fixed vector,
2501 // InvalidCost for scalable vector.
2502 if ((ValTy->getScalarSizeInBits() == 16 && !ST->hasVInstructionsF16()) ||
2503 (ValTy->getScalarSizeInBits() == 32 && !ST->hasVInstructionsF32()) ||
2504 (ValTy->getScalarSizeInBits() == 64 && !ST->hasVInstructionsF64()))
2505 return BaseT::getCmpSelInstrCost(Opcode, ValTy, CondTy, VecPred, CostKind,
2506 Op1Info, Op2Info, I);
2507
2508 // Assuming vector fp compare and mask instructions are all the same cost
2509 // until a need arises to differentiate them.
2510 switch (VecPred) {
2511 case CmpInst::FCMP_ONE: // vmflt.vv + vmflt.vv + vmor.mm
2512 case CmpInst::FCMP_ORD: // vmfeq.vv + vmfeq.vv + vmand.mm
2513 case CmpInst::FCMP_UNO: // vmfne.vv + vmfne.vv + vmor.mm
2514 case CmpInst::FCMP_UEQ: // vmflt.vv + vmflt.vv + vmnor.mm
2515 return ConstantMatCost +
2516 LT.first * getRISCVInstructionCost(
2517 {RISCV::VMFLT_VV, RISCV::VMFLT_VV, RISCV::VMOR_MM},
2518 LT.second, CostKind);
2519
2520 case CmpInst::FCMP_UGT: // vmfle.vv + vmnot.m
2521 case CmpInst::FCMP_UGE: // vmflt.vv + vmnot.m
2522 case CmpInst::FCMP_ULT: // vmfle.vv + vmnot.m
2523 case CmpInst::FCMP_ULE: // vmflt.vv + vmnot.m
2524 return ConstantMatCost +
2525 LT.first *
2526 getRISCVInstructionCost({RISCV::VMFLT_VV, RISCV::VMNAND_MM},
2527 LT.second, CostKind);
2528
2529 case CmpInst::FCMP_OEQ: // vmfeq.vv
2530 case CmpInst::FCMP_OGT: // vmflt.vv
2531 case CmpInst::FCMP_OGE: // vmfle.vv
2532 case CmpInst::FCMP_OLT: // vmflt.vv
2533 case CmpInst::FCMP_OLE: // vmfle.vv
2534 case CmpInst::FCMP_UNE: // vmfne.vv
2535 return ConstantMatCost +
2536 LT.first *
2537 getRISCVInstructionCost(RISCV::VMFLT_VV, LT.second, CostKind);
2538 default:
2539 break;
2540 }
2541 }
2542
2543 // With ShortForwardBranchOpt or ConditionalMoveFusion, scalar icmp + select
2544 // instructions will lower to SELECT_CC and lower to PseudoCCMOVGPR which will
2545 // generate a conditional branch + mv. The cost of scalar (icmp + select) will
2546 // be (0 + select instr cost).
2547 if (ST->hasConditionalMoveFusion() && I && isa<ICmpInst>(I) &&
2548 ValTy->isIntegerTy() && !I->user_empty()) {
2549 if (all_of(I->users(), [&](const User *U) {
2550 return match(U, m_Select(m_Specific(I), m_Value(), m_Value())) &&
2551 U->getType()->isIntegerTy() &&
2552 !isa<ConstantData>(U->getOperand(1)) &&
2553 !isa<ConstantData>(U->getOperand(2));
2554 }))
2555 return 0;
2556 }
2557
2558 // TODO: Add cost for scalar type.
2559
2560 return BaseT::getCmpSelInstrCost(Opcode, ValTy, CondTy, VecPred, CostKind,
2561 Op1Info, Op2Info, I);
2562}
2563
2566 const Instruction *I) const {
2568 return Opcode == Instruction::PHI ? 0 : 1;
2569 // Branches are assumed to be predicted.
2570 return 0;
2571}
2572
2574 unsigned Opcode, Type *Val, TTI::TargetCostKind CostKind, unsigned Index,
2575 const Value *Op0, const Value *Op1, TTI::VectorInstrContext VIC) const {
2576 assert(Val->isVectorTy() && "This must be a vector type");
2577
2578 // TODO: Add proper cost model for P extension fixed vectors (e.g., v4i16)
2579 // For now, skip all fixed vector cost analysis when P extension is available
2580 // to avoid crashes in getMinRVVVectorSizeInBits()
2581 if (ST->hasStdExtP() && isa<FixedVectorType>(Val)) {
2582 return 1; // Treat as single instruction cost for now
2583 }
2584
2585 if (Opcode != Instruction::ExtractElement &&
2586 Opcode != Instruction::InsertElement)
2587 return BaseT::getVectorInstrCost(Opcode, Val, CostKind, Index, Op0, Op1,
2588 VIC);
2589
2590 // Legalize the type.
2591 std::pair<InstructionCost, MVT> LT = getTypeLegalizationCost(Val);
2592
2593 // This type is legalized to a scalar type.
2594 if (!LT.second.isVector()) {
2595 auto *FixedVecTy = cast<FixedVectorType>(Val);
2596 // If Index is a known constant, cost is zero.
2597 if (Index != -1U)
2598 return 0;
2599 // Extract/InsertElement with non-constant index is very costly when
2600 // scalarized; estimate cost of loads/stores sequence via the stack:
2601 // ExtractElement cost: store vector to stack, load scalar;
2602 // InsertElement cost: store vector to stack, store scalar, load vector.
2603 Type *ElemTy = FixedVecTy->getElementType();
2604 auto NumElems = FixedVecTy->getNumElements();
2605 auto Align = DL.getPrefTypeAlign(ElemTy);
2606 InstructionCost LoadCost =
2607 getMemoryOpCost(Instruction::Load, ElemTy, Align, 0, CostKind);
2608 InstructionCost StoreCost =
2609 getMemoryOpCost(Instruction::Store, ElemTy, Align, 0, CostKind);
2610 return Opcode == Instruction::ExtractElement
2611 ? StoreCost * NumElems + LoadCost
2612 : (StoreCost + LoadCost) * NumElems + StoreCost;
2613 }
2614
2615 // For unsupported scalable vector.
2616 if (LT.second.isScalableVector() && !LT.first.isValid())
2617 return LT.first;
2618
2619 // Mask vector extract/insert is expanded via e8.
2620 if (Val->getScalarSizeInBits() == 1) {
2621 VectorType *WideTy =
2623 cast<VectorType>(Val)->getElementCount());
2624 if (Opcode == Instruction::ExtractElement) {
2625 InstructionCost ExtendCost
2626 = getCastInstrCost(Instruction::ZExt, WideTy, Val,
2628 InstructionCost ExtractCost
2629 = getVectorInstrCost(Opcode, WideTy, CostKind, Index, nullptr, nullptr);
2630 return ExtendCost + ExtractCost;
2631 }
2632 InstructionCost ExtendCost
2633 = getCastInstrCost(Instruction::ZExt, WideTy, Val,
2635 InstructionCost InsertCost
2636 = getVectorInstrCost(Opcode, WideTy, CostKind, Index, nullptr, nullptr);
2637 InstructionCost TruncCost
2638 = getCastInstrCost(Instruction::Trunc, Val, WideTy,
2640 return ExtendCost + InsertCost + TruncCost;
2641 }
2642
2643
2644 // In RVV, we could use vslidedown + vmv.x.s to extract element from vector
2645 // and vslideup + vmv.s.x to insert element to vector.
2646 unsigned MoveOpc;
2647 if (LT.second.isFloatingPoint())
2648 MoveOpc = Opcode == Instruction::InsertElement ? RISCV::VFMV_S_F
2649 : RISCV::VFMV_F_S;
2650 else
2651 MoveOpc =
2652 Opcode == Instruction::InsertElement ? RISCV::VMV_S_X : RISCV::VMV_X_S;
2653 InstructionCost BaseCost =
2654 getRISCVInstructionCost(MoveOpc, LT.second, CostKind);
2655 // When insertelement we should add the index with 1 as the input of vslideup.
2656 InstructionCost SlideCost = Opcode == Instruction::InsertElement ? 2 : 1;
2657
2658 if (Index != -1U) {
2659 // The type may be split. For fixed-width vectors we can normalize the
2660 // index to the new type.
2661 if (LT.second.isFixedLengthVector()) {
2662 unsigned Width = LT.second.getVectorNumElements();
2663 Index = Index % Width;
2664 }
2665
2666 // If exact VLEN is known, we will insert/extract into the appropriate
2667 // subvector with no additional subvector insert/extract cost.
2668 if (auto VLEN = ST->getRealVLen()) {
2669 unsigned EltSize = LT.second.getScalarSizeInBits();
2670 unsigned M1Max = *VLEN / EltSize;
2671 Index = Index % M1Max;
2672 }
2673
2674 if (Index == 0)
2675 // We can extract/insert the first element without vslidedown/vslideup.
2676 SlideCost = 0;
2677 else if (Opcode == Instruction::InsertElement)
2678 SlideCost = 1; // With a constant index, we do not need to use addi.
2679 }
2680
2681 // When the vector needs to split into multiple register groups and the index
2682 // exceeds single vector register group, we need to insert/extract the element
2683 // via stack.
2684 if (LT.first > 1 &&
2685 ((Index == -1U) || (Index >= LT.second.getVectorMinNumElements() &&
2686 LT.second.isScalableVector()))) {
2687 Type *ScalarType = Val->getScalarType();
2688 Align VecAlign = DL.getPrefTypeAlign(Val);
2689 Align SclAlign = DL.getPrefTypeAlign(ScalarType);
2690 // Extra addi for unknown index.
2691 InstructionCost IdxCost = Index == -1U ? 1 : 0;
2692
2693 // Store all split vectors into stack and load the target element.
2694 if (Opcode == Instruction::ExtractElement)
2695 return getMemoryOpCost(Instruction::Store, Val, VecAlign, 0, CostKind) +
2696 getMemoryOpCost(Instruction::Load, ScalarType, SclAlign, 0,
2697 CostKind) +
2698 IdxCost;
2699
2700 // Store all split vectors into stack and store the target element and load
2701 // vectors back.
2702 return getMemoryOpCost(Instruction::Store, Val, VecAlign, 0, CostKind) +
2703 getMemoryOpCost(Instruction::Load, Val, VecAlign, 0, CostKind) +
2704 getMemoryOpCost(Instruction::Store, ScalarType, SclAlign, 0,
2705 CostKind) +
2706 IdxCost;
2707 }
2708
2709 // Extract i64 in the target that has XLEN=32 need more instruction.
2710 if (Val->getScalarType()->isIntegerTy() &&
2711 ST->getXLen() < Val->getScalarSizeInBits()) {
2712 // For extractelement, we need the following instructions:
2713 // vsetivli zero, 1, e64, m1, ta, mu (not count)
2714 // vslidedown.vx v8, v8, a0
2715 // vmv.x.s a0, v8
2716 // li a1, 32
2717 // vsrl.vx v8, v8, a1
2718 // vmv.x.s a1, v8
2719
2720 // For insertelement, we need the following instructions:
2721 // vsetivli zero, 2, e32, m4, ta, ma (don't count)
2722 // vslide1down.vx v12, v8, a0
2723 // vslide1down.vx v12, v12, a1
2724 // addi a0, a2, 1
2725 // vsetvli zero, a0, e64, m4, tu, ma (don't count)
2726 // vslideup.vx v8, v12, a2
2727
2728 // TODO: should we count these special vsetvlis?
2729 BaseCost =
2730 Opcode == Instruction::InsertElement
2731 ? getRISCVInstructionCost({RISCV::VSLIDE1DOWN_VX,
2732 RISCV::VSLIDE1DOWN_VX,
2733 RISCV::VSLIDEUP_VX},
2734 LT.second, CostKind)
2735 : getRISCVInstructionCost({RISCV::VSLIDEDOWN_VX, RISCV::VMV_X_S,
2736 RISCV::VSRL_VX, RISCV::VMV_X_S},
2737 LT.second, CostKind);
2738 }
2739 return BaseCost + SlideCost;
2740}
2741
2745 unsigned Index) const {
2746 if (isa<FixedVectorType>(Val))
2748 Index);
2749
2750 // TODO: This code replicates what LoopVectorize.cpp used to do when asking
2751 // for the cost of extracting the last lane of a scalable vector. It probably
2752 // needs a more accurate cost.
2753 ElementCount EC = cast<VectorType>(Val)->getElementCount();
2754 assert(Index < EC.getKnownMinValue() && "Unexpected reverse index");
2755 return getVectorInstrCost(Opcode, Val, CostKind,
2756 EC.getKnownMinValue() - 1 - Index, nullptr,
2757 nullptr);
2758}
2759
2760/// Check to see if this instruction is expected to be combined to a simpler
2761/// operation during/before lowering. If so return the cost of the combined
2762/// operation rather than provided one. For instance, `udiv i16 %X, 2` is likely
2763/// to be combined to `lshr i16 %X, 1`, so return the cost of a `lshr` rather
2764/// than the cost of a `udiv`
2765std::optional<InstructionCost>
2767 unsigned Opcode, Type *Ty, TTI::TargetCostKind CostKind,
2769 ArrayRef<const Value *> Args, const Instruction *CxtI) const {
2770 // Vector unsigned division/remainder will be simplified to shifts/masks.
2771 if ((Opcode == Instruction::UDiv || Opcode == Instruction::URem) &&
2772 Opd2Info.isConstant() && Opd2Info.isPowerOf2()) {
2773 if (Opcode == Instruction::UDiv)
2774 return getArithmeticInstrCost(Instruction::LShr, Ty, CostKind, Opd1Info,
2775 Opd2Info.getNoProps());
2776 // UREM
2777 return getArithmeticInstrCost(Instruction::And, Ty, CostKind, Opd1Info,
2778 Opd2Info.getNoProps());
2779 }
2780 return std::nullopt;
2781}
2782
2784 unsigned Opcode, Type *Ty, TTI::TargetCostKind CostKind,
2786 ArrayRef<const Value *> Args, const Instruction *CxtI) const {
2787
2788 // TODO: Handle more cost kinds.
2790 return BaseT::getArithmeticInstrCost(Opcode, Ty, CostKind, Op1Info, Op2Info,
2791 Args, CxtI);
2792
2793 if (isa<FixedVectorType>(Ty) && !ST->useRVVForFixedLengthVectors())
2794 return BaseT::getArithmeticInstrCost(Opcode, Ty, CostKind, Op1Info, Op2Info,
2795 Args, CxtI);
2796
2797 // Skip if scalar size of Ty is bigger than ELEN.
2798 if (isa<VectorType>(Ty) && Ty->getScalarSizeInBits() > ST->getELen())
2799 return BaseT::getArithmeticInstrCost(Opcode, Ty, CostKind, Op1Info, Op2Info,
2800 Args, CxtI);
2801
2802 if (std::optional<InstructionCost> CombinedCost =
2804 Op2Info, Args, CxtI))
2805 return *CombinedCost;
2806
2807 // Legalize the type.
2808 std::pair<InstructionCost, MVT> LT = getTypeLegalizationCost(Ty);
2809 unsigned ISDOpcode = TLI->InstructionOpcodeToISD(Opcode);
2810
2811 // TODO: Handle scalar type.
2812 if (!LT.second.isVector()) {
2813 static const CostTblEntry DivTbl[]{
2814 {ISD::UDIV, MVT::i32, TTI::TCC_Expensive},
2815 {ISD::UDIV, MVT::i64, TTI::TCC_Expensive},
2816 {ISD::SDIV, MVT::i32, TTI::TCC_Expensive},
2817 {ISD::SDIV, MVT::i64, TTI::TCC_Expensive},
2818 {ISD::UREM, MVT::i32, TTI::TCC_Expensive},
2819 {ISD::UREM, MVT::i64, TTI::TCC_Expensive},
2820 {ISD::SREM, MVT::i32, TTI::TCC_Expensive},
2821 {ISD::SREM, MVT::i64, TTI::TCC_Expensive}};
2822 if (TLI->isOperationLegalOrPromote(ISDOpcode, LT.second))
2823 if (const auto *Entry = CostTableLookup(DivTbl, ISDOpcode, LT.second))
2824 return Entry->Cost * LT.first;
2825
2826 return BaseT::getArithmeticInstrCost(Opcode, Ty, CostKind, Op1Info, Op2Info,
2827 Args, CxtI);
2828 }
2829
2830 // f16 with zvfhmin and bf16 will be promoted to f32.
2831 // FIXME: nxv32[b]f16 will be custom lowered and split.
2832 InstructionCost CastCost = 0;
2833 if ((LT.second.getVectorElementType() == MVT::f16 ||
2834 LT.second.getVectorElementType() == MVT::bf16) &&
2835 TLI->getOperationAction(ISDOpcode, LT.second) ==
2837 MVT PromotedVT = TLI->getTypeToPromoteTo(ISDOpcode, LT.second);
2838 Type *PromotedTy = EVT(PromotedVT).getTypeForEVT(Ty->getContext());
2839 Type *LegalTy = EVT(LT.second).getTypeForEVT(Ty->getContext());
2840 // Add cost of extending arguments
2841 CastCost += LT.first * Args.size() *
2842 getCastInstrCost(Instruction::FPExt, PromotedTy, LegalTy,
2844 // Add cost of truncating result
2845 CastCost +=
2846 LT.first * getCastInstrCost(Instruction::FPTrunc, LegalTy, PromotedTy,
2848 // Compute cost of op in promoted type
2849 LT.second = PromotedVT;
2850 }
2851
2852 auto getConstantMatCost =
2853 [&](unsigned Operand, TTI::OperandValueInfo OpInfo) -> InstructionCost {
2854 if (OpInfo.isUniform() && canSplatOperand(Opcode, Operand))
2855 // Two sub-cases:
2856 // * Has a 5 bit immediate operand which can be splatted.
2857 // * Has a larger immediate which must be materialized in scalar register
2858 // We return 0 for both as we currently ignore the cost of materializing
2859 // scalar constants in GPRs.
2860 return 0;
2861
2862 return getConstantPoolLoadCost(Ty, CostKind);
2863 };
2864
2865 // Add the cost of materializing any constant vectors required.
2866 InstructionCost ConstantMatCost = 0;
2867 if (Op1Info.isConstant())
2868 ConstantMatCost += getConstantMatCost(0, Op1Info);
2869 if (Op2Info.isConstant())
2870 ConstantMatCost += getConstantMatCost(1, Op2Info);
2871
2872 unsigned Op;
2873 switch (ISDOpcode) {
2874 case ISD::ADD:
2875 case ISD::SUB:
2876 Op = RISCV::VADD_VV;
2877 break;
2878 case ISD::SHL:
2879 case ISD::SRL:
2880 case ISD::SRA:
2881 Op = RISCV::VSLL_VV;
2882 break;
2883 case ISD::AND:
2884 case ISD::OR:
2885 case ISD::XOR:
2886 Op = (Ty->getScalarSizeInBits() == 1) ? RISCV::VMAND_MM : RISCV::VAND_VV;
2887 break;
2888 case ISD::MUL:
2889 case ISD::MULHS:
2890 case ISD::MULHU:
2891 Op = RISCV::VMUL_VV;
2892 break;
2893 case ISD::SDIV:
2894 case ISD::UDIV:
2895 Op = RISCV::VDIV_VV;
2896 break;
2897 case ISD::SREM:
2898 case ISD::UREM:
2899 Op = RISCV::VREM_VV;
2900 break;
2901 case ISD::FADD:
2902 case ISD::FSUB:
2903 Op = RISCV::VFADD_VV;
2904 break;
2905 case ISD::FMUL:
2906 Op = RISCV::VFMUL_VV;
2907 break;
2908 case ISD::FDIV:
2909 Op = RISCV::VFDIV_VV;
2910 break;
2911 case ISD::FNEG:
2912 Op = RISCV::VFSGNJN_VV;
2913 break;
2914 default:
2915 // Assuming all other instructions have the same cost until a need arises to
2916 // differentiate them.
2917 return CastCost + ConstantMatCost +
2918 BaseT::getArithmeticInstrCost(Opcode, Ty, CostKind, Op1Info, Op2Info,
2919 Args, CxtI);
2920 }
2921
2922 InstructionCost InstrCost = getRISCVInstructionCost(Op, LT.second, CostKind);
2923 // We use BasicTTIImpl to calculate scalar costs, which assumes floating point
2924 // ops are twice as expensive as integer ops. Do the same for vectors so
2925 // scalar floating point ops aren't cheaper than their vector equivalents.
2926 if (Ty->isFPOrFPVectorTy())
2927 InstrCost *= 2;
2928 return CastCost + ConstantMatCost + LT.first * InstrCost;
2929}
2930
2931// TODO: Deduplicate from TargetTransformInfoImplCRTPBase.
2933 ArrayRef<const Value *> Ptrs, const Value *Base,
2934 const TTI::PointersChainInfo &Info, Type *AccessTy,
2937 // In the basic model we take into account GEP instructions only
2938 // (although here can come alloca instruction, a value, constants and/or
2939 // constant expressions, PHIs, bitcasts ... whatever allowed to be used as a
2940 // pointer). Typically, if Base is a not a GEP-instruction and all the
2941 // pointers are relative to the same base address, all the rest are
2942 // either GEP instructions, PHIs, bitcasts or constants. When we have same
2943 // base, we just calculate cost of each non-Base GEP as an ADD operation if
2944 // any their index is a non-const.
2945 // If no known dependencies between the pointers cost is calculated as a sum
2946 // of costs of GEP instructions.
2947 for (auto [I, V] : enumerate(Ptrs)) {
2948 const auto *GEP = dyn_cast<GetElementPtrInst>(V);
2949 if (!GEP)
2950 continue;
2951 if (Info.isSameBase() && V != Base) {
2952 if (GEP->hasAllConstantIndices())
2953 continue;
2954 // If the chain is unit-stride and BaseReg + stride*i is a legal
2955 // addressing mode, then presume the base GEP is sitting around in a
2956 // register somewhere and check if we can fold the offset relative to
2957 // it.
2958 unsigned Stride = DL.getTypeStoreSize(AccessTy);
2959 if (Info.isUnitStride() &&
2960 isLegalAddressingMode(AccessTy,
2961 /* BaseGV */ nullptr,
2962 /* BaseOffset */ Stride * I,
2963 /* HasBaseReg */ true,
2964 /* Scale */ 0,
2965 GEP->getType()->getPointerAddressSpace()))
2966 continue;
2967 Cost += getArithmeticInstrCost(Instruction::Add, GEP->getType(), CostKind,
2968 {TTI::OK_AnyValue, TTI::OP_None},
2969 {TTI::OK_AnyValue, TTI::OP_None}, {});
2970 } else {
2971 SmallVector<const Value *> Indices(GEP->indices());
2972 Cost += getGEPCost(GEP->getSourceElementType(), GEP->getPointerOperand(),
2973 Indices, AccessTy, CostKind);
2974 }
2975 }
2976 return Cost;
2977}
2978
2981 OptimizationRemarkEmitter *ORE) const {
2982 // TODO: More tuning on benchmarks and metrics with changes as needed
2983 // would apply to all settings below to enable performance.
2984
2985
2986 if (ST->enableDefaultUnroll())
2987 return BasicTTIImplBase::getUnrollingPreferences(L, SE, UP, ORE);
2988
2989 // Enable Upper bound unrolling universally, not dependent upon the conditions
2990 // below.
2991 UP.UpperBound = true;
2992
2993 // Disable loop unrolling for Oz and Os.
2994 UP.OptSizeThreshold = 0;
2996 if (L->getHeader()->getParent()->hasOptSize())
2997 return;
2998
2999 SmallVector<BasicBlock *, 4> ExitingBlocks;
3000 L->getExitingBlocks(ExitingBlocks);
3001 LLVM_DEBUG(dbgs() << "Loop has:\n"
3002 << "Blocks: " << L->getNumBlocks() << "\n"
3003 << "Exit blocks: " << ExitingBlocks.size() << "\n");
3004
3005 // Only allow another exit other than the latch. This acts as an early exit
3006 // as it mirrors the profitability calculation of the runtime unroller.
3007 if (ExitingBlocks.size() > 2)
3008 return;
3009
3010 // Limit the CFG of the loop body for targets with a branch predictor.
3011 // Allowing 4 blocks permits if-then-else diamonds in the body.
3012 if (L->getNumBlocks() > 4)
3013 return;
3014
3015 // Scan the loop: don't unroll loops with calls as this could prevent
3016 // inlining. Don't unroll auto-vectorized loops either, though do allow
3017 // unrolling of the scalar remainder.
3018 bool IsVectorized = getBooleanLoopAttribute(L, "llvm.loop.isvectorized");
3020 for (auto *BB : L->getBlocks()) {
3021 for (auto &I : *BB) {
3022 // Both auto-vectorized loops and the scalar remainder have the
3023 // isvectorized attribute, so differentiate between them by the presence
3024 // of vector instructions.
3025 if (IsVectorized && (I.getType()->isVectorTy() ||
3026 llvm::any_of(I.operand_values(), [](Value *V) {
3027 return V->getType()->isVectorTy();
3028 })))
3029 return;
3030
3031 if (isa<CallInst>(I) || isa<InvokeInst>(I)) {
3032 if (const Function *F = cast<CallBase>(I).getCalledFunction()) {
3033 if (!isLoweredToCall(F))
3034 continue;
3035 }
3036 return;
3037 }
3038
3039 SmallVector<const Value *> Operands(I.operand_values());
3042 }
3043 }
3044
3045 LLVM_DEBUG(dbgs() << "Cost of loop: " << Cost << "\n");
3046
3047 UP.Partial = true;
3048 UP.Runtime = true;
3049 UP.UnrollRemainder = true;
3050 UP.UnrollAndJam = true;
3051
3052 // Force unrolling small loops can be very useful because of the branch
3053 // taken cost of the backedge.
3054 if (Cost < 12)
3055 UP.Force = true;
3056}
3057
3062
3064 MemIntrinsicInfo &Info) const {
3065 const DataLayout &DL = getDataLayout();
3066 Intrinsic::ID IID = Inst->getIntrinsicID();
3067 LLVMContext &C = Inst->getContext();
3068 bool HasMask = false;
3069
3070 auto getSegNum = [](const IntrinsicInst *II, unsigned PtrOperandNo,
3071 bool IsWrite) -> int64_t {
3072 if (auto *TarExtTy =
3073 dyn_cast<TargetExtType>(II->getArgOperand(0)->getType()))
3074 return TarExtTy->getIntParameter(0);
3075
3076 return 1;
3077 };
3078
3079 switch (IID) {
3080 case Intrinsic::riscv_vle_mask:
3081 case Intrinsic::riscv_vse_mask:
3082 case Intrinsic::riscv_vlseg2_mask:
3083 case Intrinsic::riscv_vlseg3_mask:
3084 case Intrinsic::riscv_vlseg4_mask:
3085 case Intrinsic::riscv_vlseg5_mask:
3086 case Intrinsic::riscv_vlseg6_mask:
3087 case Intrinsic::riscv_vlseg7_mask:
3088 case Intrinsic::riscv_vlseg8_mask:
3089 case Intrinsic::riscv_vsseg2_mask:
3090 case Intrinsic::riscv_vsseg3_mask:
3091 case Intrinsic::riscv_vsseg4_mask:
3092 case Intrinsic::riscv_vsseg5_mask:
3093 case Intrinsic::riscv_vsseg6_mask:
3094 case Intrinsic::riscv_vsseg7_mask:
3095 case Intrinsic::riscv_vsseg8_mask:
3096 HasMask = true;
3097 [[fallthrough]];
3098 case Intrinsic::riscv_vle:
3099 case Intrinsic::riscv_vse:
3100 case Intrinsic::riscv_vlseg2:
3101 case Intrinsic::riscv_vlseg3:
3102 case Intrinsic::riscv_vlseg4:
3103 case Intrinsic::riscv_vlseg5:
3104 case Intrinsic::riscv_vlseg6:
3105 case Intrinsic::riscv_vlseg7:
3106 case Intrinsic::riscv_vlseg8:
3107 case Intrinsic::riscv_vsseg2:
3108 case Intrinsic::riscv_vsseg3:
3109 case Intrinsic::riscv_vsseg4:
3110 case Intrinsic::riscv_vsseg5:
3111 case Intrinsic::riscv_vsseg6:
3112 case Intrinsic::riscv_vsseg7:
3113 case Intrinsic::riscv_vsseg8: {
3114 // Intrinsic interface:
3115 // riscv_vle(merge, ptr, vl)
3116 // riscv_vle_mask(merge, ptr, mask, vl, policy)
3117 // riscv_vse(val, ptr, vl)
3118 // riscv_vse_mask(val, ptr, mask, vl, policy)
3119 // riscv_vlseg#(merge, ptr, vl, sew)
3120 // riscv_vlseg#_mask(merge, ptr, mask, vl, policy, sew)
3121 // riscv_vsseg#(val, ptr, vl, sew)
3122 // riscv_vsseg#_mask(val, ptr, mask, vl, sew)
3123 bool IsWrite = Inst->getType()->isVoidTy();
3124 Type *Ty = IsWrite ? Inst->getArgOperand(0)->getType() : Inst->getType();
3125 // The results of segment loads are TargetExtType.
3126 if (auto *TarExtTy = dyn_cast<TargetExtType>(Ty)) {
3127 unsigned SEW =
3128 1 << cast<ConstantInt>(Inst->getArgOperand(Inst->arg_size() - 1))
3129 ->getZExtValue();
3130 Ty = TarExtTy->getTypeParameter(0U);
3132 IntegerType::get(C, SEW),
3133 cast<ScalableVectorType>(Ty)->getMinNumElements() * 8 / SEW);
3134 }
3135 const auto *RVVIInfo = RISCVVIntrinsicsTable::getRISCVVIntrinsicInfo(IID);
3136 unsigned VLIndex = RVVIInfo->VLOperand;
3137 unsigned PtrOperandNo = VLIndex - 1 - HasMask;
3138 MaybeAlign Alignment =
3139 Inst->getArgOperand(PtrOperandNo)->getPointerAlignment(DL);
3140 Type *MaskType = Ty->getWithNewType(Type::getInt1Ty(C));
3141 Value *Mask = ConstantInt::getTrue(MaskType);
3142 if (HasMask)
3143 Mask = Inst->getArgOperand(VLIndex - 1);
3144 Value *EVL = Inst->getArgOperand(VLIndex);
3145 unsigned SegNum = getSegNum(Inst, PtrOperandNo, IsWrite);
3146 // RVV uses contiguous elements as a segment.
3147 if (SegNum > 1) {
3148 unsigned ElemSize = Ty->getScalarSizeInBits();
3149 auto *SegTy = IntegerType::get(C, ElemSize * SegNum);
3150 Ty = VectorType::get(SegTy, cast<VectorType>(Ty));
3151 }
3152 Info.InterestingOperands.emplace_back(Inst, PtrOperandNo, IsWrite, Ty,
3153 Alignment, Mask, EVL);
3154 return true;
3155 }
3156 case Intrinsic::riscv_vlse_mask:
3157 case Intrinsic::riscv_vsse_mask:
3158 case Intrinsic::riscv_vlsseg2_mask:
3159 case Intrinsic::riscv_vlsseg3_mask:
3160 case Intrinsic::riscv_vlsseg4_mask:
3161 case Intrinsic::riscv_vlsseg5_mask:
3162 case Intrinsic::riscv_vlsseg6_mask:
3163 case Intrinsic::riscv_vlsseg7_mask:
3164 case Intrinsic::riscv_vlsseg8_mask:
3165 case Intrinsic::riscv_vssseg2_mask:
3166 case Intrinsic::riscv_vssseg3_mask:
3167 case Intrinsic::riscv_vssseg4_mask:
3168 case Intrinsic::riscv_vssseg5_mask:
3169 case Intrinsic::riscv_vssseg6_mask:
3170 case Intrinsic::riscv_vssseg7_mask:
3171 case Intrinsic::riscv_vssseg8_mask:
3172 HasMask = true;
3173 [[fallthrough]];
3174 case Intrinsic::riscv_vlse:
3175 case Intrinsic::riscv_vsse:
3176 case Intrinsic::riscv_vlsseg2:
3177 case Intrinsic::riscv_vlsseg3:
3178 case Intrinsic::riscv_vlsseg4:
3179 case Intrinsic::riscv_vlsseg5:
3180 case Intrinsic::riscv_vlsseg6:
3181 case Intrinsic::riscv_vlsseg7:
3182 case Intrinsic::riscv_vlsseg8:
3183 case Intrinsic::riscv_vssseg2:
3184 case Intrinsic::riscv_vssseg3:
3185 case Intrinsic::riscv_vssseg4:
3186 case Intrinsic::riscv_vssseg5:
3187 case Intrinsic::riscv_vssseg6:
3188 case Intrinsic::riscv_vssseg7:
3189 case Intrinsic::riscv_vssseg8: {
3190 // Intrinsic interface:
3191 // riscv_vlse(merge, ptr, stride, vl)
3192 // riscv_vlse_mask(merge, ptr, stride, mask, vl, policy)
3193 // riscv_vsse(val, ptr, stride, vl)
3194 // riscv_vsse_mask(val, ptr, stride, mask, vl, policy)
3195 // riscv_vlsseg#(merge, ptr, offset, vl, sew)
3196 // riscv_vlsseg#_mask(merge, ptr, offset, mask, vl, policy, sew)
3197 // riscv_vssseg#(val, ptr, offset, vl, sew)
3198 // riscv_vssseg#_mask(val, ptr, offset, mask, vl, sew)
3199 bool IsWrite = Inst->getType()->isVoidTy();
3200 Type *Ty = IsWrite ? Inst->getArgOperand(0)->getType() : Inst->getType();
3201 // The results of segment loads are TargetExtType.
3202 if (auto *TarExtTy = dyn_cast<TargetExtType>(Ty)) {
3203 unsigned SEW =
3204 1 << cast<ConstantInt>(Inst->getArgOperand(Inst->arg_size() - 1))
3205 ->getZExtValue();
3206 Ty = TarExtTy->getTypeParameter(0U);
3208 IntegerType::get(C, SEW),
3209 cast<ScalableVectorType>(Ty)->getMinNumElements() * 8 / SEW);
3210 }
3211 const auto *RVVIInfo = RISCVVIntrinsicsTable::getRISCVVIntrinsicInfo(IID);
3212 unsigned VLIndex = RVVIInfo->VLOperand;
3213 unsigned PtrOperandNo = VLIndex - 2 - HasMask;
3214 MaybeAlign Alignment =
3215 Inst->getArgOperand(PtrOperandNo)->getPointerAlignment(DL);
3216
3217 Value *Stride = Inst->getArgOperand(PtrOperandNo + 1);
3218 // Use the pointer alignment as the element alignment if the stride is a
3219 // multiple of the pointer alignment. Otherwise, the element alignment
3220 // should be the greatest common divisor of pointer alignment and stride.
3221 // For simplicity, just consider unalignment for elements.
3222 unsigned PointerAlign = Alignment.valueOrOne().value();
3223 if (!isa<ConstantInt>(Stride) ||
3224 cast<ConstantInt>(Stride)->getZExtValue() % PointerAlign != 0)
3225 Alignment = Align(1);
3226
3227 Type *MaskType = Ty->getWithNewType(Type::getInt1Ty(C));
3228 Value *Mask = ConstantInt::getTrue(MaskType);
3229 if (HasMask)
3230 Mask = Inst->getArgOperand(VLIndex - 1);
3231 Value *EVL = Inst->getArgOperand(VLIndex);
3232 unsigned SegNum = getSegNum(Inst, PtrOperandNo, IsWrite);
3233 // RVV uses contiguous elements as a segment.
3234 if (SegNum > 1) {
3235 unsigned ElemSize = Ty->getScalarSizeInBits();
3236 auto *SegTy = IntegerType::get(C, ElemSize * SegNum);
3237 Ty = VectorType::get(SegTy, cast<VectorType>(Ty));
3238 }
3239 Info.InterestingOperands.emplace_back(Inst, PtrOperandNo, IsWrite, Ty,
3240 Alignment, Mask, EVL, Stride);
3241 return true;
3242 }
3243 case Intrinsic::riscv_vloxei_mask:
3244 case Intrinsic::riscv_vluxei_mask:
3245 case Intrinsic::riscv_vsoxei_mask:
3246 case Intrinsic::riscv_vsuxei_mask:
3247 case Intrinsic::riscv_vloxseg2_mask:
3248 case Intrinsic::riscv_vloxseg3_mask:
3249 case Intrinsic::riscv_vloxseg4_mask:
3250 case Intrinsic::riscv_vloxseg5_mask:
3251 case Intrinsic::riscv_vloxseg6_mask:
3252 case Intrinsic::riscv_vloxseg7_mask:
3253 case Intrinsic::riscv_vloxseg8_mask:
3254 case Intrinsic::riscv_vluxseg2_mask:
3255 case Intrinsic::riscv_vluxseg3_mask:
3256 case Intrinsic::riscv_vluxseg4_mask:
3257 case Intrinsic::riscv_vluxseg5_mask:
3258 case Intrinsic::riscv_vluxseg6_mask:
3259 case Intrinsic::riscv_vluxseg7_mask:
3260 case Intrinsic::riscv_vluxseg8_mask:
3261 case Intrinsic::riscv_vsoxseg2_mask:
3262 case Intrinsic::riscv_vsoxseg3_mask:
3263 case Intrinsic::riscv_vsoxseg4_mask:
3264 case Intrinsic::riscv_vsoxseg5_mask:
3265 case Intrinsic::riscv_vsoxseg6_mask:
3266 case Intrinsic::riscv_vsoxseg7_mask:
3267 case Intrinsic::riscv_vsoxseg8_mask:
3268 case Intrinsic::riscv_vsuxseg2_mask:
3269 case Intrinsic::riscv_vsuxseg3_mask:
3270 case Intrinsic::riscv_vsuxseg4_mask:
3271 case Intrinsic::riscv_vsuxseg5_mask:
3272 case Intrinsic::riscv_vsuxseg6_mask:
3273 case Intrinsic::riscv_vsuxseg7_mask:
3274 case Intrinsic::riscv_vsuxseg8_mask:
3275 HasMask = true;
3276 [[fallthrough]];
3277 case Intrinsic::riscv_vloxei:
3278 case Intrinsic::riscv_vluxei:
3279 case Intrinsic::riscv_vsoxei:
3280 case Intrinsic::riscv_vsuxei:
3281 case Intrinsic::riscv_vloxseg2:
3282 case Intrinsic::riscv_vloxseg3:
3283 case Intrinsic::riscv_vloxseg4:
3284 case Intrinsic::riscv_vloxseg5:
3285 case Intrinsic::riscv_vloxseg6:
3286 case Intrinsic::riscv_vloxseg7:
3287 case Intrinsic::riscv_vloxseg8:
3288 case Intrinsic::riscv_vluxseg2:
3289 case Intrinsic::riscv_vluxseg3:
3290 case Intrinsic::riscv_vluxseg4:
3291 case Intrinsic::riscv_vluxseg5:
3292 case Intrinsic::riscv_vluxseg6:
3293 case Intrinsic::riscv_vluxseg7:
3294 case Intrinsic::riscv_vluxseg8:
3295 case Intrinsic::riscv_vsoxseg2:
3296 case Intrinsic::riscv_vsoxseg3:
3297 case Intrinsic::riscv_vsoxseg4:
3298 case Intrinsic::riscv_vsoxseg5:
3299 case Intrinsic::riscv_vsoxseg6:
3300 case Intrinsic::riscv_vsoxseg7:
3301 case Intrinsic::riscv_vsoxseg8:
3302 case Intrinsic::riscv_vsuxseg2:
3303 case Intrinsic::riscv_vsuxseg3:
3304 case Intrinsic::riscv_vsuxseg4:
3305 case Intrinsic::riscv_vsuxseg5:
3306 case Intrinsic::riscv_vsuxseg6:
3307 case Intrinsic::riscv_vsuxseg7:
3308 case Intrinsic::riscv_vsuxseg8: {
3309 // Intrinsic interface (only listed ordered version):
3310 // riscv_vloxei(merge, ptr, index, vl)
3311 // riscv_vloxei_mask(merge, ptr, index, mask, vl, policy)
3312 // riscv_vsoxei(val, ptr, index, vl)
3313 // riscv_vsoxei_mask(val, ptr, index, mask, vl, policy)
3314 // riscv_vloxseg#(merge, ptr, index, vl, sew)
3315 // riscv_vloxseg#_mask(merge, ptr, index, mask, vl, policy, sew)
3316 // riscv_vsoxseg#(val, ptr, index, vl, sew)
3317 // riscv_vsoxseg#_mask(val, ptr, index, mask, vl, sew)
3318 bool IsWrite = Inst->getType()->isVoidTy();
3319 Type *Ty = IsWrite ? Inst->getArgOperand(0)->getType() : Inst->getType();
3320 // The results of segment loads are TargetExtType.
3321 if (auto *TarExtTy = dyn_cast<TargetExtType>(Ty)) {
3322 unsigned SEW =
3323 1 << cast<ConstantInt>(Inst->getArgOperand(Inst->arg_size() - 1))
3324 ->getZExtValue();
3325 Ty = TarExtTy->getTypeParameter(0U);
3327 IntegerType::get(C, SEW),
3328 cast<ScalableVectorType>(Ty)->getMinNumElements() * 8 / SEW);
3329 }
3330 const auto *RVVIInfo = RISCVVIntrinsicsTable::getRISCVVIntrinsicInfo(IID);
3331 unsigned VLIndex = RVVIInfo->VLOperand;
3332 unsigned PtrOperandNo = VLIndex - 2 - HasMask;
3333 Value *Mask;
3334 if (HasMask) {
3335 Mask = Inst->getArgOperand(VLIndex - 1);
3336 } else {
3337 // Mask cannot be nullptr here: vector GEP produces <vscale x N x ptr>,
3338 // and casting that to scalar i64 triggers a vector/scalar mismatch
3339 // assertion in CreatePointerCast. Use an all-true mask so ASan lowers it
3340 // via extractelement instead.
3341 Type *MaskType = Ty->getWithNewType(Type::getInt1Ty(C));
3342 Mask = ConstantInt::getTrue(MaskType);
3343 }
3344 Value *EVL = Inst->getArgOperand(VLIndex);
3345 unsigned SegNum = getSegNum(Inst, PtrOperandNo, IsWrite);
3346 // RVV uses contiguous elements as a segment.
3347 if (SegNum > 1) {
3348 unsigned ElemSize = Ty->getScalarSizeInBits();
3349 auto *SegTy = IntegerType::get(C, ElemSize * SegNum);
3350 Ty = VectorType::get(SegTy, cast<VectorType>(Ty));
3351 }
3352 Value *OffsetOp = Inst->getArgOperand(PtrOperandNo + 1);
3353 Info.InterestingOperands.emplace_back(Inst, PtrOperandNo, IsWrite, Ty,
3354 Align(1), Mask, EVL,
3355 /* Stride */ nullptr, OffsetOp);
3356 return true;
3357 }
3358 }
3359 return false;
3360}
3361
3363 if (Ty->isVectorTy()) {
3364 // f16 with only zvfhmin and bf16 will be promoted to f32
3365 Type *EltTy = cast<VectorType>(Ty)->getElementType();
3366 if ((EltTy->isHalfTy() && !ST->hasVInstructionsF16()) ||
3367 EltTy->isBFloatTy())
3368 Ty = VectorType::get(Type::getFloatTy(Ty->getContext()),
3369 cast<VectorType>(Ty));
3370
3371 TypeSize Size = DL.getTypeSizeInBits(Ty);
3372 if (Size.isScalable() && ST->hasVInstructions())
3373 return divideCeil(Size.getKnownMinValue(), RISCV::RVVBitsPerBlock);
3374
3375 if (ST->useRVVForFixedLengthVectors())
3376 return divideCeil(Size, ST->getRealMinVLen());
3377 }
3378
3379 return BaseT::getRegUsageForType(Ty);
3380}
3381
3382unsigned RISCVTTIImpl::getMaximumVF(unsigned ElemWidth, unsigned Opcode) const {
3383 if (SLPMaxVF.getNumOccurrences())
3384 return SLPMaxVF;
3385
3386 // Return how many elements can fit in getRegisterBitwidth. This is the
3387 // same routine as used in LoopVectorizer. We should probably be
3388 // accounting for whether we actually have instructions with the right
3389 // lane type, but we don't have enough information to do that without
3390 // some additional plumbing which hasn't been justified yet.
3391 TypeSize RegWidth =
3393 // If no vector registers, or absurd element widths, disable
3394 // vectorization by returning 1.
3395 return std::max<unsigned>(1U, RegWidth.getFixedValue() / ElemWidth);
3396}
3397
3401
3403 return ST->enableUnalignedVectorMem();
3404}
3405
3408 ScalarEvolution *SE) const {
3409 if (ST->hasVendorXCVmem() && !ST->is64Bit())
3410 return TTI::AMK_PostIndexed;
3411
3413}
3414
3416 const TargetTransformInfo::LSRCost &C2) const {
3417 // RISC-V specific here are "instruction number 1st priority".
3418 // If we need to emit adds inside the loop to add up base registers, then
3419 // we need at least one extra temporary register.
3420 unsigned C1NumRegs = C1.NumRegs + (C1.NumBaseAdds != 0);
3421 unsigned C2NumRegs = C2.NumRegs + (C2.NumBaseAdds != 0);
3422 return std::tie(C1.Insns, C1NumRegs, C1.AddRecCost,
3423 C1.NumIVMuls, C1.NumBaseAdds,
3424 C1.ScaleCost, C1.ImmCost, C1.SetupCost) <
3425 std::tie(C2.Insns, C2NumRegs, C2.AddRecCost,
3426 C2.NumIVMuls, C2.NumBaseAdds,
3427 C2.ScaleCost, C2.ImmCost, C2.SetupCost);
3428}
3429
3431 Align Alignment) const {
3432 auto *VTy = dyn_cast<VectorType>(DataTy);
3433 if (!VTy || VTy->isScalableTy())
3434 return false;
3435
3436 if (!isLegalMaskedLoadStore(DataTy, Alignment))
3437 return false;
3438
3439 // FIXME: If it is an i8 vector and the element count exceeds 256, we should
3440 // scalarize these types with LMUL >= maximum fixed-length LMUL.
3441 if (VTy->getElementType()->isIntegerTy(8))
3442 if (VTy->getElementCount().getFixedValue() > 256)
3443 return VTy->getPrimitiveSizeInBits() / ST->getRealMinVLen() <
3444 ST->getMaxLMULForFixedLengthVectors();
3445 return true;
3446}
3447
3449 Align Alignment) const {
3450 auto *VTy = dyn_cast<VectorType>(DataTy);
3451 if (!VTy || VTy->isScalableTy())
3452 return false;
3453
3454 if (!isLegalMaskedLoadStore(DataTy, Alignment))
3455 return false;
3456 return true;
3457}
3458
3460 ElementCount NumElements) const {
3461 // Optimized zero-stride loads can be treated as broadcasts.
3462 if (!ST->hasVInstructions() || !ST->hasOptimizedZeroStrideLoad())
3463 return false;
3464
3465 return TLI->isLegalElementTypeForRVV(TLI->getValueType(DL, ElementTy));
3466}
3467
3468/// See if \p I should be considered for address type promotion. We check if \p
3469/// I is a sext with right type and used in memory accesses. If it used in a
3470/// "complex" getelementptr, we allow it to be promoted without finding other
3471/// sext instructions that sign extended the same initial value. A getelementptr
3472/// is considered as "complex" if it has more than 2 operands.
3474 const Instruction &I, bool &AllowPromotionWithoutCommonHeader) const {
3475 bool Considerable = false;
3476 AllowPromotionWithoutCommonHeader = false;
3477 if (!isa<SExtInst>(&I))
3478 return false;
3479 Type *ConsideredSExtType =
3480 Type::getInt64Ty(I.getParent()->getParent()->getContext());
3481 if (I.getType() != ConsideredSExtType)
3482 return false;
3483 // See if the sext is the one with the right type and used in at least one
3484 // GetElementPtrInst.
3485 for (const User *U : I.users()) {
3486 if (const GetElementPtrInst *GEPInst = dyn_cast<GetElementPtrInst>(U)) {
3487 Considerable = true;
3488 // A getelementptr is considered as "complex" if it has more than 2
3489 // operands. We will promote a SExt used in such complex GEP as we
3490 // expect some computation to be merged if they are done on 64 bits.
3491 if (GEPInst->getNumOperands() > 2) {
3492 AllowPromotionWithoutCommonHeader = true;
3493 break;
3494 }
3495 }
3496 }
3497 return Considerable;
3498}
3499
3500bool RISCVTTIImpl::canSplatOperand(unsigned Opcode, int Operand) const {
3501 switch (Opcode) {
3502 case Instruction::Add:
3503 case Instruction::Sub:
3504 case Instruction::Mul:
3505 case Instruction::And:
3506 case Instruction::Or:
3507 case Instruction::Xor:
3508 case Instruction::FAdd:
3509 case Instruction::FSub:
3510 case Instruction::FMul:
3511 case Instruction::FDiv:
3512 case Instruction::ICmp:
3513 case Instruction::FCmp:
3514 return true;
3515 case Instruction::Shl:
3516 case Instruction::LShr:
3517 case Instruction::AShr:
3518 case Instruction::UDiv:
3519 case Instruction::SDiv:
3520 case Instruction::URem:
3521 case Instruction::SRem:
3522 case Instruction::Select:
3523 return Operand == 1;
3524 default:
3525 return false;
3526 }
3527}
3528
3530 if (!I->getType()->isVectorTy() || !ST->hasVInstructions())
3531 return false;
3532
3533 if (canSplatOperand(I->getOpcode(), Operand))
3534 return true;
3535
3536 auto *II = dyn_cast<IntrinsicInst>(I);
3537 if (!II)
3538 return false;
3539
3540 switch (II->getIntrinsicID()) {
3541 case Intrinsic::fma:
3542 case Intrinsic::vp_fma:
3543 case Intrinsic::fmuladd:
3544 case Intrinsic::vp_fmuladd:
3545 return Operand == 0 || Operand == 1;
3546 case Intrinsic::vp_shl:
3547 case Intrinsic::vp_lshr:
3548 case Intrinsic::vp_ashr:
3549 case Intrinsic::vp_udiv:
3550 case Intrinsic::vp_sdiv:
3551 case Intrinsic::vp_urem:
3552 case Intrinsic::vp_srem:
3553 case Intrinsic::ssub_sat:
3554 case Intrinsic::vp_ssub_sat:
3555 case Intrinsic::usub_sat:
3556 case Intrinsic::vp_usub_sat:
3557 case Intrinsic::vp_select:
3558 return Operand == 1;
3559 // These intrinsics are commutative.
3560 case Intrinsic::vp_add:
3561 case Intrinsic::vp_mul:
3562 case Intrinsic::vp_and:
3563 case Intrinsic::vp_or:
3564 case Intrinsic::vp_xor:
3565 case Intrinsic::vp_fadd:
3566 case Intrinsic::vp_fmul:
3567 case Intrinsic::vp_icmp:
3568 case Intrinsic::vp_fcmp:
3569 case Intrinsic::smin:
3570 case Intrinsic::vp_smin:
3571 case Intrinsic::umin:
3572 case Intrinsic::vp_umin:
3573 case Intrinsic::smax:
3574 case Intrinsic::vp_smax:
3575 case Intrinsic::umax:
3576 case Intrinsic::vp_umax:
3577 case Intrinsic::sadd_sat:
3578 case Intrinsic::vp_sadd_sat:
3579 case Intrinsic::uadd_sat:
3580 case Intrinsic::vp_uadd_sat:
3581 // These intrinsics have 'vr' versions.
3582 case Intrinsic::vp_sub:
3583 case Intrinsic::vp_fsub:
3584 case Intrinsic::vp_fdiv:
3585 return Operand == 0 || Operand == 1;
3586 default:
3587 return false;
3588 }
3589}
3590
3591/// Check if sinking \p I's operands to I's basic block is profitable, because
3592/// the operands can be folded into a target instruction, e.g.
3593/// splats of scalars can fold into vector instructions.
3596 using namespace llvm::PatternMatch;
3597
3598 if (I->isBitwiseLogicOp()) {
3599 if (!I->getType()->isVectorTy()) {
3600 if (ST->hasStdExtZbb() || ST->hasStdExtZbkb()) {
3601 for (auto &Op : I->operands()) {
3602 // (and/or/xor X, (not Y)) -> (andn/orn/xnor X, Y)
3603 if (match(Op.get(), m_Not(m_Value()))) {
3604 Ops.push_back(&Op);
3605 return true;
3606 }
3607 }
3608 }
3609 } else if (I->getOpcode() == Instruction::And && ST->hasStdExtZvkb()) {
3610 for (auto &Op : I->operands()) {
3611 // (and X, (not Y)) -> (vandn.vv X, Y)
3612 if (match(Op.get(), m_Not(m_Value()))) {
3613 Ops.push_back(&Op);
3614 return true;
3615 }
3616 // (and X, (splat (not Y))) -> (vandn.vx X, Y)
3618 m_ZeroInt()),
3619 m_Value(), m_ZeroMask()))) {
3620 Use &InsertElt = cast<Instruction>(Op)->getOperandUse(0);
3621 Use &Not = cast<Instruction>(InsertElt)->getOperandUse(1);
3622 Ops.push_back(&Not);
3623 Ops.push_back(&InsertElt);
3624 Ops.push_back(&Op);
3625 return true;
3626 }
3627 }
3628 }
3629 }
3630
3631 if (!I->getType()->isVectorTy() || !ST->hasVInstructions())
3632 return false;
3633
3634 // Don't sink splat operands if the target prefers it. Some targets requires
3635 // S2V transfer buffers and we can run out of them copying the same value
3636 // repeatedly.
3637 // FIXME: It could still be worth doing if it would improve vector register
3638 // pressure and prevent a vector spill.
3639 if (!ST->sinkSplatOperands())
3640 return false;
3641
3642 for (auto OpIdx : enumerate(I->operands())) {
3643 if (!canSplatOperand(I, OpIdx.index()))
3644 continue;
3645
3646 Instruction *Op = dyn_cast<Instruction>(OpIdx.value().get());
3647 // Make sure we are not already sinking this operand
3648 if (!Op || any_of(Ops, [&](Use *U) { return U->get() == Op; }))
3649 continue;
3650
3651 // We are looking for a splat that can be sunk.
3653 m_Value(), m_ZeroMask())))
3654 continue;
3655
3656 // Don't sink i1 splats.
3657 if (cast<VectorType>(Op->getType())->getElementType()->isIntegerTy(1))
3658 continue;
3659
3660 // All uses of the shuffle should be sunk to avoid duplicating it across gpr
3661 // and vector registers
3662 for (Use &U : Op->uses()) {
3663 Instruction *Insn = cast<Instruction>(U.getUser());
3664 if (!canSplatOperand(Insn, U.getOperandNo()))
3665 return false;
3666 }
3667
3668 // Sink any fpexts since they might be used in a widening fp pattern.
3669 Use *InsertEltUse = &Op->getOperandUse(0);
3670 auto *InsertElt = cast<InsertElementInst>(InsertEltUse);
3671 if (isa<FPExtInst>(InsertElt->getOperand(1)))
3672 Ops.push_back(&InsertElt->getOperandUse(1));
3673 Ops.push_back(InsertEltUse);
3674 Ops.push_back(&OpIdx.value());
3675 }
3676 return true;
3677}
3678
3680RISCVTTIImpl::enableMemCmpExpansion(bool OptSize, bool IsZeroCmp) const {
3682
3683 if (!ST->hasStdExtZbb() && !ST->hasStdExtZbkb() && !IsZeroCmp)
3684 return Options;
3685
3686 Options.AllowOverlappingLoads = true;
3687 Options.MaxNumLoads = TLI->getMaxExpandSizeMemcmp(OptSize);
3688 Options.NumLoadsPerBlock = Options.MaxNumLoads;
3689 if (ST->is64Bit()) {
3690 Options.LoadSizes = {8, 4, 2, 1};
3691 Options.AllowedTailExpansions = {3, 5, 6};
3692 } else {
3693 Options.LoadSizes = {4, 2, 1};
3694 Options.AllowedTailExpansions = {3};
3695 }
3696
3697 if (IsZeroCmp && ST->hasVInstructions()) {
3698 unsigned VLenB = ST->getRealMinVLen() / 8;
3699 // The minimum size should be `XLen / 8 + 1`, and the maxinum size should be
3700 // `VLenB * MaxLMUL` so that it fits in a single register group.
3701 unsigned MinSize = ST->getXLen() / 8 + 1;
3702 unsigned MaxSize = VLenB * ST->getMaxLMULForFixedLengthVectors();
3703 for (unsigned Size = MinSize; Size <= MaxSize; Size++)
3704 Options.LoadSizes.insert(Options.LoadSizes.begin(), Size);
3705 }
3706 return Options;
3707}
3708
3710 const Instruction *I) const {
3712 // For the binary operators (e.g. or) we need to be more careful than
3713 // selects, here we only transform them if they are already at a natural
3714 // break point in the code - the end of a block with an unconditional
3715 // terminator.
3716 if (I->getOpcode() == Instruction::Or &&
3717 isa<UncondBrInst>(I->getNextNode()))
3718 return true;
3719
3720 if (I->getOpcode() == Instruction::Add ||
3721 I->getOpcode() == Instruction::Sub)
3722 return true;
3723 }
3725}
3726
3728 const Function *Caller, const Attribute &Attr) const {
3729 // "interrupt" controls the prolog/epilog of interrupt handlers (and includes
3730 // restrictions on their signatures). We can outline from the bodies of these
3731 // handlers, but when we do we need to make sure we don't mark the outlined
3732 // function as an interrupt handler too.
3733 if (Attr.isStringAttribute() && Attr.getKindAsString() == "interrupt")
3734 return false;
3735
3737}
3738
3739std::optional<Instruction *>
3741 // If all operands of a vmv.v.x are constant, fold a bitcast(vmv.v.x) to scale
3742 // the vmv.v.x, enabling removal of the bitcast. The transform helps avoid
3743 // creating redundant masks.
3744 const DataLayout &DL = IC.getDataLayout();
3745 if (II.user_empty())
3746 return {};
3747 auto *TargetVecTy = dyn_cast<ScalableVectorType>(II.user_back()->getType());
3748 if (!TargetVecTy)
3749 return {};
3750 const APInt *Scalar;
3751 uint64_t VL;
3753 m_Poison(), m_APInt(Scalar), m_ConstantInt(VL))) ||
3754 !all_of(II.users(), [TargetVecTy](User *U) {
3755 return U->getType() == TargetVecTy && match(U, m_BitCast(m_Value()));
3756 }))
3757 return {};
3758 auto *SourceVecTy = cast<ScalableVectorType>(II.getType());
3759 unsigned TargetEltBW = DL.getTypeSizeInBits(TargetVecTy->getElementType());
3760 unsigned SourceEltBW = DL.getTypeSizeInBits(SourceVecTy->getElementType());
3761 if (TargetEltBW % SourceEltBW)
3762 return {};
3763 unsigned TargetScale = TargetEltBW / SourceEltBW;
3764 if (VL % TargetScale || TargetScale == 1)
3765 return {};
3766 Type *VLTy = II.getOperand(2)->getType();
3767 ElementCount SourceEC = SourceVecTy->getElementCount();
3768 unsigned NewEltBW = SourceEltBW * TargetScale;
3769 if (!SourceEC.isKnownMultipleOf(TargetScale) ||
3770 !DL.fitsInLegalInteger(NewEltBW))
3771 return {};
3772 auto *NewEltTy = IntegerType::get(II.getContext(), NewEltBW);
3773 if (!TLI->isLegalElementTypeForRVV(TLI->getValueType(DL, NewEltTy)))
3774 return {};
3775 ElementCount NewEC = SourceEC.divideCoefficientBy(TargetScale);
3776 Type *RetTy = VectorType::get(NewEltTy, NewEC);
3777 assert(SourceVecTy->canLosslesslyBitCastTo(RetTy) &&
3778 "Lossless bitcast between types expected");
3779 APInt NewScalar = APInt::getSplat(NewEltBW, *Scalar);
3780 return IC.replaceInstUsesWith(
3781 II,
3784 RetTy, Intrinsic::riscv_vmv_v_x,
3785 {PoisonValue::get(RetTy), ConstantInt::get(NewEltTy, NewScalar),
3786 ConstantInt::get(VLTy, VL / TargetScale)}),
3787 SourceVecTy));
3788}
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
static cl::opt< bool > EnableOrLikeSelectOpt("enable-aarch64-or-like-select", cl::init(true), cl::Hidden)
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.
Hexagon Common GEP
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[]
static LVOptions Options
Definition LVOptions.cpp:25
#define F(x, y, z)
Definition MD5.cpp:54
#define I(x, y, z)
Definition MD5.cpp:57
static const Function * getCalledFunction(const Value *V)
uint64_t IntrinsicInst * II
static InstructionCost costShuffleViaVRegSplitting(const RISCVTTIImpl &TTI, MVT LegalVT, std::optional< unsigned > VLen, VectorType *Tp, ArrayRef< int > Mask, TTI::TargetCostKind CostKind)
Try to perform better estimation of the permutation.
static InstructionCost costShuffleViaSplitting(const RISCVTTIImpl &TTI, MVT LegalVT, VectorType *Tp, ArrayRef< int > Mask, TTI::TargetCostKind CostKind)
Attempt to approximate the cost of a shuffle which will require splitting during legalization.
static bool isRepeatedConcatMask(ArrayRef< int > Mask, int &SubVectorSize)
static unsigned isM1OrSmaller(MVT VT)
static cl::opt< bool > EnableOrLikeSelectOpt("enable-riscv-or-like-select", cl::init(true), cl::Hidden)
static cl::opt< unsigned > SLPMaxVF("riscv-v-slp-max-vf", cl::desc("Overrides result used for getMaximumVF query which is used " "exclusively by SLP vectorizer."), cl::Hidden)
static cl::opt< unsigned > RVVRegisterWidthLMUL("riscv-v-register-bit-width-lmul", cl::desc("The LMUL to use for getRegisterBitWidth queries. Affects LMUL used " "by autovectorized code. Fractional LMULs are not supported."), cl::init(2), cl::Hidden)
static cl::opt< unsigned > RVVMinTripCount("riscv-v-min-trip-count", cl::desc("Set the lower bound of a trip count to decide on " "vectorization while tail-folding."), cl::init(5), cl::Hidden)
static InstructionCost getIntImmCostImpl(const DataLayout &DL, const RISCVSubtarget *ST, const APInt &Imm, Type *Ty, TTI::TargetCostKind CostKind, bool FreeZeroes)
static VectorType * getVRGatherIndexType(MVT DataVT, const RISCVSubtarget &ST, LLVMContext &C)
static const CostTblEntry VectorIntrinsicCostTable[]
static bool canUseShiftPair(Instruction *Inst, const APInt &Imm)
static bool canUseShiftCmp(Instruction *Inst, const APInt &Imm)
This file defines a TargetTransformInfoImplBase conforming object specific to the RISC-V target machi...
SI Fold Operands
static Type * getValueType(Value *V, bool LookThroughCmp=false)
Returns the "element type" of the given value/instruction V.
This file contains some templates that are useful if you are working with the STL at all.
#define LLVM_DEBUG(...)
Definition Debug.h:119
This file describes how to lower LLVM code to machine code.
This pass exposes codegen information to IR-level passes.
Class for arbitrary precision integers.
Definition APInt.h:78
static LLVM_ABI APInt getSplat(unsigned NewLen, const APInt &V)
Return a value containing V broadcasted over NewLen bits.
Definition APInt.cpp:652
static APInt getZero(unsigned numBits)
Get the '0' value for the specified bit-width.
Definition APInt.h:201
Represent a constant reference to an array (0 or more elements consecutively in memory),...
Definition ArrayRef.h:40
const T & back() const
Get the last element.
Definition ArrayRef.h:150
iterator end() const
Definition ArrayRef.h:130
size_t size() const
Get the array size.
Definition ArrayRef.h:141
Functions, function parameters, and return types can have attributes to indicate how they should be t...
Definition Attributes.h:105
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 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 *CxtI=nullptr) const override
InstructionCost getMinMaxReductionCost(Intrinsic::ID IID, VectorType *Ty, FastMathFlags FMF, TTI::TargetCostKind CostKind) const override
InstructionCost getGEPCost(Type *PointeeType, const Value *Ptr, ArrayRef< const Value * > Operands, Type *AccessType, 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 getShuffleCost(TTI::ShuffleKind Kind, VectorType *DstTy, VectorType *SrcTy, ArrayRef< int > Mask, TTI::TargetCostKind CostKind, int Index, VectorType *SubTp, ArrayRef< const Value * > Args={}, const Instruction *CxtI=nullptr) 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
std::optional< unsigned > getMaxVScale() 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 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
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.
Definition InstrTypes.h:740
@ FCMP_OEQ
0 0 0 1 True if ordered and equal
Definition InstrTypes.h:743
@ FCMP_TRUE
1 1 1 1 Always true (always folded)
Definition InstrTypes.h:757
@ ICMP_SLT
signed less than
Definition InstrTypes.h:769
@ FCMP_OLT
0 1 0 0 True if ordered and less than
Definition InstrTypes.h:746
@ FCMP_ULE
1 1 0 1 True if unordered, less than, or equal
Definition InstrTypes.h:755
@ FCMP_OGT
0 0 1 0 True if ordered and greater than
Definition InstrTypes.h:744
@ FCMP_OGE
0 0 1 1 True if ordered and greater than or equal
Definition InstrTypes.h:745
@ FCMP_ULT
1 1 0 0 True if unordered or less than
Definition InstrTypes.h:754
@ FCMP_ONE
0 1 1 0 True if ordered and operands are unequal
Definition InstrTypes.h:748
@ FCMP_UEQ
1 0 0 1 True if unordered or equal
Definition InstrTypes.h:751
@ FCMP_UGT
1 0 1 0 True if unordered or greater than
Definition InstrTypes.h:752
@ FCMP_OLE
0 1 0 1 True if ordered and less than or equal
Definition InstrTypes.h:747
@ FCMP_ORD
0 1 1 1 True if ordered (no nans)
Definition InstrTypes.h:749
@ ICMP_NE
not equal
Definition InstrTypes.h:762
@ FCMP_UNE
1 1 1 0 True if unordered or not equal
Definition InstrTypes.h:756
@ FCMP_UGE
1 0 1 1 True if unordered, greater than, or equal
Definition InstrTypes.h:753
@ FCMP_FALSE
0 0 0 0 Always false (always folded)
Definition InstrTypes.h:742
@ FCMP_UNO
1 0 0 0 True if unordered: isnan(X) | isnan(Y)
Definition InstrTypes.h:750
static bool isFPPredicate(Predicate P)
Definition InstrTypes.h:833
static bool isIntPredicate(Predicate P)
Definition InstrTypes.h:839
static LLVM_ABI ConstantInt * getTrue(LLVMContext &Context)
This class represents a range of values.
A parsed version of the target data layout string in and methods for querying it.
Definition DataLayout.h:64
Convenience struct for specifying and reasoning about fast-math flags.
Definition FMF.h:23
bool noNaNs() const
Definition FMF.h:65
Class to represent fixed width SIMD vectors.
unsigned getNumElements() const
static FixedVectorType * getDoubleElementsVectorType(FixedVectorType *VTy)
static LLVM_ABI FixedVectorType * get(Type *ElementType, unsigned NumElts)
Definition Type.cpp:867
an instruction for type-safe pointer arithmetic to access elements of arrays and structs
Value * CreateBitCast(Value *V, Type *DestTy, const Twine &Name="")
Definition IRBuilder.h:2243
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.
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:
static LLVM_ABI IntegerType * get(LLVMContext &C, unsigned NumBits)
This static method is the primary way of constructing an IntegerType.
Definition Type.cpp:348
const SmallVectorImpl< Type * > & getArgTypes() const
const SmallVectorImpl< const Value * > & getArgs() const
VectorInstrContext getVectorInstrContext() 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.
Definition LLVMContext.h:68
Represents a single loop in the control flow graph.
Definition LoopInfo.h:40
Machine Value Type.
static MVT getFloatingPointVT(unsigned BitWidth)
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
TypeSize getStoreSize() const
Return the number of bytes overwritten by a store of the specified value type.
MVT getVectorElementType() const
static MVT getIntegerVT(unsigned BitWidth)
MVT getScalarType() const
If this is a vector, return the element type, otherwise return this.
Information for memory intrinsic cost model.
unsigned getOpcode() const
Return the opcode for this Instruction or ConstantExpr.
Definition Operator.h:43
The optimization diagnostic interface.
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
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 *CxtI=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
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 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
std::optional< InstructionCost > getCombinedArithmeticInstructionCost(unsigned ISDOpcode, Type *Ty, TTI::TargetCostKind CostKind, TTI::OperandValueInfo Opd1Info, TTI::OperandValueInfo Opd2Info, ArrayRef< const Value * > Args, const Instruction *CxtI) const
Check to see if this instruction is expected to be combined to a simpler operation during/before lowe...
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...
std::optional< unsigned > getMaxVScale() const override
bool shouldExpandReduction(const IntrinsicInst *II) const override
std::optional< unsigned > getVScaleForTuning() const override
InstructionCost getMemIntrinsicInstrCost(const MemIntrinsicCostAttributes &MICA, TTI::TargetCostKind CostKind) const override
Get memory intrinsic cost based on arguments.
bool isLegalMaskedGather(Type *DataType, Align Alignment) const override
InstructionCost getShuffleCost(TTI::ShuffleKind Kind, VectorType *DstTy, VectorType *SrcTy, ArrayRef< int > Mask, TTI::TargetCostKind CostKind, int Index, VectorType *SubTp, ArrayRef< const Value * > Args={}, const Instruction *CxtI=nullptr) const override
unsigned getMaximumVF(unsigned ElemWidth, unsigned Opcode) const override
InstructionCost getPointersChainCost(ArrayRef< const Value * > Ptrs, const Value *Base, const TTI::PointersChainInfo &Info, Type *AccessTy, TTI::TargetCostKind CostKind) 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)
Definition Type.cpp:889
The main scalar evolution driver.
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.
Definition DenseSet.h:293
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.
virtual const DataLayout & getDataLayout() const
virtual bool shouldTreatInstructionLikeSelect(const Instruction *I) const
virtual TTI::AddressingModeKind getPreferredAddressingMode(const Loop *L, ScalarEvolution *SE) const
virtual bool shouldCopyAttributeWhenOutliningFrom(const Function *Caller, const Attribute &Attr) const
virtual bool isLoweredToCall(const Function *F) const
InstructionCost getInstructionCost(const User *U, ArrayRef< const Value * > Operands, TTI::TargetCostKind CostKind) const override
TargetCostKind
The kind of cost model.
@ TCK_RecipThroughput
Reciprocal throughput.
@ TCK_CodeSize
Instruction code size.
@ TCK_SizeAndLatency
The weighted sum of size and latency.
@ TCK_Latency
The latency of instruction.
static bool requiresOrderedReduction(std::optional< FastMathFlags > FMF)
A helper function to determine the type of reduction algorithm used for a given Opcode and set of Fas...
PopcntSupportKind
Flags indicating the kind of support for population count.
llvm::VectorInstrContext VectorInstrContext
@ TCC_Expensive
The cost of a 'div' instruction on x86.
@ TCC_Free
Expected to fold away in lowering.
@ TCC_Basic
The cost of a typical 'add' instruction.
AddressingModeKind
Which addressing mode Loop Strength Reduction will try to generate.
@ AMK_PostIndexed
Prefer post-indexed addressing mode.
ShuffleKind
The various kinds of shuffle patterns for vector queries.
@ SK_InsertSubvector
InsertSubvector. Index indicates start offset.
@ SK_Select
Selects elements from the corresponding lane of either source operand.
@ SK_PermuteSingleSrc
Shuffle elements of single source vector with any shuffle mask.
@ SK_Transpose
Transpose two vectors.
@ SK_Splice
Concatenates elements from the first input vector with elements of the second input vector.
@ SK_Broadcast
Broadcast element 0 to all other elements.
@ SK_PermuteTwoSrc
Merge elements from two source vectors into one with any shuffle mask.
@ SK_Reverse
Reverse the order of the vector.
@ SK_ExtractSubvector
ExtractSubvector Index indicates start offset.
CastContextHint
Represents a hint about the context in which a cast is used.
@ None
The cast is not used with a load/store of any kind.
static constexpr TypeSize getFixed(ScalarTy ExactSize)
Definition TypeSize.h:343
static constexpr TypeSize getScalable(ScalarTy MinimumSize)
Definition TypeSize.h:346
The instances of the Type class are immutable: once they are created, they are never changed.
Definition Type.h:46
static LLVM_ABI IntegerType * getInt64Ty(LLVMContext &C)
Definition Type.cpp:310
bool isVectorTy() const
True if this is an instance of VectorType.
Definition Type.h:288
LLVM_ABI bool isScalableTy(SmallPtrSetImpl< const Type * > &Visited) const
Return true if this is a type whose size is a known multiple of vscale.
Definition Type.cpp:61
bool isBFloatTy() const
Return true if this is 'bfloat', a 16-bit bfloat type.
Definition Type.h:147
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'.
Definition Type.h:368
LLVM_ABI Type * getWithNewBitWidth(unsigned NewBitWidth) const
Given an integer or vector type, change the lane bitwidth to NewBitwidth, whilst keeping the old numb...
bool isHalfTy() const
Return true if this is 'half', a 16-bit IEEE fp type.
Definition Type.h:144
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.
Definition Type.h:130
LLVM_ABI unsigned getScalarSizeInBits() const LLVM_READONLY
If this is a vector type, return the getPrimitiveSizeInBits value for the element type.
Definition Type.cpp:232
static LLVM_ABI IntegerType * getInt1Ty(LLVMContext &C)
Definition Type.cpp:306
bool isIntegerTy() const
True if this is an instance of IntegerType.
Definition Type.h:257
static LLVM_ABI IntegerType * getIntNTy(LLVMContext &C, unsigned N)
Definition Type.cpp:313
static LLVM_ABI Type * getFloatTy(LLVMContext &C)
Definition Type.cpp:286
bool isVoidTy() const
Return true if this is 'void'.
Definition Type.h:141
A Use represents the edge between a Value definition and its users.
Definition Use.h:35
Value * getOperand(unsigned i) const
Definition User.h:207
LLVM Value Representation.
Definition Value.h:75
Type * getType() const
All values are typed, get the type of this value.
Definition Value.h:255
user_iterator user_begin()
Definition Value.h:402
bool hasOneUse() const
Return true if there is exactly one use of this value.
Definition Value.h:439
LLVMContext & getContext() const
All values hold a context through their type.
Definition Value.h:258
LLVM_ABI Align getPointerAlignment(const DataLayout &DL) const
Returns an alignment of the pointer value.
Definition Value.cpp:993
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)
Definition DenseSet.h:209
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...
Definition TypeSize.h:180
constexpr ScalarTy getFixedValue() const
Definition TypeSize.h:200
static constexpr bool isKnownLE(const FixedOrScalableQuantity &LHS, const FixedOrScalableQuantity &RHS)
Definition TypeSize.h:230
static constexpr bool isKnownLT(const FixedOrScalableQuantity &LHS, const FixedOrScalableQuantity &RHS)
Definition TypeSize.h:216
constexpr ScalarTy getKnownMinValue() const
Returns the minimum value this quantity can represent.
Definition TypeSize.h:165
constexpr LeafTy divideCoefficientBy(ScalarTy RHS) const
We do not provide the '/' operator here because division for polynomial types does not work in the sa...
Definition TypeSize.h:252
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
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...
Definition ISDOpcodes.h:24
@ ADD
Simple integer binary arithmetic operators.
Definition ISDOpcodes.h:264
@ SINT_TO_FP
[SU]INT_TO_FP - These operators convert integers (whose interpreted sign depends on the first letter)...
Definition ISDOpcodes.h:890
@ FADD
Simple binary floating point operators.
Definition ISDOpcodes.h:417
@ SIGN_EXTEND
Conversion operators.
Definition ISDOpcodes.h:854
@ 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...
Definition ISDOpcodes.h:706
@ SHL
Shift and rotation operations.
Definition ISDOpcodes.h:771
@ ZERO_EXTEND
ZERO_EXTEND - Used for integer types, zeroing the new bits.
Definition ISDOpcodes.h:860
@ FP_EXTEND
X = FP_EXTEND(Y) - Extend a smaller FP type into a larger FP type.
Definition ISDOpcodes.h:988
@ FP_TO_SINT
FP_TO_[US]INT - Convert a floating point value to a signed or unsigned integer.
Definition ISDOpcodes.h:936
@ AND
Bitwise operators - logical and, logical or, logical xor.
Definition ISDOpcodes.h:741
@ FP_ROUND
X = FP_ROUND(Y, TRUNC) - Rounding 'Y' from a larger floating point type down to the precision of the ...
Definition ISDOpcodes.h:969
@ TRUNCATE
TRUNCATE - Completely drop the high bits.
Definition ISDOpcodes.h:866
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 constexpr unsigned RVVBitsPerBlock
initializer< Ty > init(const Ty &Val)
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.
Definition MathExtras.h:345
bool all_of(R &&range, UnaryPredicate P)
Provide wrappers to std::all_of which take ranges instead of having to pass begin/end explicitly.
Definition STLExtras.h:1739
const CostTblEntryT< CostType > * CostTableLookup(ArrayRef< CostTblEntryT< CostType > > Tbl, int ISD, MVT Ty)
Find in cost table.
Definition CostTable.h:36
LLVM_ABI bool getBooleanLoopAttribute(const Loop *TheLoop, StringRef Name)
Returns true if Name is applied to TheLoop and enabled.
InstructionCost Cost
constexpr bool isInt(int64_t x)
Checks if an integer fits into the given bit width.
Definition MathExtras.h:166
auto enumerate(FirstRange &&First, RestRanges &&...Rest)
Given two or more input ranges, returns a new range whose values are tuples (A, B,...
Definition STLExtras.h:2554
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:643
@ BinaryOp
One of the operands is a binary op.
auto adjacent_find(R &&Range)
Provide wrappers to std::adjacent_find which finds the first pair of adjacent elements that are equal...
Definition STLExtras.h:1818
int countr_zero(T Val)
Count number of 0's from the least significant bit to the most stopping at the first 1.
Definition bit.h:204
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...
Definition MathExtras.h:274
bool any_of(R &&range, UnaryPredicate P)
Provide wrappers to std::any_of which take ranges instead of having to pass begin/end explicitly.
Definition STLExtras.h:1746
unsigned Log2_32(uint32_t Value)
Return the floor log base 2 of the specified value, -1 if the value is zero.
Definition MathExtras.h:332
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.
Definition MathExtras.h:280
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
Definition Debug.cpp:209
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...
Definition STLExtras.h:1970
constexpr bool isUInt(uint64_t x)
Checks if an unsigned integer fits into the given bit width.
Definition MathExtras.h:190
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...
Definition Casting.h:547
constexpr int PoisonMaskElem
constexpr T divideCeil(U Numerator, V Denominator)
Returns the integer ceil(Numerator / Denominator).
Definition MathExtras.h:395
TargetTransformInfo TTI
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.
DWARFExpression::Operation Op
OutputIt copy(R &&Range, OutputIt Out)
Definition STLExtras.h:1885
CostTblEntryT< uint16_t > CostTblEntry
Definition CostTable.h:31
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:559
constexpr int64_t SignExtend64(uint64_t x)
Sign-extend the number in the bottom B bits of X to a 64-bit integer.
Definition MathExtras.h:573
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.
Definition STLExtras.h:2146
T bit_floor(T Value)
Returns the largest integral power of two no greater than Value if Value is nonzero.
Definition bit.h:347
void swap(llvm::BitVector &LHS, llvm::BitVector &RHS)
Implement std::swap in terms of BitVector swap.
Definition BitVector.h:880
This struct is a compact representation of a valid (non-zero power of two) alignment.
Definition Alignment.h:39
constexpr uint64_t value() const
This is a hole in the type system and should not be abused.
Definition Alignment.h:77
Extended Value Type.
Definition ValueTypes.h:35
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.
Definition Alignment.h:106
Align valueOrOne() const
For convenience, returns a valid alignment or 1 if undefined.
Definition Alignment.h:130
Information about a load/store intrinsic defined by the target.
unsigned Insns
TODO: Some of these could be merged.
Returns options for expansion of memcmp. IsZeroCmp is.
Describe known properties for a set of pointers.
Parameters that control the generic loop unrolling transformation.
bool UpperBound
Allow using trip count upper bound to unroll loops.
bool Force
Apply loop unroll on any kind of loop (mainly to loops that fail runtime unrolling).
unsigned PartialOptSizeThreshold
The cost threshold for the unrolled loop when optimizing for size, like OptSizeThreshold,...
bool UnrollAndJam
Allow unroll and jam. Used to enable unroll and jam for the target.
bool UnrollRemainder
Allow unrolling of all the iterations of the runtime loop remainder.
bool Runtime
Allow runtime unrolling (unrolling of loops to expand the size of the loop body even when the number ...
bool Partial
Allow partial unrolling (unrolling of loops to expand the size of the loop body, not only to eliminat...
unsigned OptSizeThreshold
The cost threshold for the unrolled loop when optimizing for size (set to UINT_MAX to disable).