1 //=====-- AMDGPUSubtarget.h - Define Subtarget for AMDGPU ------*- C++ -*-====// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //==-----------------------------------------------------------------------===// 9 // 10 /// \file 11 /// \brief AMDGPU specific subclass of TargetSubtarget. 12 // 13 //===----------------------------------------------------------------------===// 14 15 #ifndef LLVM_LIB_TARGET_AMDGPU_AMDGPUSUBTARGET_H 16 #define LLVM_LIB_TARGET_AMDGPU_AMDGPUSUBTARGET_H 17 18 #include "AMDGPU.h" 19 #include "R600InstrInfo.h" 20 #include "R600ISelLowering.h" 21 #include "R600FrameLowering.h" 22 #include "SIInstrInfo.h" 23 #include "SIISelLowering.h" 24 #include "SIFrameLowering.h" 25 #include "Utils/AMDGPUBaseInfo.h" 26 #include "llvm/CodeGen/GlobalISel/GISelAccessor.h" 27 #include "llvm/Target/TargetSubtargetInfo.h" 28 29 #define GET_SUBTARGETINFO_HEADER 30 #include "AMDGPUGenSubtargetInfo.inc" 31 32 namespace llvm { 33 34 class SIMachineFunctionInfo; 35 class StringRef; 36 37 class AMDGPUSubtarget : public AMDGPUGenSubtargetInfo { 38 public: 39 enum Generation { 40 R600 = 0, 41 R700, 42 EVERGREEN, 43 NORTHERN_ISLANDS, 44 SOUTHERN_ISLANDS, 45 SEA_ISLANDS, 46 VOLCANIC_ISLANDS, 47 }; 48 49 enum { 50 ISAVersion0_0_0, 51 ISAVersion7_0_0, 52 ISAVersion7_0_1, 53 ISAVersion8_0_0, 54 ISAVersion8_0_1, 55 ISAVersion8_0_3 56 }; 57 58 protected: 59 // Basic subtarget description. 60 Triple TargetTriple; 61 Generation Gen; 62 unsigned IsaVersion; 63 unsigned WavefrontSize; 64 int LocalMemorySize; 65 int LDSBankCount; 66 unsigned MaxPrivateElementSize; 67 68 // Possibly statically set by tablegen, but may want to be overridden. 69 bool FastFMAF32; 70 bool HalfRate64Ops; 71 72 // Dynamially set bits that enable features. 73 bool FP32Denormals; 74 bool FP64Denormals; 75 bool FPExceptions; 76 bool FlatForGlobal; 77 bool EnableXNACK; 78 bool DebuggerInsertNops; 79 bool DebuggerReserveRegs; 80 bool DebuggerEmitPrologue; 81 82 // Used as options. 83 bool EnableVGPRSpilling; 84 bool EnablePromoteAlloca; 85 bool EnableLoadStoreOpt; 86 bool EnableUnsafeDSOffsetFolding; 87 bool EnableSIScheduler; 88 bool DumpCode; 89 90 // Subtarget statically properties set by tablegen 91 bool FP64; 92 bool IsGCN; 93 bool GCN1Encoding; 94 bool GCN3Encoding; 95 bool CIInsts; 96 bool SGPRInitBug; 97 bool HasSMemRealTime; 98 bool Has16BitInsts; 99 bool FlatAddressSpace; 100 bool R600ALUInst; 101 bool CaymanISA; 102 bool CFALUBug; 103 bool HasVertexCache; 104 short TexVTXClauseSize; 105 106 // Dummy feature to use for assembler in tablegen. 107 bool FeatureDisable; 108 109 InstrItineraryData InstrItins; 110 111 public: 112 AMDGPUSubtarget(const Triple &TT, StringRef GPU, StringRef FS, 113 const TargetMachine &TM); 114 virtual ~AMDGPUSubtarget(); 115 AMDGPUSubtarget &initializeSubtargetDependencies(const Triple &TT, 116 StringRef GPU, StringRef FS); 117 118 const AMDGPUInstrInfo *getInstrInfo() const override; 119 const AMDGPUFrameLowering *getFrameLowering() const override; 120 const AMDGPUTargetLowering *getTargetLowering() const override; 121 const AMDGPURegisterInfo *getRegisterInfo() const override; 122 123 const InstrItineraryData *getInstrItineraryData() const override { 124 return &InstrItins; 125 } 126 127 void ParseSubtargetFeatures(StringRef CPU, StringRef FS); 128 129 bool isAmdHsaOS() const { 130 return TargetTriple.getOS() == Triple::AMDHSA; 131 } 132 133 Generation getGeneration() const { 134 return Gen; 135 } 136 137 unsigned getWavefrontSize() const { 138 return WavefrontSize; 139 } 140 141 int getLocalMemorySize() const { 142 return LocalMemorySize; 143 } 144 145 int getLDSBankCount() const { 146 return LDSBankCount; 147 } 148 149 unsigned getMaxPrivateElementSize() const { 150 return MaxPrivateElementSize; 151 } 152 153 bool hasHWFP64() const { 154 return FP64; 155 } 156 157 bool hasFastFMAF32() const { 158 return FastFMAF32; 159 } 160 161 bool hasHalfRate64Ops() const { 162 return HalfRate64Ops; 163 } 164 165 bool hasAddr64() const { 166 return (getGeneration() < VOLCANIC_ISLANDS); 167 } 168 169 bool hasBFE() const { 170 return (getGeneration() >= EVERGREEN); 171 } 172 173 bool hasBFI() const { 174 return (getGeneration() >= EVERGREEN); 175 } 176 177 bool hasBFM() const { 178 return hasBFE(); 179 } 180 181 bool hasBCNT(unsigned Size) const { 182 if (Size == 32) 183 return (getGeneration() >= EVERGREEN); 184 185 if (Size == 64) 186 return (getGeneration() >= SOUTHERN_ISLANDS); 187 188 return false; 189 } 190 191 bool hasMulU24() const { 192 return (getGeneration() >= EVERGREEN); 193 } 194 195 bool hasMulI24() const { 196 return (getGeneration() >= SOUTHERN_ISLANDS || 197 hasCaymanISA()); 198 } 199 200 bool hasFFBL() const { 201 return (getGeneration() >= EVERGREEN); 202 } 203 204 bool hasFFBH() const { 205 return (getGeneration() >= EVERGREEN); 206 } 207 208 bool hasCARRY() const { 209 return (getGeneration() >= EVERGREEN); 210 } 211 212 bool hasBORROW() const { 213 return (getGeneration() >= EVERGREEN); 214 } 215 216 bool hasCaymanISA() const { 217 return CaymanISA; 218 } 219 220 bool isPromoteAllocaEnabled() const { 221 return EnablePromoteAlloca; 222 } 223 224 bool unsafeDSOffsetFoldingEnabled() const { 225 return EnableUnsafeDSOffsetFolding; 226 } 227 228 bool dumpCode() const { 229 return DumpCode; 230 } 231 232 /// Return the amount of LDS that can be used that will not restrict the 233 /// occupancy lower than WaveCount. 234 unsigned getMaxLocalMemSizeWithWaveCount(unsigned WaveCount) const; 235 236 /// Inverse of getMaxLocalMemWithWaveCount. Return the maximum wavecount if 237 /// the given LDS memory size is the only constraint. 238 unsigned getOccupancyWithLocalMemSize(uint32_t Bytes) const; 239 240 241 bool hasFP32Denormals() const { 242 return FP32Denormals; 243 } 244 245 bool hasFP64Denormals() const { 246 return FP64Denormals; 247 } 248 249 bool hasFPExceptions() const { 250 return FPExceptions; 251 } 252 253 bool useFlatForGlobal() const { 254 return FlatForGlobal; 255 } 256 257 bool isXNACKEnabled() const { 258 return EnableXNACK; 259 } 260 261 unsigned getMaxWavesPerCU() const { 262 if (getGeneration() >= AMDGPUSubtarget::SOUTHERN_ISLANDS) 263 return 10; 264 265 // FIXME: Not sure what this is for other subtagets. 266 return 8; 267 } 268 269 /// \brief Returns the offset in bytes from the start of the input buffer 270 /// of the first explicit kernel argument. 271 unsigned getExplicitKernelArgOffset() const { 272 return isAmdHsaOS() ? 0 : 36; 273 } 274 275 unsigned getStackAlignment() const { 276 // Scratch is allocated in 256 dword per wave blocks. 277 return 4 * 256 / getWavefrontSize(); 278 } 279 280 bool enableMachineScheduler() const override { 281 return true; 282 } 283 284 bool enableSubRegLiveness() const override { 285 return true; 286 } 287 }; 288 289 class R600Subtarget final : public AMDGPUSubtarget { 290 private: 291 R600InstrInfo InstrInfo; 292 R600FrameLowering FrameLowering; 293 R600TargetLowering TLInfo; 294 295 public: 296 R600Subtarget(const Triple &TT, StringRef CPU, StringRef FS, 297 const TargetMachine &TM); 298 299 const R600InstrInfo *getInstrInfo() const override { 300 return &InstrInfo; 301 } 302 303 const R600FrameLowering *getFrameLowering() const override { 304 return &FrameLowering; 305 } 306 307 const R600TargetLowering *getTargetLowering() const override { 308 return &TLInfo; 309 } 310 311 const R600RegisterInfo *getRegisterInfo() const override { 312 return &InstrInfo.getRegisterInfo(); 313 } 314 315 bool hasCFAluBug() const { 316 return CFALUBug; 317 } 318 319 bool hasVertexCache() const { 320 return HasVertexCache; 321 } 322 323 short getTexVTXClauseSize() const { 324 return TexVTXClauseSize; 325 } 326 327 unsigned getStackEntrySize() const; 328 }; 329 330 class SISubtarget final : public AMDGPUSubtarget { 331 public: 332 enum { 333 FIXED_SGPR_COUNT_FOR_INIT_BUG = 80 334 }; 335 336 private: 337 SIInstrInfo InstrInfo; 338 SIFrameLowering FrameLowering; 339 SITargetLowering TLInfo; 340 std::unique_ptr<GISelAccessor> GISel; 341 342 public: 343 SISubtarget(const Triple &TT, StringRef CPU, StringRef FS, 344 const TargetMachine &TM); 345 346 const SIInstrInfo *getInstrInfo() const override { 347 return &InstrInfo; 348 } 349 350 const SIFrameLowering *getFrameLowering() const override { 351 return &FrameLowering; 352 } 353 354 const SITargetLowering *getTargetLowering() const override { 355 return &TLInfo; 356 } 357 358 const CallLowering *getCallLowering() const override { 359 assert(GISel && "Access to GlobalISel APIs not set"); 360 return GISel->getCallLowering(); 361 } 362 363 const SIRegisterInfo *getRegisterInfo() const override { 364 return &InstrInfo.getRegisterInfo(); 365 } 366 367 void setGISelAccessor(GISelAccessor &GISel) { 368 this->GISel.reset(&GISel); 369 } 370 371 void overrideSchedPolicy(MachineSchedPolicy &Policy, 372 MachineInstr *Begin, MachineInstr *End, 373 unsigned NumRegionInstrs) const override; 374 375 bool isVGPRSpillingEnabled(const Function& F) const; 376 377 unsigned getAmdKernelCodeChipID() const; 378 379 AMDGPU::IsaVersion getIsaVersion() const; 380 381 unsigned getMaxNumUserSGPRs() const { 382 return 16; 383 } 384 385 bool hasFlatAddressSpace() const { 386 return FlatAddressSpace; 387 } 388 389 bool hasSMemRealTime() const { 390 return HasSMemRealTime; 391 } 392 393 bool has16BitInsts() const { 394 return Has16BitInsts; 395 } 396 397 bool enableSIScheduler() const { 398 return EnableSIScheduler; 399 } 400 401 bool debuggerSupported() const { 402 return debuggerInsertNops() && debuggerReserveRegs() && 403 debuggerEmitPrologue(); 404 } 405 406 bool debuggerInsertNops() const { 407 return DebuggerInsertNops; 408 } 409 410 bool debuggerReserveRegs() const { 411 return DebuggerReserveRegs; 412 } 413 414 bool debuggerEmitPrologue() const { 415 return DebuggerEmitPrologue; 416 } 417 418 bool loadStoreOptEnabled() const { 419 return EnableLoadStoreOpt; 420 } 421 422 bool hasSGPRInitBug() const { 423 return SGPRInitBug; 424 } 425 }; 426 427 428 inline const AMDGPUInstrInfo *AMDGPUSubtarget::getInstrInfo() const { 429 if (getGeneration() >= SOUTHERN_ISLANDS) 430 return static_cast<const SISubtarget *>(this)->getInstrInfo(); 431 432 return static_cast<const R600Subtarget *>(this)->getInstrInfo(); 433 } 434 435 inline const AMDGPUFrameLowering *AMDGPUSubtarget::getFrameLowering() const { 436 if (getGeneration() >= SOUTHERN_ISLANDS) 437 return static_cast<const SISubtarget *>(this)->getFrameLowering(); 438 439 return static_cast<const R600Subtarget *>(this)->getFrameLowering(); 440 } 441 442 inline const AMDGPUTargetLowering *AMDGPUSubtarget::getTargetLowering() const { 443 if (getGeneration() >= SOUTHERN_ISLANDS) 444 return static_cast<const SISubtarget *>(this)->getTargetLowering(); 445 446 return static_cast<const R600Subtarget *>(this)->getTargetLowering(); 447 } 448 449 inline const AMDGPURegisterInfo *AMDGPUSubtarget::getRegisterInfo() const { 450 if (getGeneration() >= SOUTHERN_ISLANDS) 451 return static_cast<const SISubtarget *>(this)->getRegisterInfo(); 452 453 return static_cast<const R600Subtarget *>(this)->getRegisterInfo(); 454 } 455 456 } // End namespace llvm 457 458 #endif 459