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