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