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