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/ADT/StringTable.h"
22#include "llvm/CodeGen/GlobalISel/CallLowering.h"
23#include "llvm/CodeGen/GlobalISel/InlineAsmLowering.h"
24#include "llvm/CodeGen/GlobalISel/InstructionSelector.h"
25#include "llvm/CodeGen/GlobalISel/LegalizerInfo.h"
26#include "llvm/CodeGen/MachineScheduler.h"
27#include "llvm/CodeGen/TargetSubtargetInfo.h"
28#include "llvm/IR/DataLayout.h"
29#include "llvm/Support/Compiler.h"
30#include "llvm/Target/TargetMachine.h"
31#include <bitset>
32#include <memory>
33
34#define GET_RISCV_MACRO_FUSION_PRED_DECL
35#include "RISCVGenMacroFusion.inc"
36
37#define GET_SUBTARGETINFO_HEADER
38#include "RISCVGenSubtargetInfo.inc"
39
40namespace llvm {
41class StringRef;
42
43namespace RISCVTuneInfoTable {
44
45struct RISCVTuneInfo {
46 StringTable::Offset Name;
47 uint8_t PrefFunctionAlignment;
48 uint8_t PrefLoopAlignment;
49
50 // Information needed by LoopDataPrefetch.
51 uint16_t CacheLineSize;
52 uint16_t PrefetchDistance;
53 uint16_t MinPrefetchStride;
54 unsigned MaxPrefetchIterationsAhead;
55
56 unsigned MinimumJumpTableEntries;
57
58 // Tail duplication threshold at -O3.
59 unsigned TailDupAggressiveThreshold;
60
61 unsigned MaxStoresPerMemsetOptSize;
62 unsigned MaxStoresPerMemset;
63
64 unsigned MaxGluedStoresPerMemcpy;
65 unsigned MaxStoresPerMemcpyOptSize;
66 unsigned MaxStoresPerMemcpy;
67
68 unsigned MaxStoresPerMemmoveOptSize;
69 unsigned MaxStoresPerMemmove;
70
71 unsigned MaxLoadsPerMemcmpOptSize;
72 unsigned MaxLoadsPerMemcmp;
73
74 // The direction of PostRA scheduling.
75 MISched::Direction PostRASchedDirection;
76
77 bool IsJumpExpensive;
78};
79
80#define GET_RISCVTuneInfoTable_DECL
81#include "RISCVGenSearchableTables.inc"
82} // namespace RISCVTuneInfoTable
83
84class RISCVSubtarget : public RISCVGenSubtargetInfo {
85public:
86 // clang-format off
87 enum RISCVProcFamilyEnum : uint8_t {
88 Others,
89 SiFive7,
90 MIPSP8700,
91 Andes45,
92 };
93 enum RISCVVRGatherCostModelEnum : uint8_t {
94 Quadratic,
95 NLog2N,
96 };
97 // clang-format on
98private:
99 virtual void anchor();
100
101 RISCVProcFamilyEnum RISCVProcFamily = Others;
102 RISCVVRGatherCostModelEnum RISCVVRGatherCostModel = Quadratic;
103
104 bool IsLittleEndian = true;
105
106#define GET_SUBTARGETINFO_MACRO(ATTRIBUTE, DEFAULT, GETTER) \
107 bool ATTRIBUTE = DEFAULT;
108#include "RISCVGenSubtargetInfo.inc"
109
110 unsigned XSfmmTE = 0;
111 unsigned ZvlLen = 0;
112 unsigned RVVVectorBitsMin;
113 unsigned RVVVectorBitsMax;
114 uint8_t MaxInterleaveFactor = 2;
115 RISCVABI::ABI TargetABI = RISCVABI::ABI_Unknown;
116 std::bitset<RISCV::NUM_TARGET_REGS> UserReservedRegister;
117 const RISCVTuneInfoTable::RISCVTuneInfo *TuneInfo;
118
119 RISCVFrameLowering FrameLowering;
120 RISCVInstrInfo InstrInfo;
121 RISCVTargetLowering TLInfo;
122
123 /// Initializes using the passed in CPU and feature strings so that we can
124 /// use initializer lists for subtarget initialization.
125 RISCVSubtarget &initializeSubtargetDependencies(const Triple &TT,
126 StringRef CPU,
127 StringRef TuneCPU,
128 StringRef FS,
129 StringRef ABIName);
130
131public:
132 // Initializes the data members to match that of the specified triple.
133 RISCVSubtarget(const Triple &TT, StringRef CPU, StringRef TuneCPU,
134 StringRef FS, StringRef ABIName, unsigned RVVVectorBitsMin,
135 unsigned RVVVectorLMULMax, const TargetMachine &TM);
136
137 ~RISCVSubtarget() override;
138
139 // Parses features string setting specified subtarget options. The
140 // definition of this function is auto-generated by tblgen.
141 void ParseSubtargetFeatures(StringRef CPU, StringRef TuneCPU, StringRef FS);
142
143 const RISCVFrameLowering *getFrameLowering() const override {
144 return &FrameLowering;
145 }
146 const RISCVInstrInfo *getInstrInfo() const override { return &InstrInfo; }
147 const RISCVRegisterInfo *getRegisterInfo() const override {
148 return &InstrInfo.getRegisterInfo();
149 }
150 const RISCVTargetLowering *getTargetLowering() const override {
151 return &TLInfo;
152 }
153
154 void mirFileLoaded(MachineFunction &MF) const override;
155
156 bool enableMachineScheduler() const override { return true; }
157
158 bool enablePostRAScheduler() const override { return UsePostRAScheduler; }
159
160 Align getPrefFunctionAlignment() const {
161 return Align(TuneInfo->PrefFunctionAlignment);
162 }
163 Align getPrefLoopAlignment() const {
164 return Align(TuneInfo->PrefLoopAlignment);
165 }
166
167 /// Returns RISC-V processor family.
168 /// Avoid this function! CPU specifics should be kept local to this class
169 /// and preferably modeled with SubtargetFeatures or properties in
170 /// initializeProperties().
171 RISCVProcFamilyEnum getProcFamily() const { return RISCVProcFamily; }
172
173 RISCVVRGatherCostModelEnum getVRGatherCostModel() const { return RISCVVRGatherCostModel; }
174
175#define GET_SUBTARGETINFO_MACRO(ATTRIBUTE, DEFAULT, GETTER) \
176 bool GETTER() const { return ATTRIBUTE; }
177#include "RISCVGenSubtargetInfo.inc"
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 { return HasStdExtZbb || HasVendorXTHeadBb; }
191 bool hasCTZLike() const {
192 return HasStdExtZbb || (HasVendorXCVbitmanip && !IsRV64);
193 }
194 bool hasCPOPLike() const {
195 return HasStdExtZbb || (HasVendorXCVbitmanip && !IsRV64);
196 }
197 bool hasREV8Like() const {
198 return HasStdExtZbb || HasStdExtZbkb || HasVendorXTHeadBb;
199 }
200 bool hasREVLike() const {
201 return HasStdExtP || ((HasVendorXCVbitmanip || HasVendorXqcibm) && !IsRV64);
202 }
203
204 bool hasBEXTILike() const { return HasStdExtZbs || HasVendorXTHeadBs; }
205
206 bool hasConditionalMoveFusion() const {
207 // Do we support fusing a branch+mv or branch+c.mv as a conditional move.
208 return (hasConditionalCompressedMoveFusion() && hasStdExtZca()) ||
209 hasShortForwardBranchIALU();
210 }
211
212 bool hasShlAdd(int64_t ShAmt) const {
213 if (ShAmt <= 0)
214 return false;
215 if (ShAmt <= 3)
216 return HasStdExtZba || HasVendorXAndesPerf || HasVendorXTHeadBa;
217 return ShAmt <= 31 && HasVendorXqciac;
218 }
219
220 bool is64Bit() const { return IsRV64; }
221 bool isLittleEndian() const { return IsLittleEndian; }
222 MVT getXLenVT() const {
223 return is64Bit() ? MVT::i64 : MVT::i32;
224 }
225 unsigned getXLen() const {
226 return is64Bit() ? 64 : 32;
227 }
228 bool useMIPSLoadStorePairs() const;
229 bool useMIPSCCMovInsn() const;
230 unsigned getFLen() const {
231 if (HasStdExtD)
232 return 64;
233
234 if (HasStdExtF)
235 return 32;
236
237 return 0;
238 }
239
240 Align getZilsdAlign() const {
241 if (enableUnalignedScalarMem())
242 return Align(1);
243
244 if (allowZilsdWordAlign())
245 return Align(4);
246
247 return Align(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 TargetRegisterClass const *getLargestFPRegClass() const {
293 if (HasStdExtQ)
294 return &RISCV::FPR128RegClass;
295 if (HasStdExtD)
296 return &RISCV::FPR64RegClass;
297 if (HasStdExtF)
298 return &RISCV::FPR32RegClass;
299 return nullptr;
300 };
301
302 // XRay support - require D and C extensions.
303 bool isXRaySupported() const override { return hasStdExtD() && hasStdExtC(); }
304
305 // Vector codegen related methods.
306 bool hasVInstructions() const { return HasStdExtZve32x; }
307 bool hasVInstructionsI64() const { return HasStdExtZve64x; }
308 bool hasVInstructionsF16Minimal() const { return HasStdExtZvfhmin; }
309 bool hasVInstructionsF16() const { return HasStdExtZvfh; }
310 bool hasVInstructionsBF16Minimal() const {
311 return HasStdExtZvfbfmin || HasStdExtZvfbfa;
312 }
313 bool hasVInstructionsF32() const { return HasStdExtZve32f; }
314 bool hasVInstructionsF64() const { return HasStdExtZve64d; }
315 bool hasVInstructionsBF16() const { return HasStdExtZvfbfa; }
316 // F16 and F64 both require F32.
317 bool hasVInstructionsAnyF() const { return hasVInstructionsF32(); }
318 bool hasVInstructionsFullMultiply() const { return HasStdExtV; }
319 unsigned getMaxInterleaveFactor() const {
320 return hasVInstructions() ? MaxInterleaveFactor : 1;
321 }
322
323 bool hasOptimizedSegmentLoadStore(unsigned NF) const {
324 switch (NF) {
325 case 2:
326 return hasOptimizedNF2SegmentLoadStore();
327 case 3:
328 return hasOptimizedNF3SegmentLoadStore();
329 case 4:
330 return hasOptimizedNF4SegmentLoadStore();
331 case 5:
332 return hasOptimizedNF5SegmentLoadStore();
333 case 6:
334 return hasOptimizedNF6SegmentLoadStore();
335 case 7:
336 return hasOptimizedNF7SegmentLoadStore();
337 case 8:
338 return hasOptimizedNF8SegmentLoadStore();
339 default:
340 llvm_unreachable("Unexpected NF");
341 }
342 }
343
344 bool isPExtPackedType(MVT VT) const;
345 bool isPExtPackedDoubleType(MVT VT) const;
346
347 // Returns VLEN divided by DLEN. Where DLEN is the datapath width of the
348 // vector hardware implementation which may be less than VLEN.
349 unsigned getDLenFactor() const {
350 if (DLenFactor2)
351 return 2;
352 return 1;
353 }
354
355protected:
356 // SelectionDAGISel related APIs.
357 std::unique_ptr<const SelectionDAGTargetInfo> TSInfo;
358
359 // GlobalISel related APIs.
360 mutable std::unique_ptr<CallLowering> CallLoweringInfo;
361 mutable std::unique_ptr<InstructionSelector> InstSelector;
362 mutable std::unique_ptr<LegalizerInfo> Legalizer;
363 mutable std::unique_ptr<RISCVRegisterBankInfo> RegBankInfo;
364 mutable std::unique_ptr<InlineAsmLowering> InlineAsmLoweringInfo;
365
366 // Return the known range for the bit length of RVV data registers as set
367 // at the command line. A value of 0 means nothing is known about that particular
368 // limit beyond what's implied by the architecture.
369 // NOTE: Please use getRealMinVLen and getRealMaxVLen instead!
370 unsigned getMaxRVVVectorSizeInBits() const;
371 unsigned getMinRVVVectorSizeInBits() const;
372
373public:
374 const SelectionDAGTargetInfo *getSelectionDAGInfo() const override;
375 const CallLowering *getCallLowering() const override;
376 InstructionSelector *getInstructionSelector() const override;
377 const LegalizerInfo *getLegalizerInfo() const override;
378 const RISCVRegisterBankInfo *getRegBankInfo() const override;
379 const InlineAsmLowering *getInlineAsmLowering() const override;
380
381 bool isTargetAndroid() const { return getTargetTriple().isAndroid(); }
382 bool isTargetFuchsia() const { return getTargetTriple().isOSFuchsia(); }
383
384 bool useConstantPoolForLargeInts() const;
385
386 // Maximum cost used for building integers, integers will be put into constant
387 // pool if exceeded.
388 unsigned getMaxBuildIntsCost() const;
389
390 unsigned getMispredictionPenalty() const override;
391 unsigned getLoadLatency() const override;
392
393 unsigned getMaxLMULForFixedLengthVectors() const;
394 bool useRVVForFixedLengthVectors() const;
395
396 bool enableSubRegLiveness() const override;
397
398 bool enableMachinePipeliner() const override;
399
400 bool useDFAforSMS() const override { return false; }
401
402 bool useAA() const override;
403
404 unsigned getCacheLineSize() const override {
405 return TuneInfo->CacheLineSize;
406 };
407 unsigned getPrefetchDistance() const override {
408 return TuneInfo->PrefetchDistance;
409 };
410 unsigned getMinPrefetchStride(unsigned NumMemAccesses,
411 unsigned NumStridedMemAccesses,
412 unsigned NumPrefetches,
413 bool HasCall) const override {
414 return TuneInfo->MinPrefetchStride;
415 };
416 unsigned getMaxPrefetchIterationsAhead() const override {
417 return TuneInfo->MaxPrefetchIterationsAhead;
418 };
419 bool enableWritePrefetching() const override { return true; }
420
421 unsigned getMinimumJumpTableEntries() const;
422
423 unsigned getTailDupAggressiveThreshold() const {
424 return TuneInfo->TailDupAggressiveThreshold;
425 }
426
427 unsigned getMaxStoresPerMemset(bool OptSize) const {
428 return OptSize ? TuneInfo->MaxStoresPerMemsetOptSize
429 : TuneInfo->MaxStoresPerMemset;
430 }
431
432 unsigned getMaxGluedStoresPerMemcpy() const {
433 return TuneInfo->MaxGluedStoresPerMemcpy;
434 }
435
436 unsigned getMaxStoresPerMemcpy(bool OptSize) const {
437 return OptSize ? TuneInfo->MaxStoresPerMemcpyOptSize
438 : TuneInfo->MaxStoresPerMemcpy;
439 }
440
441 unsigned getMaxStoresPerMemmove(bool OptSize) const {
442 return OptSize ? TuneInfo->MaxStoresPerMemmoveOptSize
443 : TuneInfo->MaxStoresPerMemmove;
444 }
445
446 unsigned getMaxLoadsPerMemcmp(bool OptSize) const {
447 return OptSize ? TuneInfo->MaxLoadsPerMemcmpOptSize
448 : TuneInfo->MaxLoadsPerMemcmp;
449 }
450
451 MISched::Direction getPostRASchedDirection() const {
452 return TuneInfo->PostRASchedDirection;
453 }
454
455 bool isJumpExpensive() const { return TuneInfo->IsJumpExpensive; }
456
457 void overrideSchedPolicy(MachineSchedPolicy &Policy,
458 const SchedRegion &Region) const override;
459
460 void overridePostRASchedPolicy(MachineSchedPolicy &Policy,
461 const SchedRegion &Region) const override;
462};
463} // namespace llvm
464
465#endif
466