• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //==- AMDGPUArgumentrUsageInfo.h - Function Arg Usage Info -------*- 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 #ifndef LLVM_LIB_TARGET_AMDGPU_AMDGPUARGUMENTUSAGEINFO_H
10 #define LLVM_LIB_TARGET_AMDGPU_AMDGPUARGUMENTUSAGEINFO_H
11 
12 #include "llvm/ADT/DenseMap.h"
13 #include "llvm/CodeGen/Register.h"
14 #include "llvm/IR/Function.h"
15 #include "llvm/Pass.h"
16 
17 namespace llvm {
18 
19 class Function;
20 class raw_ostream;
21 class GCNSubtarget;
22 class TargetMachine;
23 class TargetRegisterClass;
24 class TargetRegisterInfo;
25 
26 struct ArgDescriptor {
27 private:
28   friend struct AMDGPUFunctionArgInfo;
29   friend class AMDGPUArgumentUsageInfo;
30 
31   union {
32     Register Reg;
33     unsigned StackOffset;
34   };
35 
36   // Bitmask to locate argument within the register.
37   unsigned Mask;
38 
39   bool IsStack : 1;
40   bool IsSet : 1;
41 
42 public:
43   ArgDescriptor(unsigned Val = 0, unsigned Mask = ~0u,
44                 bool IsStack = false, bool IsSet = false)
RegArgDescriptor45     : Reg(Val), Mask(Mask), IsStack(IsStack), IsSet(IsSet) {}
46 
47   static ArgDescriptor createRegister(Register Reg, unsigned Mask = ~0u) {
48     return ArgDescriptor(Reg, Mask, false, true);
49   }
50 
51   static ArgDescriptor createStack(unsigned Offset, unsigned Mask = ~0u) {
52     return ArgDescriptor(Offset, Mask, true, true);
53   }
54 
createArgArgDescriptor55   static ArgDescriptor createArg(const ArgDescriptor &Arg, unsigned Mask) {
56     return ArgDescriptor(Arg.Reg, Mask, Arg.IsStack, Arg.IsSet);
57   }
58 
isSetArgDescriptor59   bool isSet() const {
60     return IsSet;
61   }
62 
63   explicit operator bool() const {
64     return isSet();
65   }
66 
isRegisterArgDescriptor67   bool isRegister() const {
68     return !IsStack;
69   }
70 
getRegisterArgDescriptor71   Register getRegister() const {
72     assert(!IsStack);
73     return Reg;
74   }
75 
getStackOffsetArgDescriptor76   unsigned getStackOffset() const {
77     assert(IsStack);
78     return StackOffset;
79   }
80 
getMaskArgDescriptor81   unsigned getMask() const {
82     return Mask;
83   }
84 
isMaskedArgDescriptor85   bool isMasked() const {
86     return Mask != ~0u;
87   }
88 
89   void print(raw_ostream &OS, const TargetRegisterInfo *TRI = nullptr) const;
90 };
91 
92 inline raw_ostream &operator<<(raw_ostream &OS, const ArgDescriptor &Arg) {
93   Arg.print(OS);
94   return OS;
95 }
96 
97 struct AMDGPUFunctionArgInfo {
98   enum PreloadedValue {
99     // SGPRS:
100     PRIVATE_SEGMENT_BUFFER = 0,
101     DISPATCH_PTR        =  1,
102     QUEUE_PTR           =  2,
103     KERNARG_SEGMENT_PTR =  3,
104     DISPATCH_ID         =  4,
105     FLAT_SCRATCH_INIT   =  5,
106     WORKGROUP_ID_X      = 10,
107     WORKGROUP_ID_Y      = 11,
108     WORKGROUP_ID_Z      = 12,
109     PRIVATE_SEGMENT_WAVE_BYTE_OFFSET = 14,
110     IMPLICIT_BUFFER_PTR = 15,
111     IMPLICIT_ARG_PTR = 16,
112 
113     // VGPRS:
114     WORKITEM_ID_X       = 17,
115     WORKITEM_ID_Y       = 18,
116     WORKITEM_ID_Z       = 19,
117     FIRST_VGPR_VALUE    = WORKITEM_ID_X
118   };
119 
120   // Kernel input registers setup for the HSA ABI in allocation order.
121 
122   // User SGPRs in kernels
123   // XXX - Can these require argument spills?
124   ArgDescriptor PrivateSegmentBuffer;
125   ArgDescriptor DispatchPtr;
126   ArgDescriptor QueuePtr;
127   ArgDescriptor KernargSegmentPtr;
128   ArgDescriptor DispatchID;
129   ArgDescriptor FlatScratchInit;
130   ArgDescriptor PrivateSegmentSize;
131 
132   // System SGPRs in kernels.
133   ArgDescriptor WorkGroupIDX;
134   ArgDescriptor WorkGroupIDY;
135   ArgDescriptor WorkGroupIDZ;
136   ArgDescriptor WorkGroupInfo;
137   ArgDescriptor PrivateSegmentWaveByteOffset;
138 
139   // Pointer with offset from kernargsegmentptr to where special ABI arguments
140   // are passed to callable functions.
141   ArgDescriptor ImplicitArgPtr;
142 
143   // Input registers for non-HSA ABI
144   ArgDescriptor ImplicitBufferPtr = 0;
145 
146   // VGPRs inputs. These are always v0, v1 and v2 for entry functions.
147   ArgDescriptor WorkItemIDX;
148   ArgDescriptor WorkItemIDY;
149   ArgDescriptor WorkItemIDZ;
150 
151   std::pair<const ArgDescriptor *, const TargetRegisterClass *>
152   getPreloadedValue(PreloadedValue Value) const;
153 };
154 
155 class AMDGPUArgumentUsageInfo : public ImmutablePass {
156 private:
157   static const AMDGPUFunctionArgInfo ExternFunctionInfo;
158   DenseMap<const Function *, AMDGPUFunctionArgInfo> ArgInfoMap;
159 
160 public:
161   static char ID;
162 
AMDGPUArgumentUsageInfo()163   AMDGPUArgumentUsageInfo() : ImmutablePass(ID) { }
164 
getAnalysisUsage(AnalysisUsage & AU)165   void getAnalysisUsage(AnalysisUsage &AU) const override {
166     AU.setPreservesAll();
167   }
168 
169   bool doInitialization(Module &M) override;
170   bool doFinalization(Module &M) override;
171 
172   void print(raw_ostream &OS, const Module *M = nullptr) const override;
173 
setFuncArgInfo(const Function & F,const AMDGPUFunctionArgInfo & ArgInfo)174   void setFuncArgInfo(const Function &F, const AMDGPUFunctionArgInfo &ArgInfo) {
175     ArgInfoMap[&F] = ArgInfo;
176   }
177 
lookupFuncArgInfo(const Function & F)178   const AMDGPUFunctionArgInfo &lookupFuncArgInfo(const Function &F) const {
179     auto I = ArgInfoMap.find(&F);
180     if (I == ArgInfoMap.end()) {
181       assert(F.isDeclaration());
182       return ExternFunctionInfo;
183     }
184 
185     return I->second;
186   }
187 };
188 
189 } // end namespace llvm
190 
191 #endif
192