xref: /freebsd/contrib/llvm-project/llvm/lib/Target/RISCV/RISCVSubtarget.h (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
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/SelectionDAGTargetInfo.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 
55 #define GET_RISCVTuneInfoTable_DECL
56 #include "RISCVGenSearchableTables.inc"
57 } // namespace RISCVTuneInfoTable
58 
59 class RISCVSubtarget : public RISCVGenSubtargetInfo {
60 public:
61   // clang-format off
62   enum RISCVProcFamilyEnum : uint8_t {
63     Others,
64     SiFive7,
65     VentanaVeyron,
66   };
67   // clang-format on
68 private:
69   virtual void anchor();
70 
71   RISCVProcFamilyEnum RISCVProcFamily = Others;
72 
73 #define GET_SUBTARGETINFO_MACRO(ATTRIBUTE, DEFAULT, GETTER) \
74   bool ATTRIBUTE = DEFAULT;
75 #include "RISCVGenSubtargetInfo.inc"
76 
77   unsigned ZvlLen = 0;
78   unsigned RVVVectorBitsMin;
79   unsigned RVVVectorBitsMax;
80   uint8_t MaxInterleaveFactor = 2;
81   RISCVABI::ABI TargetABI = RISCVABI::ABI_Unknown;
82   std::bitset<RISCV::NUM_TARGET_REGS> UserReservedRegister;
83   const RISCVTuneInfoTable::RISCVTuneInfo *TuneInfo;
84 
85   RISCVFrameLowering FrameLowering;
86   RISCVInstrInfo InstrInfo;
87   RISCVRegisterInfo RegInfo;
88   RISCVTargetLowering TLInfo;
89   SelectionDAGTargetInfo TSInfo;
90 
91   /// Initializes using the passed in CPU and feature strings so that we can
92   /// use initializer lists for subtarget initialization.
93   RISCVSubtarget &initializeSubtargetDependencies(const Triple &TT,
94                                                   StringRef CPU,
95                                                   StringRef TuneCPU,
96                                                   StringRef FS,
97                                                   StringRef ABIName);
98 
99 public:
100   // Initializes the data members to match that of the specified triple.
101   RISCVSubtarget(const Triple &TT, StringRef CPU, StringRef TuneCPU,
102                  StringRef FS, StringRef ABIName, unsigned RVVVectorBitsMin,
103                  unsigned RVVVectorLMULMax, const TargetMachine &TM);
104 
105   // Parses features string setting specified subtarget options. The
106   // definition of this function is auto-generated by tblgen.
107   void ParseSubtargetFeatures(StringRef CPU, StringRef TuneCPU, StringRef FS);
108 
getFrameLowering()109   const RISCVFrameLowering *getFrameLowering() const override {
110     return &FrameLowering;
111   }
getInstrInfo()112   const RISCVInstrInfo *getInstrInfo() const override { return &InstrInfo; }
getRegisterInfo()113   const RISCVRegisterInfo *getRegisterInfo() const override {
114     return &RegInfo;
115   }
getTargetLowering()116   const RISCVTargetLowering *getTargetLowering() const override {
117     return &TLInfo;
118   }
getSelectionDAGInfo()119   const SelectionDAGTargetInfo *getSelectionDAGInfo() const override {
120     return &TSInfo;
121   }
enableMachineScheduler()122   bool enableMachineScheduler() const override { return true; }
123 
enablePostRAScheduler()124   bool enablePostRAScheduler() const override { return UsePostRAScheduler; }
125 
getPrefFunctionAlignment()126   Align getPrefFunctionAlignment() const {
127     return Align(TuneInfo->PrefFunctionAlignment);
128   }
getPrefLoopAlignment()129   Align getPrefLoopAlignment() const {
130     return Align(TuneInfo->PrefLoopAlignment);
131   }
132 
133   /// Returns RISC-V processor family.
134   /// Avoid this function! CPU specifics should be kept local to this class
135   /// and preferably modeled with SubtargetFeatures or properties in
136   /// initializeProperties().
getProcFamily()137   RISCVProcFamilyEnum getProcFamily() const { return RISCVProcFamily; }
138 
139 #define GET_SUBTARGETINFO_MACRO(ATTRIBUTE, DEFAULT, GETTER) \
140   bool GETTER() const { return ATTRIBUTE; }
141 #include "RISCVGenSubtargetInfo.inc"
142 
hasStdExtCOrZca()143   bool hasStdExtCOrZca() const { return HasStdExtC || HasStdExtZca; }
hasStdExtCOrZcd()144   bool hasStdExtCOrZcd() const { return HasStdExtC || HasStdExtZcd; }
hasStdExtCOrZcfOrZce()145   bool hasStdExtCOrZcfOrZce() const {
146     return HasStdExtC || HasStdExtZcf || HasStdExtZce;
147   }
hasStdExtZvl()148   bool hasStdExtZvl() const { return ZvlLen != 0; }
hasStdExtFOrZfinx()149   bool hasStdExtFOrZfinx() const { return HasStdExtF || HasStdExtZfinx; }
hasStdExtDOrZdinx()150   bool hasStdExtDOrZdinx() const { return HasStdExtD || HasStdExtZdinx; }
hasStdExtZfhOrZhinx()151   bool hasStdExtZfhOrZhinx() const { return HasStdExtZfh || HasStdExtZhinx; }
hasStdExtZfhminOrZhinxmin()152   bool hasStdExtZfhminOrZhinxmin() const {
153     return HasStdExtZfhmin || HasStdExtZhinxmin;
154   }
hasHalfFPLoadStoreMove()155   bool hasHalfFPLoadStoreMove() const {
156     return HasStdExtZfhmin || HasStdExtZfbfmin;
157   }
158 
hasConditionalMoveFusion()159   bool hasConditionalMoveFusion() const {
160     // Do we support fusing a branch+mv or branch+c.mv as a conditional move.
161     return (hasConditionalCompressedMoveFusion() && hasStdExtCOrZca()) ||
162            hasShortForwardBranchOpt();
163   }
164 
is64Bit()165   bool is64Bit() const { return IsRV64; }
getXLenVT()166   MVT getXLenVT() const {
167     return is64Bit() ? MVT::i64 : MVT::i32;
168   }
getXLen()169   unsigned getXLen() const {
170     return is64Bit() ? 64 : 32;
171   }
getFLen()172   unsigned getFLen() const {
173     if (HasStdExtD)
174       return 64;
175 
176     if (HasStdExtF)
177       return 32;
178 
179     return 0;
180   }
getELen()181   unsigned getELen() const {
182     assert(hasVInstructions() && "Expected V extension");
183     return hasVInstructionsI64() ? 64 : 32;
184   }
getRealMinVLen()185   unsigned getRealMinVLen() const {
186     unsigned VLen = getMinRVVVectorSizeInBits();
187     return VLen == 0 ? ZvlLen : VLen;
188   }
getRealMaxVLen()189   unsigned getRealMaxVLen() const {
190     unsigned VLen = getMaxRVVVectorSizeInBits();
191     return VLen == 0 ? 65536 : VLen;
192   }
193   // If we know the exact VLEN, return it.  Otherwise, return std::nullopt.
getRealVLen()194   std::optional<unsigned> getRealVLen() const {
195     unsigned Min = getRealMinVLen();
196     if (Min != getRealMaxVLen())
197       return std::nullopt;
198     return Min;
199   }
200 
201   /// If the ElementCount or TypeSize \p X is scalable and VScale (VLEN) is
202   /// exactly known, returns \p X converted to a fixed quantity. Otherwise
203   /// returns \p X unmodified.
expandVScale(Quantity X)204   template <typename Quantity> Quantity expandVScale(Quantity X) const {
205     if (auto VLen = getRealVLen(); VLen && X.isScalable()) {
206       const unsigned VScale = *VLen / RISCV::RVVBitsPerBlock;
207       X = Quantity::getFixed(X.getKnownMinValue() * VScale);
208     }
209     return X;
210   }
211 
getTargetABI()212   RISCVABI::ABI getTargetABI() const { return TargetABI; }
isSoftFPABI()213   bool isSoftFPABI() const {
214     return TargetABI == RISCVABI::ABI_LP64 ||
215            TargetABI == RISCVABI::ABI_ILP32 ||
216            TargetABI == RISCVABI::ABI_ILP32E;
217   }
isRegisterReservedByUser(Register i)218   bool isRegisterReservedByUser(Register i) const {
219     assert(i < RISCV::NUM_TARGET_REGS && "Register out of range");
220     return UserReservedRegister[i];
221   }
222 
223   // Vector codegen related methods.
hasVInstructions()224   bool hasVInstructions() const { return HasStdExtZve32x; }
hasVInstructionsI64()225   bool hasVInstructionsI64() const { return HasStdExtZve64x; }
hasVInstructionsF16Minimal()226   bool hasVInstructionsF16Minimal() const { return HasStdExtZvfhmin; }
hasVInstructionsF16()227   bool hasVInstructionsF16() const { return HasStdExtZvfh; }
hasVInstructionsBF16()228   bool hasVInstructionsBF16() const { return HasStdExtZvfbfmin; }
hasVInstructionsF32()229   bool hasVInstructionsF32() const { return HasStdExtZve32f; }
hasVInstructionsF64()230   bool hasVInstructionsF64() const { return HasStdExtZve64d; }
231   // F16 and F64 both require F32.
hasVInstructionsAnyF()232   bool hasVInstructionsAnyF() const { return hasVInstructionsF32(); }
hasVInstructionsFullMultiply()233   bool hasVInstructionsFullMultiply() const { return HasStdExtV; }
getMaxInterleaveFactor()234   unsigned getMaxInterleaveFactor() const {
235     return hasVInstructions() ? MaxInterleaveFactor : 1;
236   }
237 
238   // Returns VLEN divided by DLEN. Where DLEN is the datapath width of the
239   // vector hardware implementation which may be less than VLEN.
getDLenFactor()240   unsigned getDLenFactor() const {
241     if (DLenFactor2)
242       return 2;
243     return 1;
244   }
245 
246 protected:
247   // GlobalISel related APIs.
248   mutable std::unique_ptr<CallLowering> CallLoweringInfo;
249   mutable std::unique_ptr<InstructionSelector> InstSelector;
250   mutable std::unique_ptr<LegalizerInfo> Legalizer;
251   mutable std::unique_ptr<RISCVRegisterBankInfo> RegBankInfo;
252 
253   // Return the known range for the bit length of RVV data registers as set
254   // at the command line. A value of 0 means nothing is known about that particular
255   // limit beyond what's implied by the architecture.
256   // NOTE: Please use getRealMinVLen and getRealMaxVLen instead!
257   unsigned getMaxRVVVectorSizeInBits() const;
258   unsigned getMinRVVVectorSizeInBits() const;
259 
260 public:
261   const CallLowering *getCallLowering() const override;
262   InstructionSelector *getInstructionSelector() const override;
263   const LegalizerInfo *getLegalizerInfo() const override;
264   const RISCVRegisterBankInfo *getRegBankInfo() const override;
265 
isTargetAndroid()266   bool isTargetAndroid() const { return getTargetTriple().isAndroid(); }
isTargetFuchsia()267   bool isTargetFuchsia() const { return getTargetTriple().isOSFuchsia(); }
268 
269   bool useConstantPoolForLargeInts() const;
270 
271   // Maximum cost used for building integers, integers will be put into constant
272   // pool if exceeded.
273   unsigned getMaxBuildIntsCost() const;
274 
275   unsigned getMaxLMULForFixedLengthVectors() const;
276   bool useRVVForFixedLengthVectors() const;
277 
278   bool enableSubRegLiveness() const override;
279 
280   void getPostRAMutations(std::vector<std::unique_ptr<ScheduleDAGMutation>>
281                               &Mutations) const override;
282 
283   bool useAA() const override;
284 
getCacheLineSize()285   unsigned getCacheLineSize() const override {
286     return TuneInfo->CacheLineSize;
287   };
getPrefetchDistance()288   unsigned getPrefetchDistance() const override {
289     return TuneInfo->PrefetchDistance;
290   };
getMinPrefetchStride(unsigned NumMemAccesses,unsigned NumStridedMemAccesses,unsigned NumPrefetches,bool HasCall)291   unsigned getMinPrefetchStride(unsigned NumMemAccesses,
292                                 unsigned NumStridedMemAccesses,
293                                 unsigned NumPrefetches,
294                                 bool HasCall) const override {
295     return TuneInfo->MinPrefetchStride;
296   };
getMaxPrefetchIterationsAhead()297   unsigned getMaxPrefetchIterationsAhead() const override {
298     return TuneInfo->MaxPrefetchIterationsAhead;
299   };
300 
301   unsigned getMinimumJumpTableEntries() const;
302 
supportsInitUndef()303   bool supportsInitUndef() const override { return hasVInstructions(); }
304 };
305 } // End llvm namespace
306 
307 #endif
308