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