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/MachineScheduler.h" 25 #include "llvm/CodeGen/TargetSubtargetInfo.h" 26 #include "llvm/IR/DataLayout.h" 27 #include "llvm/Support/Compiler.h" 28 #include "llvm/Target/TargetMachine.h" 29 #include <bitset> 30 31 #define GET_RISCV_MACRO_FUSION_PRED_DECL 32 #include "RISCVGenMacroFusion.inc" 33 34 #define GET_SUBTARGETINFO_HEADER 35 #include "RISCVGenSubtargetInfo.inc" 36 37 namespace llvm { 38 class StringRef; 39 40 namespace RISCVTuneInfoTable { 41 42 struct RISCVTuneInfo { 43 const char *Name; 44 uint8_t PrefFunctionAlignment; 45 uint8_t PrefLoopAlignment; 46 47 // Information needed by LoopDataPrefetch. 48 uint16_t CacheLineSize; 49 uint16_t PrefetchDistance; 50 uint16_t MinPrefetchStride; 51 unsigned MaxPrefetchIterationsAhead; 52 53 unsigned MinimumJumpTableEntries; 54 55 // Tail duplication threshold at -O3. 56 unsigned TailDupAggressiveThreshold; 57 58 unsigned MaxStoresPerMemsetOptSize; 59 unsigned MaxStoresPerMemset; 60 61 unsigned MaxGluedStoresPerMemcpy; 62 unsigned MaxStoresPerMemcpyOptSize; 63 unsigned MaxStoresPerMemcpy; 64 65 unsigned MaxStoresPerMemmoveOptSize; 66 unsigned MaxStoresPerMemmove; 67 68 unsigned MaxLoadsPerMemcmpOptSize; 69 unsigned MaxLoadsPerMemcmp; 70 71 // The direction of PostRA scheduling. 72 MISched::Direction PostRASchedDirection; 73 }; 74 75 #define GET_RISCVTuneInfoTable_DECL 76 #include "RISCVGenSearchableTables.inc" 77 } // namespace RISCVTuneInfoTable 78 79 class RISCVSubtarget : public RISCVGenSubtargetInfo { 80 public: 81 // clang-format off 82 enum RISCVProcFamilyEnum : uint8_t { 83 Others, 84 SiFive7, 85 VentanaVeyron, 86 MIPSP8700, 87 Andes45, 88 }; 89 enum RISCVVRGatherCostModelEnum : uint8_t { 90 Quadratic, 91 NLog2N, 92 }; 93 // clang-format on 94 private: 95 virtual void anchor(); 96 97 RISCVProcFamilyEnum RISCVProcFamily = Others; 98 RISCVVRGatherCostModelEnum RISCVVRGatherCostModel = Quadratic; 99 100 #define GET_SUBTARGETINFO_MACRO(ATTRIBUTE, DEFAULT, GETTER) \ 101 bool ATTRIBUTE = DEFAULT; 102 #include "RISCVGenSubtargetInfo.inc" 103 104 unsigned XSfmmTE = 0; 105 unsigned ZvlLen = 0; 106 unsigned RVVVectorBitsMin; 107 unsigned RVVVectorBitsMax; 108 uint8_t MaxInterleaveFactor = 2; 109 RISCVABI::ABI TargetABI = RISCVABI::ABI_Unknown; 110 std::bitset<RISCV::NUM_TARGET_REGS> UserReservedRegister; 111 const RISCVTuneInfoTable::RISCVTuneInfo *TuneInfo; 112 113 RISCVFrameLowering FrameLowering; 114 RISCVInstrInfo InstrInfo; 115 RISCVRegisterInfo RegInfo; 116 RISCVTargetLowering TLInfo; 117 118 /// Initializes using the passed in CPU and feature strings so that we can 119 /// use initializer lists for subtarget initialization. 120 RISCVSubtarget &initializeSubtargetDependencies(const Triple &TT, 121 StringRef CPU, 122 StringRef TuneCPU, 123 StringRef FS, 124 StringRef ABIName); 125 126 public: 127 // Initializes the data members to match that of the specified triple. 128 RISCVSubtarget(const Triple &TT, StringRef CPU, StringRef TuneCPU, 129 StringRef FS, StringRef ABIName, unsigned RVVVectorBitsMin, 130 unsigned RVVVectorLMULMax, const TargetMachine &TM); 131 132 ~RISCVSubtarget() override; 133 134 // Parses features string setting specified subtarget options. The 135 // definition of this function is auto-generated by tblgen. 136 void ParseSubtargetFeatures(StringRef CPU, StringRef TuneCPU, StringRef FS); 137 getFrameLowering()138 const RISCVFrameLowering *getFrameLowering() const override { 139 return &FrameLowering; 140 } getInstrInfo()141 const RISCVInstrInfo *getInstrInfo() const override { return &InstrInfo; } getRegisterInfo()142 const RISCVRegisterInfo *getRegisterInfo() const override { 143 return &RegInfo; 144 } getTargetLowering()145 const RISCVTargetLowering *getTargetLowering() const override { 146 return &TLInfo; 147 } 148 enableMachineScheduler()149 bool enableMachineScheduler() const override { return true; } 150 enablePostRAScheduler()151 bool enablePostRAScheduler() const override { return UsePostRAScheduler; } 152 getPrefFunctionAlignment()153 Align getPrefFunctionAlignment() const { 154 return Align(TuneInfo->PrefFunctionAlignment); 155 } getPrefLoopAlignment()156 Align getPrefLoopAlignment() const { 157 return Align(TuneInfo->PrefLoopAlignment); 158 } 159 160 /// Returns RISC-V processor family. 161 /// Avoid this function! CPU specifics should be kept local to this class 162 /// and preferably modeled with SubtargetFeatures or properties in 163 /// initializeProperties(). getProcFamily()164 RISCVProcFamilyEnum getProcFamily() const { return RISCVProcFamily; } 165 getVRGatherCostModel()166 RISCVVRGatherCostModelEnum getVRGatherCostModel() const { return RISCVVRGatherCostModel; } 167 168 #define GET_SUBTARGETINFO_MACRO(ATTRIBUTE, DEFAULT, GETTER) \ 169 bool GETTER() const { return ATTRIBUTE; } 170 #include "RISCVGenSubtargetInfo.inc" 171 172 LLVM_DEPRECATED("Now Equivalent to hasStdExtZca", "hasStdExtZca") hasStdExtCOrZca()173 bool hasStdExtCOrZca() const { return HasStdExtZca; } hasStdExtCOrZcd()174 bool hasStdExtCOrZcd() const { return HasStdExtC || HasStdExtZcd; } hasStdExtCOrZcfOrZce()175 bool hasStdExtCOrZcfOrZce() const { 176 return HasStdExtC || HasStdExtZcf || HasStdExtZce; 177 } hasStdExtZvl()178 bool hasStdExtZvl() const { return ZvlLen != 0; } hasStdExtFOrZfinx()179 bool hasStdExtFOrZfinx() const { return HasStdExtF || HasStdExtZfinx; } hasStdExtDOrZdinx()180 bool hasStdExtDOrZdinx() const { return HasStdExtD || HasStdExtZdinx; } hasStdExtZfhOrZhinx()181 bool hasStdExtZfhOrZhinx() const { return HasStdExtZfh || HasStdExtZhinx; } hasStdExtZfhminOrZhinxmin()182 bool hasStdExtZfhminOrZhinxmin() const { 183 return HasStdExtZfhmin || HasStdExtZhinxmin; 184 } hasHalfFPLoadStoreMove()185 bool hasHalfFPLoadStoreMove() const { 186 return HasStdExtZfhmin || HasStdExtZfbfmin; 187 } 188 hasConditionalMoveFusion()189 bool hasConditionalMoveFusion() const { 190 // Do we support fusing a branch+mv or branch+c.mv as a conditional move. 191 return (hasConditionalCompressedMoveFusion() && hasStdExtZca()) || 192 hasShortForwardBranchOpt(); 193 } 194 is64Bit()195 bool is64Bit() const { return IsRV64; } getXLenVT()196 MVT getXLenVT() const { 197 return is64Bit() ? MVT::i64 : MVT::i32; 198 } getXLen()199 unsigned getXLen() const { 200 return is64Bit() ? 64 : 32; 201 } 202 bool useLoadStorePairs() const; 203 bool useCCMovInsn() const; getFLen()204 unsigned getFLen() const { 205 if (HasStdExtD) 206 return 64; 207 208 if (HasStdExtF) 209 return 32; 210 211 return 0; 212 } getELen()213 unsigned getELen() const { 214 assert(hasVInstructions() && "Expected V extension"); 215 return hasVInstructionsI64() ? 64 : 32; 216 } getRealMinVLen()217 unsigned getRealMinVLen() const { 218 unsigned VLen = getMinRVVVectorSizeInBits(); 219 return VLen == 0 ? ZvlLen : VLen; 220 } getRealMaxVLen()221 unsigned getRealMaxVLen() const { 222 unsigned VLen = getMaxRVVVectorSizeInBits(); 223 return VLen == 0 ? 65536 : VLen; 224 } 225 // If we know the exact VLEN, return it. Otherwise, return std::nullopt. getRealVLen()226 std::optional<unsigned> getRealVLen() const { 227 unsigned Min = getRealMinVLen(); 228 if (Min != getRealMaxVLen()) 229 return std::nullopt; 230 return Min; 231 } 232 233 /// If the ElementCount or TypeSize \p X is scalable and VScale (VLEN) is 234 /// exactly known, returns \p X converted to a fixed quantity. Otherwise 235 /// returns \p X unmodified. expandVScale(Quantity X)236 template <typename Quantity> Quantity expandVScale(Quantity X) const { 237 if (auto VLen = getRealVLen(); VLen && X.isScalable()) { 238 const unsigned VScale = *VLen / RISCV::RVVBitsPerBlock; 239 X = Quantity::getFixed(X.getKnownMinValue() * VScale); 240 } 241 return X; 242 } 243 getTargetABI()244 RISCVABI::ABI getTargetABI() const { return TargetABI; } isSoftFPABI()245 bool isSoftFPABI() const { 246 return TargetABI == RISCVABI::ABI_LP64 || 247 TargetABI == RISCVABI::ABI_ILP32 || 248 TargetABI == RISCVABI::ABI_ILP32E; 249 } isRegisterReservedByUser(Register i)250 bool isRegisterReservedByUser(Register i) const override { 251 assert(i.id() < RISCV::NUM_TARGET_REGS && "Register out of range"); 252 return UserReservedRegister[i.id()]; 253 } 254 255 // XRay support - require D and C extensions. isXRaySupported()256 bool isXRaySupported() const override { return hasStdExtD() && hasStdExtC(); } 257 258 // Vector codegen related methods. hasVInstructions()259 bool hasVInstructions() const { return HasStdExtZve32x; } hasVInstructionsI64()260 bool hasVInstructionsI64() const { return HasStdExtZve64x; } hasVInstructionsF16Minimal()261 bool hasVInstructionsF16Minimal() const { return HasStdExtZvfhmin; } hasVInstructionsF16()262 bool hasVInstructionsF16() const { return HasStdExtZvfh; } hasVInstructionsBF16Minimal()263 bool hasVInstructionsBF16Minimal() const { return HasStdExtZvfbfmin; } hasVInstructionsF32()264 bool hasVInstructionsF32() const { return HasStdExtZve32f; } hasVInstructionsF64()265 bool hasVInstructionsF64() const { return HasStdExtZve64d; } 266 // F16 and F64 both require F32. hasVInstructionsAnyF()267 bool hasVInstructionsAnyF() const { return hasVInstructionsF32(); } hasVInstructionsFullMultiply()268 bool hasVInstructionsFullMultiply() const { return HasStdExtV; } getMaxInterleaveFactor()269 unsigned getMaxInterleaveFactor() const { 270 return hasVInstructions() ? MaxInterleaveFactor : 1; 271 } 272 hasOptimizedSegmentLoadStore(unsigned NF)273 bool hasOptimizedSegmentLoadStore(unsigned NF) const { 274 switch (NF) { 275 case 2: 276 return hasOptimizedNF2SegmentLoadStore(); 277 case 3: 278 return hasOptimizedNF3SegmentLoadStore(); 279 case 4: 280 return hasOptimizedNF4SegmentLoadStore(); 281 case 5: 282 return hasOptimizedNF5SegmentLoadStore(); 283 case 6: 284 return hasOptimizedNF6SegmentLoadStore(); 285 case 7: 286 return hasOptimizedNF7SegmentLoadStore(); 287 case 8: 288 return hasOptimizedNF8SegmentLoadStore(); 289 default: 290 llvm_unreachable("Unexpected NF"); 291 } 292 } 293 294 // Returns VLEN divided by DLEN. Where DLEN is the datapath width of the 295 // vector hardware implementation which may be less than VLEN. getDLenFactor()296 unsigned getDLenFactor() const { 297 if (DLenFactor2) 298 return 2; 299 return 1; 300 } 301 302 protected: 303 // SelectionDAGISel related APIs. 304 std::unique_ptr<const SelectionDAGTargetInfo> TSInfo; 305 306 // GlobalISel related APIs. 307 mutable std::unique_ptr<CallLowering> CallLoweringInfo; 308 mutable std::unique_ptr<InstructionSelector> InstSelector; 309 mutable std::unique_ptr<LegalizerInfo> Legalizer; 310 mutable std::unique_ptr<RISCVRegisterBankInfo> RegBankInfo; 311 312 // Return the known range for the bit length of RVV data registers as set 313 // at the command line. A value of 0 means nothing is known about that particular 314 // limit beyond what's implied by the architecture. 315 // NOTE: Please use getRealMinVLen and getRealMaxVLen instead! 316 unsigned getMaxRVVVectorSizeInBits() const; 317 unsigned getMinRVVVectorSizeInBits() const; 318 319 public: 320 const SelectionDAGTargetInfo *getSelectionDAGInfo() const override; 321 const CallLowering *getCallLowering() const override; 322 InstructionSelector *getInstructionSelector() const override; 323 const LegalizerInfo *getLegalizerInfo() const override; 324 const RISCVRegisterBankInfo *getRegBankInfo() const override; 325 isTargetAndroid()326 bool isTargetAndroid() const { return getTargetTriple().isAndroid(); } isTargetFuchsia()327 bool isTargetFuchsia() const { return getTargetTriple().isOSFuchsia(); } 328 329 bool useConstantPoolForLargeInts() const; 330 331 // Maximum cost used for building integers, integers will be put into constant 332 // pool if exceeded. 333 unsigned getMaxBuildIntsCost() const; 334 335 unsigned getMaxLMULForFixedLengthVectors() const; 336 bool useRVVForFixedLengthVectors() const; 337 338 bool enableSubRegLiveness() const override; 339 340 bool enableMachinePipeliner() const override; 341 useDFAforSMS()342 bool useDFAforSMS() const override { return false; } 343 344 bool useAA() const override; 345 getCacheLineSize()346 unsigned getCacheLineSize() const override { 347 return TuneInfo->CacheLineSize; 348 }; getPrefetchDistance()349 unsigned getPrefetchDistance() const override { 350 return TuneInfo->PrefetchDistance; 351 }; getMinPrefetchStride(unsigned NumMemAccesses,unsigned NumStridedMemAccesses,unsigned NumPrefetches,bool HasCall)352 unsigned getMinPrefetchStride(unsigned NumMemAccesses, 353 unsigned NumStridedMemAccesses, 354 unsigned NumPrefetches, 355 bool HasCall) const override { 356 return TuneInfo->MinPrefetchStride; 357 }; getMaxPrefetchIterationsAhead()358 unsigned getMaxPrefetchIterationsAhead() const override { 359 return TuneInfo->MaxPrefetchIterationsAhead; 360 }; enableWritePrefetching()361 bool enableWritePrefetching() const override { return true; } 362 363 unsigned getMinimumJumpTableEntries() const; 364 getTailDupAggressiveThreshold()365 unsigned getTailDupAggressiveThreshold() const { 366 return TuneInfo->TailDupAggressiveThreshold; 367 } 368 getMaxStoresPerMemset(bool OptSize)369 unsigned getMaxStoresPerMemset(bool OptSize) const { 370 return OptSize ? TuneInfo->MaxStoresPerMemsetOptSize 371 : TuneInfo->MaxStoresPerMemset; 372 } 373 getMaxGluedStoresPerMemcpy()374 unsigned getMaxGluedStoresPerMemcpy() const { 375 return TuneInfo->MaxGluedStoresPerMemcpy; 376 } 377 getMaxStoresPerMemcpy(bool OptSize)378 unsigned getMaxStoresPerMemcpy(bool OptSize) const { 379 return OptSize ? TuneInfo->MaxStoresPerMemcpyOptSize 380 : TuneInfo->MaxStoresPerMemcpy; 381 } 382 getMaxStoresPerMemmove(bool OptSize)383 unsigned getMaxStoresPerMemmove(bool OptSize) const { 384 return OptSize ? TuneInfo->MaxStoresPerMemmoveOptSize 385 : TuneInfo->MaxStoresPerMemmove; 386 } 387 getMaxLoadsPerMemcmp(bool OptSize)388 unsigned getMaxLoadsPerMemcmp(bool OptSize) const { 389 return OptSize ? TuneInfo->MaxLoadsPerMemcmpOptSize 390 : TuneInfo->MaxLoadsPerMemcmp; 391 } 392 getPostRASchedDirection()393 MISched::Direction getPostRASchedDirection() const { 394 return TuneInfo->PostRASchedDirection; 395 } 396 397 void overrideSchedPolicy(MachineSchedPolicy &Policy, 398 unsigned NumRegionInstrs) const override; 399 400 void overridePostRASchedPolicy(MachineSchedPolicy &Policy, 401 unsigned NumRegionInstrs) const override; 402 }; 403 } // End llvm namespace 404 405 #endif 406