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