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