1 //===-- RISCVSubtarget.h - Define Subtarget for the RISCV -------*- 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 RISCV 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 "MCTargetDesc/RISCVBaseInfo.h"
17 #include "RISCVFrameLowering.h"
18 #include "RISCVISelLowering.h"
19 #include "RISCVInstrInfo.h"
20 #include "llvm/CodeGen/GlobalISel/CallLowering.h"
21 #include "llvm/CodeGen/GlobalISel/InstructionSelector.h"
22 #include "llvm/CodeGen/GlobalISel/LegalizerInfo.h"
23 #include "llvm/CodeGen/RegisterBankInfo.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 
29 #define GET_SUBTARGETINFO_HEADER
30 #include "RISCVGenSubtargetInfo.inc"
31 
32 namespace llvm {
33 class StringRef;
34 
35 class RISCVSubtarget : public RISCVGenSubtargetInfo {
36 public:
37   enum RISCVProcFamilyEnum : uint8_t {
38     Others,
39     SiFive7,
40   };
41 
42 private:
43   virtual void anchor();
44 
45   RISCVProcFamilyEnum RISCVProcFamily = Others;
46 
47   bool HasStdExtM = false;
48   bool HasStdExtA = false;
49   bool HasStdExtF = false;
50   bool HasStdExtD = false;
51   bool HasStdExtC = false;
52   bool HasStdExtZihintpause = false;
53   bool HasStdExtZba = false;
54   bool HasStdExtZbb = false;
55   bool HasStdExtZbc = false;
56   bool HasStdExtZbe = false;
57   bool HasStdExtZbf = false;
58   bool HasStdExtZbm = false;
59   bool HasStdExtZbp = false;
60   bool HasStdExtZbr = false;
61   bool HasStdExtZbs = false;
62   bool HasStdExtZbt = false;
63   bool HasStdExtV = false;
64   bool HasStdExtZve32x = false;
65   bool HasStdExtZve32f = false;
66   bool HasStdExtZve64x = false;
67   bool HasStdExtZve64f = false;
68   bool HasStdExtZve64d = false;
69   bool HasStdExtZvfh = false;
70   bool HasStdExtZfhmin = false;
71   bool HasStdExtZfh = false;
72   bool HasStdExtZfinx = false;
73   bool HasStdExtZdinx = false;
74   bool HasStdExtZhinxmin = false;
75   bool HasStdExtZhinx = false;
76   bool HasStdExtZbkb = false;
77   bool HasStdExtZbkc = false;
78   bool HasStdExtZbkx = false;
79   bool HasStdExtZknd = false;
80   bool HasStdExtZkne = false;
81   bool HasStdExtZknh = false;
82   bool HasStdExtZksed = false;
83   bool HasStdExtZksh = false;
84   bool HasStdExtZkr = false;
85   bool HasStdExtZkn = false;
86   bool HasStdExtZks = false;
87   bool HasStdExtZkt = false;
88   bool HasStdExtZk = false;
89   bool HasStdExtZicbom = false;
90   bool HasStdExtZicboz = false;
91   bool HasStdExtZicbop = false;
92   bool HasStdExtZmmul = false;
93   bool HasRV64 = false;
94   bool IsRV32E = false;
95   bool EnableLinkerRelax = false;
96   bool EnableRVCHintInstrs = true;
97   bool EnableDefaultUnroll = true;
98   bool EnableSaveRestore = false;
99   bool EnableUnalignedScalarMem = false;
100   bool HasLUIADDIFusion = false;
101   unsigned XLen = 32;
102   unsigned ZvlLen = 0;
103   MVT XLenVT = MVT::i32;
104   uint8_t MaxInterleaveFactor = 2;
105   RISCVABI::ABI TargetABI = RISCVABI::ABI_Unknown;
106   BitVector UserReservedRegister;
107   RISCVFrameLowering FrameLowering;
108   RISCVInstrInfo InstrInfo;
109   RISCVRegisterInfo RegInfo;
110   RISCVTargetLowering TLInfo;
111   SelectionDAGTargetInfo TSInfo;
112 
113   /// Initializes using the passed in CPU and feature strings so that we can
114   /// use initializer lists for subtarget initialization.
115   RISCVSubtarget &initializeSubtargetDependencies(const Triple &TT,
116                                                   StringRef CPU,
117                                                   StringRef TuneCPU,
118                                                   StringRef FS,
119                                                   StringRef ABIName);
120 
121 public:
122   // Initializes the data members to match that of the specified triple.
123   RISCVSubtarget(const Triple &TT, StringRef CPU, StringRef TuneCPU,
124                  StringRef FS, StringRef ABIName, const TargetMachine &TM);
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   const SelectionDAGTargetInfo *getSelectionDAGInfo() const override {
141     return &TSInfo;
142   }
143   bool enableMachineScheduler() const override { return true; }
144 
145   /// Returns RISCV processor family.
146   /// Avoid this function! CPU specifics should be kept local to this class
147   /// and preferably modeled with SubtargetFeatures or properties in
148   /// initializeProperties().
149   RISCVProcFamilyEnum getProcFamily() const { return RISCVProcFamily; }
150 
151   bool hasStdExtM() const { return HasStdExtM; }
152   bool hasStdExtA() const { return HasStdExtA; }
153   bool hasStdExtF() const { return HasStdExtF; }
154   bool hasStdExtD() const { return HasStdExtD; }
155   bool hasStdExtC() const { return HasStdExtC; }
156   bool hasStdExtV() const { return HasStdExtV; }
157   bool hasStdExtZihintpause() const { return HasStdExtZihintpause; }
158   bool hasStdExtZba() const { return HasStdExtZba; }
159   bool hasStdExtZbb() const { return HasStdExtZbb; }
160   bool hasStdExtZbc() const { return HasStdExtZbc; }
161   bool hasStdExtZbe() const { return HasStdExtZbe; }
162   bool hasStdExtZbf() const { return HasStdExtZbf; }
163   bool hasStdExtZbm() const { return HasStdExtZbm; }
164   bool hasStdExtZbp() const { return HasStdExtZbp; }
165   bool hasStdExtZbr() const { return HasStdExtZbr; }
166   bool hasStdExtZbs() const { return HasStdExtZbs; }
167   bool hasStdExtZbt() const { return HasStdExtZbt; }
168   bool hasStdExtZvl() const { return ZvlLen != 0; }
169   bool hasStdExtZvfh() const { return HasStdExtZvfh; }
170   bool hasStdExtZfhmin() const { return HasStdExtZfhmin; }
171   bool hasStdExtZfh() const { return HasStdExtZfh; }
172   bool hasStdExtZfinx() const { return HasStdExtZfinx; }
173   bool hasStdExtZdinx() const { return HasStdExtZdinx; }
174   bool hasStdExtZhinxmin() const { return HasStdExtZhinxmin; }
175   bool hasStdExtZhinx() const { return HasStdExtZhinx; }
176   bool hasStdExtZbkb() const { return HasStdExtZbkb; }
177   bool hasStdExtZbkc() const { return HasStdExtZbkc; }
178   bool hasStdExtZbkx() const { return HasStdExtZbkx; }
179   bool hasStdExtZknd() const { return HasStdExtZknd; }
180   bool hasStdExtZkne() const { return HasStdExtZkne; }
181   bool hasStdExtZknh() const { return HasStdExtZknh; }
182   bool hasStdExtZksed() const { return HasStdExtZksed; }
183   bool hasStdExtZksh() const { return HasStdExtZksh; }
184   bool hasStdExtZkr() const { return HasStdExtZkr; }
185   bool hasStdExtZicbom() const { return HasStdExtZicbom; }
186   bool hasStdExtZicboz() const { return HasStdExtZicboz; }
187   bool hasStdExtZicbop() const { return HasStdExtZicbop; }
188   bool hasStdExtZmmul() const { return HasStdExtZmmul; }
189   bool is64Bit() const { return HasRV64; }
190   bool isRV32E() const { return IsRV32E; }
191   bool enableLinkerRelax() const { return EnableLinkerRelax; }
192   bool enableRVCHintInstrs() const { return EnableRVCHintInstrs; }
193   bool enableDefaultUnroll() const { return EnableDefaultUnroll; }
194   bool enableSaveRestore() const { return EnableSaveRestore; }
195   bool enableUnalignedScalarMem() const { return EnableUnalignedScalarMem; }
196   bool hasLUIADDIFusion() const { return HasLUIADDIFusion; }
197   MVT getXLenVT() const { return XLenVT; }
198   unsigned getXLen() const { return XLen; }
199   unsigned getFLen() const {
200     if (HasStdExtD)
201       return 64;
202 
203     if (HasStdExtF)
204       return 32;
205 
206     return 0;
207   }
208   unsigned getELEN() const {
209     assert(hasVInstructions() && "Expected V extension");
210     return hasVInstructionsI64() ? 64 : 32;
211   }
212   unsigned getRealMinVLen() const {
213     unsigned VLen = getMinRVVVectorSizeInBits();
214     return VLen == 0 ? getArchMinVLen() : VLen;
215   }
216   unsigned getRealMaxVLen() const {
217     unsigned VLen = getMaxRVVVectorSizeInBits();
218     return VLen == 0 ? getArchMaxVLen() : VLen;
219   }
220   RISCVABI::ABI getTargetABI() const { return TargetABI; }
221   bool isRegisterReservedByUser(Register i) const {
222     assert(i < RISCV::NUM_TARGET_REGS && "Register out of range");
223     return UserReservedRegister[i];
224   }
225 
226   bool hasMacroFusion() const { return hasLUIADDIFusion(); }
227 
228   // Vector codegen related methods.
229   bool hasVInstructions() const { return HasStdExtZve32x; }
230   bool hasVInstructionsI64() const { return HasStdExtZve64x; }
231   bool hasVInstructionsF16() const { return HasStdExtZvfh && HasStdExtZfh; }
232   // FIXME: Consider Zfinx in the future
233   bool hasVInstructionsF32() const { return HasStdExtZve32f && HasStdExtF; }
234   // FIXME: Consider Zdinx in the future
235   bool hasVInstructionsF64() const { return HasStdExtZve64d && HasStdExtD; }
236   // F16 and F64 both require F32.
237   bool hasVInstructionsAnyF() const { return hasVInstructionsF32(); }
238   unsigned getMaxInterleaveFactor() const {
239     return hasVInstructions() ? MaxInterleaveFactor : 1;
240   }
241 
242 protected:
243   // GlobalISel related APIs.
244   std::unique_ptr<CallLowering> CallLoweringInfo;
245   std::unique_ptr<InstructionSelector> InstSelector;
246   std::unique_ptr<LegalizerInfo> Legalizer;
247   std::unique_ptr<RegisterBankInfo> RegBankInfo;
248 
249   // Return the known range for the bit length of RVV data registers as set
250   // at the command line. A value of 0 means nothing is known about that particular
251   // limit beyond what's implied by the architecture.
252   // NOTE: Please use getRealMinVLen and getRealMaxVLen instead!
253   unsigned getMaxRVVVectorSizeInBits() const;
254   unsigned getMinRVVVectorSizeInBits() const;
255 
256   // Return the known range for the bit length of RVV data registers as indicated
257   // by -march and -mattr.
258   unsigned getArchMinVLen() const { return ZvlLen; }
259   unsigned getArchMaxVLen() const { return 65536; }
260 
261 public:
262   const CallLowering *getCallLowering() const override;
263   InstructionSelector *getInstructionSelector() const override;
264   const LegalizerInfo *getLegalizerInfo() const override;
265   const RegisterBankInfo *getRegBankInfo() const override;
266 
267   bool useConstantPoolForLargeInts() const;
268 
269   // Maximum cost used for building integers, integers will be put into constant
270   // pool if exceeded.
271   unsigned getMaxBuildIntsCost() const;
272 
273   unsigned getMaxLMULForFixedLengthVectors() const;
274   bool useRVVForFixedLengthVectors() const;
275 
276   bool enableSubRegLiveness() const override;
277 
278   void getPostRAMutations(std::vector<std::unique_ptr<ScheduleDAGMutation>>
279                               &Mutations) const override;
280 };
281 } // End llvm namespace
282 
283 #endif
284