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> getMaxVScale() const override;
132 std::optional<unsigned> getVScaleForTuning() const override;
133
134 TypeSize
135 getRegisterBitWidth(TargetTransformInfo::RegisterKind K) const override;
136
137 unsigned getRegUsageForType(Type *Ty) const override;
138
139 unsigned getMaximumVF(unsigned ElemWidth, unsigned Opcode) const override;
140
141 bool preferAlternateOpcodeVectorization() const override;
142
143 bool preferEpilogueVectorization(ElementCount Iters) const override {
144 // Epilogue vectorization is usually unprofitable - tail folding or
145 // a smaller VF would have been better. This a blunt hammer - we
146 // should re-examine this once vectorization is better tuned.
147 return false;
148 }
149
150 bool shouldConsiderVectorizationRegPressure() const override { return true; }
151
152 InstructionCost
153 getMemIntrinsicInstrCost(const MemIntrinsicCostAttributes &MICA,
154 TTI::TargetCostKind CostKind) const override;
155
156 InstructionCost getMaskedMemoryOpCost(const MemIntrinsicCostAttributes &MICA,
157 TTI::TargetCostKind CostKind) const;
158
159 InstructionCost
160 getPointersChainCost(ArrayRef<const Value *> Ptrs, const Value *Base,
161 const TTI::PointersChainInfo &Info, Type *AccessTy,
162 TTI::TargetCostKind CostKind) const override;
163
164 void getUnrollingPreferences(Loop *L, ScalarEvolution &SE,
165 TTI::UnrollingPreferences &UP,
166 OptimizationRemarkEmitter *ORE) const override;
167
168 void getPeelingPreferences(Loop *L, ScalarEvolution &SE,
169 TTI::PeelingPreferences &PP) const override;
170
171 bool getTgtMemIntrinsic(IntrinsicInst *Inst,
172 MemIntrinsicInfo &Info) const override;
173
174 unsigned getMinVectorRegisterBitWidth() const override {
175 return ST->useRVVForFixedLengthVectors() ? 16 : 0;
176 }
177
178 InstructionCost
179 getShuffleCost(TTI::ShuffleKind Kind, VectorType *DstTy, VectorType *SrcTy,
180 ArrayRef<int> Mask, TTI::TargetCostKind CostKind, int Index,
181 VectorType *SubTp, ArrayRef<const Value *> Args = {},
182 const Instruction *CxtI = nullptr) const override;
183
184 InstructionCost
185 getScalarizationOverhead(VectorType *Ty, const APInt &DemandedElts,
186 bool Insert, bool Extract,
187 TTI::TargetCostKind CostKind,
188 bool ForPoisonSrc = true, ArrayRef<Value *> VL = {},
189 TTI::VectorInstrContext VIC =
190 TTI::VectorInstrContext::None) const override;
191
192 InstructionCost
193 getIntrinsicInstrCost(const IntrinsicCostAttributes &ICA,
194 TTI::TargetCostKind CostKind) const override;
195
196 InstructionCost
197 getAddressComputationCost(Type *PTy, ScalarEvolution *SE, const SCEV *Ptr,
198 TTI::TargetCostKind CostKind) const override;
199
200 InstructionCost getInterleavedMemoryOpCost(
201 unsigned Opcode, Type *VecTy, unsigned Factor, ArrayRef<unsigned> Indices,
202 Align Alignment, unsigned AddressSpace, TTI::TargetCostKind CostKind,
203 bool UseMaskForCond = false, bool UseMaskForGaps = false) const override;
204
205 InstructionCost getGatherScatterOpCost(const MemIntrinsicCostAttributes &MICA,
206 TTI::TargetCostKind CostKind) const;
207
208 InstructionCost
209 getExpandCompressMemoryOpCost(const MemIntrinsicCostAttributes &MICA,
210 TTI::TargetCostKind CostKind) const;
211
212 InstructionCost getStridedMemoryOpCost(const MemIntrinsicCostAttributes &MICA,
213 TTI::TargetCostKind CostKind) const;
214
215 InstructionCost
216 getCostOfKeepingLiveOverCall(ArrayRef<Type *> Tys) const override;
217
218 InstructionCost
219 getCastInstrCost(unsigned Opcode, Type *Dst, Type *Src,
220 TTI::CastContextHint CCH, TTI::TargetCostKind CostKind,
221 const Instruction *I = nullptr) const override;
222
223 InstructionCost
224 getMinMaxReductionCost(Intrinsic::ID IID, VectorType *Ty, FastMathFlags FMF,
225 TTI::TargetCostKind CostKind) const override;
226
227 std::optional<InstructionCost> getCombinedArithmeticInstructionCost(
228 unsigned ISDOpcode, Type *Ty, TTI::TargetCostKind CostKind,
229 TTI::OperandValueInfo Opd1Info, TTI::OperandValueInfo Opd2Info,
230 ArrayRef<const Value *> Args, const Instruction *CxtI) const;
231
232 InstructionCost
233 getArithmeticReductionCost(unsigned Opcode, VectorType *Ty,
234 std::optional<FastMathFlags> FMF,
235 TTI::TargetCostKind CostKind) const override;
236
237 InstructionCost
238 getExtendedReductionCost(unsigned Opcode, bool IsUnsigned, Type *ResTy,
239 VectorType *ValTy, std::optional<FastMathFlags> FMF,
240 TTI::TargetCostKind CostKind) const override;
241
242 InstructionCost getMemoryOpCost(
243 unsigned Opcode, Type *Src, Align Alignment, unsigned AddressSpace,
244 TTI::TargetCostKind CostKind,
245 TTI::OperandValueInfo OpdInfo = {.Kind: TTI::OK_AnyValue, .Properties: TTI::OP_None},
246 const Instruction *I = nullptr) const override;
247
248 InstructionCost getCmpSelInstrCost(
249 unsigned Opcode, Type *ValTy, Type *CondTy, CmpInst::Predicate VecPred,
250 TTI::TargetCostKind CostKind,
251 TTI::OperandValueInfo Op1Info = {.Kind: TTI::OK_AnyValue, .Properties: TTI::OP_None},
252 TTI::OperandValueInfo Op2Info = {.Kind: TTI::OK_AnyValue, .Properties: TTI::OP_None},
253 const Instruction *I = nullptr) const override;
254
255 InstructionCost getCFInstrCost(unsigned Opcode, TTI::TargetCostKind CostKind,
256 const Instruction *I = nullptr) const override;
257
258 using BaseT::getVectorInstrCost;
259 InstructionCost
260 getVectorInstrCost(unsigned Opcode, Type *Val, TTI::TargetCostKind CostKind,
261 unsigned Index, const Value *Op0, const Value *Op1,
262 TTI::VectorInstrContext VIC =
263 TTI::VectorInstrContext::None) const override;
264
265 InstructionCost
266 getIndexedVectorInstrCostFromEnd(unsigned Opcode, Type *Val,
267 TTI::TargetCostKind CostKind,
268 unsigned Index) const override;
269
270 InstructionCost getArithmeticInstrCost(
271 unsigned Opcode, Type *Ty, TTI::TargetCostKind CostKind,
272 TTI::OperandValueInfo Op1Info = {.Kind: TTI::OK_AnyValue, .Properties: TTI::OP_None},
273 TTI::OperandValueInfo Op2Info = {.Kind: TTI::OK_AnyValue, .Properties: TTI::OP_None},
274 ArrayRef<const Value *> Args = {},
275 const Instruction *CxtI = nullptr) const override;
276
277 bool isElementTypeLegalForScalableVector(Type *Ty) const override {
278 return TLI->isLegalElementTypeForRVV(ScalarTy: TLI->getValueType(DL, Ty));
279 }
280
281 bool isLegalMaskedLoadStore(Type *DataType, Align Alignment) const {
282 if (!ST->hasVInstructions())
283 return false;
284
285 EVT DataTypeVT = TLI->getValueType(DL, Ty: DataType);
286
287 // Only support fixed vectors if we know the minimum vector size.
288 if (DataTypeVT.isFixedLengthVector() && !ST->useRVVForFixedLengthVectors())
289 return false;
290
291 EVT ElemType = DataTypeVT.getScalarType();
292 if (!ST->enableUnalignedVectorMem() && Alignment < ElemType.getStoreSize())
293 return false;
294
295 return TLI->isLegalElementTypeForRVV(ScalarTy: ElemType);
296 }
297
298 bool isLegalMaskedLoad(Type *DataType, Align Alignment,
299 unsigned /*AddressSpace*/,
300 TTI::MaskKind /*MaskKind*/) const override {
301 return isLegalMaskedLoadStore(DataType, Alignment);
302 }
303 bool isLegalMaskedStore(Type *DataType, Align Alignment,
304 unsigned /*AddressSpace*/,
305 TTI::MaskKind /*MaskKind*/) const override {
306 return isLegalMaskedLoadStore(DataType, Alignment);
307 }
308
309 bool isLegalMaskedGatherScatter(Type *DataType, Align Alignment) const {
310 if (!ST->hasVInstructions())
311 return false;
312
313 EVT DataTypeVT = TLI->getValueType(DL, Ty: DataType);
314
315 // Only support fixed vectors if we know the minimum vector size.
316 if (DataTypeVT.isFixedLengthVector() && !ST->useRVVForFixedLengthVectors())
317 return false;
318
319 // We also need to check if the vector of address is valid.
320 EVT PointerTypeVT = EVT(TLI->getPointerTy(DL));
321 if (DataTypeVT.isScalableVector() &&
322 !TLI->isLegalElementTypeForRVV(ScalarTy: PointerTypeVT))
323 return false;
324
325 EVT ElemType = DataTypeVT.getScalarType();
326 if (!ST->enableUnalignedVectorMem() && Alignment < ElemType.getStoreSize())
327 return false;
328
329 return TLI->isLegalElementTypeForRVV(ScalarTy: ElemType);
330 }
331
332 bool isLegalMaskedGather(Type *DataType, Align Alignment) const override {
333 return isLegalMaskedGatherScatter(DataType, Alignment);
334 }
335 bool isLegalMaskedScatter(Type *DataType, Align Alignment) const override {
336 return isLegalMaskedGatherScatter(DataType, Alignment);
337 }
338
339 bool forceScalarizeMaskedGather(VectorType *VTy,
340 Align Alignment) const override {
341 // Scalarize masked gather for RV64 if EEW=64 indices aren't supported.
342 return ST->is64Bit() && !ST->hasVInstructionsI64();
343 }
344
345 bool forceScalarizeMaskedScatter(VectorType *VTy,
346 Align Alignment) const override {
347 // Scalarize masked scatter for RV64 if EEW=64 indices aren't supported.
348 return ST->is64Bit() && !ST->hasVInstructionsI64();
349 }
350
351 bool isLegalStridedLoadStore(Type *DataType, Align Alignment) const override {
352 EVT DataTypeVT = TLI->getValueType(DL, Ty: DataType);
353 return TLI->isLegalStridedLoadStore(DataType: DataTypeVT, Alignment);
354 }
355
356 bool isLegalInterleavedAccessType(VectorType *VTy, unsigned Factor,
357 Align Alignment,
358 unsigned AddrSpace) const override {
359 return TLI->isLegalInterleavedAccessType(VTy, Factor, Alignment, AddrSpace,
360 DL);
361 }
362
363 bool isLegalMaskedExpandLoad(Type *DataType, Align Alignment) const override;
364
365 bool isLegalMaskedCompressStore(Type *DataTy, Align Alignment) const override;
366
367 bool isLegalBroadcastLoad(Type *ElementTy,
368 ElementCount NumElements) const override;
369
370 /// \returns How the target needs this vector-predicated operation to be
371 /// transformed.
372 TargetTransformInfo::VPLegalization
373 getVPLegalizationStrategy(const VPIntrinsic &PI) const override {
374 using VPLegalization = TargetTransformInfo::VPLegalization;
375 static const Intrinsic::ID Supported[] = {
376 Intrinsic::experimental_vp_strided_load,
377 Intrinsic::experimental_vp_strided_store,
378 Intrinsic::experimental_vp_reverse,
379 Intrinsic::experimental_vp_splice,
380 Intrinsic::vp_cttz_elts,
381 Intrinsic::vp_gather,
382 Intrinsic::vp_load,
383 Intrinsic::vp_load_ff,
384 Intrinsic::vp_merge,
385 Intrinsic::vp_reduce_add,
386 Intrinsic::vp_reduce_and,
387 Intrinsic::vp_reduce_fadd,
388 Intrinsic::vp_reduce_fmax,
389 Intrinsic::vp_reduce_fmaximum,
390 Intrinsic::vp_reduce_fmin,
391 Intrinsic::vp_reduce_fminimum,
392 Intrinsic::vp_reduce_fmul,
393 Intrinsic::vp_reduce_mul,
394 Intrinsic::vp_reduce_or,
395 Intrinsic::vp_reduce_smax,
396 Intrinsic::vp_reduce_smin,
397 Intrinsic::vp_reduce_umax,
398 Intrinsic::vp_reduce_umin,
399 Intrinsic::vp_reduce_xor,
400 Intrinsic::vp_scatter,
401 Intrinsic::vp_sdiv,
402 Intrinsic::vp_srem,
403 Intrinsic::vp_store,
404 Intrinsic::vp_udiv,
405 Intrinsic::vp_urem};
406 if (!ST->hasVInstructions() ||
407 (PI.getIntrinsicID() == Intrinsic::vp_reduce_mul &&
408 cast<VectorType>(Val: PI.getArgOperand(i: 1)->getType())
409 ->getElementType()
410 ->getIntegerBitWidth() != 1) ||
411 !is_contained(Range: Supported, Element: PI.getIntrinsicID()))
412 return VPLegalization(VPLegalization::Discard, VPLegalization::Convert);
413 return VPLegalization(VPLegalization::Legal, VPLegalization::Legal);
414 }
415
416 bool isLegalToVectorizeReduction(const RecurrenceDescriptor &RdxDesc,
417 ElementCount VF) const override {
418 if (!VF.isScalable())
419 return true;
420
421 Type *Ty = RdxDesc.getRecurrenceType();
422 if (!TLI->isLegalElementTypeForRVV(ScalarTy: TLI->getValueType(DL, Ty)))
423 return false;
424
425 switch (RdxDesc.getRecurrenceKind()) {
426 case RecurKind::Add:
427 case RecurKind::Sub:
428 case RecurKind::AddChainWithSubs:
429 case RecurKind::And:
430 case RecurKind::Or:
431 case RecurKind::Xor:
432 case RecurKind::SMin:
433 case RecurKind::SMax:
434 case RecurKind::UMin:
435 case RecurKind::UMax:
436 case RecurKind::FMin:
437 case RecurKind::FMax:
438 case RecurKind::FindLast:
439 return true;
440 case RecurKind::AnyOf:
441 case RecurKind::FAdd:
442 case RecurKind::FMulAdd:
443 // We can't promote f16/bf16 fadd reductions and scalable vectors can't be
444 // expanded.
445 if (Ty->isBFloatTy() || (Ty->isHalfTy() && !ST->hasVInstructionsF16()))
446 return false;
447 return true;
448 default:
449 return false;
450 }
451 }
452
453 unsigned getMaxInterleaveFactor(ElementCount VF,
454 bool HasUnorderedReductions) const override {
455 // Don't interleave if the loop has been vectorized with scalable vectors.
456 if (VF.isScalable())
457 return 1;
458 // If the loop will not be vectorized, don't interleave the loop.
459 // Let regular unroll to unroll the loop.
460 return VF.isScalar() ? 1 : ST->getMaxInterleaveFactor();
461 }
462
463 bool enableInterleavedAccessVectorization() const override { return true; }
464
465 bool enableMaskedInterleavedAccessVectorization() const override {
466 return ST->hasVInstructions();
467 }
468
469 unsigned getMinTripCountTailFoldingThreshold() const override;
470
471 enum RISCVRegisterClass { GPRRC, FPRRC, VRRC };
472 unsigned getNumberOfRegisters(unsigned ClassID) const override {
473 switch (ClassID) {
474 case RISCVRegisterClass::GPRRC:
475 // 31 = 32 GPR - x0 (zero register)
476 // FIXME: Should we exclude fixed registers like SP, TP or GP?
477 return 31;
478 case RISCVRegisterClass::FPRRC:
479 if (ST->hasStdExtF())
480 return 32;
481 return 0;
482 case RISCVRegisterClass::VRRC:
483 // Although there are 32 vector registers, v0 is special in that it is the
484 // only register that can be used to hold a mask.
485 // FIXME: Should we conservatively return 31 as the number of usable
486 // vector registers?
487 return ST->hasVInstructions() ? 32 : 0;
488 }
489 llvm_unreachable("unknown register class");
490 }
491
492 TTI::AddressingModeKind
493 getPreferredAddressingMode(const Loop *L, ScalarEvolution *SE) const override;
494
495 unsigned getRegisterClassForType(bool Vector,
496 Type *Ty = nullptr) const override {
497 if (Vector)
498 return RISCVRegisterClass::VRRC;
499 if (!Ty)
500 return RISCVRegisterClass::GPRRC;
501
502 Type *ScalarTy = Ty->getScalarType();
503 if ((ScalarTy->isHalfTy() && ST->hasStdExtZfhmin()) ||
504 (ScalarTy->isFloatTy() && ST->hasStdExtF()) ||
505 (ScalarTy->isDoubleTy() && ST->hasStdExtD())) {
506 return RISCVRegisterClass::FPRRC;
507 }
508
509 return RISCVRegisterClass::GPRRC;
510 }
511
512 const char *getRegisterClassName(unsigned ClassID) const override {
513 switch (ClassID) {
514 case RISCVRegisterClass::GPRRC:
515 return "RISCV::GPRRC";
516 case RISCVRegisterClass::FPRRC:
517 return "RISCV::FPRRC";
518 case RISCVRegisterClass::VRRC:
519 return "RISCV::VRRC";
520 }
521 llvm_unreachable("unknown register class");
522 }
523
524 bool isLSRCostLess(const TargetTransformInfo::LSRCost &C1,
525 const TargetTransformInfo::LSRCost &C2) const override;
526
527 bool shouldConsiderAddressTypePromotion(
528 const Instruction &I,
529 bool &AllowPromotionWithoutCommonHeader) const override;
530 std::optional<unsigned> getMinPageSize() const override { return 4096; }
531 /// Return true if the (vector) instruction I will be lowered to an
532 /// instruction with a scalar splat operand for the given Operand number.
533 bool canSplatOperand(Instruction *I, int Operand) const;
534 /// Return true if a vector instruction will lower to a target instruction
535 /// able to splat the given operand.
536 bool canSplatOperand(unsigned Opcode, int Operand) const;
537
538 bool isProfitableToSinkOperands(Instruction *I,
539 SmallVectorImpl<Use *> &Ops) const override;
540
541 TTI::MemCmpExpansionOptions
542 enableMemCmpExpansion(bool OptSize, bool IsZeroCmp) const override;
543
544 bool enableSelectOptimize() const override {
545 return ST->enableSelectOptimize();
546 }
547
548 bool shouldTreatInstructionLikeSelect(const Instruction *I) const override;
549
550 bool
551 shouldCopyAttributeWhenOutliningFrom(const Function *Caller,
552 const Attribute &Attr) const override;
553
554 std::optional<Instruction *>
555 instCombineIntrinsic(InstCombiner &IC, IntrinsicInst &II) const override;
556};
557
558} // end namespace llvm
559
560#endif // LLVM_LIB_TARGET_RISCV_RISCVTARGETTRANSFORMINFO_H
561