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