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