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 "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 #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 {
125     return getSchedModel().PostRAScheduler || UsePostRAScheduler;
126   }
127 
getPrefFunctionAlignment()128   Align getPrefFunctionAlignment() const {
129     return Align(TuneInfo->PrefFunctionAlignment);
130   }
getPrefLoopAlignment()131   Align getPrefLoopAlignment() const {
132     return Align(TuneInfo->PrefLoopAlignment);
133   }
134 
135   /// Returns RISC-V processor family.
136   /// Avoid this function! CPU specifics should be kept local to this class
137   /// and preferably modeled with SubtargetFeatures or properties in
138   /// initializeProperties().
getProcFamily()139   RISCVProcFamilyEnum getProcFamily() const { return RISCVProcFamily; }
140 
141 #define GET_SUBTARGETINFO_MACRO(ATTRIBUTE, DEFAULT, GETTER) \
142   bool GETTER() const { return ATTRIBUTE; }
143 #include "RISCVGenSubtargetInfo.inc"
144 
hasStdExtCOrZca()145   bool hasStdExtCOrZca() const { return HasStdExtC || HasStdExtZca; }
hasStdExtZvl()146   bool hasStdExtZvl() const { return ZvlLen != 0; }
hasStdExtFOrZfinx()147   bool hasStdExtFOrZfinx() const { return HasStdExtF || HasStdExtZfinx; }
hasStdExtDOrZdinx()148   bool hasStdExtDOrZdinx() const { return HasStdExtD || HasStdExtZdinx; }
hasStdExtZfhOrZhinx()149   bool hasStdExtZfhOrZhinx() const { return HasStdExtZfh || HasStdExtZhinx; }
hasStdExtZfhminOrZhinxmin()150   bool hasStdExtZfhminOrZhinxmin() const {
151     return HasStdExtZfhmin || HasStdExtZhinxmin;
152   }
hasHalfFPLoadStoreMove()153   bool hasHalfFPLoadStoreMove() const {
154     return HasStdExtZfhmin || HasStdExtZfbfmin;
155   }
156 
hasConditionalMoveFusion()157   bool hasConditionalMoveFusion() const {
158     // Do we support fusing a branch+mv or branch+c.mv as a conditional move.
159     return (hasConditionalCompressedMoveFusion() && hasStdExtCOrZca()) ||
160            hasShortForwardBranchOpt();
161   }
162 
is64Bit()163   bool is64Bit() const { return IsRV64; }
getXLenVT()164   MVT getXLenVT() const {
165     return is64Bit() ? MVT::i64 : MVT::i32;
166   }
getXLen()167   unsigned getXLen() const {
168     return is64Bit() ? 64 : 32;
169   }
getFLen()170   unsigned getFLen() const {
171     if (HasStdExtD)
172       return 64;
173 
174     if (HasStdExtF)
175       return 32;
176 
177     return 0;
178   }
getELen()179   unsigned getELen() const {
180     assert(hasVInstructions() && "Expected V extension");
181     return hasVInstructionsI64() ? 64 : 32;
182   }
getRealMinVLen()183   unsigned getRealMinVLen() const {
184     unsigned VLen = getMinRVVVectorSizeInBits();
185     return VLen == 0 ? ZvlLen : VLen;
186   }
getRealMaxVLen()187   unsigned getRealMaxVLen() const {
188     unsigned VLen = getMaxRVVVectorSizeInBits();
189     return VLen == 0 ? 65536 : VLen;
190   }
getTargetABI()191   RISCVABI::ABI getTargetABI() const { return TargetABI; }
isSoftFPABI()192   bool isSoftFPABI() const {
193     return TargetABI == RISCVABI::ABI_LP64 ||
194            TargetABI == RISCVABI::ABI_ILP32 ||
195            TargetABI == RISCVABI::ABI_ILP32E;
196   }
isRegisterReservedByUser(Register i)197   bool isRegisterReservedByUser(Register i) const {
198     assert(i < RISCV::NUM_TARGET_REGS && "Register out of range");
199     return UserReservedRegister[i];
200   }
201 
202   // Vector codegen related methods.
hasVInstructions()203   bool hasVInstructions() const { return HasStdExtZve32x; }
hasVInstructionsI64()204   bool hasVInstructionsI64() const { return HasStdExtZve64x; }
hasVInstructionsF16Minimal()205   bool hasVInstructionsF16Minimal() const { return HasStdExtZvfhmin; }
hasVInstructionsF16()206   bool hasVInstructionsF16() const { return HasStdExtZvfh; }
hasVInstructionsBF16()207   bool hasVInstructionsBF16() const { return HasStdExtZvfbfmin; }
hasVInstructionsF32()208   bool hasVInstructionsF32() const { return HasStdExtZve32f; }
hasVInstructionsF64()209   bool hasVInstructionsF64() const { return HasStdExtZve64d; }
210   // F16 and F64 both require F32.
hasVInstructionsAnyF()211   bool hasVInstructionsAnyF() const { return hasVInstructionsF32(); }
hasVInstructionsFullMultiply()212   bool hasVInstructionsFullMultiply() const { return HasStdExtV; }
getMaxInterleaveFactor()213   unsigned getMaxInterleaveFactor() const {
214     return hasVInstructions() ? MaxInterleaveFactor : 1;
215   }
216 
217   // Returns VLEN divided by DLEN. Where DLEN is the datapath width of the
218   // vector hardware implementation which may be less than VLEN.
getDLenFactor()219   unsigned getDLenFactor() const {
220     if (DLenFactor2)
221       return 2;
222     return 1;
223   }
224 
225 protected:
226   // GlobalISel related APIs.
227   std::unique_ptr<CallLowering> CallLoweringInfo;
228   std::unique_ptr<InstructionSelector> InstSelector;
229   std::unique_ptr<LegalizerInfo> Legalizer;
230   std::unique_ptr<RegisterBankInfo> RegBankInfo;
231 
232   // Return the known range for the bit length of RVV data registers as set
233   // at the command line. A value of 0 means nothing is known about that particular
234   // limit beyond what's implied by the architecture.
235   // NOTE: Please use getRealMinVLen and getRealMaxVLen instead!
236   unsigned getMaxRVVVectorSizeInBits() const;
237   unsigned getMinRVVVectorSizeInBits() const;
238 
239 public:
240   const CallLowering *getCallLowering() const override;
241   InstructionSelector *getInstructionSelector() const override;
242   const LegalizerInfo *getLegalizerInfo() const override;
243   const RegisterBankInfo *getRegBankInfo() const override;
244 
isTargetFuchsia()245   bool isTargetFuchsia() const { return getTargetTriple().isOSFuchsia(); }
246 
247   bool useConstantPoolForLargeInts() const;
248 
249   // Maximum cost used for building integers, integers will be put into constant
250   // pool if exceeded.
251   unsigned getMaxBuildIntsCost() const;
252 
253   unsigned getMaxLMULForFixedLengthVectors() const;
254   bool useRVVForFixedLengthVectors() const;
255 
256   bool enableSubRegLiveness() const override;
257 
258   void getPostRAMutations(std::vector<std::unique_ptr<ScheduleDAGMutation>>
259                               &Mutations) const override;
260 
261   bool useAA() const override;
262 
getCacheLineSize()263   unsigned getCacheLineSize() const override {
264     return TuneInfo->CacheLineSize;
265   };
getPrefetchDistance()266   unsigned getPrefetchDistance() const override {
267     return TuneInfo->PrefetchDistance;
268   };
getMinPrefetchStride(unsigned NumMemAccesses,unsigned NumStridedMemAccesses,unsigned NumPrefetches,bool HasCall)269   unsigned getMinPrefetchStride(unsigned NumMemAccesses,
270                                 unsigned NumStridedMemAccesses,
271                                 unsigned NumPrefetches,
272                                 bool HasCall) const override {
273     return TuneInfo->MinPrefetchStride;
274   };
getMaxPrefetchIterationsAhead()275   unsigned getMaxPrefetchIterationsAhead() const override {
276     return TuneInfo->MaxPrefetchIterationsAhead;
277   };
278 
279   unsigned getMinimumJumpTableEntries() const;
280 };
281 } // End llvm namespace
282 
283 #endif
284