1 //===- LLVMSPIRVInternal.h -  SPIR-V internal header file -------*- C++ -*-===//
2 //
3 //                     The LLVM/SPIRV Translator
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 // Copyright (c) 2014 Advanced Micro Devices, Inc. All rights reserved.
9 //
10 // Permission is hereby granted, free of charge, to any person obtaining a
11 // copy of this software and associated documentation files (the "Software"),
12 // to deal with the Software without restriction, including without limitation
13 // the rights to use, copy, modify, merge, publish, distribute, sublicense,
14 // and/or sell copies of the Software, and to permit persons to whom the
15 // Software is furnished to do so, subject to the following conditions:
16 //
17 // Redistributions of source code must retain the above copyright notice,
18 // this list of conditions and the following disclaimers.
19 // Redistributions in binary form must reproduce the above copyright notice,
20 // this list of conditions and the following disclaimers in the documentation
21 // and/or other materials provided with the distribution.
22 // Neither the names of Advanced Micro Devices, Inc., nor the names of its
23 // contributors may be used to endorse or promote products derived from this
24 // Software without specific prior written permission.
25 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
26 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
27 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
28 // CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
29 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
30 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS WITH
31 // THE SOFTWARE.
32 //
33 //===----------------------------------------------------------------------===//
34 /// \file
35 ///
36 /// This file declares classes and functions shared by SPIR-V reader/writer.
37 ///
38 //===----------------------------------------------------------------------===//
39 #ifndef SPIRV_SPIRVINTERNAL_H
40 #define SPIRV_SPIRVINTERNAL_H
41 
42 #include "NameMangleAPI.h"
43 #include "libSPIRV/SPIRVEnum.h"
44 #include "libSPIRV/SPIRVError.h"
45 #include "libSPIRV/SPIRVNameMapEnum.h"
46 #include "libSPIRV/SPIRVType.h"
47 #include "libSPIRV/SPIRVUtil.h"
48 
49 #include "LLVMSPIRVLib.h"
50 #include "llvm/IR/Attributes.h"
51 #include "llvm/IR/Constants.h"
52 #include "llvm/IR/Instructions.h"
53 
54 #include <functional>
55 #include <utility>
56 
57 using namespace SPIRV;
58 using namespace llvm;
59 
60 namespace llvm {
61 class IntrinsicInst;
62 }
63 
64 namespace SPIRV {
65 
66 /// The LLVM/SPIR-V translator version used to fill the lower 16 bits of the
67 /// generator's magic number in the generated SPIR-V module.
68 /// This number should be bumped up whenever the generated SPIR-V changes.
69 const static unsigned short KTranslatorVer = 14;
70 
71 #define SPCV_TARGET_LLVM_IMAGE_TYPE_ENCODE_ACCESS_QUAL 0
72 // Workaround for SPIR 2 producer bug about kernel function calling convention.
73 // This workaround checks metadata to determine if a function is kernel.
74 #define SPCV_RELAX_KERNEL_CALLING_CONV 1
75 
76 class SPIRVOpaqueType;
77 typedef SPIRVMap<std::string, Op, SPIRVOpaqueType> SPIRVOpaqueTypeOpCodeMap;
78 
79 // Ad hoc function used by LLVM/SPIRV converter for type casting
80 #define SPCV_CAST "spcv.cast"
81 #define LLVM_MEMCPY "llvm.memcpy"
82 
83 // The name of function generated by Clang to initialize sampler(which is
84 // opaqueue type) by 32-bit integer. The name is taken from
85 // CodeGenModule::createOpenCLIntToSamplerConversion().
86 #define SAMPLER_INIT "__translate_sampler_initializer"
87 
init()88 template <> inline void SPIRVMap<unsigned, Op>::init() {
89 #define _SPIRV_OP(x, y) add(Instruction::x, Op##y);
90   /* Casts */
91   _SPIRV_OP(ZExt, UConvert)
92   _SPIRV_OP(SExt, SConvert)
93   _SPIRV_OP(Trunc, UConvert)
94   _SPIRV_OP(FPToUI, ConvertFToU)
95   _SPIRV_OP(FPToSI, ConvertFToS)
96   _SPIRV_OP(UIToFP, ConvertUToF)
97   _SPIRV_OP(SIToFP, ConvertSToF)
98   _SPIRV_OP(FPTrunc, FConvert)
99   _SPIRV_OP(FPExt, FConvert)
100   _SPIRV_OP(PtrToInt, ConvertPtrToU)
101   _SPIRV_OP(IntToPtr, ConvertUToPtr)
102   _SPIRV_OP(BitCast, Bitcast)
103   _SPIRV_OP(AddrSpaceCast, GenericCastToPtr)
104   _SPIRV_OP(GetElementPtr, AccessChain)
105   _SPIRV_OP(FNeg, FNegate)
106   /*Binary*/
107   _SPIRV_OP(And, BitwiseAnd)
108   _SPIRV_OP(Or, BitwiseOr)
109   _SPIRV_OP(Xor, BitwiseXor)
110   _SPIRV_OP(Add, IAdd)
111   _SPIRV_OP(FAdd, FAdd)
112   _SPIRV_OP(Sub, ISub)
113   _SPIRV_OP(FSub, FSub)
114   _SPIRV_OP(Mul, IMul)
115   _SPIRV_OP(FMul, FMul)
116   _SPIRV_OP(UDiv, UDiv)
117   _SPIRV_OP(SDiv, SDiv)
118   _SPIRV_OP(FDiv, FDiv)
119   _SPIRV_OP(SRem, SRem)
120   _SPIRV_OP(FRem, FRem)
121   _SPIRV_OP(URem, UMod)
122   _SPIRV_OP(Shl, ShiftLeftLogical)
123   _SPIRV_OP(LShr, ShiftRightLogical)
124   _SPIRV_OP(AShr, ShiftRightArithmetic)
125 #undef _SPIRV_OP
126 }
127 typedef SPIRVMap<unsigned, Op> OpCodeMap;
128 
init()129 template <> inline void SPIRVMap<CmpInst::Predicate, Op>::init() {
130 #define _SPIRV_OP(x, y) add(CmpInst::x, Op##y);
131   _SPIRV_OP(FCMP_OEQ, FOrdEqual)
132   _SPIRV_OP(FCMP_OGT, FOrdGreaterThan)
133   _SPIRV_OP(FCMP_OGE, FOrdGreaterThanEqual)
134   _SPIRV_OP(FCMP_OLT, FOrdLessThan)
135   _SPIRV_OP(FCMP_OLE, FOrdLessThanEqual)
136   _SPIRV_OP(FCMP_ONE, FOrdNotEqual)
137   _SPIRV_OP(FCMP_ORD, Ordered)
138   _SPIRV_OP(FCMP_UNO, Unordered)
139   _SPIRV_OP(FCMP_UEQ, FUnordEqual)
140   _SPIRV_OP(FCMP_UGT, FUnordGreaterThan)
141   _SPIRV_OP(FCMP_UGE, FUnordGreaterThanEqual)
142   _SPIRV_OP(FCMP_ULT, FUnordLessThan)
143   _SPIRV_OP(FCMP_ULE, FUnordLessThanEqual)
144   _SPIRV_OP(FCMP_UNE, FUnordNotEqual)
145   _SPIRV_OP(ICMP_EQ, IEqual)
146   _SPIRV_OP(ICMP_NE, INotEqual)
147   _SPIRV_OP(ICMP_UGT, UGreaterThan)
148   _SPIRV_OP(ICMP_UGE, UGreaterThanEqual)
149   _SPIRV_OP(ICMP_ULT, ULessThan)
150   _SPIRV_OP(ICMP_ULE, ULessThanEqual)
151   _SPIRV_OP(ICMP_SGT, SGreaterThan)
152   _SPIRV_OP(ICMP_SGE, SGreaterThanEqual)
153   _SPIRV_OP(ICMP_SLT, SLessThan)
154   _SPIRV_OP(ICMP_SLE, SLessThanEqual)
155 #undef _SPIRV_OP
156 }
157 typedef SPIRVMap<CmpInst::Predicate, Op> CmpMap;
158 
159 class IntBoolOpMapId;
init()160 template <> inline void SPIRVMap<Op, Op, IntBoolOpMapId>::init() {
161   add(OpNot, OpLogicalNot);
162   add(OpBitwiseAnd, OpLogicalAnd);
163   add(OpBitwiseOr, OpLogicalOr);
164   add(OpBitwiseXor, OpLogicalNotEqual);
165   add(OpIEqual, OpLogicalEqual);
166   add(OpINotEqual, OpLogicalNotEqual);
167 }
168 typedef SPIRVMap<Op, Op, IntBoolOpMapId> IntBoolOpMap;
169 
170 #define SPIR_TARGETTRIPLE32 "spir-unknown-unknown"
171 #define SPIR_TARGETTRIPLE64 "spir64-unknown-unknown"
172 #define SPIR_DATALAYOUT32                                                      \
173   "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32"                             \
174   "-i64:64:64-f32:32:32-f64:64:64-v16:16:16-v24:32:32"                         \
175   "-v32:32:32-v48:64:64-v64:64:64-v96:128:128"                                 \
176   "-v128:128:128-v192:256:256-v256:256:256"                                    \
177   "-v512:512:512-v1024:1024:1024"
178 #define SPIR_DATALAYOUT64                                                      \
179   "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32"                             \
180   "-i64:64:64-f32:32:32-f64:64:64-v16:16:16-v24:32:32"                         \
181   "-v32:32:32-v48:64:64-v64:64:64-v96:128:128"                                 \
182   "-v128:128:128-v192:256:256-v256:256:256"                                    \
183   "-v512:512:512-v1024:1024:1024"
184 
185 enum SPIRAddressSpace {
186   SPIRAS_Private,
187   SPIRAS_Global,
188   SPIRAS_Constant,
189   SPIRAS_Local,
190   SPIRAS_Generic,
191   SPIRAS_GlobalDevice,
192   SPIRAS_GlobalHost,
193   SPIRAS_Input,
194   SPIRAS_Output,
195   SPIRAS_Count,
196 };
197 
init()198 template <> inline void SPIRVMap<SPIRAddressSpace, std::string>::init() {
199   add(SPIRAS_Private, "Private");
200   add(SPIRAS_Global, "Global");
201   add(SPIRAS_Constant, "Constant");
202   add(SPIRAS_Local, "Local");
203   add(SPIRAS_Generic, "Generic");
204   add(SPIRAS_Input, "Input");
205   add(SPIRAS_GlobalDevice, "GlobalDevice");
206   add(SPIRAS_GlobalHost, "GlobalHost");
207 }
208 typedef SPIRVMap<SPIRAddressSpace, SPIRVStorageClassKind>
209     SPIRAddrSpaceCapitalizedNameMap;
210 
211 template <>
init()212 inline void SPIRVMap<SPIRAddressSpace, SPIRVStorageClassKind>::init() {
213   add(SPIRAS_Private, StorageClassFunction);
214   add(SPIRAS_Global, StorageClassCrossWorkgroup);
215   add(SPIRAS_Constant, StorageClassUniformConstant);
216   add(SPIRAS_Local, StorageClassWorkgroup);
217   add(SPIRAS_Generic, StorageClassGeneric);
218   add(SPIRAS_Input, StorageClassInput);
219   add(SPIRAS_GlobalDevice, StorageClassDeviceOnlyINTEL);
220   add(SPIRAS_GlobalHost, StorageClassHostOnlyINTEL);
221 }
222 typedef SPIRVMap<SPIRAddressSpace, SPIRVStorageClassKind> SPIRSPIRVAddrSpaceMap;
223 
224 // Maps OCL builtin function to SPIRV builtin variable.
225 template <>
init()226 inline void SPIRVMap<std::string, SPIRVAccessQualifierKind>::init() {
227   add("read_only", AccessQualifierReadOnly);
228   add("write_only", AccessQualifierWriteOnly);
229   add("read_write", AccessQualifierReadWrite);
230 }
231 typedef SPIRVMap<std::string, SPIRVAccessQualifierKind>
232     SPIRSPIRVAccessQualifierMap;
233 
234 template <>
init()235 inline void SPIRVMap<Attribute::AttrKind, SPIRVFuncParamAttrKind>::init() {
236   add(Attribute::ZExt, FunctionParameterAttributeZext);
237   add(Attribute::SExt, FunctionParameterAttributeSext);
238   add(Attribute::ByVal, FunctionParameterAttributeByVal);
239   add(Attribute::StructRet, FunctionParameterAttributeSret);
240   add(Attribute::NoAlias, FunctionParameterAttributeNoAlias);
241   add(Attribute::NoCapture, FunctionParameterAttributeNoCapture);
242   add(Attribute::ReadOnly, FunctionParameterAttributeNoWrite);
243 }
244 typedef SPIRVMap<Attribute::AttrKind, SPIRVFuncParamAttrKind>
245     SPIRSPIRVFuncParamAttrMap;
246 
247 template <>
248 inline void
init()249 SPIRVMap<Attribute::AttrKind, SPIRVFunctionControlMaskKind>::init() {
250   add(Attribute::ReadNone, FunctionControlPureMask);
251   add(Attribute::ReadOnly, FunctionControlConstMask);
252   add(Attribute::AlwaysInline, FunctionControlInlineMask);
253   add(Attribute::NoInline, FunctionControlDontInlineMask);
254   add(Attribute::OptimizeNone, internal::FunctionControlOptNoneINTELMask);
255 }
256 typedef SPIRVMap<Attribute::AttrKind, SPIRVFunctionControlMaskKind>
257     SPIRSPIRVFuncCtlMaskMap;
258 
259 class SPIRVExtSetShortName;
260 template <>
261 inline void
init()262 SPIRVMap<SPIRVExtInstSetKind, std::string, SPIRVExtSetShortName>::init() {
263   add(SPIRVEIS_OpenCL, "ocl");
264 }
265 typedef SPIRVMap<SPIRVExtInstSetKind, std::string, SPIRVExtSetShortName>
266     SPIRVExtSetShortNameMap;
267 
268 #define SPIR_MD_COMPILER_OPTIONS "opencl.compiler.options"
269 #define SPIR_MD_KERNEL_ARG_ADDR_SPACE "kernel_arg_addr_space"
270 #define SPIR_MD_KERNEL_ARG_ACCESS_QUAL "kernel_arg_access_qual"
271 #define SPIR_MD_KERNEL_ARG_TYPE "kernel_arg_type"
272 #define SPIR_MD_KERNEL_ARG_BASE_TYPE "kernel_arg_base_type"
273 #define SPIR_MD_KERNEL_ARG_TYPE_QUAL "kernel_arg_type_qual"
274 #define SPIR_MD_KERNEL_ARG_NAME "kernel_arg_name"
275 
276 #define OCL_TYPE_NAME_SAMPLER_T "sampler_t"
277 #define SPIR_TYPE_NAME_EVENT_T "opencl.event_t"
278 #define SPIR_TYPE_NAME_CLK_EVENT_T "opencl.clk_event_t"
279 #define SPIR_TYPE_NAME_BLOCK_T "opencl.block"
280 #define SPIR_INTRINSIC_BLOCK_BIND "spir_block_bind"
281 #define SPIR_INTRINSIC_GET_BLOCK_INVOKE "spir_get_block_invoke"
282 #define SPIR_INTRINSIC_GET_BLOCK_CONTEXT "spir_get_block_context"
283 #define SPIR_TEMP_NAME_PREFIX_BLOCK "block"
284 #define SPIR_TEMP_NAME_PREFIX_CALL "call"
285 
286 namespace kLLVMTypeName {
287 const static char StructPrefix[] = "struct.";
288 } // namespace kLLVMTypeName
289 
290 namespace kSPIRVImageSampledTypeName {
291 const static char Float[] = "float";
292 const static char Half[] = "half";
293 const static char Int[] = "int";
294 const static char UInt[] = "uint";
295 const static char Void[] = "void";
296 } // namespace kSPIRVImageSampledTypeName
297 
298 namespace kSPIRVTypeName {
299 const static char Delimiter = '.';
300 const static char DeviceEvent[] = "DeviceEvent";
301 const static char Event[] = "Event";
302 const static char Image[] = "Image";
303 const static char Pipe[] = "Pipe";
304 const static char PostfixDelim = '_';
305 const static char Prefix[] = "spirv";
306 const static char PrefixAndDelim[] = "spirv.";
307 const static char Queue[] = "Queue";
308 const static char ReserveId[] = "ReserveId";
309 const static char SampledImg[] = "SampledImage";
310 const static char Sampler[] = "Sampler";
311 const static char ConstantSampler[] = "ConstantSampler";
312 const static char PipeStorage[] = "PipeStorage";
313 const static char ConstantPipeStorage[] = "ConstantPipeStorage";
314 const static char VmeImageINTEL[] = "VmeImageINTEL";
315 } // namespace kSPIRVTypeName
316 
317 namespace kSPR2TypeName {
318 const static char Delimiter = '.';
319 const static char OCLPrefix[] = "opencl.";
320 const static char ImagePrefix[] = "opencl.image";
321 const static char PipeRO[] = "opencl.pipe_ro_t";
322 const static char PipeWO[] = "opencl.pipe_wo_t";
323 const static char Sampler[] = "opencl.sampler_t";
324 const static char Event[] = "opencl.event_t";
325 } // namespace kSPR2TypeName
326 
327 namespace kAccessQualName {
328 const static char ReadOnly[] = "read_only";
329 const static char WriteOnly[] = "write_only";
330 const static char ReadWrite[] = "read_write";
331 } // namespace kAccessQualName
332 
333 namespace kAccessQualPostfix {
334 const static char ReadOnly[] = "_ro";
335 const static char WriteOnly[] = "_wo";
336 const static char ReadWrite[] = "_rw";
337 const static char Type[] = "_t";
338 } // namespace kAccessQualPostfix
339 
340 namespace kMangledName {
341 const static char Sampler[] = "11ocl_sampler";
342 const static char AtomicPrefixIncoming[] = "U7_Atomic";
343 const static char AtomicPrefixInternal[] = "atomic_";
344 } // namespace kMangledName
345 
346 namespace kSPIRVName {
347 const static char GroupPrefix[] = "group_";
348 const static char GroupNonUniformPrefix[] = "group_non_uniform_";
349 const static char ClusteredPrefix[] = "clustered_";
350 const static char Prefix[] = "__spirv_";
351 const static char Postfix[] = "__";
352 const static char ImageQuerySize[] = "ImageQuerySize";
353 const static char ImageQuerySizeLod[] = "ImageQuerySizeLod";
354 const static char ImageSampleExplicitLod[] = "ImageSampleExplicitLod";
355 const static char ReservedPrefix[] = "reserved_";
356 const static char SampledImage[] = "SampledImage";
357 const static char TempSampledImage[] = "TempSampledImage";
358 const static char TranslateOCLMemOrder[] = "__translate_ocl_memory_order";
359 const static char TranslateOCLMemScope[] = "__translate_ocl_memory_scope";
360 const static char TranslateSPIRVMemOrder[] = "__translate_spirv_memory_order";
361 const static char TranslateSPIRVMemScope[] = "__translate_spirv_memory_scope";
362 const static char TranslateSPIRVMemFence[] = "__translate_spirv_memory_fence";
363 } // namespace kSPIRVName
364 
365 namespace kSPIRVPostfix {
366 const static char ToGlobal[] = "ToGlobal";
367 const static char ToLocal[] = "ToLocal";
368 const static char ToPrivate[] = "ToPrivate";
369 const static char Sat[] = "sat";
370 const static char Rtz[] = "rtz";
371 const static char Rte[] = "rte";
372 const static char Rtp[] = "rtp";
373 const static char Rtn[] = "rtn";
374 const static char Rt[] = "rt";
375 const static char Return[] = "R";
376 const static char Divider[] = "_";
377 /// Divider between extended instruction name and postfix
378 const static char ExtDivider[] = "__";
379 } // namespace kSPIRVPostfix
380 
381 namespace kSPIRVMD {
382 const static char Capability[] = "spirv.Capability";
383 const static char EntryPoint[] = "spirv.EntryPoint";
384 const static char ExecutionMode[] = "spirv.ExecutionMode";
385 const static char Extension[] = "spirv.Extension";
386 const static char Generator[] = "spirv.Generator";
387 const static char Source[] = "spirv.Source";
388 const static char SourceExtension[] = "spirv.SourceExtension";
389 const static char MemoryModel[] = "spirv.MemoryModel";
390 } // namespace kSPIRVMD
391 
392 namespace kSPIR2MD {
393 const static char Extensions[] = "opencl.used.extensions";
394 const static char FPContract[] = "opencl.enable.FP_CONTRACT";
395 const static char OCLVer[] = "opencl.ocl.version";
396 const static char OptFeatures[] = "opencl.used.optional.core.features";
397 const static char SPIRVer[] = "opencl.spir.version";
398 const static char VecTyHint[] = "vec_type_hint";
399 const static char WGSize[] = "reqd_work_group_size";
400 const static char WGSizeHint[] = "work_group_size_hint";
401 const static char SubgroupSize[] = "intel_reqd_sub_group_size";
402 const static char MaxWGSize[] = "max_work_group_size";
403 const static char NoGlobalOffset[] = "no_global_work_offset";
404 const static char MaxWGDim[] = "max_global_work_dim";
405 const static char NumSIMD[] = "num_simd_work_items";
406 const static char StallEnable[] = "stall_enable";
407 const static char FmaxMhz[] = "scheduler_target_fmax_mhz";
408 const static char LoopFuse[] = "loop_fuse";
409 const static char PreferDSP[] = "prefer_dsp";
410 const static char PropDSPPref[] = "propagate_dsp_preference";
411 const static char InitiationInterval[] = "initiation_interval";
412 const static char MaxConcurrency[] = "max_concurrency";
413 const static char DisableLoopPipelining[] = "disable_loop_pipelining";
414 } // namespace kSPIR2MD
415 
416 enum Spir2SamplerKind {
417   CLK_ADDRESS_NONE = 0x0000,
418   CLK_ADDRESS_CLAMP = 0x0004,
419   CLK_ADDRESS_CLAMP_TO_EDGE = 0x0002,
420   CLK_ADDRESS_REPEAT = 0x0006,
421   CLK_ADDRESS_MIRRORED_REPEAT = 0x0008,
422   CLK_NORMALIZED_COORDS_FALSE = 0x0000,
423   CLK_NORMALIZED_COORDS_TRUE = 0x0001,
424   CLK_FILTER_NEAREST = 0x0010,
425   CLK_FILTER_LINEAR = 0x0020,
426 };
427 
428 /// Additional information for mangling a function argument type.
429 struct BuiltinArgTypeMangleInfo {
430   bool IsSigned;
431   bool IsVoidPtr;
432   bool IsEnum;
433   bool IsSampler;
434   bool IsAtomic;
435   bool IsLocalArgBlock;
436   SPIR::TypePrimitiveEnum Enum;
437   unsigned Attr;
BuiltinArgTypeMangleInfoBuiltinArgTypeMangleInfo438   BuiltinArgTypeMangleInfo()
439       : IsSigned(true), IsVoidPtr(false), IsEnum(false), IsSampler(false),
440         IsAtomic(false), IsLocalArgBlock(false), Enum(SPIR::PRIMITIVE_NONE),
441         Attr(0) {}
442 };
443 
444 /// Information for mangling builtin function.
445 class BuiltinFuncMangleInfo {
446 public:
447   /// Translate builtin function name and set
448   /// argument attributes and unsigned args.
449   BuiltinFuncMangleInfo(const std::string &UniqName = "")
450       : LocalArgBlockIdx(-1), VarArgIdx(-1) {
451     if (!UniqName.empty())
452       init(UniqName);
453   }
~BuiltinFuncMangleInfo()454   virtual ~BuiltinFuncMangleInfo() {}
getUnmangledName()455   const std::string &getUnmangledName() const { return UnmangledName; }
addUnsignedArg(int Ndx)456   void addUnsignedArg(int Ndx) { UnsignedArgs.insert(Ndx); }
addUnsignedArgs(int StartNdx,int StopNdx)457   void addUnsignedArgs(int StartNdx, int StopNdx) {
458     assert(StartNdx < StopNdx && "wrong parameters");
459     for (int I = StartNdx; I <= StopNdx; ++I)
460       addUnsignedArg(I);
461   }
addVoidPtrArg(int Ndx)462   void addVoidPtrArg(int Ndx) { VoidPtrArgs.insert(Ndx); }
addSamplerArg(int Ndx)463   void addSamplerArg(int Ndx) { SamplerArgs.insert(Ndx); }
addAtomicArg(int Ndx)464   void addAtomicArg(int Ndx) { AtomicArgs.insert(Ndx); }
setLocalArgBlock(int Ndx)465   void setLocalArgBlock(int Ndx) {
466     assert(0 <= Ndx && "it is not allowed to set less than zero index");
467     LocalArgBlockIdx = Ndx;
468   }
setEnumArg(int Ndx,SPIR::TypePrimitiveEnum Enum)469   void setEnumArg(int Ndx, SPIR::TypePrimitiveEnum Enum) {
470     EnumArgs[Ndx] = Enum;
471   }
setArgAttr(int Ndx,unsigned Attr)472   void setArgAttr(int Ndx, unsigned Attr) { Attrs[Ndx] = Attr; }
setVarArg(int Ndx)473   void setVarArg(int Ndx) {
474     assert(0 <= Ndx && "it is not allowed to set less than zero index");
475     VarArgIdx = Ndx;
476   }
isArgUnsigned(int Ndx)477   bool isArgUnsigned(int Ndx) {
478     return UnsignedArgs.count(-1) || UnsignedArgs.count(Ndx);
479   }
isArgVoidPtr(int Ndx)480   bool isArgVoidPtr(int Ndx) {
481     return VoidPtrArgs.count(-1) || VoidPtrArgs.count(Ndx);
482   }
isArgSampler(int Ndx)483   bool isArgSampler(int Ndx) { return SamplerArgs.count(Ndx); }
isArgAtomic(int Ndx)484   bool isArgAtomic(int Ndx) { return AtomicArgs.count(Ndx); }
isLocalArgBlock(int Ndx)485   bool isLocalArgBlock(int Ndx) { return LocalArgBlockIdx == Ndx; }
486   bool isArgEnum(int Ndx, SPIR::TypePrimitiveEnum *Enum = nullptr) {
487     auto Loc = EnumArgs.find(Ndx);
488     if (Loc == EnumArgs.end())
489       Loc = EnumArgs.find(-1);
490     if (Loc == EnumArgs.end())
491       return false;
492     if (Enum)
493       *Enum = Loc->second;
494     return true;
495   }
getArgAttr(int Ndx)496   unsigned getArgAttr(int Ndx) {
497     auto Loc = Attrs.find(Ndx);
498     if (Loc == Attrs.end())
499       Loc = Attrs.find(-1);
500     if (Loc == Attrs.end())
501       return 0;
502     return Loc->second;
503   }
504   // get ellipsis index, single ellipsis at the end of the function is possible
505   // only return value < 0 if none
getVarArg()506   int getVarArg() const { return VarArgIdx; }
getTypeMangleInfo(int Ndx)507   BuiltinArgTypeMangleInfo getTypeMangleInfo(int Ndx) {
508     BuiltinArgTypeMangleInfo Info;
509     Info.IsSigned = !isArgUnsigned(Ndx);
510     Info.IsVoidPtr = isArgVoidPtr(Ndx);
511     Info.IsEnum = isArgEnum(Ndx, &Info.Enum);
512     Info.IsSampler = isArgSampler(Ndx);
513     Info.IsAtomic = isArgAtomic(Ndx);
514     Info.IsLocalArgBlock = isLocalArgBlock(Ndx);
515     Info.Attr = getArgAttr(Ndx);
516     return Info;
517   }
init(StringRef UniqUnmangledName)518   virtual void init(StringRef UniqUnmangledName) {
519     UnmangledName = UniqUnmangledName.str();
520   }
521 
522 protected:
523   std::string UnmangledName;
524   std::set<int> UnsignedArgs; // unsigned arguments, or -1 if all are unsigned
525   std::set<int> VoidPtrArgs;  // void pointer arguments, or -1 if all are void
526                               // pointer
527   std::set<int> SamplerArgs;  // sampler arguments
528   std::set<int> AtomicArgs;   // atomic arguments
529   std::map<int, SPIR::TypePrimitiveEnum> EnumArgs; // enum arguments
530   std::map<int, unsigned> Attrs;                   // argument attributes
531   int LocalArgBlockIdx; // index of a block with local arguments, idx < 0 if
532                         // none
533   int VarArgIdx;        // index of ellipsis argument, idx < 0 if none
534 };
535 
536 /// \returns a vector of types for a collection of values.
getTypes(T V)537 template <class T> std::vector<Type *> getTypes(T V) {
538   std::vector<Type *> Tys;
539   for (auto &I : V)
540     Tys.push_back(I->getType());
541   return Tys;
542 }
543 
544 /// Move elements of std::vector from [begin, end) to target.
545 template <typename T>
move(std::vector<T> & V,size_t Begin,size_t End,size_t Target)546 void move(std::vector<T> &V, size_t Begin, size_t End, size_t Target) {
547   assert(Begin < End && End <= V.size() && Target <= V.size() &&
548          !(Begin < Target && Target < End));
549   if (Begin <= Target && Target <= End)
550     return;
551   auto B = V.begin() + Begin, E = V.begin() + End;
552   if (Target > V.size())
553     Target = V.size();
554   if (Target > End)
555     Target -= (End - Begin);
556   std::vector<T> Segment(B, E);
557   V.erase(B, E);
558   V.insert(V.begin() + Target, Segment.begin(), Segment.end());
559 }
560 
561 /// Find position of first pointer type value in a vector.
findFirstPtr(const std::vector<Value * > & Args)562 inline size_t findFirstPtr(const std::vector<Value *> &Args) {
563   auto PtArg = std::find_if(Args.begin(), Args.end(), [](Value *V) {
564     return V->getType()->isPointerTy();
565   });
566   return PtArg - Args.begin();
567 }
568 
569 bool isSupportedTriple(Triple T);
570 void removeFnAttr(CallInst *Call, Attribute::AttrKind Attr);
571 void addFnAttr(CallInst *Call, Attribute::AttrKind Attr);
572 void saveLLVMModule(Module *M, const std::string &OutputFile);
573 std::string mapSPIRVTypeToOCLType(SPIRVType *Ty, bool Signed);
574 std::string mapLLVMTypeToOCLType(const Type *Ty, bool Signed);
575 SPIRVDecorate *mapPostfixToDecorate(StringRef Postfix, SPIRVEntry *Target);
576 
577 /// Add decorations to a SPIR-V entry.
578 /// \param Decs Each string is a postfix without _ at the beginning.
579 SPIRVValue *addDecorations(SPIRVValue *Target,
580                            const SmallVectorImpl<std::string> &Decs);
581 
582 PointerType *getOrCreateOpaquePtrType(Module *M, const std::string &Name,
583                                       unsigned AddrSpace = SPIRAS_Global);
584 PointerType *getSamplerType(Module *M);
585 PointerType *getPipeStorageType(Module *M);
586 PointerType *getSPIRVOpaquePtrType(Module *M, Op OC);
587 void getFunctionTypeParameterTypes(llvm::FunctionType *FT,
588                                    std::vector<Type *> &ArgTys);
589 Function *getOrCreateFunction(Module *M, Type *RetTy, ArrayRef<Type *> ArgTypes,
590                               StringRef Name,
591                               BuiltinFuncMangleInfo *Mangle = nullptr,
592                               AttributeList *Attrs = nullptr,
593                               bool TakeName = true);
594 
595 PointerType *getOCLClkEventType(Module *M);
596 PointerType *getOCLClkEventPtrType(Module *M);
597 Constant *getOCLNullClkEventPtr(Module *M);
598 
599 /// Get function call arguments.
600 /// \param Start Starting index.
601 /// \param End Ending index.
602 std::vector<Value *> getArguments(CallInst *CI, unsigned Start = 0,
603                                   unsigned End = 0);
604 
605 /// Get constant function call argument as an integer.
606 /// \param I argument index.
607 uint64_t getArgAsInt(CallInst *CI, unsigned I);
608 
609 /// Get constant function call argument as type \param T.
610 /// \param I argument index.
getArgAs(CallInst * CI,unsigned I)611 template <typename T> T getArgAs(CallInst *CI, unsigned I) {
612   return static_cast<T>(getArgAsInt(CI, I));
613 }
614 
615 /// Get constant function call argument as a Scope enum.
616 /// \param I argument index.
617 Scope getArgAsScope(CallInst *CI, unsigned I);
618 
619 /// Get constant function call argument as a Decoration enum.
620 /// \param I argument index.
621 Decoration getArgAsDecoration(CallInst *CI, unsigned I);
622 
623 bool isPointerToOpaqueStructType(llvm::Type *Ty);
624 bool isPointerToOpaqueStructType(llvm::Type *Ty, const std::string &Name);
625 
626 /// Check if a type is OCL image type.
627 /// \return type name without "opencl." prefix.
628 bool isOCLImageType(llvm::Type *Ty, StringRef *Name = nullptr);
629 
630 /// \param BaseTyName is the type name as in spirv.BaseTyName.Postfixes
631 /// \param Postfix contains postfixes extracted from the SPIR-V image
632 ///   type name as spirv.BaseTyName.Postfixes.
633 bool isSPIRVType(llvm::Type *Ty, StringRef BaseTyName, StringRef *Postfix = 0);
634 
635 /// Decorate a function name as __spirv_{Name}_
636 std::string decorateSPIRVFunction(const std::string &S);
637 
638 /// Remove prefix/postfix from __spirv_{Name}_
639 StringRef undecorateSPIRVFunction(StringRef S);
640 
641 /// Check if a function has decorated name as __spirv_{Name}_
642 /// and get the original name.
643 bool isDecoratedSPIRVFunc(const Function *F, StringRef &UndecName);
644 
645 StringRef dePrefixSPIRVName(StringRef R, SmallVectorImpl<StringRef> &Postfix);
646 
647 /// Get a canonical function name for a SPIR-V op code.
648 std::string getSPIRVFuncName(Op OC, StringRef PostFix = "");
649 
650 std::string getSPIRVFuncName(Op OC, const Type *PRetTy, bool IsSigned = false);
651 
652 std::string getSPIRVFuncName(SPIRVBuiltinVariableKind BVKind);
653 
654 /// Get a canonical function name for a SPIR-V extended instruction
655 std::string getSPIRVExtFuncName(SPIRVExtInstSetKind Set, unsigned ExtOp,
656                                 StringRef PostFix = "");
657 
658 /// Get SPIR-V op code given the canonical function name.
659 /// Assume \param Name is either IA64 mangled or unmangled, and the unmangled
660 /// name takes the __spirv_{OpName}_{Postfixes} format.
661 /// \return op code if the unmangled function name is a valid op code name,
662 ///   otherwise return OpNop.
663 /// \param Dec contains decorations decoded from function name if it is
664 ///   not nullptr.
665 Op getSPIRVFuncOC(StringRef Name, SmallVectorImpl<std::string> *Dec = nullptr);
666 
667 /// Get SPIR-V builtin variable enum given the canonical builtin name
668 /// Assume \param Name is in format __spirv_BuiltIn{Name}
669 /// \return false if \param Name is not a valid builtin name.
670 bool getSPIRVBuiltin(const std::string &Name, spv::BuiltIn &Builtin);
671 
672 /// \param Name LLVM function name
673 /// \param DemangledName demanged name of the OpenCL built-in function
674 /// \returns true if Name is the name of the OpenCL built-in function,
675 /// false for other functions
676 bool oclIsBuiltin(StringRef Name, StringRef &DemangledName, bool IsCpp = false);
677 
678 /// Check if a function type is void(void).
679 bool isVoidFuncTy(FunctionType *FT);
680 
681 /// \returns true if \p T is a function pointer type.
682 bool isFunctionPointerType(Type *T);
683 
684 /// \returns true if function \p F has function pointer type argument.
685 /// \param AI points to the function pointer type argument if returns true.
686 bool hasFunctionPointerArg(Function *F, Function::arg_iterator &AI);
687 
688 /// \returns true if function \p F has array type argument.
689 bool hasArrayArg(Function *F);
690 
691 /// Mutates function call instruction by changing the arguments.
692 /// \param ArgMutate mutates the function arguments.
693 /// \return mutated call instruction.
694 CallInst *mutateCallInst(
695     Module *M, CallInst *CI,
696     std::function<std::string(CallInst *, std::vector<Value *> &)> ArgMutate,
697     BuiltinFuncMangleInfo *Mangle = nullptr, AttributeList *Attrs = nullptr,
698     bool TakeName = false);
699 
700 /// Mutates function call instruction by changing the arguments and return
701 /// value.
702 /// \param ArgMutate mutates the function arguments.
703 /// \param RetMutate mutates the return value.
704 /// \return mutated instruction.
705 Instruction *mutateCallInst(
706     Module *M, CallInst *CI,
707     std::function<std::string(CallInst *, std::vector<Value *> &, Type *&RetTy)>
708         ArgMutate,
709     std::function<Instruction *(CallInst *)> RetMutate,
710     BuiltinFuncMangleInfo *Mangle = nullptr, AttributeList *Attrs = nullptr,
711     bool TakeName = false);
712 
713 /// Mutate call instruction to call SPIR-V builtin function.
714 CallInst *mutateCallInstSPIRV(
715     Module *M, CallInst *CI,
716     std::function<std::string(CallInst *, std::vector<Value *> &)> ArgMutate,
717     AttributeList *Attrs = nullptr);
718 
719 /// Mutate call instruction to call SPIR-V builtin function.
720 Instruction *mutateCallInstSPIRV(
721     Module *M, CallInst *CI,
722     std::function<std::string(CallInst *, std::vector<Value *> &, Type *&RetTy)>
723         ArgMutate,
724     std::function<Instruction *(CallInst *)> RetMutate,
725     AttributeList *Attrs = nullptr);
726 
727 /// Mutate function by change the arguments.
728 /// \param ArgMutate mutates the function arguments.
729 /// \param TakeName Take the original function's name if a new function with
730 ///   different type needs to be created.
731 void mutateFunction(
732     Function *F,
733     std::function<std::string(CallInst *, std::vector<Value *> &)> ArgMutate,
734     BuiltinFuncMangleInfo *Mangle = nullptr, AttributeList *Attrs = nullptr,
735     bool TakeName = true);
736 
737 /// Add a call instruction at \p Pos.
738 CallInst *addCallInst(Module *M, StringRef FuncName, Type *RetTy,
739                       ArrayRef<Value *> Args, AttributeList *Attrs,
740                       Instruction *Pos, BuiltinFuncMangleInfo *Mangle = nullptr,
741                       StringRef InstName = SPIR_TEMP_NAME_PREFIX_CALL,
742                       bool TakeFuncName = true);
743 
744 /// Add a call instruction for SPIR-V builtin function.
745 CallInst *addCallInstSPIRV(Module *M, StringRef FuncName, Type *RetTy,
746                            ArrayRef<Value *> Args, AttributeList *Attrs,
747                            Instruction *Pos, StringRef InstName);
748 
749 /// Add a call of spir_block_bind function.
750 CallInst *addBlockBind(Module *M, Function *InvokeFunc, Value *BlkCtx,
751                        Value *CtxLen, Value *CtxAlign, Instruction *InsPos,
752                        StringRef InstName = SPIR_TEMP_NAME_PREFIX_BLOCK);
753 
754 typedef std::pair<std::vector<Value *>::iterator,
755                   std::vector<Value *>::iterator>
756     ValueVecRange;
757 
758 /// Add a vector at \param InsPos.
759 Value *addVector(Instruction *InsPos, ValueVecRange Range);
760 
761 /// Replace scalar values with a vector created at \param InsPos.
762 void makeVector(Instruction *InsPos, std::vector<Value *> &Ops,
763                 ValueVecRange Range);
764 
765 /// Expand a vector type value in \param Ops at index \param VecPos.
766 /// Generate extract element instructions at \param InsPos and replace
767 /// the vector type value with scalar type values.
768 /// If the value to be expanded is not vector type, do nothing.
769 void expandVector(Instruction *InsPos, std::vector<Value *> &Ops,
770                   size_t VecPos);
771 
772 /// Get size_t type.
773 IntegerType *getSizetType(Module *M);
774 
775 /// Get void(void) function type.
776 Type *getVoidFuncType(Module *M);
777 
778 /// Get void(void) function pointer type.
779 Type *getVoidFuncPtrType(Module *M, unsigned AddrSpace = 0);
780 
781 /// Get a 64 bit integer constant.
782 ConstantInt *getInt64(Module *M, int64_t Value);
783 
784 /// Get a 32 bit integer constant.
785 ConstantInt *getInt32(Module *M, int Value);
786 
787 /// Get a 32 bit unsigned integer constant.
788 ConstantInt *getUInt32(Module *M, unsigned Value);
789 
790 /// Get 32 bit integer constant if the value fits in 32 bits,
791 /// return 64 bit integer constant otherwise
792 ConstantInt *getInt(Module *M, int64_t Value);
793 
794 /// Get 32 bit unsigned integer constant if the value fits in 32 bits,
795 /// return 64 bit unsigned integer constant otherwise
796 ConstantInt *getUInt(Module *M, uint64_t Value);
797 
798 /// Get a 16 bit unsigned integer constant.
799 ConstantInt *getUInt16(Module *M, unsigned short Value);
800 
801 // Get a 32 bit floating point constant.
802 Constant *getFloat32(Module *M, float Value);
803 
804 /// Get a 32 bit integer constant vector.
805 std::vector<Value *> getInt32(Module *M, const std::vector<int> &Value);
806 
807 /// Get a size_t type constant.
808 ConstantInt *getSizet(Module *M, uint64_t Value);
809 
810 /// Get metadata operand as int.
811 int64_t getMDOperandAsInt(MDNode *N, unsigned I);
812 
813 /// Get metadata operand as string.
814 std::string getMDOperandAsString(MDNode *N, unsigned I);
815 
816 /// Get metadata operand as another metadata node
817 MDNode *getMDOperandAsMDNode(MDNode *N, unsigned I);
818 
819 /// Get metadata operand as type.
820 Type *getMDOperandAsType(MDNode *N, unsigned I);
821 
822 /// Get a named metadata as a set of string.
823 /// Assume the named metadata has one or more operands each of which might
824 /// contain set of strings. For instance:
825 /// !opencl.used.optional.core.features = !{!0}
826 /// !0 = !{!"cl_doubles", !"cl_images"}
827 /// or if we linked two modules we may have
828 /// !opencl.used.optional.core.features = !{!0, !1}
829 /// !0 = !{!"cl_doubles"}
830 /// !1 = !{!"cl_images"}
831 std::set<std::string> getNamedMDAsStringSet(Module *M,
832                                             const std::string &MDName);
833 
834 /// Get SPIR-V language by SPIR-V metadata spirv.Source
835 std::tuple<unsigned, unsigned, std::string> getSPIRVSource(Module *M);
836 
837 /// Map an unsigned integer constant by applying a function.
838 ConstantInt *mapUInt(Module *M, ConstantInt *I,
839                      std::function<unsigned(unsigned)> F);
840 
841 /// Map a signed integer constant by applying a function.
842 ConstantInt *mapSInt(Module *M, ConstantInt *I, std::function<int(int)> F);
843 
844 /// Get postfix for given decoration.
845 /// The returned postfix does not include "_" at the beginning.
846 std::string getPostfix(Decoration Dec, unsigned Value = 0);
847 
848 /// Get postfix _R{ReturnType} for return type
849 /// The returned postfix does not includ "_" at the beginning
850 std::string getPostfixForReturnType(CallInst *CI, bool IsSigned = false);
851 std::string getPostfixForReturnType(const Type *PRetTy, bool IsSigned = false);
852 
853 Constant *getScalarOrVectorConstantInt(Type *T, uint64_t V,
854                                        bool IsSigned = false);
855 
856 /// Get a constant int or a constant int array.
857 /// \param T is the type of the constant. It should be an integer type or
858 //  an integer pointer type.
859 /// \param Len is the length of the array.
860 /// \param V is the value to fill the array.
861 Value *getScalarOrArrayConstantInt(Instruction *P, Type *T, unsigned Len,
862                                    uint64_t V, bool IsSigned = false);
863 
864 /// Get the array from GEP.
865 /// \param V is a GEP whose pointer operand is a pointer to an array of size
866 /// \param Size.
867 Value *getScalarOrArray(Value *V, unsigned Size, Instruction *Pos);
868 
869 void dumpUsers(Value *V, StringRef Prompt = "");
870 
871 /// Get SPIR-V type name as spirv.BaseTyName.Postfixes.
872 std::string getSPIRVTypeName(StringRef BaseTyName, StringRef Postfixes = "");
873 
874 /// Checks if given type name is either ConstantSampler or ConsantPipeStorage.
875 bool isSPIRVConstantName(StringRef TyName);
876 
877 /// Get SPIR-V type by changing the type name from spirv.OldName.Postfixes
878 /// to spirv.NewName.Postfixes.
879 Type *getSPIRVTypeByChangeBaseTypeName(Module *M, Type *T, StringRef OldName,
880                                        StringRef NewName);
881 
882 /// Get the postfixes of SPIR-V image type name as in spirv.Image.postfixes.
883 std::string getSPIRVImageTypePostfixes(StringRef SampledType,
884                                        SPIRVTypeImageDescriptor Desc,
885                                        SPIRVAccessQualifierKind Acc);
886 
887 /// Get the sampled type name used in postfix of image type in SPIR-V
888 /// friendly LLVM IR.
889 std::string getSPIRVImageSampledTypeName(SPIRVType *Ty);
890 
891 /// Translates OpenCL image type names to SPIR-V.
892 /// E.g. %opencl.image1d_rw_t -> %spirv.Image._void_0_0_0_0_0_0_2
893 Type *getSPIRVImageTypeFromOCL(Module *M, Type *T);
894 
895 /// Get LLVM type for sampled type of SPIR-V image type by postfix.
896 Type *getLLVMTypeForSPIRVImageSampledTypePostfix(StringRef Postfix,
897                                                  LLVMContext &Ctx);
898 
899 /// Return the unqualified and unsuffixed base name of an image type.
900 /// E.g. opencl.image2d_ro_t.3 -> image2d_t
901 std::string getImageBaseTypeName(StringRef Name);
902 
903 /// Map OpenCL opaque type name to SPIR-V type name.
904 std::string mapOCLTypeNameToSPIRV(StringRef Name, StringRef Acc = "");
905 
906 /// Check if access qualifier is encoded in the type name.
907 bool hasAccessQualifiedName(StringRef TyName);
908 
909 /// Get access qualifier from the type name.
910 SPIRVAccessQualifierKind getAccessQualifier(StringRef TyName);
911 
912 /// Get access qualifier from the type name.
913 StringRef getAccessQualifierPostfix(SPIRVAccessQualifierKind Access);
914 
915 /// Get access qualifier from the type name.
916 StringRef getAccessQualifierFullName(StringRef TyName);
917 
918 bool eraseUselessFunctions(Module *M);
919 
920 /// Erase a function if it is declaration, has internal linkage and has no use.
921 bool eraseIfNoUse(Function *F);
922 
923 void eraseIfNoUse(Value *V);
924 
925 // Check if a mangled type name is unsigned
926 bool isMangledTypeUnsigned(char Mangled);
927 
928 // Check if a mangled type name is signed
929 bool isMangledTypeSigned(char Mangled);
930 
931 // Check if a mangled type name is floating point (except half)
932 bool isMangledTypeFP(char Mangled);
933 
934 // Check if a mangled type name is half
935 bool isMangledTypeHalf(std::string Mangled);
936 
937 // Check if \param I is valid vector size: 2, 3, 4, 8, 16.
938 bool isValidVectorSize(unsigned I);
939 
940 enum class ParamType { FLOAT = 0, SIGNED = 1, UNSIGNED = 2, UNKNOWN = 3 };
941 
942 ParamType lastFuncParamType(StringRef MangledName);
943 
944 // Check if the last function parameter is signed
945 bool isLastFuncParamSigned(StringRef MangledName);
946 
947 // Check if a mangled function name contains unsigned atomic type
948 bool containsUnsignedAtomicType(StringRef Name);
949 
950 /// Mangle builtin function name.
951 /// \return \param UniqName if \param BtnInfo is null pointer, otherwise
952 ///    return IA64 mangled name.
953 std::string mangleBuiltin(StringRef UniqName, ArrayRef<Type *> ArgTypes,
954                           BuiltinFuncMangleInfo *BtnInfo);
955 
956 /// Mangle a function from OpenCL extended instruction set in SPIR-V friendly IR
957 /// manner
958 std::string getSPIRVFriendlyIRFunctionName(OCLExtOpKind ExtOpId,
959                                            ArrayRef<Type *> ArgTys,
960                                            Type *RetTy = nullptr);
961 
962 /// Mangle a function in SPIR-V friendly IR manner
963 /// \param UniqName full unmangled name of the SPIR-V built-in function that
964 /// contains possible postfixes that depend not on opcode but on decorations or
965 /// return type, for example __spirv_UConvert_Rint_sat.
966 /// \param OC opcode of corresponding built-in instruction. Used to gather info
967 /// for unsigned/constant arguments.
968 /// \param Types of arguments of SPIR-V built-in function
969 /// \return IA64 mangled name.
970 std::string getSPIRVFriendlyIRFunctionName(const std::string &UniqName,
971                                            spv::Op OC, ArrayRef<Type *> ArgTys);
972 
973 /// Remove cast from a value.
974 Value *removeCast(Value *V);
975 
976 /// Cast a function to a void(void) funtion pointer.
977 Constant *castToVoidFuncPtr(Function *F);
978 
979 /// Get i8* with the same address space.
980 PointerType *getInt8PtrTy(PointerType *T);
981 
982 /// Cast a value to a i8* by inserting a cast instruction.
983 Value *castToInt8Ptr(Value *V, Instruction *Pos);
984 
init()985 template <> inline void SPIRVMap<std::string, Op, SPIRVOpaqueType>::init() {
986 #define _SPIRV_OP(x) add(#x, OpType##x);
987   _SPIRV_OP(DeviceEvent)
988   _SPIRV_OP(Event)
989   _SPIRV_OP(Image)
990   _SPIRV_OP(Pipe)
991   _SPIRV_OP(Queue)
992   _SPIRV_OP(ReserveId)
993   _SPIRV_OP(Sampler)
994   _SPIRV_OP(SampledImage)
995   // SPV_INTEL_device_side_avc_motion_estimation types
996   _SPIRV_OP(AvcMcePayloadINTEL)
997   _SPIRV_OP(AvcImePayloadINTEL)
998   _SPIRV_OP(AvcRefPayloadINTEL)
999   _SPIRV_OP(AvcSicPayloadINTEL)
1000   _SPIRV_OP(AvcMceResultINTEL)
1001   _SPIRV_OP(AvcImeResultINTEL)
1002   _SPIRV_OP(AvcImeResultSingleReferenceStreamoutINTEL)
1003   _SPIRV_OP(AvcImeResultDualReferenceStreamoutINTEL)
1004   _SPIRV_OP(AvcImeSingleReferenceStreaminINTEL)
1005   _SPIRV_OP(AvcImeDualReferenceStreaminINTEL)
1006   _SPIRV_OP(AvcRefResultINTEL)
1007   _SPIRV_OP(AvcSicResultINTEL)
1008 #undef _SPIRV_OP
1009 }
1010 
1011 // Check if the module contains llvm.loop.* metadata
1012 bool hasLoopMetadata(const Module *M);
1013 
1014 // Check if CI is a call to instruction from OpenCL Extended Instruction Set.
1015 // If so, return it's extended opcode in ExtOp.
1016 bool isSPIRVOCLExtInst(const CallInst *CI, OCLExtOpKind *ExtOp);
1017 
1018 // check LLVM Intrinsics type(s) for validity
1019 bool checkTypeForSPIRVExtendedInstLowering(IntrinsicInst *II, SPIRVModule *BM);
1020 
1021 /// Decode SPIR-V type name in the format spirv.{TypeName}._{Postfixes}
1022 /// where Postfixes are strings separated by underscores.
1023 /// \return TypeName.
1024 /// \param Strs contains the integers decoded from postfixes.
1025 std::string decodeSPIRVTypeName(StringRef Name,
1026                                 SmallVectorImpl<std::string> &Strs);
1027 
1028 // Copy attributes from function to call site.
1029 void setAttrByCalledFunc(CallInst *Call);
1030 bool isSPIRVBuiltinVariable(GlobalVariable *GV, SPIRVBuiltinVariableKind *Kind);
1031 // Transform builtin variable from GlobalVariable to builtin call.
1032 // e.g.
1033 // - GlobalInvolcationId[x] -> _Z33__spirv_BuiltInGlobalInvocationIdi(x)
1034 // - WorkDim -> _Z22__spirv_BuiltInWorkDimv()
1035 bool lowerBuiltinVariableToCall(GlobalVariable *GV,
1036                                 SPIRVBuiltinVariableKind Kind);
1037 // Transform all builtin variables into calls
1038 bool lowerBuiltinVariablesToCalls(Module *M);
1039 
1040 /// \brief Post-process OpenCL or SPIRV builtin function returning struct type.
1041 ///
1042 /// Some builtin functions are translated to SPIR-V instructions with
1043 /// struct type result, e.g. NDRange creation functions. Such functions
1044 /// need to be post-processed to return the struct through sret argument.
1045 bool postProcessBuiltinReturningStruct(Function *F);
1046 
1047 /// \brief Post-process OpenCL or SPIRV builtin function having array argument.
1048 ///
1049 /// These functions are translated to functions with array type argument
1050 /// first, then post-processed to have pointer arguments.
1051 bool postProcessBuiltinWithArrayArguments(Function *F, StringRef DemangledName);
1052 
1053 bool postProcessBuiltinsReturningStruct(Module *M, bool IsCpp = false);
1054 
1055 bool postProcessBuiltinsWithArrayArguments(Module *M, bool IsCpp = false);
1056 
1057 } // namespace SPIRV
1058 
1059 #endif // SPIRV_SPIRVINTERNAL_H
1060