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