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 bool IsLittleEndian = true;
101
102#define GET_SUBTARGETINFO_MACRO(ATTRIBUTE, DEFAULT, GETTER) \
103 bool ATTRIBUTE = DEFAULT;
104#include "RISCVGenSubtargetInfo.inc"
105
106 unsigned XSfmmTE = 0;
107 unsigned ZvlLen = 0;
108 unsigned RVVVectorBitsMin;
109 unsigned RVVVectorBitsMax;
110 uint8_t MaxInterleaveFactor = 2;
111 RISCVABI::ABI TargetABI = RISCVABI::ABI_Unknown;
112 std::bitset<RISCV::NUM_TARGET_REGS> UserReservedRegister;
113 const RISCVTuneInfoTable::RISCVTuneInfo *TuneInfo;
114
115 RISCVFrameLowering FrameLowering;
116 RISCVInstrInfo InstrInfo;
117 RISCVTargetLowering TLInfo;
118
119 /// Initializes using the passed in CPU and feature strings so that we can
120 /// use initializer lists for subtarget initialization.
121 RISCVSubtarget &initializeSubtargetDependencies(const Triple &TT,
122 StringRef CPU,
123 StringRef TuneCPU,
124 StringRef FS,
125 StringRef ABIName);
126
127public:
128 // Initializes the data members to match that of the specified triple.
129 RISCVSubtarget(const Triple &TT, StringRef CPU, StringRef TuneCPU,
130 StringRef FS, StringRef ABIName, unsigned RVVVectorBitsMin,
131 unsigned RVVVectorLMULMax, const TargetMachine &TM);
132
133 ~RISCVSubtarget() override;
134
135 // Parses features string setting specified subtarget options. The
136 // definition of this function is auto-generated by tblgen.
137 void ParseSubtargetFeatures(StringRef CPU, StringRef TuneCPU, StringRef FS);
138
139 const RISCVFrameLowering *getFrameLowering() const override {
140 return &FrameLowering;
141 }
142 const RISCVInstrInfo *getInstrInfo() const override { return &InstrInfo; }
143 const RISCVRegisterInfo *getRegisterInfo() const override {
144 return &InstrInfo.getRegisterInfo();
145 }
146 const RISCVTargetLowering *getTargetLowering() const override {
147 return &TLInfo;
148 }
149
150 void mirFileLoaded(MachineFunction &MF) const override;
151
152 bool enableMachineScheduler() const override { return true; }
153
154 bool enablePostRAScheduler() const override { return UsePostRAScheduler; }
155
156 Align getPrefFunctionAlignment() const {
157 return Align(TuneInfo->PrefFunctionAlignment);
158 }
159 Align getPrefLoopAlignment() const {
160 return Align(TuneInfo->PrefLoopAlignment);
161 }
162
163 /// Returns RISC-V processor family.
164 /// Avoid this function! CPU specifics should be kept local to this class
165 /// and preferably modeled with SubtargetFeatures or properties in
166 /// initializeProperties().
167 RISCVProcFamilyEnum getProcFamily() const { return RISCVProcFamily; }
168
169 RISCVVRGatherCostModelEnum getVRGatherCostModel() const { return RISCVVRGatherCostModel; }
170
171#define GET_SUBTARGETINFO_MACRO(ATTRIBUTE, DEFAULT, GETTER) \
172 bool GETTER() const { return ATTRIBUTE; }
173#include "RISCVGenSubtargetInfo.inc"
174
175 LLVM_DEPRECATED("Now Equivalent to hasStdExtZcd", "hasStdExtZcd")
176 bool hasStdExtCOrZcd() const { return HasStdExtZcd; }
177 LLVM_DEPRECATED("Now Equivalent to hasStdExtZcf", "hasStdExtZcf")
178 bool hasStdExtCOrZcfOrZce() const { return HasStdExtZcf; }
179 bool hasStdExtZvl() const { return ZvlLen != 0; }
180 bool hasStdExtFOrZfinx() const { return HasStdExtF || HasStdExtZfinx; }
181 bool hasStdExtDOrZdinx() const { return HasStdExtD || HasStdExtZdinx; }
182 bool hasStdExtZfhOrZhinx() const { return HasStdExtZfh || HasStdExtZhinx; }
183 bool hasStdExtZfhminOrZhinxmin() const {
184 return HasStdExtZfhmin || HasStdExtZhinxmin;
185 }
186 bool hasHalfFPLoadStoreMove() const {
187 return HasStdExtZfhmin || HasStdExtZfbfmin;
188 }
189
190 bool hasCLZLike() const {
191 return HasStdExtZbb || HasVendorXTHeadBb ||
192 (HasVendorXCVbitmanip && !IsRV64);
193 }
194 bool hasCTZLike() const {
195 return HasStdExtZbb || (HasVendorXCVbitmanip && !IsRV64);
196 }
197 bool hasCPOPLike() const {
198 return HasStdExtZbb || (HasVendorXCVbitmanip && !IsRV64);
199 }
200 bool hasREV8Like() const {
201 return HasStdExtZbb || HasStdExtZbkb || HasVendorXTHeadBb;
202 }
203 bool hasREVLike() const {
204 return HasStdExtP || ((HasVendorXCVbitmanip || HasVendorXqcibm) && !IsRV64);
205 }
206
207 bool hasBEXTILike() const { return HasStdExtZbs || HasVendorXTHeadBs; }
208
209 bool hasCZEROLike() const {
210 return HasStdExtZicond || HasVendorXVentanaCondOps;
211 }
212
213 bool hasConditionalMoveFusion() const {
214 // Do we support fusing a branch+mv or branch+c.mv as a conditional move.
215 return (hasConditionalCompressedMoveFusion() && hasStdExtZca()) ||
216 hasShortForwardBranchIALU();
217 }
218
219 bool hasShlAdd(int64_t ShAmt) const {
220 if (ShAmt <= 0)
221 return false;
222 if (ShAmt <= 3)
223 return HasStdExtZba || HasVendorXAndesPerf || HasVendorXTHeadBa;
224 return ShAmt <= 31 && HasVendorXqciac;
225 }
226
227 bool is64Bit() const { return IsRV64; }
228 bool isLittleEndian() const { return IsLittleEndian; }
229 MVT getXLenVT() const {
230 return is64Bit() ? MVT::i64 : MVT::i32;
231 }
232 unsigned getXLen() const {
233 return is64Bit() ? 64 : 32;
234 }
235 bool useMIPSLoadStorePairs() const;
236 bool useMIPSCCMovInsn() const;
237 unsigned getFLen() const {
238 if (HasStdExtD)
239 return 64;
240
241 if (HasStdExtF)
242 return 32;
243
244 return 0;
245 }
246
247 Align getZilsdAlign() const {
248 return Align(enableUnalignedScalarMem() ? 1
249 : allowZilsd4ByteAlign() ? 4
250 : 8);
251 }
252
253 unsigned getELen() const {
254 assert(hasVInstructions() && "Expected V extension");
255 return hasVInstructionsI64() ? 64 : 32;
256 }
257 unsigned getRealMinVLen() const {
258 unsigned VLen = getMinRVVVectorSizeInBits();
259 return VLen == 0 ? ZvlLen : VLen;
260 }
261 unsigned getRealMaxVLen() const {
262 unsigned VLen = getMaxRVVVectorSizeInBits();
263 return VLen == 0 ? 65536 : VLen;
264 }
265 // If we know the exact VLEN, return it. Otherwise, return std::nullopt.
266 std::optional<unsigned> getRealVLen() const {
267 unsigned Min = getRealMinVLen();
268 if (Min != getRealMaxVLen())
269 return std::nullopt;
270 return Min;
271 }
272
273 /// If the ElementCount or TypeSize \p X is scalable and VScale (VLEN) is
274 /// exactly known, returns \p X converted to a fixed quantity. Otherwise
275 /// returns \p X unmodified.
276 template <typename Quantity> Quantity expandVScale(Quantity X) const {
277 if (auto VLen = getRealVLen(); VLen && X.isScalable()) {
278 const unsigned VScale = *VLen / RISCV::RVVBitsPerBlock;
279 X = Quantity::getFixed(X.getKnownMinValue() * VScale);
280 }
281 return X;
282 }
283
284 RISCVABI::ABI getTargetABI() const { return TargetABI; }
285 bool isSoftFPABI() const {
286 return TargetABI == RISCVABI::ABI_LP64 ||
287 TargetABI == RISCVABI::ABI_ILP32 ||
288 TargetABI == RISCVABI::ABI_ILP32E;
289 }
290 bool isRegisterReservedByUser(Register i) const override {
291 assert(i.id() < RISCV::NUM_TARGET_REGS && "Register out of range");
292 return UserReservedRegister[i.id()];
293 }
294
295 // XRay support - require D and C extensions.
296 bool isXRaySupported() const override { return hasStdExtD() && hasStdExtC(); }
297
298 // Vector codegen related methods.
299 bool hasVInstructions() const { return HasStdExtZve32x; }
300 bool hasVInstructionsI64() const { return HasStdExtZve64x; }
301 bool hasVInstructionsF16Minimal() const { return HasStdExtZvfhmin; }
302 bool hasVInstructionsF16() const { return HasStdExtZvfh; }
303 bool hasVInstructionsBF16Minimal() const {
304 return HasStdExtZvfbfmin || HasStdExtZvfbfa;
305 }
306 bool hasVInstructionsF32() const { return HasStdExtZve32f; }
307 bool hasVInstructionsF64() const { return HasStdExtZve64d; }
308 bool hasVInstructionsBF16() const { return HasStdExtZvfbfa; }
309 // F16 and F64 both require F32.
310 bool hasVInstructionsAnyF() const { return hasVInstructionsF32(); }
311 bool hasVInstructionsFullMultiply() const { return HasStdExtV; }
312 unsigned getMaxInterleaveFactor() const {
313 return hasVInstructions() ? MaxInterleaveFactor : 1;
314 }
315
316 bool hasOptimizedSegmentLoadStore(unsigned NF) const {
317 switch (NF) {
318 case 2:
319 return hasOptimizedNF2SegmentLoadStore();
320 case 3:
321 return hasOptimizedNF3SegmentLoadStore();
322 case 4:
323 return hasOptimizedNF4SegmentLoadStore();
324 case 5:
325 return hasOptimizedNF5SegmentLoadStore();
326 case 6:
327 return hasOptimizedNF6SegmentLoadStore();
328 case 7:
329 return hasOptimizedNF7SegmentLoadStore();
330 case 8:
331 return hasOptimizedNF8SegmentLoadStore();
332 default:
333 llvm_unreachable("Unexpected NF");
334 }
335 }
336
337 bool isPExtPackedType(MVT VT) const;
338
339 // Returns VLEN divided by DLEN. Where DLEN is the datapath width of the
340 // vector hardware implementation which may be less than VLEN.
341 unsigned getDLenFactor() const {
342 if (DLenFactor2)
343 return 2;
344 return 1;
345 }
346
347protected:
348 // SelectionDAGISel related APIs.
349 std::unique_ptr<const SelectionDAGTargetInfo> TSInfo;
350
351 // GlobalISel related APIs.
352 mutable std::unique_ptr<CallLowering> CallLoweringInfo;
353 mutable std::unique_ptr<InstructionSelector> InstSelector;
354 mutable std::unique_ptr<LegalizerInfo> Legalizer;
355 mutable std::unique_ptr<RISCVRegisterBankInfo> RegBankInfo;
356
357 // Return the known range for the bit length of RVV data registers as set
358 // at the command line. A value of 0 means nothing is known about that particular
359 // limit beyond what's implied by the architecture.
360 // NOTE: Please use getRealMinVLen and getRealMaxVLen instead!
361 unsigned getMaxRVVVectorSizeInBits() const;
362 unsigned getMinRVVVectorSizeInBits() const;
363
364public:
365 const SelectionDAGTargetInfo *getSelectionDAGInfo() const override;
366 const CallLowering *getCallLowering() const override;
367 InstructionSelector *getInstructionSelector() const override;
368 const LegalizerInfo *getLegalizerInfo() const override;
369 const RISCVRegisterBankInfo *getRegBankInfo() const override;
370
371 bool isTargetAndroid() const { return getTargetTriple().isAndroid(); }
372 bool isTargetFuchsia() const { return getTargetTriple().isOSFuchsia(); }
373
374 bool useConstantPoolForLargeInts() const;
375
376 // Maximum cost used for building integers, integers will be put into constant
377 // pool if exceeded.
378 unsigned getMaxBuildIntsCost() const;
379
380 unsigned getMaxLMULForFixedLengthVectors() const;
381 bool useRVVForFixedLengthVectors() const;
382
383 bool enableSubRegLiveness() const override;
384
385 bool enableMachinePipeliner() const override;
386
387 bool useDFAforSMS() const override { return false; }
388
389 bool useAA() const override;
390
391 unsigned getCacheLineSize() const override {
392 return TuneInfo->CacheLineSize;
393 };
394 unsigned getPrefetchDistance() const override {
395 return TuneInfo->PrefetchDistance;
396 };
397 unsigned getMinPrefetchStride(unsigned NumMemAccesses,
398 unsigned NumStridedMemAccesses,
399 unsigned NumPrefetches,
400 bool HasCall) const override {
401 return TuneInfo->MinPrefetchStride;
402 };
403 unsigned getMaxPrefetchIterationsAhead() const override {
404 return TuneInfo->MaxPrefetchIterationsAhead;
405 };
406 bool enableWritePrefetching() const override { return true; }
407
408 unsigned getMinimumJumpTableEntries() const;
409
410 unsigned getTailDupAggressiveThreshold() const {
411 return TuneInfo->TailDupAggressiveThreshold;
412 }
413
414 unsigned getMaxStoresPerMemset(bool OptSize) const {
415 return OptSize ? TuneInfo->MaxStoresPerMemsetOptSize
416 : TuneInfo->MaxStoresPerMemset;
417 }
418
419 unsigned getMaxGluedStoresPerMemcpy() const {
420 return TuneInfo->MaxGluedStoresPerMemcpy;
421 }
422
423 unsigned getMaxStoresPerMemcpy(bool OptSize) const {
424 return OptSize ? TuneInfo->MaxStoresPerMemcpyOptSize
425 : TuneInfo->MaxStoresPerMemcpy;
426 }
427
428 unsigned getMaxStoresPerMemmove(bool OptSize) const {
429 return OptSize ? TuneInfo->MaxStoresPerMemmoveOptSize
430 : TuneInfo->MaxStoresPerMemmove;
431 }
432
433 unsigned getMaxLoadsPerMemcmp(bool OptSize) const {
434 return OptSize ? TuneInfo->MaxLoadsPerMemcmpOptSize
435 : TuneInfo->MaxLoadsPerMemcmp;
436 }
437
438 MISched::Direction getPostRASchedDirection() const {
439 return TuneInfo->PostRASchedDirection;
440 }
441
442 void overrideSchedPolicy(MachineSchedPolicy &Policy,
443 const SchedRegion &Region) const override;
444
445 void overridePostRASchedPolicy(MachineSchedPolicy &Policy,
446 const SchedRegion &Region) const override;
447};
448} // namespace llvm
449
450#endif
451