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