Run DCE after a LoopFlatten test to reduce spurious output [nfc]
[llvm-project.git] / llvm / lib / Target / RISCV / RISCVTargetTransformInfo.h
blob81a45f623d294e889ea3aa595697f3491a4f4a24
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 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.
13 ///
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"
25 #include <optional>
27 namespace llvm {
29 class RISCVTTIImpl : public BasicTTIImplBase<RISCVTTIImpl> {
30 using BaseT = BasicTTIImplBase<RISCVTTIImpl>;
31 using TTI = TargetTransformInfo;
33 friend BaseT;
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
52 /// type.
53 InstructionCost getConstantPoolLoadCost(Type *Ty,
54 TTI::TargetCostKind CostKind);
55 public:
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(); }
81 TailFoldingStyle
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.
99 return false;
102 InstructionCost getMaskedMemoryOpCost(unsigned Opcode, Type *Src,
103 Align Alignment, unsigned AddressSpace,
104 TTI::TargetCostKind CostKind);
106 InstructionCost getPointersChainCost(ArrayRef<const Value *> Ptrs,
107 const Value *Base,
108 const TTI::PointersChainInfo &Info,
109 Type *AccessTy,
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,
124 ArrayRef<int> Mask,
125 TTI::TargetCostKind CostKind, int Index,
126 VectorType *SubTp,
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,
139 Align Alignment,
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,
149 FastMathFlags FMF,
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,
158 FastMathFlags FMF,
159 TTI::TargetCostKind CostKind);
161 InstructionCost
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())
193 return false;
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())
199 return false;
201 EVT ElemType = DataTypeVT.getScalarType();
202 if (!ST->enableUnalignedVectorMem() && Alignment < ElemType.getStoreSize())
203 return false;
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())
218 return false;
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())
224 return false;
226 EVT ElemType = DataTypeVT.getScalarType();
227 if (!ST->enableUnalignedVectorMem() && Alignment < ElemType.getStoreSize())
228 return false;
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
255 /// transformed.
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())
262 ->getElementType()
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())
271 return true;
273 Type *Ty = RdxDesc.getRecurrenceType();
274 if (!TLI->isLegalElementTypeForRVV(TLI->getValueType(DL, Ty)))
275 return false;
277 switch (RdxDesc.getRecurrenceKind()) {
278 case RecurKind::Add:
279 case RecurKind::FAdd:
280 case RecurKind::And:
281 case RecurKind::Or:
282 case RecurKind::Xor:
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:
292 return true;
293 default:
294 return false;
298 unsigned getMaxInterleaveFactor(ElementCount VF) {
299 // Don't interleave if the loop has been vectorized with scalable vectors.
300 if (VF.isScalable())
301 return 1;
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 {
311 switch (ClassID) {
312 case RISCVRegisterClass::GPRRC:
313 // 31 = 32 GPR - x0 (zero register)
314 // FIXME: Should we exclude fixed registers like SP, TP or GP?
315 return 31;
316 case RISCVRegisterClass::FPRRC:
317 if (ST->hasStdExtF())
318 return 32;
319 return 0;
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
324 // vector registers?
325 return ST->hasVInstructions() ? 32 : 0;
327 llvm_unreachable("unknown register class");
330 unsigned getRegisterClassForType(bool Vector, Type *Ty = nullptr) const {
331 if (Vector)
332 return RISCVRegisterClass::VRRC;
333 if (!Ty)
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 {
347 switch (ClassID) {
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