1 // RUN: mlir-opt -split-input-file -convert-memref-to-spirv="bool-num-bits=8" %s -o - | FileCheck %s
3 // Check that with proper compute and storage extensions, we don't need to
4 // perform special tricks.
7 spv.target_env = #spv.target_env<
10 Shader, Int8, Int16, Int64, Float16, Float64,
11 StorageBuffer16BitAccess, StorageUniform16, StoragePushConstant16,
12 StorageBuffer8BitAccess, UniformAndStorageBuffer8BitAccess, StoragePushConstant8
14 [SPV_KHR_16bit_storage, SPV_KHR_8bit_storage, SPV_KHR_storage_buffer_storage_class]>, {}>
17 // CHECK-LABEL: @load_store_zero_rank_float
18 func @load_store_zero_rank_float(%arg0: memref<f32>, %arg1: memref<f32>) {
19 // CHECK: [[ARG0:%.*]] = builtin.unrealized_conversion_cast {{.+}} : memref<f32> to !spv.ptr<!spv.struct<(!spv.array<1 x f32, stride=4> [0])>, StorageBuffer>
20 // CHECK: [[ARG1:%.*]] = builtin.unrealized_conversion_cast {{.+}} : memref<f32> to !spv.ptr<!spv.struct<(!spv.array<1 x f32, stride=4> [0])>, StorageBuffer>
21 // CHECK: [[ZERO1:%.*]] = spv.Constant 0 : i32
22 // CHECK: spv.AccessChain [[ARG0]][
23 // CHECK-SAME: [[ZERO1]], [[ZERO1]]
25 // CHECK: spv.Load "StorageBuffer" %{{.*}} : f32
26 %0 = memref.load %arg0[] : memref<f32>
27 // CHECK: [[ZERO2:%.*]] = spv.Constant 0 : i32
28 // CHECK: spv.AccessChain [[ARG1]][
29 // CHECK-SAME: [[ZERO2]], [[ZERO2]]
31 // CHECK: spv.Store "StorageBuffer" %{{.*}} : f32
32 memref.store %0, %arg1[] : memref<f32>
36 // CHECK-LABEL: @load_store_zero_rank_int
37 func @load_store_zero_rank_int(%arg0: memref<i32>, %arg1: memref<i32>) {
38 // CHECK: [[ARG0:%.*]] = builtin.unrealized_conversion_cast {{.+}} : memref<i32> to !spv.ptr<!spv.struct<(!spv.array<1 x i32, stride=4> [0])>, StorageBuffer>
39 // CHECK: [[ARG1:%.*]] = builtin.unrealized_conversion_cast {{.+}} : memref<i32> to !spv.ptr<!spv.struct<(!spv.array<1 x i32, stride=4> [0])>, StorageBuffer>
40 // CHECK: [[ZERO1:%.*]] = spv.Constant 0 : i32
41 // CHECK: spv.AccessChain [[ARG0]][
42 // CHECK-SAME: [[ZERO1]], [[ZERO1]]
44 // CHECK: spv.Load "StorageBuffer" %{{.*}} : i32
45 %0 = memref.load %arg0[] : memref<i32>
46 // CHECK: [[ZERO2:%.*]] = spv.Constant 0 : i32
47 // CHECK: spv.AccessChain [[ARG1]][
48 // CHECK-SAME: [[ZERO2]], [[ZERO2]]
50 // CHECK: spv.Store "StorageBuffer" %{{.*}} : i32
51 memref.store %0, %arg1[] : memref<i32>
55 // CHECK-LABEL: func @load_store_unknown_dim
56 func @load_store_unknown_dim(%i: index, %source: memref<?xi32>, %dest: memref<?xi32>) {
57 // CHECK: %[[SRC:.+]] = builtin.unrealized_conversion_cast {{.+}} : memref<?xi32> to !spv.ptr<!spv.struct<(!spv.rtarray<i32, stride=4> [0])>, StorageBuffer>
58 // CHECK: %[[DST:.+]] = builtin.unrealized_conversion_cast {{.+}} : memref<?xi32> to !spv.ptr<!spv.struct<(!spv.rtarray<i32, stride=4> [0])>, StorageBuffer>
59 // CHECK: %[[AC0:.+]] = spv.AccessChain %[[SRC]]
60 // CHECK: spv.Load "StorageBuffer" %[[AC0]]
61 %0 = memref.load %source[%i] : memref<?xi32>
62 // CHECK: %[[AC1:.+]] = spv.AccessChain %[[DST]]
63 // CHECK: spv.Store "StorageBuffer" %[[AC1]]
64 memref.store %0, %dest[%i]: memref<?xi32>
68 // CHECK-LABEL: func @load_i1
69 // CHECK-SAME: (%[[SRC:.+]]: memref<4xi1>, %[[IDX:.+]]: index)
70 func @load_i1(%src: memref<4xi1>, %i : index) -> i1 {
71 // CHECK-DAG: %[[SRC_CAST:.+]] = builtin.unrealized_conversion_cast %[[SRC]] : memref<4xi1> to !spv.ptr<!spv.struct<(!spv.array<4 x i8, stride=1> [0])>, StorageBuffer>
72 // CHECK-DAG: %[[IDX_CAST:.+]] = builtin.unrealized_conversion_cast %[[IDX]]
73 // CHECK: %[[ZERO_0:.+]] = spv.Constant 0 : i32
74 // CHECK: %[[ZERO_1:.+]] = spv.Constant 0 : i32
75 // CHECK: %[[ONE:.+]] = spv.Constant 1 : i32
76 // CHECK: %[[MUL:.+]] = spv.IMul %[[ONE]], %[[IDX_CAST]] : i32
77 // CHECK: %[[ADD:.+]] = spv.IAdd %[[ZERO_1]], %[[MUL]] : i32
78 // CHECK: %[[ADDR:.+]] = spv.AccessChain %[[SRC_CAST]][%[[ZERO_0]], %[[ADD]]]
79 // CHECK: %[[VAL:.+]] = spv.Load "StorageBuffer" %[[ADDR]] : i8
80 // CHECK: %[[ONE_I8:.+]] = spv.Constant 1 : i8
81 // CHECK: %[[BOOL:.+]] = spv.IEqual %[[VAL]], %[[ONE_I8]] : i8
82 %0 = memref.load %src[%i] : memref<4xi1>
83 // CHECK: return %[[BOOL]]
87 // CHECK-LABEL: func @store_i1
88 // CHECK-SAME: %[[DST:.+]]: memref<4xi1>,
89 // CHECK-SAME: %[[IDX:.+]]: index
90 func @store_i1(%dst: memref<4xi1>, %i: index) {
91 %true = arith.constant true
92 // CHECK-DAG: %[[DST_CAST:.+]] = builtin.unrealized_conversion_cast %[[DST]] : memref<4xi1> to !spv.ptr<!spv.struct<(!spv.array<4 x i8, stride=1> [0])>, StorageBuffer>
93 // CHECK-DAG: %[[IDX_CAST:.+]] = builtin.unrealized_conversion_cast %[[IDX]]
94 // CHECK: %[[ZERO_0:.+]] = spv.Constant 0 : i32
95 // CHECK: %[[ZERO_1:.+]] = spv.Constant 0 : i32
96 // CHECK: %[[ONE:.+]] = spv.Constant 1 : i32
97 // CHECK: %[[MUL:.+]] = spv.IMul %[[ONE]], %[[IDX_CAST]] : i32
98 // CHECK: %[[ADD:.+]] = spv.IAdd %[[ZERO_1]], %[[MUL]] : i32
99 // CHECK: %[[ADDR:.+]] = spv.AccessChain %[[DST_CAST]][%[[ZERO_0]], %[[ADD]]]
100 // CHECK: %[[ZERO_I8:.+]] = spv.Constant 0 : i8
101 // CHECK: %[[ONE_I8:.+]] = spv.Constant 1 : i8
102 // CHECK: %[[RES:.+]] = spv.Select %{{.+}}, %[[ONE_I8]], %[[ZERO_I8]] : i1, i8
103 // CHECK: spv.Store "StorageBuffer" %[[ADDR]], %[[RES]] : i8
104 memref.store %true, %dst[%i]: memref<4xi1>
112 // Check that access chain indices are properly adjusted if non-32-bit types are
113 // emulated via 32-bit types.
114 // TODO: Test i64 types.
116 spv.target_env = #spv.target_env<
117 #spv.vce<v1.0, [Shader], [SPV_KHR_storage_buffer_storage_class]>, {}>
120 // CHECK-LABEL: @load_i1
121 func @load_i1(%arg0: memref<i1>) -> i1 {
122 // CHECK: %[[ZERO:.+]] = spv.Constant 0 : i32
123 // CHECK: %[[FOUR1:.+]] = spv.Constant 4 : i32
124 // CHECK: %[[QUOTIENT:.+]] = spv.SDiv %[[ZERO]], %[[FOUR1]] : i32
125 // CHECK: %[[PTR:.+]] = spv.AccessChain %{{.+}}[%[[ZERO]], %[[QUOTIENT]]]
126 // CHECK: %[[LOAD:.+]] = spv.Load "StorageBuffer" %[[PTR]]
127 // CHECK: %[[FOUR2:.+]] = spv.Constant 4 : i32
128 // CHECK: %[[EIGHT:.+]] = spv.Constant 8 : i32
129 // CHECK: %[[IDX:.+]] = spv.UMod %[[ZERO]], %[[FOUR2]] : i32
130 // CHECK: %[[BITS:.+]] = spv.IMul %[[IDX]], %[[EIGHT]] : i32
131 // CHECK: %[[VALUE:.+]] = spv.ShiftRightArithmetic %[[LOAD]], %[[BITS]] : i32, i32
132 // CHECK: %[[MASK:.+]] = spv.Constant 255 : i32
133 // CHECK: %[[T1:.+]] = spv.BitwiseAnd %[[VALUE]], %[[MASK]] : i32
134 // CHECK: %[[T2:.+]] = spv.Constant 24 : i32
135 // CHECK: %[[T3:.+]] = spv.ShiftLeftLogical %[[T1]], %[[T2]] : i32, i32
136 // CHECK: %[[T4:.+]] = spv.ShiftRightArithmetic %[[T3]], %[[T2]] : i32, i32
137 // Convert to i1 type.
138 // CHECK: %[[ONE:.+]] = spv.Constant 1 : i32
139 // CHECK: %[[RES:.+]] = spv.IEqual %[[T4]], %[[ONE]] : i32
140 // CHECK: return %[[RES]]
141 %0 = memref.load %arg0[] : memref<i1>
145 // CHECK-LABEL: @load_i8
146 func @load_i8(%arg0: memref<i8>) {
147 // CHECK: %[[ZERO:.+]] = spv.Constant 0 : i32
148 // CHECK: %[[FOUR1:.+]] = spv.Constant 4 : i32
149 // CHECK: %[[QUOTIENT:.+]] = spv.SDiv %[[ZERO]], %[[FOUR1]] : i32
150 // CHECK: %[[PTR:.+]] = spv.AccessChain %{{.+}}[%[[ZERO]], %[[QUOTIENT]]]
151 // CHECK: %[[LOAD:.+]] = spv.Load "StorageBuffer" %[[PTR]]
152 // CHECK: %[[FOUR2:.+]] = spv.Constant 4 : i32
153 // CHECK: %[[EIGHT:.+]] = spv.Constant 8 : i32
154 // CHECK: %[[IDX:.+]] = spv.UMod %[[ZERO]], %[[FOUR2]] : i32
155 // CHECK: %[[BITS:.+]] = spv.IMul %[[IDX]], %[[EIGHT]] : i32
156 // CHECK: %[[VALUE:.+]] = spv.ShiftRightArithmetic %[[LOAD]], %[[BITS]] : i32, i32
157 // CHECK: %[[MASK:.+]] = spv.Constant 255 : i32
158 // CHECK: %[[T1:.+]] = spv.BitwiseAnd %[[VALUE]], %[[MASK]] : i32
159 // CHECK: %[[T2:.+]] = spv.Constant 24 : i32
160 // CHECK: %[[T3:.+]] = spv.ShiftLeftLogical %[[T1]], %[[T2]] : i32, i32
161 // CHECK: spv.ShiftRightArithmetic %[[T3]], %[[T2]] : i32, i32
162 %0 = memref.load %arg0[] : memref<i8>
166 // CHECK-LABEL: @load_i16
167 // CHECK: (%[[ARG0:.+]]: {{.*}}, %[[ARG1:.+]]: index)
168 func @load_i16(%arg0: memref<10xi16>, %index : index) {
169 // CHECK: %[[ARG1_CAST:.+]] = builtin.unrealized_conversion_cast %[[ARG1]] : index to i32
170 // CHECK: %[[ZERO:.+]] = spv.Constant 0 : i32
171 // CHECK: %[[OFFSET:.+]] = spv.Constant 0 : i32
172 // CHECK: %[[ONE:.+]] = spv.Constant 1 : i32
173 // CHECK: %[[UPDATE:.+]] = spv.IMul %[[ONE]], %[[ARG1_CAST]] : i32
174 // CHECK: %[[FLAT_IDX:.+]] = spv.IAdd %[[OFFSET]], %[[UPDATE]] : i32
175 // CHECK: %[[TWO1:.+]] = spv.Constant 2 : i32
176 // CHECK: %[[QUOTIENT:.+]] = spv.SDiv %[[FLAT_IDX]], %[[TWO1]] : i32
177 // CHECK: %[[PTR:.+]] = spv.AccessChain %{{.+}}[%[[ZERO]], %[[QUOTIENT]]]
178 // CHECK: %[[LOAD:.+]] = spv.Load "StorageBuffer" %[[PTR]]
179 // CHECK: %[[TWO2:.+]] = spv.Constant 2 : i32
180 // CHECK: %[[SIXTEEN:.+]] = spv.Constant 16 : i32
181 // CHECK: %[[IDX:.+]] = spv.UMod %[[FLAT_IDX]], %[[TWO2]] : i32
182 // CHECK: %[[BITS:.+]] = spv.IMul %[[IDX]], %[[SIXTEEN]] : i32
183 // CHECK: %[[VALUE:.+]] = spv.ShiftRightArithmetic %[[LOAD]], %[[BITS]] : i32, i32
184 // CHECK: %[[MASK:.+]] = spv.Constant 65535 : i32
185 // CHECK: %[[T1:.+]] = spv.BitwiseAnd %[[VALUE]], %[[MASK]] : i32
186 // CHECK: %[[T2:.+]] = spv.Constant 16 : i32
187 // CHECK: %[[T3:.+]] = spv.ShiftLeftLogical %[[T1]], %[[T2]] : i32, i32
188 // CHECK: spv.ShiftRightArithmetic %[[T3]], %[[T2]] : i32, i32
189 %0 = memref.load %arg0[%index] : memref<10xi16>
193 // CHECK-LABEL: @load_i32
194 func @load_i32(%arg0: memref<i32>) {
195 // CHECK-NOT: spv.SDiv
197 // CHECK-NOT: spv.ShiftRightArithmetic
198 %0 = memref.load %arg0[] : memref<i32>
202 // CHECK-LABEL: @load_f32
203 func @load_f32(%arg0: memref<f32>) {
204 // CHECK-NOT: spv.SDiv
206 // CHECK-NOT: spv.ShiftRightArithmetic
207 %0 = memref.load %arg0[] : memref<f32>
211 // CHECK-LABEL: @store_i1
212 // CHECK: (%[[ARG0:.+]]: {{.*}}, %[[ARG1:.+]]: i1)
213 func @store_i1(%arg0: memref<i1>, %value: i1) {
214 // CHECK: %[[ARG0_CAST:.+]] = builtin.unrealized_conversion_cast %[[ARG0]]
215 // CHECK: %[[ZERO:.+]] = spv.Constant 0 : i32
216 // CHECK: %[[FOUR:.+]] = spv.Constant 4 : i32
217 // CHECK: %[[EIGHT:.+]] = spv.Constant 8 : i32
218 // CHECK: %[[IDX:.+]] = spv.UMod %[[ZERO]], %[[FOUR]] : i32
219 // CHECK: %[[OFFSET:.+]] = spv.IMul %[[IDX]], %[[EIGHT]] : i32
220 // CHECK: %[[MASK1:.+]] = spv.Constant 255 : i32
221 // CHECK: %[[TMP1:.+]] = spv.ShiftLeftLogical %[[MASK1]], %[[OFFSET]] : i32, i32
222 // CHECK: %[[MASK:.+]] = spv.Not %[[TMP1]] : i32
223 // CHECK: %[[ZERO1:.+]] = spv.Constant 0 : i32
224 // CHECK: %[[ONE1:.+]] = spv.Constant 1 : i32
225 // CHECK: %[[CASTED_ARG1:.+]] = spv.Select %[[ARG1]], %[[ONE1]], %[[ZERO1]] : i1, i32
226 // CHECK: %[[CLAMPED_VAL:.+]] = spv.BitwiseAnd %[[CASTED_ARG1]], %[[MASK1]] : i32
227 // CHECK: %[[STORE_VAL:.+]] = spv.ShiftLeftLogical %[[CLAMPED_VAL]], %[[OFFSET]] : i32, i32
228 // CHECK: %[[FOUR2:.+]] = spv.Constant 4 : i32
229 // CHECK: %[[ACCESS_IDX:.+]] = spv.SDiv %[[ZERO]], %[[FOUR2]] : i32
230 // CHECK: %[[PTR:.+]] = spv.AccessChain %[[ARG0_CAST]][%[[ZERO]], %[[ACCESS_IDX]]]
231 // CHECK: spv.AtomicAnd "Device" "AcquireRelease" %[[PTR]], %[[MASK]]
232 // CHECK: spv.AtomicOr "Device" "AcquireRelease" %[[PTR]], %[[STORE_VAL]]
233 memref.store %value, %arg0[] : memref<i1>
237 // CHECK-LABEL: @store_i8
238 // CHECK: (%[[ARG0:.+]]: {{.*}}, %[[ARG1:.+]]: i8)
239 func @store_i8(%arg0: memref<i8>, %value: i8) {
240 // CHECK-DAG: %[[ARG1_CAST:.+]] = builtin.unrealized_conversion_cast %[[ARG1]] : i8 to i32
241 // CHECK-DAG: %[[ARG0_CAST:.+]] = builtin.unrealized_conversion_cast %[[ARG0]]
242 // CHECK: %[[ZERO:.+]] = spv.Constant 0 : i32
243 // CHECK: %[[FOUR:.+]] = spv.Constant 4 : i32
244 // CHECK: %[[EIGHT:.+]] = spv.Constant 8 : i32
245 // CHECK: %[[IDX:.+]] = spv.UMod %[[ZERO]], %[[FOUR]] : i32
246 // CHECK: %[[OFFSET:.+]] = spv.IMul %[[IDX]], %[[EIGHT]] : i32
247 // CHECK: %[[MASK1:.+]] = spv.Constant 255 : i32
248 // CHECK: %[[TMP1:.+]] = spv.ShiftLeftLogical %[[MASK1]], %[[OFFSET]] : i32, i32
249 // CHECK: %[[MASK:.+]] = spv.Not %[[TMP1]] : i32
250 // CHECK: %[[CLAMPED_VAL:.+]] = spv.BitwiseAnd %[[ARG1_CAST]], %[[MASK1]] : i32
251 // CHECK: %[[STORE_VAL:.+]] = spv.ShiftLeftLogical %[[CLAMPED_VAL]], %[[OFFSET]] : i32, i32
252 // CHECK: %[[FOUR2:.+]] = spv.Constant 4 : i32
253 // CHECK: %[[ACCESS_IDX:.+]] = spv.SDiv %[[ZERO]], %[[FOUR2]] : i32
254 // CHECK: %[[PTR:.+]] = spv.AccessChain %[[ARG0_CAST]][%[[ZERO]], %[[ACCESS_IDX]]]
255 // CHECK: spv.AtomicAnd "Device" "AcquireRelease" %[[PTR]], %[[MASK]]
256 // CHECK: spv.AtomicOr "Device" "AcquireRelease" %[[PTR]], %[[STORE_VAL]]
257 memref.store %value, %arg0[] : memref<i8>
261 // CHECK-LABEL: @store_i16
262 // CHECK: (%[[ARG0:.+]]: memref<10xi16>, %[[ARG1:.+]]: index, %[[ARG2:.+]]: i16)
263 func @store_i16(%arg0: memref<10xi16>, %index: index, %value: i16) {
264 // CHECK-DAG: %[[ARG2_CAST:.+]] = builtin.unrealized_conversion_cast %[[ARG2]] : i16 to i32
265 // CHECK-DAG: %[[ARG0_CAST:.+]] = builtin.unrealized_conversion_cast %[[ARG0]]
266 // CHECK-DAG: %[[ARG1_CAST:.+]] = builtin.unrealized_conversion_cast %[[ARG1]] : index to i32
267 // CHECK: %[[ZERO:.+]] = spv.Constant 0 : i32
268 // CHECK: %[[OFFSET:.+]] = spv.Constant 0 : i32
269 // CHECK: %[[ONE:.+]] = spv.Constant 1 : i32
270 // CHECK: %[[UPDATE:.+]] = spv.IMul %[[ONE]], %[[ARG1_CAST]] : i32
271 // CHECK: %[[FLAT_IDX:.+]] = spv.IAdd %[[OFFSET]], %[[UPDATE]] : i32
272 // CHECK: %[[TWO:.+]] = spv.Constant 2 : i32
273 // CHECK: %[[SIXTEEN:.+]] = spv.Constant 16 : i32
274 // CHECK: %[[IDX:.+]] = spv.UMod %[[FLAT_IDX]], %[[TWO]] : i32
275 // CHECK: %[[OFFSET:.+]] = spv.IMul %[[IDX]], %[[SIXTEEN]] : i32
276 // CHECK: %[[MASK1:.+]] = spv.Constant 65535 : i32
277 // CHECK: %[[TMP1:.+]] = spv.ShiftLeftLogical %[[MASK1]], %[[OFFSET]] : i32, i32
278 // CHECK: %[[MASK:.+]] = spv.Not %[[TMP1]] : i32
279 // CHECK: %[[CLAMPED_VAL:.+]] = spv.BitwiseAnd %[[ARG2_CAST]], %[[MASK1]] : i32
280 // CHECK: %[[STORE_VAL:.+]] = spv.ShiftLeftLogical %[[CLAMPED_VAL]], %[[OFFSET]] : i32, i32
281 // CHECK: %[[TWO2:.+]] = spv.Constant 2 : i32
282 // CHECK: %[[ACCESS_IDX:.+]] = spv.SDiv %[[FLAT_IDX]], %[[TWO2]] : i32
283 // CHECK: %[[PTR:.+]] = spv.AccessChain %[[ARG0_CAST]][%[[ZERO]], %[[ACCESS_IDX]]]
284 // CHECK: spv.AtomicAnd "Device" "AcquireRelease" %[[PTR]], %[[MASK]]
285 // CHECK: spv.AtomicOr "Device" "AcquireRelease" %[[PTR]], %[[STORE_VAL]]
286 memref.store %value, %arg0[%index] : memref<10xi16>
290 // CHECK-LABEL: @store_i32
291 func @store_i32(%arg0: memref<i32>, %value: i32) {
293 // CHECK-NOT: spv.AtomicAnd
294 // CHECK-NOT: spv.AtomicOr
295 memref.store %value, %arg0[] : memref<i32>
299 // CHECK-LABEL: @store_f32
300 func @store_f32(%arg0: memref<f32>, %value: f32) {
302 // CHECK-NOT: spv.AtomicAnd
303 // CHECK-NOT: spv.AtomicOr
304 memref.store %value, %arg0[] : memref<f32>
312 // Check that access chain indices are properly adjusted if non-16/32-bit types
313 // are emulated via 32-bit types.
315 spv.target_env = #spv.target_env<
316 #spv.vce<v1.0, [Int16, StorageBuffer16BitAccess, Shader],
317 [SPV_KHR_storage_buffer_storage_class, SPV_KHR_16bit_storage]>, {}>
320 // CHECK-LABEL: @load_i8
321 func @load_i8(%arg0: memref<i8>) {
322 // CHECK: %[[ZERO:.+]] = spv.Constant 0 : i32
323 // CHECK: %[[FOUR1:.+]] = spv.Constant 4 : i32
324 // CHECK: %[[QUOTIENT:.+]] = spv.SDiv %[[ZERO]], %[[FOUR1]] : i32
325 // CHECK: %[[PTR:.+]] = spv.AccessChain %{{.+}}[%[[ZERO]], %[[QUOTIENT]]]
326 // CHECK: %[[LOAD:.+]] = spv.Load "StorageBuffer" %[[PTR]]
327 // CHECK: %[[FOUR2:.+]] = spv.Constant 4 : i32
328 // CHECK: %[[EIGHT:.+]] = spv.Constant 8 : i32
329 // CHECK: %[[IDX:.+]] = spv.UMod %[[ZERO]], %[[FOUR2]] : i32
330 // CHECK: %[[BITS:.+]] = spv.IMul %[[IDX]], %[[EIGHT]] : i32
331 // CHECK: %[[VALUE:.+]] = spv.ShiftRightArithmetic %[[LOAD]], %[[BITS]] : i32, i32
332 // CHECK: %[[MASK:.+]] = spv.Constant 255 : i32
333 // CHECK: %[[T1:.+]] = spv.BitwiseAnd %[[VALUE]], %[[MASK]] : i32
334 // CHECK: %[[T2:.+]] = spv.Constant 24 : i32
335 // CHECK: %[[T3:.+]] = spv.ShiftLeftLogical %[[T1]], %[[T2]] : i32, i32
336 // CHECK: spv.ShiftRightArithmetic %[[T3]], %[[T2]] : i32, i32
337 %0 = memref.load %arg0[] : memref<i8>
341 // CHECK-LABEL: @load_i16
342 func @load_i16(%arg0: memref<i16>) {
343 // CHECK-NOT: spv.SDiv
345 // CHECK-NOT: spv.ShiftRightArithmetic
346 %0 = memref.load %arg0[] : memref<i16>
350 // CHECK-LABEL: @store_i8
351 // CHECK: (%[[ARG0:.+]]: {{.*}}, %[[ARG1:.+]]: i8)
352 func @store_i8(%arg0: memref<i8>, %value: i8) {
353 // CHECK-DAG: %[[ARG1_CAST:.+]] = builtin.unrealized_conversion_cast %[[ARG1]] : i8 to i32
354 // CHECK-DAG: %[[ARG0_CAST:.+]] = builtin.unrealized_conversion_cast %[[ARG0]]
355 // CHECK: %[[ZERO:.+]] = spv.Constant 0 : i32
356 // CHECK: %[[FOUR:.+]] = spv.Constant 4 : i32
357 // CHECK: %[[EIGHT:.+]] = spv.Constant 8 : i32
358 // CHECK: %[[IDX:.+]] = spv.UMod %[[ZERO]], %[[FOUR]] : i32
359 // CHECK: %[[OFFSET:.+]] = spv.IMul %[[IDX]], %[[EIGHT]] : i32
360 // CHECK: %[[MASK1:.+]] = spv.Constant 255 : i32
361 // CHECK: %[[TMP1:.+]] = spv.ShiftLeftLogical %[[MASK1]], %[[OFFSET]] : i32, i32
362 // CHECK: %[[MASK:.+]] = spv.Not %[[TMP1]] : i32
363 // CHECK: %[[CLAMPED_VAL:.+]] = spv.BitwiseAnd %[[ARG1_CAST]], %[[MASK1]] : i32
364 // CHECK: %[[STORE_VAL:.+]] = spv.ShiftLeftLogical %[[CLAMPED_VAL]], %[[OFFSET]] : i32, i32
365 // CHECK: %[[FOUR2:.+]] = spv.Constant 4 : i32
366 // CHECK: %[[ACCESS_IDX:.+]] = spv.SDiv %[[ZERO]], %[[FOUR2]] : i32
367 // CHECK: %[[PTR:.+]] = spv.AccessChain %[[ARG0_CAST]][%[[ZERO]], %[[ACCESS_IDX]]]
368 // CHECK: spv.AtomicAnd "Device" "AcquireRelease" %[[PTR]], %[[MASK]]
369 // CHECK: spv.AtomicOr "Device" "AcquireRelease" %[[PTR]], %[[STORE_VAL]]
370 memref.store %value, %arg0[] : memref<i8>
374 // CHECK-LABEL: @store_i16
375 func @store_i16(%arg0: memref<10xi16>, %index: index, %value: i16) {
377 // CHECK-NOT: spv.AtomicAnd
378 // CHECK-NOT: spv.AtomicOr
379 memref.store %value, %arg0[%index] : memref<10xi16>