1 /*========================== begin_copyright_notice ============================
2 
3 Copyright (C) 2020-2021 Intel Corporation
4 
5 SPDX-License-Identifier: MIT
6 
7 ============================= end_copyright_notice ===========================*/
8 
9 #ifndef VCOPT_LIB_GENXCODEGEN_GENXOCLRUNTIMEINFO_H
10 #define VCOPT_LIB_GENXCODEGEN_GENXOCLRUNTIMEINFO_H
11 
12 #include "vc/GenXOpts/Utils/KernelInfo.h"
13 #include "vc/Support/BackendConfig.h"
14 
15 #include "llvm/ADT/Optional.h"
16 #include "llvm/Pass.h"
17 
18 #include "JitterDataStruct.h"
19 #include "RelocationInfo.h"
20 
21 #include <cstdint>
22 #include <map>
23 
24 #include "Probe/Assertion.h"
25 
26 namespace llvm {
27 class Function;
28 
29 class FunctionGroup;
30 class GenXSubtarget;
31 
32 class KernelArgBuilder;
33 
34 void initializeGenXOCLRuntimeInfoPass(PassRegistry &PR);
35 
36 class GenXOCLRuntimeInfo : public ModulePass {
37 public:
38   class KernelArgInfo {
39     friend class KernelArgBuilder;
40 
41   public:
42     enum class KindType {
43       General,
44       LocalSize,
45       GroupCount,
46       Buffer,
47       SVM,
48       Sampler,
49       Image1D,
50       Image1DArray,
51       Image2D,
52       Image2DArray,
53       Image2DMediaBlock,
54       Image3D,
55       PrintBuffer,
56       PrivateBase,
57       ByValSVM,
58       BindlessBuffer,
59     };
60 
61     enum class AccessKindType { None, ReadOnly, WriteOnly, ReadWrite };
62 
63   private:
64     unsigned Index;
65     KindType Kind;
66     AccessKindType AccessKind;
67     unsigned Offset;
68     unsigned OffsetInArg; // Implicit arguments may be mapped to some part of an
69                           // explicit argument. This field shows offset in the
70                           // explicit arg.
71     unsigned SizeInBytes;
72     unsigned BTI;
73 
74   private:
75     KernelArgInfo() = default;
76 
77   public:
getIndex()78     unsigned getIndex() const { return Index; }
getKind()79     KindType getKind() const { return Kind; }
getAccessKind()80     AccessKindType getAccessKind() const { return AccessKind; }
getOffset()81     unsigned getOffset() const { return Offset; }
getSizeInBytes()82     unsigned getSizeInBytes() const { return SizeInBytes; }
getBTI()83     unsigned getBTI() const { return BTI; }
getOffsetInArg()84     unsigned getOffsetInArg() const { return OffsetInArg; }
85 
isImage()86     bool isImage() const {
87       switch (Kind) {
88       case KindType::Image1D:
89       case KindType::Image1DArray:
90       case KindType::Image2D:
91       case KindType::Image2DArray:
92       case KindType::Image2DMediaBlock:
93       case KindType::Image3D:
94         return true;
95       default:
96         return false;
97       }
98     }
99 
isResource()100     bool isResource() const {
101       if (Kind == KindType::Buffer || Kind == KindType::SVM)
102         return true;
103       return isImage();
104     }
105 
isWritable()106     bool isWritable() const {
107       IGC_ASSERT_MESSAGE(isResource(),
108                          "Only resources can have writable property");
109       return AccessKind != AccessKindType::ReadOnly;
110     }
111   };
112 
113   struct TableInfo {
114     void *Buffer = nullptr;
115     unsigned Size = 0;
116     unsigned Entries = 0;
117   };
118 
119   // Symbols and reloacations are collected in zebin format. Later they are
120   // translated into legacy format for patch token generation.
121   using SymbolSeq = std::vector<vISA::ZESymEntry>;
122   using RelocationSeq = std::vector<vISA::ZERelocEntry>;
123 
124   struct DataInfo {
125     std::vector<uint8_t> Buffer;
126     int Alignment = 0;
127     // Runtime can allocate bigger zeroed out buffer, and fill only
128     // the first part of it with the data from Buffer field. So there's no
129     // need to fill Buffer with zero, one can just set AdditionalZeroedSpace,
130     // and it will be additionally allocated. The size is in bytes.
131     std::size_t AdditionalZeroedSpace = 0;
132 
clearDataInfo133     void clear() {
134       Buffer.clear();
135       Alignment = 0;
136       AdditionalZeroedSpace = 0;
137     }
138   };
139 
140   struct SectionInfo {
141     DataInfo Data;
142     // Symbols inside this section. Symbol offsets must be in bounds of
143     // \p Data.
144     SymbolSeq Symbols;
145     // Relocations inside this section. "Inside" means that relocation/patching
146     // happens inside this section a relocated symbol itself may refer to any
147     // section, including the current one.
148     RelocationSeq Relocations;
149 
clearSectionInfo150     void clear() {
151       Data.clear();
152       Symbols.clear();
153       Relocations.clear();
154     }
155   };
156 
157   // Additional kernel info that are not provided by finalizer
158   // but still required for runtime.
159   struct KernelInfo {
160     SectionInfo Func;
161     // Duplicates Func.Relocations. Cannot unify it on VC side since the
162     // duplication happens on Finalizer side.
163     TableInfo LegacyFuncRelocations;
164 
165   private:
166     std::string Name;
167 
168     bool UsesGroupId = false;
169     bool UsesDPAS = false;
170 
171     // Jitter info contains similar field.
172     // Whom should we believe?
173     bool UsesBarriers = false;
174 
175     bool UsesReadWriteImages = false;
176 
177     bool SupportsDebugging = false;
178 
179     unsigned SLMSize = 0;
180     unsigned ThreadPrivateMemSize = 0;
181     unsigned StatelessPrivateMemSize = 0;
182 
183     unsigned GRFSizeInBytes;
184 
185     using ArgInfoStorageTy = std::vector<KernelArgInfo>;
186     using PrintStringStorageTy = std::vector<std::string>;
187     ArgInfoStorageTy ArgInfos;
188     PrintStringStorageTy PrintStrings;
189 
190   private:
191     void setInstructionUsageProperties(const FunctionGroup &FG,
192                                        const GenXBackendConfig &BC);
193     void setMetadataProperties(genx::KernelMetadata &KM,
194                                const GenXSubtarget &ST);
195     void setArgumentProperties(const Function &Kernel,
196                                const genx::KernelMetadata &KM,
197                                const GenXSubtarget &ST,
198                                const GenXBackendConfig &BC);
199     void setPrintStrings(const Module &KernelModule);
200 
201   public:
202     using arg_iterator = ArgInfoStorageTy::iterator;
203     using arg_const_iterator = ArgInfoStorageTy::const_iterator;
204     using arg_size_type = ArgInfoStorageTy::size_type;
205 
206   public:
207     // Creates kernel info for empty kernel.
208     KernelInfo(const GenXSubtarget &ST);
209     // Creates kernel info for given function group.
210     KernelInfo(const FunctionGroup &FG, const GenXSubtarget &ST,
211                const GenXBackendConfig &BC);
212 
getNameKernelInfo213     const std::string &getName() const { return Name; }
214 
215     // These are considered to always be true (at least in igcmc).
216     // Preserve this here.
usesLocalIdXKernelInfo217     bool usesLocalIdX() const { return true; }
usesLocalIdYKernelInfo218     bool usesLocalIdY() const { return true; }
usesLocalIdZKernelInfo219     bool usesLocalIdZ() const { return true; }
220 
221     // Deduced from actual function instructions.
usesGroupIdKernelInfo222     bool usesGroupId() const { return UsesGroupId; }
223 
supportsDebuggingKernelInfo224     bool supportsDebugging() const { return SupportsDebugging; }
225 
226     // SIMD size is always set by igcmc to one. Preserve this here.
getSIMDSizeKernelInfo227     unsigned getSIMDSize() const { return 1; }
getSLMSizeKernelInfo228     unsigned getSLMSize() const { return SLMSize; }
229 
230     // Deduced from actual function instructions.
getTPMSizeKernelInfo231     unsigned getTPMSize() const { return ThreadPrivateMemSize; }
getStatelessPrivMemSizeKernelInfo232     unsigned getStatelessPrivMemSize() const { return StatelessPrivateMemSize; }
233 
getGRFSizeInBytesKernelInfo234     unsigned getGRFSizeInBytes() const { return GRFSizeInBytes; }
235 
236     // Deduced from actual function instructions.
usesDPASKernelInfo237     bool usesDPAS() const { return UsesDPAS; }
238 
usesBarriersKernelInfo239     bool usesBarriers() const { return UsesBarriers; }
usesReadWriteImagesKernelInfo240     bool usesReadWriteImages() const { return UsesReadWriteImages; }
241 
242     // Arguments accessors.
arg_beginKernelInfo243     arg_iterator arg_begin() { return ArgInfos.begin(); }
arg_endKernelInfo244     arg_iterator arg_end() { return ArgInfos.end(); }
arg_beginKernelInfo245     arg_const_iterator arg_begin() const { return ArgInfos.begin(); }
arg_endKernelInfo246     arg_const_iterator arg_end() const { return ArgInfos.end(); }
argsKernelInfo247     iterator_range<arg_iterator> args() { return {arg_begin(), arg_end()}; }
argsKernelInfo248     iterator_range<arg_const_iterator> args() const {
249       return {arg_begin(), arg_end()};
250     }
arg_sizeKernelInfo251     arg_size_type arg_size() const { return ArgInfos.size(); }
arg_emptyKernelInfo252     bool arg_empty() const { return ArgInfos.empty(); }
getPrintStringsKernelInfo253     const PrintStringStorageTy &getPrintStrings() const { return PrintStrings; }
254   };
255 
256   using GTPinInfo = std::vector<char>;
257 
258   class CompiledKernel {
259     KernelInfo CompilerInfo;
260     FINALIZER_INFO JitterInfo;
261     GTPinInfo GtpinInfo;
262     std::vector<char> DebugInfo;
263 
264   public:
265     CompiledKernel(KernelInfo &&KI, const FINALIZER_INFO &JI,
266                    const GTPinInfo &GI, std::vector<char> DebugInfo);
267 
getKernelInfo()268     const KernelInfo &getKernelInfo() const { return CompilerInfo; }
getJitterInfo()269     const FINALIZER_INFO &getJitterInfo() const { return JitterInfo; }
getGTPinInfo()270     const GTPinInfo &getGTPinInfo() const { return GtpinInfo; }
getGenBinary()271     const std::vector<uint8_t> &getGenBinary() const {
272       return CompilerInfo.Func.Data.Buffer;
273     }
getDebugInfo()274     const std::vector<char> &getDebugInfo() const { return DebugInfo; }
275   };
276 
277   struct ModuleInfoT {
278     SectionInfo Constant;
279     SectionInfo Global;
280 
clearModuleInfoT281     void clear() {
282       Constant.clear();
283       Global.clear();
284     }
285   };
286 
287   struct CompiledModuleT {
288     using KernelStorageTy = std::vector<CompiledKernel>;
289     ModuleInfoT ModuleInfo;
290     KernelStorageTy Kernels;
291     unsigned PointerSizeInBytes = 0;
292 
clearCompiledModuleT293     void clear() {
294       ModuleInfo.clear();
295       Kernels.clear();
296       PointerSizeInBytes = 0;
297     }
298   };
299 
300 public:
301   using KernelStorageTy = CompiledModuleT::KernelStorageTy;
302 
303   using kernel_iterator = KernelStorageTy::iterator;
304   using kernel_const_iterator = KernelStorageTy::const_iterator;
305   using kernel_size_type = KernelStorageTy::size_type;
306 
307 private:
308   CompiledModuleT CompiledModule;
309 
310 public:
311   static char ID;
312 
GenXOCLRuntimeInfo()313   GenXOCLRuntimeInfo() : ModulePass(ID) {
314     initializeGenXOCLRuntimeInfoPass(*PassRegistry::getPassRegistry());
315   }
316 
getPassName()317   StringRef getPassName() const override { return "GenX OCL Runtime Info"; }
318 
319   void getAnalysisUsage(AnalysisUsage &AU) const override;
320   bool runOnModule(Module &M) override;
321 
releaseMemory()322   void releaseMemory() override { CompiledModule.clear(); }
323   void print(raw_ostream &OS, const Module *M) const override;
324 
325   // Move compiled kernels out of this pass.
stealCompiledModule()326   CompiledModuleT stealCompiledModule() { return std::move(CompiledModule); }
327 
328   // Kernel descriptor accessors.
kernel_begin()329   kernel_iterator kernel_begin() { return CompiledModule.Kernels.begin(); }
kernel_end()330   kernel_iterator kernel_end() { return CompiledModule.Kernels.end(); }
kernel_begin()331   kernel_const_iterator kernel_begin() const {
332     return CompiledModule.Kernels.begin();
333   }
kernel_end()334   kernel_const_iterator kernel_end() const {
335     return CompiledModule.Kernels.end();
336   }
kernels()337   iterator_range<kernel_iterator> kernels() {
338     return {kernel_begin(), kernel_end()};
339   }
kernels()340   iterator_range<kernel_const_iterator> kernels() const {
341     return {kernel_begin(), kernel_end()};
342   }
kernel_size()343   kernel_size_type kernel_size() const { return CompiledModule.Kernels.size(); }
kernel_empty()344   bool kernel_empty() const { return CompiledModule.Kernels.empty(); }
345 };
346 
347 ModulePass *
348 createGenXOCLInfoExtractorPass(GenXOCLRuntimeInfo::CompiledModuleT &Dest);
349 } // namespace llvm
350 
351 #endif
352