@@ -17,7 +17,7 @@ an obvious way. These include:
1717 * SPIR-V types mapped to LLVM types
1818 * SPIR-V instructions mapped to LLVM function calls
1919 * SPIR-V extended instructions mapped to LLVM function calls
20- * SPIR-V builtins variables mapped to LLVM global variables
20+ * SPIR-V builtin variables mapped to LLVM function calls or LLVM global variables
2121 * SPIR-V instructions mapped to LLVM metadata
2222 * SPIR-V types mapped to LLVM opaque types
2323 * SPIR-V decorations mapped to LLVM metadata or named attributes
@@ -203,11 +203,58 @@ where
203203 * {VectorLoadOpCodeName} = vloadn|vload_half|vload_halfn|vloada_halfn
204204
205205
206- SPIR-V Builtins Variables Mapped to LLVM Global Variables
207- =========================================================
206+ SPIR-V Builtin Variables Mapped to LLVM Function Calls or LLVM Global Variables
207+ ===============================================================================
208208
209- SPIR-V builtin variables are mapped to LLVM global variables with unmangled
210- name __spirv_BuiltIn{Name}.
209+ By default each access of SPIR-V builtin variable's value is mapped to LLVM
210+ function call. The unmangled names of these functions follow the convention:
211+
212+ .. code-block :: c
213+
214+ __spirv_BuiltIn{VariableName}
215+
216+ In case if SPIR-V builtin variable has vector type, the corresponding
217+ LLVM function will have an integer argument, so each access of the variable's
218+ scalar component is mapped to a function call with index argument, i.e.:
219+
220+ .. code-block :: llvm
221+
222+ ; For scalar variables
223+ ; SPIR-V
224+ OpDecorate %__spirv_BuiltInGlobalInvocationId BuiltIn GlobalInvocationId
225+ %13 = OpLoad %uint %__spirv_BuiltInGlobalLinearId Aligned 4
226+
227+ ; Will be transformed into the following LLVM IR:
228+ %0 = call spir_func i32 @_Z29__spirv_BuiltInGlobalLinearIdv()
229+
230+ ; For vector variables
231+ ; SPIRV
232+ OpDecorate %__spirv_BuiltInGlobalInvocationId BuiltIn GlobalInvocationId
233+ %14 = OpLoad %v3ulong %__spirv_BuiltInGlobalInvocationId Aligned 32
234+ %15 = OpCompositeExtract %ulong %14 1
235+
236+ ; Can be transformed into the following LLVM IR:
237+ %0 = call spir_func i64 @_Z33__spirv_BuiltInGlobalInvocationIdi(i32 1)
238+
239+ ; However SPIRV-LLVM translator will transform it to the following pattern:
240+ %1 = call spir_func i64 @_Z33__spirv_BuiltInGlobalInvocationIdi(i32 0)
241+ %2 = insertelement <3 x i64> undef, i64 %1, i32 0
242+ %3 = call spir_func i64 @_Z33__spirv_BuiltInGlobalInvocationIdi(i32 1)
243+ %4 = insertelement <3 x i64> %2, i64 %3, i32 1
244+ %5 = call spir_func i64 @_Z33__spirv_BuiltInGlobalInvocationIdi(i32 2)
245+ %6 = insertelement <3 x i64> %4, i64 %5, i32 2
246+ %7 = extractelement <3 x i64> %6, i32 1
247+ ; In case some actions are performed with the variable's value in vector form.
248+
249+ SPIR-V builtin variables can also be mapped to LLVM global variables with
250+ unmangled name __spirv_BuiltIn{Name}.
251+
252+ The representation with variables is closer to SPIR-V, so it is easier to
253+ translate from SPIR-V to LLVM and back using it.
254+ Hovewer in languages like OpenCL the functionality covered by SPIR-V builtin
255+ variables is usually represented by builtin functions, so it is easier to
256+ translate from/to SPIR-V friendly IR to/from LLVM IR produced from OpenCL-like
257+ source languages. That is why both forms of mapping are supported.
211258
212259SPIR-V instructions mapped to LLVM metadata
213260===========================================
0 commit comments