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 /// Return the cost of accessing a constant pool entry of the specified
53 InstructionCost
getConstantPoolLoadCost(Type
*Ty
,
54 TTI::TargetCostKind CostKind
);
56 explicit RISCVTTIImpl(const RISCVTargetMachine
*TM
, const Function
&F
)
57 : BaseT(TM
, F
.getParent()->getDataLayout()), ST(TM
->getSubtargetImpl(F
)),
58 TLI(ST
->getTargetLowering()) {}
60 /// Return the cost of materializing an immediate for a value operand of
61 /// a store instruction.
62 InstructionCost
getStoreImmCost(Type
*VecTy
, TTI::OperandValueInfo OpInfo
,
63 TTI::TargetCostKind CostKind
);
65 InstructionCost
getIntImmCost(const APInt
&Imm
, Type
*Ty
,
66 TTI::TargetCostKind CostKind
);
67 InstructionCost
getIntImmCostInst(unsigned Opcode
, unsigned Idx
,
68 const APInt
&Imm
, Type
*Ty
,
69 TTI::TargetCostKind CostKind
,
70 Instruction
*Inst
= nullptr);
71 InstructionCost
getIntImmCostIntrin(Intrinsic::ID IID
, unsigned Idx
,
72 const APInt
&Imm
, Type
*Ty
,
73 TTI::TargetCostKind CostKind
);
75 TargetTransformInfo::PopcntSupportKind
getPopcntSupport(unsigned TyWidth
);
77 bool shouldExpandReduction(const IntrinsicInst
*II
) const;
78 bool supportsScalableVectors() const { return ST
->hasVInstructions(); }
79 bool enableOrderedReductions() const { return true; }
80 bool enableScalableVectorization() const { return ST
->hasVInstructions(); }
82 getPreferredTailFoldingStyle(bool IVUpdateMayOverflow
) const {
83 return ST
->hasVInstructions() ? TailFoldingStyle::Data
84 : TailFoldingStyle::DataWithoutLaneMask
;
86 std::optional
<unsigned> getMaxVScale() const;
87 std::optional
<unsigned> getVScaleForTuning() const;
89 TypeSize
getRegisterBitWidth(TargetTransformInfo::RegisterKind K
) const;
91 unsigned getRegUsageForType(Type
*Ty
);
93 unsigned getMaximumVF(unsigned ElemWidth
, unsigned Opcode
) const;
95 bool preferEpilogueVectorization() const {
96 // Epilogue vectorization is usually unprofitable - tail folding or
97 // a smaller VF would have been better. This a blunt hammer - we
98 // should re-examine this once vectorization is better tuned.
102 InstructionCost
getMaskedMemoryOpCost(unsigned Opcode
, Type
*Src
,
103 Align Alignment
, unsigned AddressSpace
,
104 TTI::TargetCostKind CostKind
);
106 InstructionCost
getPointersChainCost(ArrayRef
<const Value
*> Ptrs
,
108 const TTI::PointersChainInfo
&Info
,
110 TTI::TargetCostKind CostKind
);
112 void getUnrollingPreferences(Loop
*L
, ScalarEvolution
&SE
,
113 TTI::UnrollingPreferences
&UP
,
114 OptimizationRemarkEmitter
*ORE
);
116 void getPeelingPreferences(Loop
*L
, ScalarEvolution
&SE
,
117 TTI::PeelingPreferences
&PP
);
119 unsigned getMinVectorRegisterBitWidth() const {
120 return ST
->useRVVForFixedLengthVectors() ? 16 : 0;
123 InstructionCost
getShuffleCost(TTI::ShuffleKind Kind
, VectorType
*Tp
,
125 TTI::TargetCostKind CostKind
, int Index
,
127 ArrayRef
<const Value
*> Args
= std::nullopt
);
129 InstructionCost
getIntrinsicInstrCost(const IntrinsicCostAttributes
&ICA
,
130 TTI::TargetCostKind CostKind
);
132 InstructionCost
getInterleavedMemoryOpCost(
133 unsigned Opcode
, Type
*VecTy
, unsigned Factor
, ArrayRef
<unsigned> Indices
,
134 Align Alignment
, unsigned AddressSpace
, TTI::TargetCostKind CostKind
,
135 bool UseMaskForCond
= false, bool UseMaskForGaps
= false);
137 InstructionCost
getGatherScatterOpCost(unsigned Opcode
, Type
*DataTy
,
138 const Value
*Ptr
, bool VariableMask
,
140 TTI::TargetCostKind CostKind
,
141 const Instruction
*I
);
143 InstructionCost
getCastInstrCost(unsigned Opcode
, Type
*Dst
, Type
*Src
,
144 TTI::CastContextHint CCH
,
145 TTI::TargetCostKind CostKind
,
146 const Instruction
*I
= nullptr);
148 InstructionCost
getMinMaxReductionCost(Intrinsic::ID IID
, VectorType
*Ty
,
150 TTI::TargetCostKind CostKind
);
152 InstructionCost
getArithmeticReductionCost(unsigned Opcode
, VectorType
*Ty
,
153 std::optional
<FastMathFlags
> FMF
,
154 TTI::TargetCostKind CostKind
);
156 InstructionCost
getExtendedReductionCost(unsigned Opcode
, bool IsUnsigned
,
157 Type
*ResTy
, VectorType
*ValTy
,
159 TTI::TargetCostKind CostKind
);
162 getMemoryOpCost(unsigned Opcode
, Type
*Src
, MaybeAlign Alignment
,
163 unsigned AddressSpace
, TTI::TargetCostKind CostKind
,
164 TTI::OperandValueInfo OpdInfo
= {TTI::OK_AnyValue
, TTI::OP_None
},
165 const Instruction
*I
= nullptr);
167 InstructionCost
getCmpSelInstrCost(unsigned Opcode
, Type
*ValTy
, Type
*CondTy
,
168 CmpInst::Predicate VecPred
,
169 TTI::TargetCostKind CostKind
,
170 const Instruction
*I
= nullptr);
172 InstructionCost
getCFInstrCost(unsigned Opcode
, TTI::TargetCostKind CostKind
,
173 const Instruction
*I
= nullptr);
175 using BaseT::getVectorInstrCost
;
176 InstructionCost
getVectorInstrCost(unsigned Opcode
, Type
*Val
,
177 TTI::TargetCostKind CostKind
,
178 unsigned Index
, Value
*Op0
, Value
*Op1
);
180 InstructionCost
getArithmeticInstrCost(
181 unsigned Opcode
, Type
*Ty
, TTI::TargetCostKind CostKind
,
182 TTI::OperandValueInfo Op1Info
= {TTI::OK_AnyValue
, TTI::OP_None
},
183 TTI::OperandValueInfo Op2Info
= {TTI::OK_AnyValue
, TTI::OP_None
},
184 ArrayRef
<const Value
*> Args
= ArrayRef
<const Value
*>(),
185 const Instruction
*CxtI
= nullptr);
187 bool isElementTypeLegalForScalableVector(Type
*Ty
) const {
188 return TLI
->isLegalElementTypeForRVV(TLI
->getValueType(DL
, Ty
));
191 bool isLegalMaskedLoadStore(Type
*DataType
, Align Alignment
) {
192 if (!ST
->hasVInstructions())
195 EVT DataTypeVT
= TLI
->getValueType(DL
, DataType
);
197 // Only support fixed vectors if we know the minimum vector size.
198 if (DataTypeVT
.isFixedLengthVector() && !ST
->useRVVForFixedLengthVectors())
201 EVT ElemType
= DataTypeVT
.getScalarType();
202 if (!ST
->enableUnalignedVectorMem() && Alignment
< ElemType
.getStoreSize())
205 return TLI
->isLegalElementTypeForRVV(ElemType
);
209 bool isLegalMaskedLoad(Type
*DataType
, Align Alignment
) {
210 return isLegalMaskedLoadStore(DataType
, Alignment
);
212 bool isLegalMaskedStore(Type
*DataType
, Align Alignment
) {
213 return isLegalMaskedLoadStore(DataType
, Alignment
);
216 bool isLegalMaskedGatherScatter(Type
*DataType
, Align Alignment
) {
217 if (!ST
->hasVInstructions())
220 EVT DataTypeVT
= TLI
->getValueType(DL
, DataType
);
222 // Only support fixed vectors if we know the minimum vector size.
223 if (DataTypeVT
.isFixedLengthVector() && !ST
->useRVVForFixedLengthVectors())
226 EVT ElemType
= DataTypeVT
.getScalarType();
227 if (!ST
->enableUnalignedVectorMem() && Alignment
< ElemType
.getStoreSize())
230 return TLI
->isLegalElementTypeForRVV(ElemType
);
233 bool isLegalMaskedGather(Type
*DataType
, Align Alignment
) {
234 return isLegalMaskedGatherScatter(DataType
, Alignment
);
236 bool isLegalMaskedScatter(Type
*DataType
, Align Alignment
) {
237 return isLegalMaskedGatherScatter(DataType
, Alignment
);
240 bool forceScalarizeMaskedGather(VectorType
*VTy
, Align Alignment
) {
241 // Scalarize masked gather for RV64 if EEW=64 indices aren't supported.
242 return ST
->is64Bit() && !ST
->hasVInstructionsI64();
245 bool forceScalarizeMaskedScatter(VectorType
*VTy
, Align Alignment
) {
246 // Scalarize masked scatter for RV64 if EEW=64 indices aren't supported.
247 return ST
->is64Bit() && !ST
->hasVInstructionsI64();
250 bool isVScaleKnownToBeAPowerOfTwo() const {
251 return TLI
->isVScaleKnownToBeAPowerOfTwo();
254 /// \returns How the target needs this vector-predicated operation to be
256 TargetTransformInfo::VPLegalization
257 getVPLegalizationStrategy(const VPIntrinsic
&PI
) const {
258 using VPLegalization
= TargetTransformInfo::VPLegalization
;
259 if (!ST
->hasVInstructions() ||
260 (PI
.getIntrinsicID() == Intrinsic::vp_reduce_mul
&&
261 cast
<VectorType
>(PI
.getArgOperand(1)->getType())
263 ->getIntegerBitWidth() != 1))
264 return VPLegalization(VPLegalization::Discard
, VPLegalization::Convert
);
265 return VPLegalization(VPLegalization::Legal
, VPLegalization::Legal
);
268 bool isLegalToVectorizeReduction(const RecurrenceDescriptor
&RdxDesc
,
269 ElementCount VF
) const {
270 if (!VF
.isScalable())
273 Type
*Ty
= RdxDesc
.getRecurrenceType();
274 if (!TLI
->isLegalElementTypeForRVV(TLI
->getValueType(DL
, Ty
)))
277 switch (RdxDesc
.getRecurrenceKind()) {
279 case RecurKind::FAdd
:
283 case RecurKind::SMin
:
284 case RecurKind::SMax
:
285 case RecurKind::UMin
:
286 case RecurKind::UMax
:
287 case RecurKind::FMin
:
288 case RecurKind::FMax
:
289 case RecurKind::FMulAdd
:
290 case RecurKind::IAnyOf
:
291 case RecurKind::FAnyOf
:
298 unsigned getMaxInterleaveFactor(ElementCount VF
) {
299 // Don't interleave if the loop has been vectorized with scalable vectors.
302 // If the loop will not be vectorized, don't interleave the loop.
303 // Let regular unroll to unroll the loop.
304 return VF
.isScalar() ? 1 : ST
->getMaxInterleaveFactor();
307 bool enableInterleavedAccessVectorization() { return true; }
309 enum RISCVRegisterClass
{ GPRRC
, FPRRC
, VRRC
};
310 unsigned getNumberOfRegisters(unsigned ClassID
) const {
312 case RISCVRegisterClass::GPRRC
:
313 // 31 = 32 GPR - x0 (zero register)
314 // FIXME: Should we exclude fixed registers like SP, TP or GP?
316 case RISCVRegisterClass::FPRRC
:
317 if (ST
->hasStdExtF())
320 case RISCVRegisterClass::VRRC
:
321 // Although there are 32 vector registers, v0 is special in that it is the
322 // only register that can be used to hold a mask.
323 // FIXME: Should we conservatively return 31 as the number of usable
325 return ST
->hasVInstructions() ? 32 : 0;
327 llvm_unreachable("unknown register class");
330 unsigned getRegisterClassForType(bool Vector
, Type
*Ty
= nullptr) const {
332 return RISCVRegisterClass::VRRC
;
334 return RISCVRegisterClass::GPRRC
;
336 Type
*ScalarTy
= Ty
->getScalarType();
337 if ((ScalarTy
->isHalfTy() && ST
->hasStdExtZfhOrZfhmin()) ||
338 (ScalarTy
->isFloatTy() && ST
->hasStdExtF()) ||
339 (ScalarTy
->isDoubleTy() && ST
->hasStdExtD())) {
340 return RISCVRegisterClass::FPRRC
;
343 return RISCVRegisterClass::GPRRC
;
346 const char *getRegisterClassName(unsigned ClassID
) const {
348 case RISCVRegisterClass::GPRRC
:
349 return "RISCV::GPRRC";
350 case RISCVRegisterClass::FPRRC
:
351 return "RISCV::FPRRC";
352 case RISCVRegisterClass::VRRC
:
353 return "RISCV::VRRC";
355 llvm_unreachable("unknown register class");
358 bool isLSRCostLess(const TargetTransformInfo::LSRCost
&C1
,
359 const TargetTransformInfo::LSRCost
&C2
);
362 } // end namespace llvm
364 #endif // LLVM_LIB_TARGET_RISCV_RISCVTARGETTRANSFORMINFO_H