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