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