[RISCV] Fix the code alignment for GroupFloatVectors. NFC
[llvm-project.git] / mlir / test / Conversion / MemRefToSPIRV / memref-to-spirv.mlir
blob90492ff14247dd40c7a88e58b41b0f0aeff814ca
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.
6 module attributes {
7   spv.target_env = #spv.target_env<
8     #spv.vce<v1.0,
9       [
10         Shader, Int8, Int16, Int64, Float16, Float64,
11         StorageBuffer16BitAccess, StorageUniform16, StoragePushConstant16,
12         StorageBuffer8BitAccess, UniformAndStorageBuffer8BitAccess, StoragePushConstant8
13       ],
14       [SPV_KHR_16bit_storage, SPV_KHR_8bit_storage, SPV_KHR_storage_buffer_storage_class]>, {}>
15 } {
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]]
24   // CHECK-SAME: ] :
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]]
30   // CHECK-SAME: ] :
31   //      CHECK: spv.Store "StorageBuffer" %{{.*}} : f32
32   memref.store %0, %arg1[] : memref<f32>
33   return
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]]
43   // CHECK-SAME: ] :
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]]
49   // CHECK-SAME: ] :
50   //      CHECK: spv.Store "StorageBuffer" %{{.*}} : i32
51   memref.store %0, %arg1[] : memref<i32>
52   return
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>
65   return
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]]
84   return %0: i1
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>
105   return
108 } // end module
110 // -----
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.
115 module attributes {
116   spv.target_env = #spv.target_env<
117     #spv.vce<v1.0, [Shader], [SPV_KHR_storage_buffer_storage_class]>, {}>
118 } {
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>
142   return %0 : 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>
163   return
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>
190   return
193 // CHECK-LABEL: @load_i32
194 func @load_i32(%arg0: memref<i32>) {
195   // CHECK-NOT: spv.SDiv
196   //     CHECK: spv.Load
197   // CHECK-NOT: spv.ShiftRightArithmetic
198   %0 = memref.load %arg0[] : memref<i32>
199   return
202 // CHECK-LABEL: @load_f32
203 func @load_f32(%arg0: memref<f32>) {
204   // CHECK-NOT: spv.SDiv
205   //     CHECK: spv.Load
206   // CHECK-NOT: spv.ShiftRightArithmetic
207   %0 = memref.load %arg0[] : memref<f32>
208   return
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>
234   return
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>
258   return
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>
287   return
290 // CHECK-LABEL: @store_i32
291 func @store_i32(%arg0: memref<i32>, %value: i32) {
292   //     CHECK: spv.Store
293   // CHECK-NOT: spv.AtomicAnd
294   // CHECK-NOT: spv.AtomicOr
295   memref.store %value, %arg0[] : memref<i32>
296   return
299 // CHECK-LABEL: @store_f32
300 func @store_f32(%arg0: memref<f32>, %value: f32) {
301   //     CHECK: spv.Store
302   // CHECK-NOT: spv.AtomicAnd
303   // CHECK-NOT: spv.AtomicOr
304   memref.store %value, %arg0[] : memref<f32>
305   return
308 } // end module
310 // -----
312 // Check that access chain indices are properly adjusted if non-16/32-bit types
313 // are emulated via 32-bit types.
314 module attributes {
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]>, {}>
318 } {
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>
338   return
341 // CHECK-LABEL: @load_i16
342 func @load_i16(%arg0: memref<i16>) {
343   // CHECK-NOT: spv.SDiv
344   //     CHECK: spv.Load
345   // CHECK-NOT: spv.ShiftRightArithmetic
346   %0 = memref.load %arg0[] : memref<i16>
347   return
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>
371   return
374 // CHECK-LABEL: @store_i16
375 func @store_i16(%arg0: memref<10xi16>, %index: index, %value: i16) {
376   //     CHECK: spv.Store
377   // CHECK-NOT: spv.AtomicAnd
378   // CHECK-NOT: spv.AtomicOr
379   memref.store %value, %arg0[%index] : memref<10xi16>
380   return
383 } // end module