1 /*========================== begin_copyright_notice ============================
2 
3 Copyright (C) 2017-2021 Intel Corporation
4 
5 SPDX-License-Identifier: MIT
6 
7 ============================= end_copyright_notice ===========================*/
8 
9 #pragma once
10 
11 #include "Compiler/CISACodeGen/CISACodeGen.h"
12 #include "Compiler/CISACodeGen/WIAnalysis.hpp"
13 #include "Compiler/MetaDataApi/MetaDataApi.h"
14 #include "GenISAIntrinsics/GenIntrinsics.h"
15 
16 #include <vector>
17 #include <set>
18 #include <map>
19 #include <string>
20 
21 namespace llvm
22 {
23     class LLVMContext;
24     class Function;
25     class Type;
26 }
27 
28 namespace IGC
29 {
30     /// @brief  ImplicitArg is used for representing the implict information that is passed from the
31     ///         OpenCL runtime to IGC, characterize it and allow IGC to use it.
32     /// @Author Marina Yatsina
33     class ImplicitArg {
34     public:
35 
36         /// @brief  Type of implicit information passed from the OpenCL runtime
37         enum ArgType {
38             R0,
39             START_ID = R0,
40             PAYLOAD_HEADER,
41 
42             // WI information
43             WORK_DIM,
44             NUM_GROUPS,
45             GLOBAL_SIZE,
46             LOCAL_SIZE,
47             ENQUEUED_LOCAL_WORK_SIZE,
48             LOCAL_ID_X,
49             LOCAL_ID_Y,
50             LOCAL_ID_Z,
51 
52             // Pointer bases and buffers
53             CONSTANT_BASE,
54             GLOBAL_BASE,
55             PRIVATE_BASE,
56             PRINTF_BUFFER,
57 
58             // Buffer offset (for stateless to stateful optim)
59             BUFFER_OFFSET,
60 
61             // Aggregates
62             STRUCT_START,
63             CONSTANT_REG_FP32 = STRUCT_START,
64             CONSTANT_REG_QWORD,
65             CONSTANT_REG_DWORD,
66             CONSTANT_REG_WORD,
67             CONSTANT_REG_BYTE,
68             STRUCT_END = CONSTANT_REG_BYTE,
69 
70             // Images
71             IMAGES_START,
72             IMAGE_HEIGHT = IMAGES_START,
73             IMAGE_WIDTH,
74             IMAGE_DEPTH,
75             IMAGE_NUM_MIP_LEVELS,
76             IMAGE_CHANNEL_DATA_TYPE,
77             IMAGE_CHANNEL_ORDER,
78             IMAGE_SRGB_CHANNEL_ORDER,
79             IMAGE_ARRAY_SIZE,
80             IMAGE_NUM_SAMPLES,
81             SAMPLER_ADDRESS,
82             SAMPLER_NORMALIZED,
83             SAMPLER_SNAP_WA,
84             FLAT_IMAGE_BASEOFFSET,
85             FLAT_IMAGE_HEIGHT,
86             FLAT_IMAGE_WIDTH,
87             FLAT_IMAGE_PITCH,
88             IMAGES_END = FLAT_IMAGE_PITCH,
89 
90             // VME
91             VME_MB_BLOCK_TYPE,
92             VME_SUBPIXEL_MODE,
93             VME_SAD_ADJUST_MODE,
94             VME_SEARCH_PATH_TYPE,
95 
96             // Device Enqueue
97             DEVICE_ENQUEUE_DEFAULT_DEVICE_QUEUE,
98             DEVICE_ENQUEUE_EVENT_POOL,
99             DEVICE_ENQUEUE_MAX_WORKGROUP_SIZE,
100             DEVICE_ENQUEUE_PARENT_EVENT,
101             DEVICE_ENQUEUE_PREFERED_WORKGROUP_MULTIPLE,
102             GET_OBJECT_ID,
103             GET_BLOCK_SIMD_SIZE,
104 
105             // GAS
106             LOCAL_MEMORY_STATELESS_WINDOW_START_ADDRESS,
107             LOCAL_MEMORY_STATELESS_WINDOW_SIZE,
108             PRIVATE_MEMORY_STATELESS_SIZE,
109 
110             STAGE_IN_GRID_ORIGIN,
111             STAGE_IN_GRID_SIZE,
112 
113             SYNC_BUFFER,
114 
115             // Bindless buffer (for stateless to bindless optim)
116             BINDLESS_OFFSET,
117 
118             // Pointer to implicit arguments prepared by runtime
119             IMPLICIT_ARG_BUFFER_PTR,
120 
121             // Inlined local id buffer prepared by runtime
122             IMPLICIT_ARG_LOCALID,
123 
124             NUM_IMPLICIT_ARGS
125         };
126 
127         /// @brief This set type is used to contain function arguments
128         typedef std::set<int> ArgValSet;
129 
130         /// @brief This map type is used to map implicit argument types to
131         ///        sets that contain the relevant Values.
132         typedef std::map<ImplicitArg::ArgType, ArgValSet> ArgMap;
133 
134         typedef std::pair<ImplicitArg::ArgType, unsigned int> StructArgElement;
135         typedef std::vector<StructArgElement> StructArgList;
136 
137         /// @brief  LLVM Type
138         enum ValType {
139             BYTE,
140             SHORT,
141             INT,
142             LONG,
143             FP32,
144             CONSTPTR,
145             PRIVATEPTR,
146             GLOBALPTR
147         };
148 
149         enum ValAlign {
150             ALIGN_QWORD,
151             ALIGN_DWORD,
152             ALIGN_GRF,
153             ALIGN_PTR
154         };
155 
156         ImplicitArg(
157             const ArgType&                  argType,
158             const std::string&              name,
159             const ValType                   valType,
160             WIAnalysis::WIDependancy        dependency,
161             unsigned int                    nbElement,
162             ValAlign                        align,
163             bool                            isConstantBuf);
164 
165         ImplicitArg(
166             const ArgType& argType,
167             const std::string& name,
168             const ValType                   valType,
169             WIAnalysis::WIDependancy        dependency,
170             unsigned int                    nbElement,
171             ValAlign                        align,
172             bool                            isConstantBuf,
173             llvm::GenISAIntrinsic::ID       GenIntrinsicID);
174 
175         /// @brief  Getter functions
176         ArgType                         getArgType() const;
177         const std::string&              getName() const;
178         llvm::Type*                     getLLVMType(llvm::LLVMContext& context) const;
179         WIAnalysis::WIDependancy        getDependency() const;
180         unsigned int                    getAllocateSize(const llvm::DataLayout& DL) const;
181         unsigned int                    getNumberElements() const;
182         VISA_Type                       getVISAType(const llvm::DataLayout& DL) const;
183         IGC::e_alignment                getAlignType(const llvm::DataLayout& DL) const;
184         size_t                          getAlignment(const llvm::DataLayout& DL) const;
185         unsigned int                    getPointerSize(const llvm::DataLayout& DL) const;
186         bool                            isConstantBuf() const;
187         bool                            isLocalIDs() const;
188         llvm::GenISAIntrinsic::ID       getGenIntrinsicID() const;
189 
190     private:
191         const ArgType                   m_argType;
192         const std::string               m_name;
193         const ValType                   m_valType;
194         const WIAnalysis::WIDependancy  m_dependency;
195         const unsigned int              m_nbElement;
196         const ValAlign                  m_align;
197         const bool                      m_isConstantBuf;
198         const llvm::GenISAIntrinsic::ID m_GenIntrinsicID;
199     };
200 
201     /// @brief  ImplicitArgs is used for accessing the actual implict information that is passed from
202     ///         the OpenCL runtime to IGC.
203     /// @Author Marina Yatsina
204     class ImplicitArgs {
205     public:
206         // Constructors
ImplicitArgs()207         ImplicitArgs() {}
208 
209         /// @brief  Constructor.
210         ///         Constructs the function's implicit arguments based on the given function's metadata
211         ///         It actually constructs a mapping to a subset of IMPLICIT_ARGS
212         /// @param  func the function to get impilcit args for.
213         /// @param  the metadata utils object
214         ImplicitArgs(const llvm::Function& func, const IGCMD::MetaDataUtils* pMdUtils);
215 
216         /// @brief  Returns the number of implicit arguments that are passed from the runtime
217         /// @return The number of implicit arguments
218         unsigned int size() const;
219 
220         /// @brief  Returns the i-th implicit argument
221         /// @param  i               The implicit argument index
222         /// @return The i-th implicit argument
223         const ImplicitArg& operator[](unsigned int i) const;
224 
225         /// @brief  Returns the index of the appropriate implicit argument based on the given argument type
226         /// @param  argType         The implicit argument type
227         /// @return The implicit argument's index for a given argument type
228         unsigned int getArgIndex(ImplicitArg::ArgType argType) const;
229 
230         /// @brief  Returns the index of the appropriate implicit image or sampler argument
231         ///         based on the given argument type and the associated image argument
232         /// @param  argType         The implicit argument type
233         ///                         (height/width/depth for images, normalized/address/snapwa for samplers)
234         /// @param  image           The associated image/sampler argument
235         /// @return The implicit argument's index for a given argument type
236         unsigned int getImageArgIndex(ImplicitArg::ArgType argType, const llvm::Argument* image) const;
237 
238         /// @brief  Returns the index of the appropriate implicit argument
239         ///         based on the given argument type and the argument number
240         /// @param  argType         The implicit argument type
241         ///                         (height/width/depth for images, normalized/address/snapwa for samplers)
242         /// @param  argNum          The explicit argument number of the type
243         /// @return The implicit argument's index for a given argument type
244         unsigned int getNumberedArgIndex(ImplicitArg::ArgType argType, int argNum) const;
245 
246         /// @brief  Returns the argument type of the argument at the given index
247         /// @param  i               The implicit argument index
248         /// @return The argument type of the argument at the given index
249         ImplicitArg::ArgType getArgType(unsigned int i) const;
250 
251         /// @brief  Returns the argument type of the given matching intrinsic ID
252         /// @param  i               The GenISAIntrinsic ID
253         /// @return The argument type
254         static ImplicitArg::ArgType getArgType(llvm::GenISAIntrinsic::ID id);
255 
256         /// @brief  Returns the argument dependency of the given matching intrinsic ID
257         /// @param  i               The GenISAIntrinsic ID
258         /// @return The argument dependency
259         static IGC::WIAnalysis::WIDependancy getArgDep(llvm::GenISAIntrinsic::ID id);
260 
261         /// @brief  Returns if the given arg type supports the GenISAIntrinsic instruction
262         /// @param  i               The ImplicitArg type
263         /// @return If intrinsic supported
264         static bool hasIntrinsicSupport(ImplicitArg::ArgType i);
265 
266         /// @brief  Returns the explicit argument number of the given implicit argument index
267         /// @param  i               The implicit argument index
268         /// @return The explicit argument number of the given implicit argument index
269         int32_t getExplicitArgNum(uint index) const;
270 
271         /// @brief  Returns the structure offset of the given implicit argument index
272         /// @param  i               The implicit argument index
273         /// @return The structure offset of the given implicit argument index
274         int32_t getStructArgOffset(uint index) const;
275 
276         /// @brief  Creates implict arguments metadata for the given function based on the given implicit arguments
277         ///         it should receive. If implicit metadata exists, it adds to it.
278         /// @param  F               The function for which to create the implicit argument's metadata
279         /// @param  implicitArgs    The implicit argument that are required by the given function
280         /// @param  pMdUtils The Metadata API object
281         static void addImplicitArgs(llvm::Function& F, const llvm::SmallVectorImpl<ImplicitArg::ArgType>& implicitArgs, const IGCMD::MetaDataUtils* pMdUtils);
282         //TODO doc
283 
284         /// @brief  Creates implict image arguments metadata for the given function based on the given implicit image
285         ///         arguments it should receive. If implicit image metadata exists, it adds to it.
286         /// @param  F The function for which to create the implicit argument's metadata
287         /// @param  argMap          A map of implict argument types to the Value pointers to the arguments
288         /// @param  pMdUtils The Metadata API object
289         static void addImageArgs(llvm::Function& F, const ImplicitArg::ArgMap& argMap, const IGCMD::MetaDataUtils* pMdUtils);
290         // TODO doc
291 
292         static void addStructArgs(llvm::Function& F, const llvm::Argument* A, const ImplicitArg::StructArgList& S, const IGCMD::MetaDataUtils* pMdUtils);
293 
294         /// @brief  Creates implict arguments metadata for the given function based on the given implicit arguments
295         ///         it should receive. If implicit metadata exists, it adds to it.
296         /// @param  F               The function for which to create the implicit argument's metadata
297         /// @param  argMap          A map of implict argument types to the set of numbers of arguments
298         /// @param  pMdUtils        The Metadata API object
299         static void addNumberedArgs(llvm::Function& F, const ImplicitArg::ArgMap& argMap, const IGCMD::MetaDataUtils* pMdUtils);
300 
301         /// @brief  Create implicit arguments metadata for the given function. It adds one
302         ///         implicit argument for each explicit pointer argument to global or constant buffer.
303         /// @param  F               The function for which to create the implicit argument's metadata
304         /// @param  pMdUtils        The Metadata API object
305         static void addBufferOffsetArgs(llvm::Function& F, const IGCMD::MetaDataUtils* pMdUtils, IGC::ModuleMetaData* modMD);
306 
307         /// @brief  Create implicit arguments metadata for the given function. It adds one
308         ///         implicit argument for each explicit pointer argument to global or constant buffer.
309         /// @param  F               The function for which to create the implicit argument's metadata
310         /// @param  pMdUtils        The Metadata API object
311         static void addBindlessOffsetArgs(llvm::Function& F, const IGCMD::MetaDataUtils* pMdUtils, IGC::ModuleMetaData* modMD);
312 
313         /// @brief  Check if the given implicit argument type exist in the(implicit) function argument associated
314         /// @param  argType         The type of the implict argument that should be checked
315         /// @return true if the argument exist, false otherwise.
316         bool isImplicitArgExist(ImplicitArg::ArgType argType) const;
317         static bool isImplicitArgExist(llvm::Function& F, ImplicitArg::ArgType argType, const IGCMD::MetaDataUtils* pMdUtils);
318 
319         /// @brief  Returns the (implicit) function argument associated with the given implicit argument type
320         /// @param  F           The Function for which the implict argument should be returned
321         /// @param  argType         The type of the implict argument that should be returned
322         /// @return The (implicit) function argument associated with the given argument type
323         ///         In case the argument doesn't exist, return nullptr
324         llvm::Argument* getImplicitArg(llvm::Function &F, ImplicitArg::ArgType argType) const;
325 
326         /// @brief  Returns the (implicit) function argument associated with the given implicit argument type
327         ///         and argument number
328         /// @param  F        The Function for which the implict argument should be returned
329         /// @param  argType  The type of the implict argument that should be returned
330         /// @param  argNum   The explicit argument number of the type
331         /// @return The (implicit) function argument associated with the given argument type and number
332         ///         In case the argument doesn't exist, return nullptr
333         llvm::Argument* getNumberedImplicitArg(llvm::Function &F, ImplicitArg::ArgType argType, int argNum) const;
334 
335         /// @brief  Returns true if the given argument type is an image or sampler.
336         /// @param  argType The argument type to check.
337         static bool isImplicitImage(ImplicitArg::ArgType argType);
338 
339         /// @brief  Returns true if the given argument type is a struct
340         /// @param  argType The argument type to check.
341         static bool isImplicitStruct(ImplicitArg::ArgType argType);
342 
343         llvm::Value* getImplicitArgValue(llvm::Function& F, ImplicitArg::ArgType argType, const IGCMD::MetaDataUtils* pMdUtils);
344 
345     private:
346         /// @brief The function's metadata information.
347         IGCMD::FunctionInfoMetaDataHandle m_funcInfoMD;
348 
349         static bool isImplicitArgExist(
350             const IGCMD::FunctionInfoMetaDataHandle& funcInfo,
351             ImplicitArg::ArgType argType);
352     };
353 
354 } // namespace IGC
355