@@ -108,7 +108,7 @@ the `__sycl_getSpecConstantValue` calls with constants - default values of
108
108
the spec constant's type. No maps are generated, and SYCL program can't change
109
109
the value of a spec constant.
110
110
111
- #### LLVMIR- SPIR-V translator
111
+ #### LLVM -> SPIR-V translation
112
112
113
113
Given the `__spirv_SpecConstant` intrinsic calls produced by the
114
114
`SpecConstants` pass:
@@ -175,7 +175,7 @@ struct A {
175
175
176
176
struct POD {
177
177
A a[2];
178
- int b;
178
+ cl::sycl::vec< int, 2> b;
179
179
};
180
180
```
181
181
@@ -187,7 +187,7 @@ and the user says
187
187
{ goldi, goldf },
188
188
{ goldi + 1, goldf + 1 },
189
189
},
190
- goldi
190
+ { goldi, goldi }
191
191
};
192
192
193
193
cl::sycl::ONEAPI::experimental::spec_constant<POD, MyConst> sc = program4.set_spec_constant<MyConst >(gold);
@@ -197,21 +197,27 @@ and the user says
197
197
198
198
##### The SpecConstant pass changes
199
199
200
- - The SpecConstants pass in the post-link will have the following IR as input (`sret` conversion is omitted for clarity):
200
+ The SpecConstants pass in the post-link will have the following IR as input
201
+ (`sret` conversion is omitted for clarity):
201
202
202
203
```
203
- %struct.POD = type { [ 2 x %struct.A] , i32 }
204
+ %struct.POD = type { [ 2 x %struct.A] , <2 x i32> }
204
205
%struct.A = type { i32, float }
205
206
206
- %spec_const = call %struct.POD __ sycl_getSpecConstantValue <POD type mangling > ("MyConst_mangled")
207
+ %spec_const = call %struct.POD __ sycl_getCompositeSpecConstantValue <POD type mangling > ("MyConst_mangled")
207
208
```
208
209
209
- Based on the fact that `__sycl_getSpecConstantValue` returns `llvm::StructType`,
210
- it will be replaced with a set of `__spirv_SpecConstant` calls for each member
211
- of its return type plus one `__spirv_SpecConstantComposite` to gather members
212
- back into a single composite. If any composite member is another composite, then
213
- it will be also represented by number of `__spirv_SpecConstant` plus one
214
- `__spirv_SpecConstantComposite`:
210
+ `__sycl_getCompositeSpecConstantValue` is a new "intrinsic" (in addition to
211
+ `__sycl_getSpecConstantValue`) recognized by `SpecConstants` pass, which creates
212
+ a value of a composite (of non-primitive type) specialization constant.
213
+ It does not need a default value, because its default value consists of default
214
+ values of its leaf specialization constants (see below).
215
+
216
+ `__sycl_getCompositeSpecConstantValue` will be replaced with a set of
217
+ `__spirv_SpecConstant` calls for each member of its return type plus one
218
+ `__spirv_SpecConstantComposite` to gather members back into a single composite.
219
+ If any composite member is another composite, then it will be also represented
220
+ by number of `__spirv_SpecConstant` plus one `__spirv_SpecConstantComposite`:
215
221
216
222
```
217
223
%gold_POD_A0_x = call i32 __ spirv_SpecConstant(i32 10, i32 0)
@@ -225,9 +231,12 @@ it will be also represented by number of `__spirv_SpecConstant` plus one
225
231
%gold_POD_A1 = call %struct.A __ spirv_SpecConstantComposite(i32 %gold_POD_A1_x, float %gold_POD_A1_y)
226
232
227
233
%gold_POD_A = call [ 2 x %struct.A] __ spirv_SpecConstantComposite(%struct.A %gold_POD_A0, %struct.A %gold_POD_A1)
228
- %gold_POD_b = call i32 __ spirv_SpecConstant(i32 14, i32 0)
229
234
230
- %gold = call %struct.POD __ spirv_SpecConstantComposite([ 2 x %struct.A] %gold_POD_A, i32 %gold_POD_b)
235
+ %gold_POD_b0 = call i32 __ spirv_SpecConstant(i32 14, i32 0)
236
+ %gold_POD_b1 = call i32 __ spirv_SpecConstant(i32 15, i32 0)
237
+ %gold_POD_b = call <2 x i32> __ spirv_SpecConstant(i32 %gold_POD_b0, i32 %gold_POD_b1)
238
+
239
+ %gold = call %struct.POD __ spirv_SpecConstantComposite([ 2 x %struct.A] %gold_POD_A, <2 x i32> %gold_POD_b)
231
240
232
241
```
233
242
@@ -236,6 +245,46 @@ it - it will use IDs of the leaves instead.
236
245
Yet, the SPIR-V specification does not allow `SpecID` decoration for composite
237
246
spec constants, because its defined by its members instead.
238
247
248
+ `__spirv_SpecConstantComposite` is a new "intrinsic", which represents composite
249
+ specialization constant. Its arguments are LLVM IR valures corresponding to
250
+ elements of composite type of the constant.
251
+
252
+ ##### LLVM -> SPIR-V translation
253
+
254
+ Given the `__spirv_SpecConstantComposite` intrinsic calls produced by the
255
+ `SpecConstants` pass:
256
+ ```
257
+
258
+ %struct.A = type { i32, float }
259
+
260
+ ; Function Attrs: alwaysinline
261
+ define dso_local spir_func void @get (%struct.A* sret %ret.ptr) local_unnamed_addr #0 {
262
+ ; args are "ID" and "default value":
263
+ %1 = tail call spir_func i32 @_ Z20__ spirv_SpecConstantii(i32 42, i32 0)
264
+ %2 = tail call spir_func i32 @_ Z20__ spirv_SpecConstantif(i32 43, float 0.000000e+00)
265
+ %ret = tail call spir_func %struct.A @_ Z29__ spirv_SpecConstantCompositeif(%1, %2)
266
+ store %struct.A %ret, %struct.A* %ret.ptr
267
+ ret void
268
+ }
269
+ ```
270
+
271
+ the translator will generate ` OpSpecConstant ` and ` OpSpecConstantComposite `
272
+ SPIR-V instructions with proper ` SpecId ` decorations:
273
+
274
+ ```
275
+ OpDecorate %i32 SpecId 42 ; ID
276
+ OpDecorate %float SpecId 43 ; ID
277
+ %i32 = OpSpecConstant %int.type 0 ; Default value
278
+ %float = OpSpecConstant %float.type 0.0 ; Default value
279
+ %struct = OpSpecConstantComposite %struct.type %i32 %float ; No ID, defined by its elements
280
+ %1 = OpTypeFunction %struct.type
281
+
282
+ %get = OpFunction %struct.type None %1
283
+ %2 = OpLabel
284
+ OpReturnValue %struct
285
+ OpFunctionEnd
286
+ ```
287
+
239
288
##### The post-link tool changes
240
289
241
290
For composite specialization constants the post link tool will additionally
0 commit comments