1 //===- RISCVTargetTransformInfo.h - RISC-V specific TTI ---------*- C++ -*-===//
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
7 //===----------------------------------------------------------------------===//
9 /// This file defines a TargetTransformInfo::Concept 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.
14 //===----------------------------------------------------------------------===//
16 #ifndef LLVM_LIB_TARGET_RISCV_RISCVTARGETTRANSFORMINFO_H
17 #define LLVM_LIB_TARGET_RISCV_RISCVTARGETTRANSFORMINFO_H
19 #include "RISCVSubtarget.h"
20 #include "RISCVTargetMachine.h"
21 #include "llvm/Analysis/IVDescriptors.h"
22 #include "llvm/Analysis/TargetTransformInfo.h"
23 #include "llvm/CodeGen/BasicTTIImpl.h"
24 #include "llvm/IR/Function.h"
29 class RISCVTTIImpl
: public BasicTTIImplBase
<RISCVTTIImpl
> {
30 using BaseT
= BasicTTIImplBase
<RISCVTTIImpl
>;
31 using TTI
= TargetTransformInfo
;
35 const RISCVSubtarget
*ST
;
36 const RISCVTargetLowering
*TLI
;
38 const RISCVSubtarget
*getST() const { return ST
; }
39 const RISCVTargetLowering
*getTLI() const { return TLI
; }
41 /// This function returns an estimate for VL to be used in VL based terms
42 /// of the cost model. For fixed length vectors, this is simply the
43 /// vector length. For scalable vectors, we return results consistent
44 /// with getVScaleForTuning under the assumption that clients are also
45 /// using that when comparing costs between scalar and vector representation.
46 /// This does unfortunately mean that we can both undershoot and overshot
47 /// the true cost significantly if getVScaleForTuning is wildly off for the
48 /// actual target hardware.
49 unsigned getEstimatedVLFor(VectorType
*Ty
);
51 InstructionCost
getRISCVInstructionCost(ArrayRef
<unsigned> OpCodes
, MVT VT
,
52 TTI::TargetCostKind CostKind
);
54 /// Return the cost of accessing a constant pool entry of the specified
56 InstructionCost
getConstantPoolLoadCost(Type
*Ty
,
57 TTI::TargetCostKind CostKind
);
59 explicit RISCVTTIImpl(const RISCVTargetMachine
*TM
, const Function
&F
)
60 : BaseT(TM
, F
.getParent()->getDataLayout()), ST(TM
->getSubtargetImpl(F
)),
61 TLI(ST
->getTargetLowering()) {}
63 bool areInlineCompatible(const Function
*Caller
,
64 const Function
*Callee
) const;
66 /// Return the cost of materializing an immediate for a value operand of
67 /// a store instruction.
68 InstructionCost
getStoreImmCost(Type
*VecTy
, TTI::OperandValueInfo OpInfo
,
69 TTI::TargetCostKind CostKind
);
71 InstructionCost
getIntImmCost(const APInt
&Imm
, Type
*Ty
,
72 TTI::TargetCostKind CostKind
);
73 InstructionCost
getIntImmCostInst(unsigned Opcode
, unsigned Idx
,
74 const APInt
&Imm
, Type
*Ty
,
75 TTI::TargetCostKind CostKind
,
76 Instruction
*Inst
= nullptr);
77 InstructionCost
getIntImmCostIntrin(Intrinsic::ID IID
, unsigned Idx
,
78 const APInt
&Imm
, Type
*Ty
,
79 TTI::TargetCostKind CostKind
);
81 /// \name EVL Support for predicated vectorization.
82 /// Whether the target supports the %evl parameter of VP intrinsic efficiently
83 /// in hardware, for the given opcode and type/alignment. (see LLVM Language
84 /// Reference - "Vector Predication Intrinsics",
85 /// https://llvm.org/docs/LangRef.html#vector-predication-intrinsics and
86 /// "IR-level VP intrinsics",
87 /// https://llvm.org/docs/Proposals/VectorPredication.html#ir-level-vp-intrinsics).
88 /// \param Opcode the opcode of the instruction checked for predicated version
90 /// \param DataType the type of the instruction with the \p Opcode checked for
91 /// prediction support.
92 /// \param Alignment the alignment for memory access operation checked for
93 /// predicated version support.
94 bool hasActiveVectorLength(unsigned Opcode
, Type
*DataType
,
95 Align Alignment
) const;
97 TargetTransformInfo::PopcntSupportKind
getPopcntSupport(unsigned TyWidth
);
99 bool shouldExpandReduction(const IntrinsicInst
*II
) const;
100 bool supportsScalableVectors() const { return ST
->hasVInstructions(); }
101 bool enableOrderedReductions() const { return true; }
102 bool enableScalableVectorization() const { return ST
->hasVInstructions(); }
104 getPreferredTailFoldingStyle(bool IVUpdateMayOverflow
) const {
105 return ST
->hasVInstructions() ? TailFoldingStyle::Data
106 : TailFoldingStyle::DataWithoutLaneMask
;
108 std::optional
<unsigned> getMaxVScale() const;
109 std::optional
<unsigned> getVScaleForTuning() const;
111 TypeSize
getRegisterBitWidth(TargetTransformInfo::RegisterKind K
) const;
113 unsigned getRegUsageForType(Type
*Ty
);
115 unsigned getMaximumVF(unsigned ElemWidth
, unsigned Opcode
) const;
117 bool preferEpilogueVectorization() const {
118 // Epilogue vectorization is usually unprofitable - tail folding or
119 // a smaller VF would have been better. This a blunt hammer - we
120 // should re-examine this once vectorization is better tuned.
124 InstructionCost
getMaskedMemoryOpCost(unsigned Opcode
, Type
*Src
,
125 Align Alignment
, unsigned AddressSpace
,
126 TTI::TargetCostKind CostKind
);
128 InstructionCost
getPointersChainCost(ArrayRef
<const Value
*> Ptrs
,
130 const TTI::PointersChainInfo
&Info
,
132 TTI::TargetCostKind CostKind
);
134 void getUnrollingPreferences(Loop
*L
, ScalarEvolution
&SE
,
135 TTI::UnrollingPreferences
&UP
,
136 OptimizationRemarkEmitter
*ORE
);
138 void getPeelingPreferences(Loop
*L
, ScalarEvolution
&SE
,
139 TTI::PeelingPreferences
&PP
);
141 unsigned getMinVectorRegisterBitWidth() const {
142 return ST
->useRVVForFixedLengthVectors() ? 16 : 0;
145 InstructionCost
getShuffleCost(TTI::ShuffleKind Kind
, VectorType
*Tp
,
147 TTI::TargetCostKind CostKind
, int Index
,
149 ArrayRef
<const Value
*> Args
= std::nullopt
,
150 const Instruction
*CxtI
= nullptr);
152 InstructionCost
getIntrinsicInstrCost(const IntrinsicCostAttributes
&ICA
,
153 TTI::TargetCostKind CostKind
);
155 InstructionCost
getInterleavedMemoryOpCost(
156 unsigned Opcode
, Type
*VecTy
, unsigned Factor
, ArrayRef
<unsigned> Indices
,
157 Align Alignment
, unsigned AddressSpace
, TTI::TargetCostKind CostKind
,
158 bool UseMaskForCond
= false, bool UseMaskForGaps
= false);
160 InstructionCost
getGatherScatterOpCost(unsigned Opcode
, Type
*DataTy
,
161 const Value
*Ptr
, bool VariableMask
,
163 TTI::TargetCostKind CostKind
,
164 const Instruction
*I
);
166 InstructionCost
getStridedMemoryOpCost(unsigned Opcode
, Type
*DataTy
,
167 const Value
*Ptr
, bool VariableMask
,
169 TTI::TargetCostKind CostKind
,
170 const Instruction
*I
);
172 InstructionCost
getCastInstrCost(unsigned Opcode
, Type
*Dst
, Type
*Src
,
173 TTI::CastContextHint CCH
,
174 TTI::TargetCostKind CostKind
,
175 const Instruction
*I
= nullptr);
177 InstructionCost
getMinMaxReductionCost(Intrinsic::ID IID
, VectorType
*Ty
,
179 TTI::TargetCostKind CostKind
);
181 InstructionCost
getArithmeticReductionCost(unsigned Opcode
, VectorType
*Ty
,
182 std::optional
<FastMathFlags
> FMF
,
183 TTI::TargetCostKind CostKind
);
185 InstructionCost
getExtendedReductionCost(unsigned Opcode
, bool IsUnsigned
,
186 Type
*ResTy
, VectorType
*ValTy
,
188 TTI::TargetCostKind CostKind
);
191 getMemoryOpCost(unsigned Opcode
, Type
*Src
, MaybeAlign Alignment
,
192 unsigned AddressSpace
, TTI::TargetCostKind CostKind
,
193 TTI::OperandValueInfo OpdInfo
= {TTI::OK_AnyValue
, TTI::OP_None
},
194 const Instruction
*I
= nullptr);
196 InstructionCost
getCmpSelInstrCost(unsigned Opcode
, Type
*ValTy
, Type
*CondTy
,
197 CmpInst::Predicate VecPred
,
198 TTI::TargetCostKind CostKind
,
199 const Instruction
*I
= nullptr);
201 InstructionCost
getCFInstrCost(unsigned Opcode
, TTI::TargetCostKind CostKind
,
202 const Instruction
*I
= nullptr);
204 using BaseT::getVectorInstrCost
;
205 InstructionCost
getVectorInstrCost(unsigned Opcode
, Type
*Val
,
206 TTI::TargetCostKind CostKind
,
207 unsigned Index
, Value
*Op0
, Value
*Op1
);
209 InstructionCost
getArithmeticInstrCost(
210 unsigned Opcode
, Type
*Ty
, TTI::TargetCostKind CostKind
,
211 TTI::OperandValueInfo Op1Info
= {TTI::OK_AnyValue
, TTI::OP_None
},
212 TTI::OperandValueInfo Op2Info
= {TTI::OK_AnyValue
, TTI::OP_None
},
213 ArrayRef
<const Value
*> Args
= std::nullopt
,
214 const Instruction
*CxtI
= nullptr);
216 bool isElementTypeLegalForScalableVector(Type
*Ty
) const {
217 return TLI
->isLegalElementTypeForRVV(TLI
->getValueType(DL
, Ty
));
220 bool isLegalMaskedLoadStore(Type
*DataType
, Align Alignment
) {
221 if (!ST
->hasVInstructions())
224 EVT DataTypeVT
= TLI
->getValueType(DL
, DataType
);
226 // Only support fixed vectors if we know the minimum vector size.
227 if (DataTypeVT
.isFixedLengthVector() && !ST
->useRVVForFixedLengthVectors())
230 EVT ElemType
= DataTypeVT
.getScalarType();
231 if (!ST
->enableUnalignedVectorMem() && Alignment
< ElemType
.getStoreSize())
234 return TLI
->isLegalElementTypeForRVV(ElemType
);
238 bool isLegalMaskedLoad(Type
*DataType
, Align Alignment
) {
239 return isLegalMaskedLoadStore(DataType
, Alignment
);
241 bool isLegalMaskedStore(Type
*DataType
, Align Alignment
) {
242 return isLegalMaskedLoadStore(DataType
, Alignment
);
245 bool isLegalMaskedGatherScatter(Type
*DataType
, Align Alignment
) {
246 if (!ST
->hasVInstructions())
249 EVT DataTypeVT
= TLI
->getValueType(DL
, DataType
);
251 // Only support fixed vectors if we know the minimum vector size.
252 if (DataTypeVT
.isFixedLengthVector() && !ST
->useRVVForFixedLengthVectors())
255 EVT ElemType
= DataTypeVT
.getScalarType();
256 if (!ST
->enableUnalignedVectorMem() && Alignment
< ElemType
.getStoreSize())
259 return TLI
->isLegalElementTypeForRVV(ElemType
);
262 bool isLegalMaskedGather(Type
*DataType
, Align Alignment
) {
263 return isLegalMaskedGatherScatter(DataType
, Alignment
);
265 bool isLegalMaskedScatter(Type
*DataType
, Align Alignment
) {
266 return isLegalMaskedGatherScatter(DataType
, Alignment
);
269 bool forceScalarizeMaskedGather(VectorType
*VTy
, Align Alignment
) {
270 // Scalarize masked gather for RV64 if EEW=64 indices aren't supported.
271 return ST
->is64Bit() && !ST
->hasVInstructionsI64();
274 bool forceScalarizeMaskedScatter(VectorType
*VTy
, Align Alignment
) {
275 // Scalarize masked scatter for RV64 if EEW=64 indices aren't supported.
276 return ST
->is64Bit() && !ST
->hasVInstructionsI64();
279 bool isLegalStridedLoadStore(Type
*DataType
, Align Alignment
) {
280 EVT DataTypeVT
= TLI
->getValueType(DL
, DataType
);
281 return TLI
->isLegalStridedLoadStore(DataTypeVT
, Alignment
);
284 bool isLegalMaskedCompressStore(Type
*DataTy
, Align Alignment
);
286 bool isVScaleKnownToBeAPowerOfTwo() const {
287 return TLI
->isVScaleKnownToBeAPowerOfTwo();
290 /// \returns How the target needs this vector-predicated operation to be
292 TargetTransformInfo::VPLegalization
293 getVPLegalizationStrategy(const VPIntrinsic
&PI
) const {
294 using VPLegalization
= TargetTransformInfo::VPLegalization
;
295 if (!ST
->hasVInstructions() ||
296 (PI
.getIntrinsicID() == Intrinsic::vp_reduce_mul
&&
297 cast
<VectorType
>(PI
.getArgOperand(1)->getType())
299 ->getIntegerBitWidth() != 1))
300 return VPLegalization(VPLegalization::Discard
, VPLegalization::Convert
);
301 return VPLegalization(VPLegalization::Legal
, VPLegalization::Legal
);
304 bool isLegalToVectorizeReduction(const RecurrenceDescriptor
&RdxDesc
,
305 ElementCount VF
) const {
306 if (!VF
.isScalable())
309 Type
*Ty
= RdxDesc
.getRecurrenceType();
310 if (!TLI
->isLegalElementTypeForRVV(TLI
->getValueType(DL
, Ty
)))
313 switch (RdxDesc
.getRecurrenceKind()) {
315 case RecurKind::FAdd
:
319 case RecurKind::SMin
:
320 case RecurKind::SMax
:
321 case RecurKind::UMin
:
322 case RecurKind::UMax
:
323 case RecurKind::FMin
:
324 case RecurKind::FMax
:
325 case RecurKind::FMulAdd
:
326 case RecurKind::IAnyOf
:
327 case RecurKind::FAnyOf
:
334 unsigned getMaxInterleaveFactor(ElementCount VF
) {
335 // Don't interleave if the loop has been vectorized with scalable vectors.
338 // If the loop will not be vectorized, don't interleave the loop.
339 // Let regular unroll to unroll the loop.
340 return VF
.isScalar() ? 1 : ST
->getMaxInterleaveFactor();
343 bool enableInterleavedAccessVectorization() { return true; }
345 enum RISCVRegisterClass
{ GPRRC
, FPRRC
, VRRC
};
346 unsigned getNumberOfRegisters(unsigned ClassID
) const {
348 case RISCVRegisterClass::GPRRC
:
349 // 31 = 32 GPR - x0 (zero register)
350 // FIXME: Should we exclude fixed registers like SP, TP or GP?
352 case RISCVRegisterClass::FPRRC
:
353 if (ST
->hasStdExtF())
356 case RISCVRegisterClass::VRRC
:
357 // Although there are 32 vector registers, v0 is special in that it is the
358 // only register that can be used to hold a mask.
359 // FIXME: Should we conservatively return 31 as the number of usable
361 return ST
->hasVInstructions() ? 32 : 0;
363 llvm_unreachable("unknown register class");
366 unsigned getRegisterClassForType(bool Vector
, Type
*Ty
= nullptr) const {
368 return RISCVRegisterClass::VRRC
;
370 return RISCVRegisterClass::GPRRC
;
372 Type
*ScalarTy
= Ty
->getScalarType();
373 if ((ScalarTy
->isHalfTy() && ST
->hasStdExtZfhmin()) ||
374 (ScalarTy
->isFloatTy() && ST
->hasStdExtF()) ||
375 (ScalarTy
->isDoubleTy() && ST
->hasStdExtD())) {
376 return RISCVRegisterClass::FPRRC
;
379 return RISCVRegisterClass::GPRRC
;
382 const char *getRegisterClassName(unsigned ClassID
) const {
384 case RISCVRegisterClass::GPRRC
:
385 return "RISCV::GPRRC";
386 case RISCVRegisterClass::FPRRC
:
387 return "RISCV::FPRRC";
388 case RISCVRegisterClass::VRRC
:
389 return "RISCV::VRRC";
391 llvm_unreachable("unknown register class");
394 bool isLSRCostLess(const TargetTransformInfo::LSRCost
&C1
,
395 const TargetTransformInfo::LSRCost
&C2
);
397 bool shouldFoldTerminatingConditionAfterLSR() const {
402 } // end namespace llvm
404 #endif // LLVM_LIB_TARGET_RISCV_RISCVTARGETTRANSFORMINFO_H