1//===-- RISCVSubtarget.h - Define Subtarget for the RISC-V ------*- 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//
9// This file declares the RISC-V specific subclass of TargetSubtargetInfo.
10//
11//===----------------------------------------------------------------------===//
12
13#ifndef LLVM_LIB_TARGET_RISCV_RISCVSUBTARGET_H
14#define LLVM_LIB_TARGET_RISCV_RISCVSUBTARGET_H
15
16#include "GISel/RISCVRegisterBankInfo.h"
17#include "MCTargetDesc/RISCVBaseInfo.h"
18#include "RISCVFrameLowering.h"
19#include "RISCVISelLowering.h"
20#include "RISCVInstrInfo.h"
21#include "llvm/CodeGen/GlobalISel/CallLowering.h"
22#include "llvm/CodeGen/GlobalISel/InstructionSelector.h"
23#include "llvm/CodeGen/GlobalISel/LegalizerInfo.h"
24#include "llvm/CodeGen/MachineScheduler.h"
25#include "llvm/CodeGen/TargetSubtargetInfo.h"
26#include "llvm/IR/DataLayout.h"
27#include "llvm/Support/Compiler.h"
28#include "llvm/Target/TargetMachine.h"
29#include <bitset>
30
31#define GET_RISCV_MACRO_FUSION_PRED_DECL
32#include "RISCVGenMacroFusion.inc"
33
34#define GET_SUBTARGETINFO_HEADER
35#include "RISCVGenSubtargetInfo.inc"
36
37namespace llvm {
38class StringRef;
39
40namespace RISCVTuneInfoTable {
41
42struct RISCVTuneInfo {
43 const char *Name;
44 uint8_t PrefFunctionAlignment;
45 uint8_t PrefLoopAlignment;
46
47 // Information needed by LoopDataPrefetch.
48 uint16_t CacheLineSize;
49 uint16_t PrefetchDistance;
50 uint16_t MinPrefetchStride;
51 unsigned MaxPrefetchIterationsAhead;
52
53 unsigned MinimumJumpTableEntries;
54
55 // Tail duplication threshold at -O3.
56 unsigned TailDupAggressiveThreshold;
57
58 unsigned MaxStoresPerMemsetOptSize;
59 unsigned MaxStoresPerMemset;
60
61 unsigned MaxGluedStoresPerMemcpy;
62 unsigned MaxStoresPerMemcpyOptSize;
63 unsigned MaxStoresPerMemcpy;
64
65 unsigned MaxStoresPerMemmoveOptSize;
66 unsigned MaxStoresPerMemmove;
67
68 unsigned MaxLoadsPerMemcmpOptSize;
69 unsigned MaxLoadsPerMemcmp;
70
71 // The direction of PostRA scheduling.
72 MISched::Direction PostRASchedDirection;
73};
74
75#define GET_RISCVTuneInfoTable_DECL
76#include "RISCVGenSearchableTables.inc"
77} // namespace RISCVTuneInfoTable
78
79class RISCVSubtarget : public RISCVGenSubtargetInfo {
80public:
81 // clang-format off
82 enum RISCVProcFamilyEnum : uint8_t {
83 Others,
84 SiFive7,
85 VentanaVeyron,
86 MIPSP8700,
87 Andes45,
88 };
89 enum RISCVVRGatherCostModelEnum : uint8_t {
90 Quadratic,
91 NLog2N,
92 };
93 // clang-format on
94private:
95 virtual void anchor();
96
97 RISCVProcFamilyEnum RISCVProcFamily = Others;
98 RISCVVRGatherCostModelEnum RISCVVRGatherCostModel = Quadratic;
99
100#define GET_SUBTARGETINFO_MACRO(ATTRIBUTE, DEFAULT, GETTER) \
101 bool ATTRIBUTE = DEFAULT;
102#include "RISCVGenSubtargetInfo.inc"
103
104 unsigned XSfmmTE = 0;
105 unsigned ZvlLen = 0;
106 unsigned RVVVectorBitsMin;
107 unsigned RVVVectorBitsMax;
108 uint8_t MaxInterleaveFactor = 2;
109 RISCVABI::ABI TargetABI = RISCVABI::ABI_Unknown;
110 std::bitset<RISCV::NUM_TARGET_REGS> UserReservedRegister;
111 const RISCVTuneInfoTable::RISCVTuneInfo *TuneInfo;
112
113 RISCVFrameLowering FrameLowering;
114 RISCVInstrInfo InstrInfo;
115 RISCVRegisterInfo RegInfo;
116 RISCVTargetLowering TLInfo;
117
118 /// Initializes using the passed in CPU and feature strings so that we can
119 /// use initializer lists for subtarget initialization.
120 RISCVSubtarget &initializeSubtargetDependencies(const Triple &TT,
121 StringRef CPU,
122 StringRef TuneCPU,
123 StringRef FS,
124 StringRef ABIName);
125
126public:
127 // Initializes the data members to match that of the specified triple.
128 RISCVSubtarget(const Triple &TT, StringRef CPU, StringRef TuneCPU,
129 StringRef FS, StringRef ABIName, unsigned RVVVectorBitsMin,
130 unsigned RVVVectorLMULMax, const TargetMachine &TM);
131
132 ~RISCVSubtarget() override;
133
134 // Parses features string setting specified subtarget options. The
135 // definition of this function is auto-generated by tblgen.
136 void ParseSubtargetFeatures(StringRef CPU, StringRef TuneCPU, StringRef FS);
137
138 const RISCVFrameLowering *getFrameLowering() const override {
139 return &FrameLowering;
140 }
141 const RISCVInstrInfo *getInstrInfo() const override { return &InstrInfo; }
142 const RISCVRegisterInfo *getRegisterInfo() const override {
143 return &RegInfo;
144 }
145 const RISCVTargetLowering *getTargetLowering() const override {
146 return &TLInfo;
147 }
148
149 bool enableMachineScheduler() const override { return true; }
150
151 bool enablePostRAScheduler() const override { return UsePostRAScheduler; }
152
153 Align getPrefFunctionAlignment() const {
154 return Align(TuneInfo->PrefFunctionAlignment);
155 }
156 Align getPrefLoopAlignment() const {
157 return Align(TuneInfo->PrefLoopAlignment);
158 }
159
160 /// Returns RISC-V processor family.
161 /// Avoid this function! CPU specifics should be kept local to this class
162 /// and preferably modeled with SubtargetFeatures or properties in
163 /// initializeProperties().
164 RISCVProcFamilyEnum getProcFamily() const { return RISCVProcFamily; }
165
166 RISCVVRGatherCostModelEnum getVRGatherCostModel() const { return RISCVVRGatherCostModel; }
167
168#define GET_SUBTARGETINFO_MACRO(ATTRIBUTE, DEFAULT, GETTER) \
169 bool GETTER() const { return ATTRIBUTE; }
170#include "RISCVGenSubtargetInfo.inc"
171
172 LLVM_DEPRECATED("Now Equivalent to hasStdExtZca", "hasStdExtZca")
173 bool hasStdExtCOrZca() const { return HasStdExtZca; }
174 bool hasStdExtCOrZcd() const { return HasStdExtC || HasStdExtZcd; }
175 bool hasStdExtCOrZcfOrZce() const {
176 return HasStdExtC || HasStdExtZcf || HasStdExtZce;
177 }
178 bool hasStdExtZvl() const { return ZvlLen != 0; }
179 bool hasStdExtFOrZfinx() const { return HasStdExtF || HasStdExtZfinx; }
180 bool hasStdExtDOrZdinx() const { return HasStdExtD || HasStdExtZdinx; }
181 bool hasStdExtZfhOrZhinx() const { return HasStdExtZfh || HasStdExtZhinx; }
182 bool hasStdExtZfhminOrZhinxmin() const {
183 return HasStdExtZfhmin || HasStdExtZhinxmin;
184 }
185 bool hasHalfFPLoadStoreMove() const {
186 return HasStdExtZfhmin || HasStdExtZfbfmin;
187 }
188
189 bool hasConditionalMoveFusion() const {
190 // Do we support fusing a branch+mv or branch+c.mv as a conditional move.
191 return (hasConditionalCompressedMoveFusion() && hasStdExtZca()) ||
192 hasShortForwardBranchOpt();
193 }
194
195 bool is64Bit() const { return IsRV64; }
196 MVT getXLenVT() const {
197 return is64Bit() ? MVT::i64 : MVT::i32;
198 }
199 unsigned getXLen() const {
200 return is64Bit() ? 64 : 32;
201 }
202 bool useLoadStorePairs() const;
203 bool useCCMovInsn() const;
204 unsigned getFLen() const {
205 if (HasStdExtD)
206 return 64;
207
208 if (HasStdExtF)
209 return 32;
210
211 return 0;
212 }
213 unsigned getELen() const {
214 assert(hasVInstructions() && "Expected V extension");
215 return hasVInstructionsI64() ? 64 : 32;
216 }
217 unsigned getRealMinVLen() const {
218 unsigned VLen = getMinRVVVectorSizeInBits();
219 return VLen == 0 ? ZvlLen : VLen;
220 }
221 unsigned getRealMaxVLen() const {
222 unsigned VLen = getMaxRVVVectorSizeInBits();
223 return VLen == 0 ? 65536 : VLen;
224 }
225 // If we know the exact VLEN, return it. Otherwise, return std::nullopt.
226 std::optional<unsigned> getRealVLen() const {
227 unsigned Min = getRealMinVLen();
228 if (Min != getRealMaxVLen())
229 return std::nullopt;
230 return Min;
231 }
232
233 /// If the ElementCount or TypeSize \p X is scalable and VScale (VLEN) is
234 /// exactly known, returns \p X converted to a fixed quantity. Otherwise
235 /// returns \p X unmodified.
236 template <typename Quantity> Quantity expandVScale(Quantity X) const {
237 if (auto VLen = getRealVLen(); VLen && X.isScalable()) {
238 const unsigned VScale = *VLen / RISCV::RVVBitsPerBlock;
239 X = Quantity::getFixed(X.getKnownMinValue() * VScale);
240 }
241 return X;
242 }
243
244 RISCVABI::ABI getTargetABI() const { return TargetABI; }
245 bool isSoftFPABI() const {
246 return TargetABI == RISCVABI::ABI_LP64 ||
247 TargetABI == RISCVABI::ABI_ILP32 ||
248 TargetABI == RISCVABI::ABI_ILP32E;
249 }
250 bool isRegisterReservedByUser(Register i) const override {
251 assert(i.id() < RISCV::NUM_TARGET_REGS && "Register out of range");
252 return UserReservedRegister[i.id()];
253 }
254
255 // XRay support - require D and C extensions.
256 bool isXRaySupported() const override { return hasStdExtD() && hasStdExtC(); }
257
258 // Vector codegen related methods.
259 bool hasVInstructions() const { return HasStdExtZve32x; }
260 bool hasVInstructionsI64() const { return HasStdExtZve64x; }
261 bool hasVInstructionsF16Minimal() const { return HasStdExtZvfhmin; }
262 bool hasVInstructionsF16() const { return HasStdExtZvfh; }
263 bool hasVInstructionsBF16Minimal() const { return HasStdExtZvfbfmin; }
264 bool hasVInstructionsF32() const { return HasStdExtZve32f; }
265 bool hasVInstructionsF64() const { return HasStdExtZve64d; }
266 // F16 and F64 both require F32.
267 bool hasVInstructionsAnyF() const { return hasVInstructionsF32(); }
268 bool hasVInstructionsFullMultiply() const { return HasStdExtV; }
269 unsigned getMaxInterleaveFactor() const {
270 return hasVInstructions() ? MaxInterleaveFactor : 1;
271 }
272
273 bool hasOptimizedSegmentLoadStore(unsigned NF) const {
274 switch (NF) {
275 case 2:
276 return hasOptimizedNF2SegmentLoadStore();
277 case 3:
278 return hasOptimizedNF3SegmentLoadStore();
279 case 4:
280 return hasOptimizedNF4SegmentLoadStore();
281 case 5:
282 return hasOptimizedNF5SegmentLoadStore();
283 case 6:
284 return hasOptimizedNF6SegmentLoadStore();
285 case 7:
286 return hasOptimizedNF7SegmentLoadStore();
287 case 8:
288 return hasOptimizedNF8SegmentLoadStore();
289 default:
290 llvm_unreachable("Unexpected NF");
291 }
292 }
293
294 // Returns VLEN divided by DLEN. Where DLEN is the datapath width of the
295 // vector hardware implementation which may be less than VLEN.
296 unsigned getDLenFactor() const {
297 if (DLenFactor2)
298 return 2;
299 return 1;
300 }
301
302protected:
303 // SelectionDAGISel related APIs.
304 std::unique_ptr<const SelectionDAGTargetInfo> TSInfo;
305
306 // GlobalISel related APIs.
307 mutable std::unique_ptr<CallLowering> CallLoweringInfo;
308 mutable std::unique_ptr<InstructionSelector> InstSelector;
309 mutable std::unique_ptr<LegalizerInfo> Legalizer;
310 mutable std::unique_ptr<RISCVRegisterBankInfo> RegBankInfo;
311
312 // Return the known range for the bit length of RVV data registers as set
313 // at the command line. A value of 0 means nothing is known about that particular
314 // limit beyond what's implied by the architecture.
315 // NOTE: Please use getRealMinVLen and getRealMaxVLen instead!
316 unsigned getMaxRVVVectorSizeInBits() const;
317 unsigned getMinRVVVectorSizeInBits() const;
318
319public:
320 const SelectionDAGTargetInfo *getSelectionDAGInfo() const override;
321 const CallLowering *getCallLowering() const override;
322 InstructionSelector *getInstructionSelector() const override;
323 const LegalizerInfo *getLegalizerInfo() const override;
324 const RISCVRegisterBankInfo *getRegBankInfo() const override;
325
326 bool isTargetAndroid() const { return getTargetTriple().isAndroid(); }
327 bool isTargetFuchsia() const { return getTargetTriple().isOSFuchsia(); }
328
329 bool useConstantPoolForLargeInts() const;
330
331 // Maximum cost used for building integers, integers will be put into constant
332 // pool if exceeded.
333 unsigned getMaxBuildIntsCost() const;
334
335 unsigned getMaxLMULForFixedLengthVectors() const;
336 bool useRVVForFixedLengthVectors() const;
337
338 bool enableSubRegLiveness() const override;
339
340 bool enableMachinePipeliner() const override;
341
342 bool useDFAforSMS() const override { return false; }
343
344 bool useAA() const override;
345
346 unsigned getCacheLineSize() const override {
347 return TuneInfo->CacheLineSize;
348 };
349 unsigned getPrefetchDistance() const override {
350 return TuneInfo->PrefetchDistance;
351 };
352 unsigned getMinPrefetchStride(unsigned NumMemAccesses,
353 unsigned NumStridedMemAccesses,
354 unsigned NumPrefetches,
355 bool HasCall) const override {
356 return TuneInfo->MinPrefetchStride;
357 };
358 unsigned getMaxPrefetchIterationsAhead() const override {
359 return TuneInfo->MaxPrefetchIterationsAhead;
360 };
361 bool enableWritePrefetching() const override { return true; }
362
363 unsigned getMinimumJumpTableEntries() const;
364
365 unsigned getTailDupAggressiveThreshold() const {
366 return TuneInfo->TailDupAggressiveThreshold;
367 }
368
369 unsigned getMaxStoresPerMemset(bool OptSize) const {
370 return OptSize ? TuneInfo->MaxStoresPerMemsetOptSize
371 : TuneInfo->MaxStoresPerMemset;
372 }
373
374 unsigned getMaxGluedStoresPerMemcpy() const {
375 return TuneInfo->MaxGluedStoresPerMemcpy;
376 }
377
378 unsigned getMaxStoresPerMemcpy(bool OptSize) const {
379 return OptSize ? TuneInfo->MaxStoresPerMemcpyOptSize
380 : TuneInfo->MaxStoresPerMemcpy;
381 }
382
383 unsigned getMaxStoresPerMemmove(bool OptSize) const {
384 return OptSize ? TuneInfo->MaxStoresPerMemmoveOptSize
385 : TuneInfo->MaxStoresPerMemmove;
386 }
387
388 unsigned getMaxLoadsPerMemcmp(bool OptSize) const {
389 return OptSize ? TuneInfo->MaxLoadsPerMemcmpOptSize
390 : TuneInfo->MaxLoadsPerMemcmp;
391 }
392
393 MISched::Direction getPostRASchedDirection() const {
394 return TuneInfo->PostRASchedDirection;
395 }
396
397 void overrideSchedPolicy(MachineSchedPolicy &Policy,
398 unsigned NumRegionInstrs) const override;
399
400 void overridePostRASchedPolicy(MachineSchedPolicy &Policy,
401 unsigned NumRegionInstrs) const override;
402};
403} // End llvm namespace
404
405#endif
406