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