1 //===-- AMDGPUSubtarget.cpp - AMDGPU Subtarget Information ----------------===// 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 Implements the AMDGPU specific subclass of TargetSubtarget. 12 // 13 //===----------------------------------------------------------------------===// 14 15 #include "AMDGPUSubtarget.h" 16 #include "R600ISelLowering.h" 17 #include "R600InstrInfo.h" 18 #include "SIFrameLowering.h" 19 #include "SIISelLowering.h" 20 #include "SIInstrInfo.h" 21 #include "SIMachineFunctionInfo.h" 22 #include "llvm/ADT/SmallString.h" 23 #include "llvm/CodeGen/MachineScheduler.h" 24 25 using namespace llvm; 26 27 #define DEBUG_TYPE "amdgpu-subtarget" 28 29 #define GET_SUBTARGETINFO_ENUM 30 #define GET_SUBTARGETINFO_TARGET_DESC 31 #define GET_SUBTARGETINFO_CTOR 32 #include "AMDGPUGenSubtargetInfo.inc" 33 34 AMDGPUSubtarget::~AMDGPUSubtarget() {} 35 36 AMDGPUSubtarget & 37 AMDGPUSubtarget::initializeSubtargetDependencies(const Triple &TT, 38 StringRef GPU, StringRef FS) { 39 // Determine default and user-specified characteristics 40 // On SI+, we want FP64 denormals to be on by default. FP32 denormals can be 41 // enabled, but some instructions do not respect them and they run at the 42 // double precision rate, so don't enable by default. 43 // 44 // We want to be able to turn these off, but making this a subtarget feature 45 // for SI has the unhelpful behavior that it unsets everything else if you 46 // disable it. 47 48 SmallString<256> FullFS("+promote-alloca,+fp64-denormals,+load-store-opt,"); 49 if (isAmdHsaOS()) // Turn on FlatForGlobal for HSA. 50 FullFS += "+flat-for-global,+unaligned-buffer-access,"; 51 FullFS += FS; 52 53 ParseSubtargetFeatures(GPU, FullFS); 54 55 // FIXME: I don't think think Evergreen has any useful support for 56 // denormals, but should be checked. Should we issue a warning somewhere 57 // if someone tries to enable these? 58 if (getGeneration() <= AMDGPUSubtarget::NORTHERN_ISLANDS) { 59 FP32Denormals = false; 60 FP64Denormals = false; 61 } 62 63 // Set defaults if needed. 64 if (MaxPrivateElementSize == 0) 65 MaxPrivateElementSize = 4; 66 67 return *this; 68 } 69 70 AMDGPUSubtarget::AMDGPUSubtarget(const Triple &TT, StringRef GPU, StringRef FS, 71 const TargetMachine &TM) 72 : AMDGPUGenSubtargetInfo(TT, GPU, FS), 73 TargetTriple(TT), 74 Gen(TT.getArch() == Triple::amdgcn ? SOUTHERN_ISLANDS : R600), 75 IsaVersion(ISAVersion0_0_0), 76 WavefrontSize(64), 77 LocalMemorySize(0), 78 LDSBankCount(0), 79 MaxPrivateElementSize(0), 80 81 FastFMAF32(false), 82 HalfRate64Ops(false), 83 84 FP32Denormals(false), 85 FP64Denormals(false), 86 FPExceptions(false), 87 FlatForGlobal(false), 88 UnalignedScratchAccess(false), 89 UnalignedBufferAccess(false), 90 91 EnableXNACK(false), 92 DebuggerInsertNops(false), 93 DebuggerReserveRegs(false), 94 DebuggerEmitPrologue(false), 95 96 EnableVGPRSpilling(false), 97 EnablePromoteAlloca(false), 98 EnableLoadStoreOpt(false), 99 EnableUnsafeDSOffsetFolding(false), 100 EnableSIScheduler(false), 101 DumpCode(false), 102 103 FP64(false), 104 IsGCN(false), 105 GCN1Encoding(false), 106 GCN3Encoding(false), 107 CIInsts(false), 108 SGPRInitBug(false), 109 HasSMemRealTime(false), 110 Has16BitInsts(false), 111 HasMovrel(false), 112 HasVGPRIndexMode(false), 113 HasScalarStores(false), 114 HasInv2PiInlineImm(false), 115 FlatAddressSpace(false), 116 117 R600ALUInst(false), 118 CaymanISA(false), 119 CFALUBug(false), 120 HasVertexCache(false), 121 TexVTXClauseSize(0), 122 123 FeatureDisable(false), 124 InstrItins(getInstrItineraryForCPU(GPU)), 125 TSInfo() { 126 initializeSubtargetDependencies(TT, GPU, FS); 127 } 128 129 // FIXME: These limits are for SI. Did they change with the larger maximum LDS 130 // size? 131 unsigned AMDGPUSubtarget::getMaxLocalMemSizeWithWaveCount(unsigned NWaves) const { 132 switch (NWaves) { 133 case 10: 134 return 1638; 135 case 9: 136 return 1820; 137 case 8: 138 return 2048; 139 case 7: 140 return 2340; 141 case 6: 142 return 2730; 143 case 5: 144 return 3276; 145 case 4: 146 return 4096; 147 case 3: 148 return 5461; 149 case 2: 150 return 8192; 151 default: 152 return getLocalMemorySize(); 153 } 154 } 155 156 unsigned AMDGPUSubtarget::getOccupancyWithLocalMemSize(uint32_t Bytes) const { 157 if (Bytes <= 1638) 158 return 10; 159 160 if (Bytes <= 1820) 161 return 9; 162 163 if (Bytes <= 2048) 164 return 8; 165 166 if (Bytes <= 2340) 167 return 7; 168 169 if (Bytes <= 2730) 170 return 6; 171 172 if (Bytes <= 3276) 173 return 5; 174 175 if (Bytes <= 4096) 176 return 4; 177 178 if (Bytes <= 5461) 179 return 3; 180 181 if (Bytes <= 8192) 182 return 2; 183 184 return 1; 185 } 186 187 std::pair<unsigned, unsigned> AMDGPUSubtarget::getFlatWorkGroupSizes( 188 const Function &F) const { 189 190 // Default minimum/maximum flat work group sizes. 191 std::pair<unsigned, unsigned> Default = 192 AMDGPU::isCompute(F.getCallingConv()) ? 193 std::pair<unsigned, unsigned>(getWavefrontSize() * 2, 194 getWavefrontSize() * 4) : 195 std::pair<unsigned, unsigned>(1, getWavefrontSize()); 196 197 // TODO: Do not process "amdgpu-max-work-group-size" attribute once mesa 198 // starts using "amdgpu-flat-work-group-size" attribute. 199 Default.second = AMDGPU::getIntegerAttribute( 200 F, "amdgpu-max-work-group-size", Default.second); 201 Default.first = std::min(Default.first, Default.second); 202 203 // Requested minimum/maximum flat work group sizes. 204 std::pair<unsigned, unsigned> Requested = AMDGPU::getIntegerPairAttribute( 205 F, "amdgpu-flat-work-group-size", Default); 206 207 // Make sure requested minimum is less than requested maximum. 208 if (Requested.first > Requested.second) 209 return Default; 210 211 // Make sure requested values do not violate subtarget's specifications. 212 if (Requested.first < getMinFlatWorkGroupSize()) 213 return Default; 214 if (Requested.second > getMaxFlatWorkGroupSize()) 215 return Default; 216 217 return Requested; 218 } 219 220 std::pair<unsigned, unsigned> AMDGPUSubtarget::getWavesPerEU( 221 const Function &F) const { 222 223 // Default minimum/maximum number of waves per execution unit. 224 std::pair<unsigned, unsigned> Default(1, 0); 225 226 // Default/requested minimum/maximum flat work group sizes. 227 std::pair<unsigned, unsigned> FlatWorkGroupSizes = getFlatWorkGroupSizes(F); 228 229 // If minimum/maximum flat work group sizes were explicitly requested using 230 // "amdgpu-flat-work-group-size" attribute, then set default minimum/maximum 231 // number of waves per execution unit to values implied by requested 232 // minimum/maximum flat work group sizes. 233 unsigned MinImpliedByFlatWorkGroupSize = 234 getMaxWavesPerEU(FlatWorkGroupSizes.second); 235 bool RequestedFlatWorkGroupSize = false; 236 237 // TODO: Do not process "amdgpu-max-work-group-size" attribute once mesa 238 // starts using "amdgpu-flat-work-group-size" attribute. 239 if (F.hasFnAttribute("amdgpu-max-work-group-size") || 240 F.hasFnAttribute("amdgpu-flat-work-group-size")) { 241 Default.first = MinImpliedByFlatWorkGroupSize; 242 RequestedFlatWorkGroupSize = true; 243 } 244 245 // Requested minimum/maximum number of waves per execution unit. 246 std::pair<unsigned, unsigned> Requested = AMDGPU::getIntegerPairAttribute( 247 F, "amdgpu-waves-per-eu", Default, true); 248 249 // Make sure requested minimum is less than requested maximum. 250 if (Requested.second && Requested.first > Requested.second) 251 return Default; 252 253 // Make sure requested values do not violate subtarget's specifications. 254 if (Requested.first < getMinWavesPerEU() || 255 Requested.first > getMaxWavesPerEU()) 256 return Default; 257 if (Requested.second > getMaxWavesPerEU()) 258 return Default; 259 260 // Make sure requested values are compatible with values implied by requested 261 // minimum/maximum flat work group sizes. 262 if (RequestedFlatWorkGroupSize && 263 Requested.first > MinImpliedByFlatWorkGroupSize) 264 return Default; 265 266 return Requested; 267 } 268 269 R600Subtarget::R600Subtarget(const Triple &TT, StringRef GPU, StringRef FS, 270 const TargetMachine &TM) : 271 AMDGPUSubtarget(TT, GPU, FS, TM), 272 InstrInfo(*this), 273 FrameLowering(TargetFrameLowering::StackGrowsUp, getStackAlignment(), 0), 274 TLInfo(TM, *this) {} 275 276 SISubtarget::SISubtarget(const Triple &TT, StringRef GPU, StringRef FS, 277 const TargetMachine &TM) : 278 AMDGPUSubtarget(TT, GPU, FS, TM), 279 InstrInfo(*this), 280 FrameLowering(TargetFrameLowering::StackGrowsUp, getStackAlignment(), 0), 281 TLInfo(TM, *this), 282 GISel() {} 283 284 void SISubtarget::overrideSchedPolicy(MachineSchedPolicy &Policy, 285 unsigned NumRegionInstrs) const { 286 // Track register pressure so the scheduler can try to decrease 287 // pressure once register usage is above the threshold defined by 288 // SIRegisterInfo::getRegPressureSetLimit() 289 Policy.ShouldTrackPressure = true; 290 291 // Enabling both top down and bottom up scheduling seems to give us less 292 // register spills than just using one of these approaches on its own. 293 Policy.OnlyTopDown = false; 294 Policy.OnlyBottomUp = false; 295 296 // Enabling ShouldTrackLaneMasks crashes the SI Machine Scheduler. 297 if (!enableSIScheduler()) 298 Policy.ShouldTrackLaneMasks = true; 299 } 300 301 bool SISubtarget::isVGPRSpillingEnabled(const Function& F) const { 302 return EnableVGPRSpilling || !AMDGPU::isShader(F.getCallingConv()); 303 } 304 305 unsigned SISubtarget::getKernArgSegmentSize(unsigned ExplicitArgBytes) const { 306 unsigned ImplicitBytes = getImplicitArgNumBytes(); 307 if (ImplicitBytes == 0) 308 return ExplicitArgBytes; 309 310 unsigned Alignment = getAlignmentForImplicitArgPtr(); 311 return alignTo(ExplicitArgBytes, Alignment) + ImplicitBytes; 312 } 313 314 unsigned SISubtarget::getOccupancyWithNumSGPRs(unsigned SGPRs) const { 315 if (getGeneration() >= SISubtarget::VOLCANIC_ISLANDS) { 316 if (SGPRs <= 80) 317 return 10; 318 if (SGPRs <= 88) 319 return 9; 320 if (SGPRs <= 100) 321 return 8; 322 return 7; 323 } 324 if (SGPRs <= 48) 325 return 10; 326 if (SGPRs <= 56) 327 return 9; 328 if (SGPRs <= 64) 329 return 8; 330 if (SGPRs <= 72) 331 return 7; 332 if (SGPRs <= 80) 333 return 6; 334 return 5; 335 } 336 337 unsigned SISubtarget::getOccupancyWithNumVGPRs(unsigned VGPRs) const { 338 if (VGPRs <= 24) 339 return 10; 340 if (VGPRs <= 28) 341 return 9; 342 if (VGPRs <= 32) 343 return 8; 344 if (VGPRs <= 36) 345 return 7; 346 if (VGPRs <= 40) 347 return 6; 348 if (VGPRs <= 48) 349 return 5; 350 if (VGPRs <= 64) 351 return 4; 352 if (VGPRs <= 84) 353 return 3; 354 if (VGPRs <= 128) 355 return 2; 356 return 1; 357 } 358 359 unsigned SISubtarget::getMaxNumSGPRs() const { 360 if (hasSGPRInitBug()) 361 return SISubtarget::FIXED_SGPR_COUNT_FOR_INIT_BUG; 362 363 if (getGeneration() >= VOLCANIC_ISLANDS) 364 return 102; 365 366 return 104; 367 } 368