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