1//===- RISCVTargetTransformInfo.h - RISC-V specific TTI ---------*- C++ -*-===//
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/// \file
9/// This file defines a TargetTransformInfoImplBase conforming object specific
10/// to the RISC-V target machine. It uses the target's detailed information to
11/// provide more precise answers to certain TTI queries, while letting the
12/// target independent and default TTI implementations handle the rest.
13///
14//===----------------------------------------------------------------------===//
15
16#ifndef LLVM_LIB_TARGET_RISCV_RISCVTARGETTRANSFORMINFO_H
17#define LLVM_LIB_TARGET_RISCV_RISCVTARGETTRANSFORMINFO_H
18
19#include "RISCVSubtarget.h"
20#include "RISCVTargetMachine.h"
21#include "llvm/Analysis/TargetTransformInfo.h"
22#include "llvm/CodeGen/BasicTTIImpl.h"
23#include "llvm/IR/Function.h"
24#include <optional>
25
26namespace llvm {
27
28class RISCVTTIImpl final : public BasicTTIImplBase<RISCVTTIImpl> {
29 using BaseT = BasicTTIImplBase<RISCVTTIImpl>;
30 using TTI = TargetTransformInfo;
31
32 friend BaseT;
33
34 const RISCVSubtarget *ST;
35 const RISCVTargetLowering *TLI;
36
37 const RISCVSubtarget *getST() const { return ST; }
38 const RISCVTargetLowering *getTLI() const { return TLI; }
39
40 /// This function returns an estimate for VL to be used in VL based terms
41 /// of the cost model. For fixed length vectors, this is simply the
42 /// vector length. For scalable vectors, we return results consistent
43 /// with getVScaleForTuning under the assumption that clients are also
44 /// using that when comparing costs between scalar and vector representation.
45 /// This does unfortunately mean that we can both undershoot and overshot
46 /// the true cost significantly if getVScaleForTuning is wildly off for the
47 /// actual target hardware.
48 unsigned getEstimatedVLFor(VectorType *Ty) const;
49
50 /// This function calculates the costs for one or more RVV opcodes based
51 /// on the vtype and the cost kind.
52 /// \param Opcodes A list of opcodes of the RVV instruction to evaluate.
53 /// \param VT The MVT of vtype associated with the RVV instructions.
54 /// For widening/narrowing instructions where the result and source types
55 /// differ, it is important to check the spec to determine whether the vtype
56 /// refers to the result or source type.
57 /// \param CostKind The type of cost to compute.
58 InstructionCost getRISCVInstructionCost(ArrayRef<unsigned> OpCodes, MVT VT,
59 TTI::TargetCostKind CostKind) const;
60
61 // Return the cost of generating a PC relative address
62 InstructionCost
63 getStaticDataAddrGenerationCost(const TTI::TargetCostKind CostKind) const;
64
65 /// Return the cost of accessing a constant pool entry of the specified
66 /// type.
67 InstructionCost getConstantPoolLoadCost(Type *Ty,
68 TTI::TargetCostKind CostKind) const;
69
70 /// If this shuffle can be lowered as a masked slide pair (at worst),
71 /// return a cost for it.
72 InstructionCost getSlideCost(FixedVectorType *Tp, ArrayRef<int> Mask,
73 TTI::TargetCostKind CostKind) const;
74
75public:
76 explicit RISCVTTIImpl(const RISCVTargetMachine *TM, const Function &F)
77 : BaseT(TM, F.getDataLayout()), ST(TM->getSubtargetImpl(F)),
78 TLI(ST->getTargetLowering()) {}
79
80 /// Return the cost of materializing an immediate for a value operand of
81 /// a store instruction.
82 InstructionCost getStoreImmCost(Type *VecTy, TTI::OperandValueInfo OpInfo,
83 TTI::TargetCostKind CostKind) const;
84
85 InstructionCost getIntImmCost(const APInt &Imm, Type *Ty,
86 TTI::TargetCostKind CostKind) const override;
87 InstructionCost getIntImmCostInst(unsigned Opcode, unsigned Idx,
88 const APInt &Imm, Type *Ty,
89 TTI::TargetCostKind CostKind,
90 Instruction *Inst = nullptr) const override;
91 InstructionCost
92 getIntImmCostIntrin(Intrinsic::ID IID, unsigned Idx, const APInt &Imm,
93 Type *Ty, TTI::TargetCostKind CostKind) const override;
94
95 /// \name EVL Support for predicated vectorization.
96 /// Whether the target supports the %evl parameter of VP intrinsic efficiently
97 /// in hardware. (see LLVM Language Reference - "Vector Predication
98 /// Intrinsics",
99 /// https://llvm.org/docs/LangRef.html#vector-predication-intrinsics and
100 /// "IR-level VP intrinsics",
101 /// https://llvm.org/docs/Proposals/VectorPredication.html#ir-level-vp-intrinsics).
102 bool hasActiveVectorLength() const override;
103
104 TargetTransformInfo::PopcntSupportKind
105 getPopcntSupport(unsigned TyWidth) const override;
106
107 InstructionCost getPartialReductionCost(
108 unsigned Opcode, Type *InputTypeA, Type *InputTypeB, Type *AccumType,
109 ElementCount VF, TTI::PartialReductionExtendKind OpAExtend,
110 TTI::PartialReductionExtendKind OpBExtend, std::optional<unsigned> BinOp,
111 TTI::TargetCostKind CostKind,
112 std::optional<FastMathFlags> FMF) const override;
113
114 bool shouldExpandReduction(const IntrinsicInst *II) const override;
115 bool supportsScalableVectors() const override {
116 // VLEN=32 support is incomplete.
117 return ST->hasVInstructions() &&
118 (ST->getRealMinVLen() >= RISCV::RVVBitsPerBlock);
119 }
120 bool enableOrderedReductions() const override { return true; }
121 bool enableScalableVectorization() const override {
122 return ST->hasVInstructions();
123 }
124 bool preferTailFoldingOverEpilogue(TailFoldingInfo *TFI) const override {
125 return ST->hasVInstructions();
126 }
127 TailFoldingStyle getPreferredTailFoldingStyle() const override {
128 return ST->hasVInstructions() ? TailFoldingStyle::DataWithEVL
129 : TailFoldingStyle::None;
130 }
131 std::optional<unsigned> getVScaleForTuning() const override;
132
133 TypeSize
134 getRegisterBitWidth(TargetTransformInfo::RegisterKind K) const override;
135
136 unsigned getRegUsageForType(Type *Ty) const override;
137
138 unsigned getMaximumVF(unsigned ElemWidth, unsigned Opcode) const override;
139
140 bool preferAlternateOpcodeVectorization() const override;
141
142 bool preferEpilogueVectorization(ElementCount Iters) const override {
143 // Epilogue vectorization is usually unprofitable - tail folding or
144 // a smaller VF would have been better. This a blunt hammer - we
145 // should re-examine this once vectorization is better tuned.
146 return false;
147 }
148
149 bool shouldConsiderVectorizationRegPressure() const override { return true; }
150
151 InstructionCost
152 getMemIntrinsicInstrCost(const MemIntrinsicCostAttributes &MICA,
153 TTI::TargetCostKind CostKind) const override;
154
155 InstructionCost getMaskedMemoryOpCost(const MemIntrinsicCostAttributes &MICA,
156 TTI::TargetCostKind CostKind) const;
157
158 InstructionCost
159 getPointersChainCost(ArrayRef<const Value *> Ptrs, const Value *Base,
160 const TTI::PointersChainInfo &Info, Type *AccessTy,
161 const TTI::TargetCostKind CostKind) const override;
162
163 void getUnrollingPreferences(Loop *L, ScalarEvolution &SE,
164 TTI::UnrollingPreferences &UP,
165 OptimizationRemarkEmitter *ORE) const override;
166
167 void getPeelingPreferences(Loop *L, ScalarEvolution &SE,
168 TTI::PeelingPreferences &PP) const override;
169
170 bool getTgtMemIntrinsic(IntrinsicInst *Inst,
171 MemIntrinsicInfo &Info) const override;
172
173 unsigned getMinVectorRegisterBitWidth() const override {
174 return ST->useRVVForFixedLengthVectors() ? 16 : 0;
175 }
176
177 InstructionCost
178 getShuffleCost(TTI::ShuffleKind Kind, VectorType *DstTy, VectorType *SrcTy,
179 TTI::TargetCostKind CostKind, ArrayRef<int> Mask, int Index,
180 VectorType *SubTp, ArrayRef<const Value *> Args = {},
181 const Instruction *CxtI = nullptr) const override;
182
183 InstructionCost
184 getScalarizationOverhead(VectorType *Ty, const APInt &DemandedElts,
185 bool Insert, bool Extract,
186 TTI::TargetCostKind CostKind,
187 bool ForPoisonSrc = true, ArrayRef<Value *> VL = {},
188 TTI::VectorInstrContext VIC =
189 TTI::VectorInstrContext::None) const override;
190
191 InstructionCost
192 getIntrinsicInstrCost(const IntrinsicCostAttributes &ICA,
193 TTI::TargetCostKind CostKind) const override;
194
195 InstructionCost
196 getAddressComputationCost(Type *PTy, ScalarEvolution *SE, const SCEV *Ptr,
197 TTI::TargetCostKind CostKind) const override;
198
199 InstructionCost getInterleavedMemoryOpCost(
200 unsigned Opcode, Type *VecTy, unsigned Factor, ArrayRef<unsigned> Indices,
201 Align Alignment, unsigned AddressSpace, TTI::TargetCostKind CostKind,
202 bool UseMaskForCond = false, bool UseMaskForGaps = false) const override;
203
204 InstructionCost getGatherScatterOpCost(const MemIntrinsicCostAttributes &MICA,
205 TTI::TargetCostKind CostKind) const;
206
207 InstructionCost
208 getExpandCompressMemoryOpCost(const MemIntrinsicCostAttributes &MICA,
209 TTI::TargetCostKind CostKind) const;
210
211 InstructionCost getStridedMemoryOpCost(const MemIntrinsicCostAttributes &MICA,
212 TTI::TargetCostKind CostKind) const;
213
214 InstructionCost
215 getCostOfKeepingLiveOverCall(ArrayRef<Type *> Tys) const override;
216
217 InstructionCost
218 getCastInstrCost(unsigned Opcode, Type *Dst, Type *Src,
219 TTI::CastContextHint CCH, TTI::TargetCostKind CostKind,
220 const Instruction *I = nullptr) const override;
221
222 InstructionCost
223 getMinMaxReductionCost(Intrinsic::ID IID, VectorType *Ty, FastMathFlags FMF,
224 TTI::TargetCostKind CostKind) const override;
225
226 std::optional<InstructionCost> getCombinedArithmeticInstructionCost(
227 unsigned ISDOpcode, Type *Ty, TTI::TargetCostKind CostKind,
228 TTI::OperandValueInfo Opd1Info, TTI::OperandValueInfo Opd2Info,
229 ArrayRef<const Value *> Args, const Instruction *CxtI) const;
230
231 InstructionCost
232 getArithmeticReductionCost(unsigned Opcode, VectorType *Ty,
233 std::optional<FastMathFlags> FMF,
234 TTI::TargetCostKind CostKind) const override;
235
236 InstructionCost
237 getExtendedReductionCost(unsigned Opcode, bool IsUnsigned, Type *ResTy,
238 VectorType *ValTy, std::optional<FastMathFlags> FMF,
239 TTI::TargetCostKind CostKind) const override;
240
241 InstructionCost getMemoryOpCost(
242 unsigned Opcode, Type *Src, Align Alignment, unsigned AddressSpace,
243 TTI::TargetCostKind CostKind,
244 TTI::OperandValueInfo OpdInfo = {.Kind: TTI::OK_AnyValue, .Properties: TTI::OP_None},
245 const Instruction *I = nullptr) const override;
246
247 InstructionCost getCmpSelInstrCost(
248 unsigned Opcode, Type *ValTy, Type *CondTy, CmpInst::Predicate VecPred,
249 TTI::TargetCostKind CostKind,
250 TTI::OperandValueInfo Op1Info = {.Kind: TTI::OK_AnyValue, .Properties: TTI::OP_None},
251 TTI::OperandValueInfo Op2Info = {.Kind: TTI::OK_AnyValue, .Properties: TTI::OP_None},
252 const Instruction *I = nullptr) const override;
253
254 InstructionCost getCFInstrCost(unsigned Opcode, TTI::TargetCostKind CostKind,
255 const Instruction *I = nullptr) const override;
256
257 using BaseT::getVectorInstrCost;
258 InstructionCost
259 getVectorInstrCost(unsigned Opcode, Type *Val, TTI::TargetCostKind CostKind,
260 unsigned Index, const Value *Op0, const Value *Op1,
261 TTI::VectorInstrContext VIC =
262 TTI::VectorInstrContext::None) const override;
263
264 InstructionCost
265 getIndexedVectorInstrCostFromEnd(unsigned Opcode, Type *Val,
266 TTI::TargetCostKind CostKind,
267 unsigned Index) const override;
268
269 InstructionCost getArithmeticInstrCost(
270 unsigned Opcode, Type *Ty, TTI::TargetCostKind CostKind,
271 TTI::OperandValueInfo Op1Info = {.Kind: TTI::OK_AnyValue, .Properties: TTI::OP_None},
272 TTI::OperandValueInfo Op2Info = {.Kind: TTI::OK_AnyValue, .Properties: TTI::OP_None},
273 ArrayRef<const Value *> Args = {},
274 const Instruction *CxtI = nullptr) const override;
275
276 bool isElementTypeLegalForScalableVector(Type *Ty) const override {
277 return TLI->isLegalElementTypeForRVV(ScalarTy: TLI->getValueType(DL, Ty));
278 }
279
280 bool isLegalMaskedLoadStore(Type *DataType, Align Alignment) const {
281 if (!ST->hasVInstructions())
282 return false;
283
284 EVT DataTypeVT = TLI->getValueType(DL, Ty: DataType);
285
286 // Only support fixed vectors if we know the minimum vector size.
287 if (DataTypeVT.isFixedLengthVector() && !ST->useRVVForFixedLengthVectors())
288 return false;
289
290 EVT ElemType = DataTypeVT.getScalarType();
291 if (!ST->enableUnalignedVectorMem() && Alignment < ElemType.getStoreSize())
292 return false;
293
294 return TLI->isLegalElementTypeForRVV(ScalarTy: ElemType);
295 }
296
297 bool isLegalMaskedLoad(Type *DataType, Align Alignment,
298 unsigned /*AddressSpace*/,
299 TTI::MaskKind /*MaskKind*/) const override {
300 return isLegalMaskedLoadStore(DataType, Alignment);
301 }
302 bool isLegalMaskedStore(Type *DataType, Align Alignment,
303 unsigned /*AddressSpace*/,
304 TTI::MaskKind /*MaskKind*/) const override {
305 return isLegalMaskedLoadStore(DataType, Alignment);
306 }
307
308 bool isLegalMaskedGatherScatter(Type *DataType, Align Alignment) const {
309 if (!ST->hasVInstructions())
310 return false;
311
312 EVT DataTypeVT = TLI->getValueType(DL, Ty: DataType);
313
314 // Only support fixed vectors if we know the minimum vector size.
315 if (DataTypeVT.isFixedLengthVector() && !ST->useRVVForFixedLengthVectors())
316 return false;
317
318 // We also need to check if the vector of address is valid.
319 EVT PointerTypeVT = EVT(TLI->getPointerTy(DL));
320 if (DataTypeVT.isScalableVector() &&
321 !TLI->isLegalElementTypeForRVV(ScalarTy: PointerTypeVT))
322 return false;
323
324 EVT ElemType = DataTypeVT.getScalarType();
325 if (!ST->enableUnalignedVectorMem() && Alignment < ElemType.getStoreSize())
326 return false;
327
328 return TLI->isLegalElementTypeForRVV(ScalarTy: ElemType);
329 }
330
331 bool isLegalMaskedGather(Type *DataType, Align Alignment) const override {
332 return isLegalMaskedGatherScatter(DataType, Alignment);
333 }
334 bool isLegalMaskedScatter(Type *DataType, Align Alignment) const override {
335 return isLegalMaskedGatherScatter(DataType, Alignment);
336 }
337
338 bool forceScalarizeMaskedGather(VectorType *VTy,
339 Align Alignment) const override {
340 // Scalarize masked gather for RV64 if EEW=64 indices aren't supported.
341 return ST->is64Bit() && !ST->hasVInstructionsI64();
342 }
343
344 bool forceScalarizeMaskedScatter(VectorType *VTy,
345 Align Alignment) const override {
346 // Scalarize masked scatter for RV64 if EEW=64 indices aren't supported.
347 return ST->is64Bit() && !ST->hasVInstructionsI64();
348 }
349
350 bool isLegalStridedLoadStore(Type *DataType, Align Alignment) const override {
351 EVT DataTypeVT = TLI->getValueType(DL, Ty: DataType);
352 return TLI->isLegalStridedLoadStore(DataType: DataTypeVT, Alignment);
353 }
354
355 bool isLegalInterleavedAccessType(VectorType *VTy, unsigned Factor,
356 Align Alignment,
357 unsigned AddrSpace) const override {
358 return TLI->isLegalInterleavedAccessType(VTy, Factor, Alignment, AddrSpace,
359 DL);
360 }
361
362 bool isLegalMaskedExpandLoad(Type *DataType, Align Alignment) const override;
363
364 bool isLegalMaskedCompressStore(Type *DataTy, Align Alignment) const override;
365
366 bool isLegalBroadcastLoad(Type *ElementTy,
367 ElementCount NumElements) const override;
368
369 /// \returns How the target needs this vector-predicated operation to be
370 /// transformed.
371 TargetTransformInfo::VPLegalization
372 getVPLegalizationStrategy(const VPIntrinsic &PI) const override {
373 using VPLegalization = TargetTransformInfo::VPLegalization;
374 static const Intrinsic::ID Supported[] = {
375 Intrinsic::experimental_vp_strided_load,
376 Intrinsic::experimental_vp_strided_store,
377 Intrinsic::experimental_vp_reverse,
378 Intrinsic::experimental_vp_splice,
379 Intrinsic::vp_cttz_elts,
380 Intrinsic::vp_gather,
381 Intrinsic::vp_load,
382 Intrinsic::vp_load_ff,
383 Intrinsic::vp_merge,
384 Intrinsic::vp_reduce_add,
385 Intrinsic::vp_reduce_and,
386 Intrinsic::vp_reduce_fadd,
387 Intrinsic::vp_reduce_fmax,
388 Intrinsic::vp_reduce_fmaximum,
389 Intrinsic::vp_reduce_fmin,
390 Intrinsic::vp_reduce_fminimum,
391 Intrinsic::vp_reduce_fmul,
392 Intrinsic::vp_reduce_mul,
393 Intrinsic::vp_reduce_or,
394 Intrinsic::vp_reduce_smax,
395 Intrinsic::vp_reduce_smin,
396 Intrinsic::vp_reduce_umax,
397 Intrinsic::vp_reduce_umin,
398 Intrinsic::vp_reduce_xor,
399 Intrinsic::vp_scatter,
400 Intrinsic::vp_sdiv,
401 Intrinsic::vp_srem,
402 Intrinsic::vp_store,
403 Intrinsic::vp_udiv,
404 Intrinsic::vp_urem};
405 if (!ST->hasVInstructions() ||
406 (PI.getIntrinsicID() == Intrinsic::vp_reduce_mul &&
407 cast<VectorType>(Val: PI.getArgOperand(i: 1)->getType())
408 ->getElementType()
409 ->getIntegerBitWidth() != 1) ||
410 !is_contained(Range: Supported, Element: PI.getIntrinsicID()))
411 return VPLegalization(VPLegalization::Discard, VPLegalization::Convert);
412 return VPLegalization(VPLegalization::Legal, VPLegalization::Legal);
413 }
414
415 bool isLegalToVectorizeReduction(const RecurrenceDescriptor &RdxDesc,
416 ElementCount VF) const override {
417 if (!VF.isScalable())
418 return true;
419
420 Type *Ty = RdxDesc.getRecurrenceType();
421 if (!TLI->isLegalElementTypeForRVV(ScalarTy: TLI->getValueType(DL, Ty)))
422 return false;
423
424 switch (RdxDesc.getRecurrenceKind()) {
425 case RecurKind::Add:
426 case RecurKind::Sub:
427 case RecurKind::AddChainWithSubs:
428 case RecurKind::And:
429 case RecurKind::Or:
430 case RecurKind::Xor:
431 case RecurKind::SMin:
432 case RecurKind::SMax:
433 case RecurKind::UMin:
434 case RecurKind::UMax:
435 case RecurKind::FMin:
436 case RecurKind::FMax:
437 case RecurKind::FindIV:
438 case RecurKind::FindLast:
439 return true;
440 case RecurKind::AnyOf:
441 case RecurKind::FAdd:
442 case RecurKind::FSub:
443 case RecurKind::FMulAdd:
444 // We can't promote f16/bf16 fadd reductions and scalable vectors can't be
445 // expanded.
446 if (Ty->isBFloatTy() || (Ty->isHalfTy() && !ST->hasVInstructionsF16()))
447 return false;
448 return true;
449 case RecurKind::Mul:
450 case RecurKind::FMul:
451 case RecurKind::FMinNum:
452 case RecurKind::FMaxNum:
453 case RecurKind::FMinimum:
454 case RecurKind::FMaximum:
455 case RecurKind::FMinimumNum:
456 case RecurKind::FMaximumNum:
457 case RecurKind::FAddChainWithSubs:
458 return false;
459 case RecurKind::None:
460 llvm_unreachable("Unknown reduction kind.");
461 }
462 }
463
464 unsigned getMaxInterleaveFactor(ElementCount VF,
465 bool HasUnorderedReductions) const override {
466 // Don't interleave if the loop has been vectorized with scalable vectors.
467 if (VF.isScalable())
468 return 1;
469 // If the loop will not be vectorized, don't interleave the loop.
470 // Let regular unroll to unroll the loop.
471 return VF.isScalar() ? 1 : ST->getMaxInterleaveFactor();
472 }
473
474 bool enableInterleavedAccessVectorization() const override { return true; }
475
476 bool enableMaskedInterleavedAccessVectorization() const override {
477 return ST->hasVInstructions();
478 }
479
480 unsigned getMinTripCountTailFoldingThreshold() const override;
481
482 enum RISCVRegisterClass { GPRRC, FPRRC, VRRC };
483 unsigned getNumberOfRegisters(unsigned ClassID) const override {
484 switch (ClassID) {
485 case RISCVRegisterClass::GPRRC:
486 // 31 = 32 GPR - x0 (zero register)
487 // FIXME: Should we exclude fixed registers like SP, TP or GP?
488 return 31;
489 case RISCVRegisterClass::FPRRC:
490 if (ST->hasStdExtF())
491 return 32;
492 return 0;
493 case RISCVRegisterClass::VRRC:
494 // Although there are 32 vector registers, v0 is special in that it is the
495 // only register that can be used to hold a mask.
496 // FIXME: Should we conservatively return 31 as the number of usable
497 // vector registers?
498 return ST->hasVInstructions() ? 32 : 0;
499 }
500 llvm_unreachable("unknown register class");
501 }
502
503 TTI::AddressingModeKind
504 getPreferredAddressingMode(const Loop *L, ScalarEvolution *SE) const override;
505
506 unsigned getRegisterClassForType(bool Vector,
507 Type *Ty = nullptr) const override {
508 if (Vector)
509 return RISCVRegisterClass::VRRC;
510 if (!Ty)
511 return RISCVRegisterClass::GPRRC;
512
513 Type *ScalarTy = Ty->getScalarType();
514 if ((ScalarTy->isHalfTy() && ST->hasStdExtZfhmin()) ||
515 (ScalarTy->isFloatTy() && ST->hasStdExtF()) ||
516 (ScalarTy->isDoubleTy() && ST->hasStdExtD())) {
517 return RISCVRegisterClass::FPRRC;
518 }
519
520 return RISCVRegisterClass::GPRRC;
521 }
522
523 const char *getRegisterClassName(unsigned ClassID) const override {
524 switch (ClassID) {
525 case RISCVRegisterClass::GPRRC:
526 return "RISCV::GPRRC";
527 case RISCVRegisterClass::FPRRC:
528 return "RISCV::FPRRC";
529 case RISCVRegisterClass::VRRC:
530 return "RISCV::VRRC";
531 }
532 llvm_unreachable("unknown register class");
533 }
534
535 bool isLSRCostLess(const TargetTransformInfo::LSRCost &C1,
536 const TargetTransformInfo::LSRCost &C2) const override;
537
538 bool shouldConsiderAddressTypePromotion(
539 const Instruction &I,
540 bool &AllowPromotionWithoutCommonHeader) const override;
541 std::optional<unsigned> getMinPageSize() const override { return 4096; }
542 /// Return true if the (vector) instruction I will be lowered to an
543 /// instruction with a scalar splat operand for the given Operand number.
544 bool canSplatOperand(Instruction *I, int Operand) const;
545 /// Return true if a vector instruction will lower to a target instruction
546 /// able to splat the given operand.
547 bool canSplatOperand(unsigned Opcode, int Operand) const;
548
549 bool isProfitableToSinkOperands(Instruction *I,
550 SmallVectorImpl<Use *> &Ops) const override;
551
552 TTI::MemCmpExpansionOptions
553 enableMemCmpExpansion(bool OptSize, bool IsZeroCmp) const override;
554
555 bool enableSelectOptimize() const override {
556 return ST->enableSelectOptimize();
557 }
558
559 bool shouldTreatInstructionLikeSelect(const Instruction *I) const override;
560
561 bool
562 shouldCopyAttributeWhenOutliningFrom(const Function *Caller,
563 const Attribute &Attr) const override;
564
565 std::optional<Instruction *>
566 instCombineIntrinsic(InstCombiner &IC, IntrinsicInst &II) const override;
567};
568
569} // end namespace llvm
570
571#endif // LLVM_LIB_TARGET_RISCV_RISCVTARGETTRANSFORMINFO_H
572