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
36namespace llvm {
37class StringRef;
38
39namespace RISCVTuneInfoTable {
40
41struct 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
59class RISCVSubtarget : public RISCVGenSubtargetInfo {
60public:
61 // clang-format off
62 enum RISCVProcFamilyEnum : uint8_t {
63 Others,
64 SiFive7,
65 VentanaVeyron,
66 };
67 // clang-format on
68private:
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
99public:
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
109 const RISCVFrameLowering *getFrameLowering() const override {
110 return &FrameLowering;
111 }
112 const RISCVInstrInfo *getInstrInfo() const override { return &InstrInfo; }
113 const RISCVRegisterInfo *getRegisterInfo() const override {
114 return &RegInfo;
115 }
116 const RISCVTargetLowering *getTargetLowering() const override {
117 return &TLInfo;
118 }
119 const SelectionDAGTargetInfo *getSelectionDAGInfo() const override {
120 return &TSInfo;
121 }
122 bool enableMachineScheduler() const override { return true; }
123
124 bool enablePostRAScheduler() const override { return UsePostRAScheduler; }
125
126 Align getPrefFunctionAlignment() const {
127 return Align(TuneInfo->PrefFunctionAlignment);
128 }
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().
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
143 bool hasStdExtCOrZca() const { return HasStdExtC || HasStdExtZca; }
144 bool hasStdExtCOrZcd() const { return HasStdExtC || HasStdExtZcd; }
145 bool hasStdExtCOrZcfOrZce() const {
146 return HasStdExtC || HasStdExtZcf || HasStdExtZce;
147 }
148 bool hasStdExtZvl() const { return ZvlLen != 0; }
149 bool hasStdExtFOrZfinx() const { return HasStdExtF || HasStdExtZfinx; }
150 bool hasStdExtDOrZdinx() const { return HasStdExtD || HasStdExtZdinx; }
151 bool hasStdExtZfhOrZhinx() const { return HasStdExtZfh || HasStdExtZhinx; }
152 bool hasStdExtZfhminOrZhinxmin() const {
153 return HasStdExtZfhmin || HasStdExtZhinxmin;
154 }
155 bool hasHalfFPLoadStoreMove() const {
156 return HasStdExtZfhmin || HasStdExtZfbfmin;
157 }
158
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
165 bool is64Bit() const { return IsRV64; }
166 MVT getXLenVT() const {
167 return is64Bit() ? MVT::i64 : MVT::i32;
168 }
169 unsigned getXLen() const {
170 return is64Bit() ? 64 : 32;
171 }
172 unsigned getFLen() const {
173 if (HasStdExtD)
174 return 64;
175
176 if (HasStdExtF)
177 return 32;
178
179 return 0;
180 }
181 unsigned getELen() const {
182 assert(hasVInstructions() && "Expected V extension");
183 return hasVInstructionsI64() ? 64 : 32;
184 }
185 unsigned getRealMinVLen() const {
186 unsigned VLen = getMinRVVVectorSizeInBits();
187 return VLen == 0 ? ZvlLen : VLen;
188 }
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.
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.
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
212 RISCVABI::ABI getTargetABI() const { return TargetABI; }
213 bool isSoftFPABI() const {
214 return TargetABI == RISCVABI::ABI_LP64 ||
215 TargetABI == RISCVABI::ABI_ILP32 ||
216 TargetABI == RISCVABI::ABI_ILP32E;
217 }
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.
224 bool hasVInstructions() const { return HasStdExtZve32x; }
225 bool hasVInstructionsI64() const { return HasStdExtZve64x; }
226 bool hasVInstructionsF16Minimal() const { return HasStdExtZvfhmin; }
227 bool hasVInstructionsF16() const { return HasStdExtZvfh; }
228 bool hasVInstructionsBF16() const { return HasStdExtZvfbfmin; }
229 bool hasVInstructionsF32() const { return HasStdExtZve32f; }
230 bool hasVInstructionsF64() const { return HasStdExtZve64d; }
231 // F16 and F64 both require F32.
232 bool hasVInstructionsAnyF() const { return hasVInstructionsF32(); }
233 bool hasVInstructionsFullMultiply() const { return HasStdExtV; }
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.
240 unsigned getDLenFactor() const {
241 if (DLenFactor2)
242 return 2;
243 return 1;
244 }
245
246protected:
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
260public:
261 const CallLowering *getCallLowering() const override;
262 InstructionSelector *getInstructionSelector() const override;
263 const LegalizerInfo *getLegalizerInfo() const override;
264 const RISCVRegisterBankInfo *getRegBankInfo() const override;
265
266 bool isTargetAndroid() const { return getTargetTriple().isAndroid(); }
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
285 unsigned getCacheLineSize() const override {
286 return TuneInfo->CacheLineSize;
287 };
288 unsigned getPrefetchDistance() const override {
289 return TuneInfo->PrefetchDistance;
290 };
291 unsigned getMinPrefetchStride(unsigned NumMemAccesses,
292 unsigned NumStridedMemAccesses,
293 unsigned NumPrefetches,
294 bool HasCall) const override {
295 return TuneInfo->MinPrefetchStride;
296 };
297 unsigned getMaxPrefetchIterationsAhead() const override {
298 return TuneInfo->MaxPrefetchIterationsAhead;
299 };
300
301 unsigned getMinimumJumpTableEntries() const;
302
303 bool supportsInitUndef() const override { return hasVInstructions(); }
304};
305} // End llvm namespace
306
307#endif
308