xref: /llvm-project/mlir/test/Dialect/SPIRV/Transforms/unify-aliased-resource.mlir (revision bdf00e2216280edef1ec91ccc07987db92197b59)
1// RUN: mlir-opt -split-input-file -spirv-unify-aliased-resource -verify-diagnostics %s | FileCheck %s
2
3spirv.module Logical GLSL450 {
4  spirv.GlobalVariable @var01s bind(0, 1) {aliased} : !spirv.ptr<!spirv.struct<(!spirv.rtarray<f32, stride=4> [0])>, StorageBuffer>
5  spirv.GlobalVariable @var01v bind(0, 1) {aliased} : !spirv.ptr<!spirv.struct<(!spirv.rtarray<vector<4xf32>, stride=16> [0])>, StorageBuffer>
6
7  spirv.func @load_store_scalar(%index: i32) -> f32 "None" {
8    %c0 = spirv.Constant 0 : i32
9    %addr = spirv.mlir.addressof @var01s : !spirv.ptr<!spirv.struct<(!spirv.rtarray<f32, stride=4> [0])>, StorageBuffer>
10    %ac = spirv.AccessChain %addr[%c0, %index] : !spirv.ptr<!spirv.struct<(!spirv.rtarray<f32, stride=4> [0])>, StorageBuffer>, i32, i32 -> !spirv.ptr<f32, StorageBuffer>
11    %value = spirv.Load "StorageBuffer" %ac : f32
12    spirv.Store "StorageBuffer" %ac, %value : f32
13    spirv.ReturnValue %value : f32
14  }
15}
16
17// CHECK-LABEL: spirv.module
18
19// CHECK-NOT: @var01s
20//     CHECK: spirv.GlobalVariable @var01v bind(0, 1) : !spirv.ptr<!spirv.struct<(!spirv.rtarray<vector<4xf32>, stride=16> [0])>, StorageBuffer>
21// CHECK-NOT: @var01s
22
23//     CHECK: spirv.func @load_store_scalar(%[[INDEX:.+]]: i32)
24// CHECK-DAG:   %[[C0:.+]] = spirv.Constant 0 : i32
25// CHECK-DAG:   %[[C4:.+]] = spirv.Constant 4 : i32
26// CHECK-DAG:   %[[ADDR:.+]] = spirv.mlir.addressof @var01v
27//     CHECK:   %[[DIV:.+]] = spirv.SDiv %[[INDEX]], %[[C4]] : i32
28//     CHECK:   %[[MOD:.+]] = spirv.SMod %[[INDEX]], %[[C4]] : i32
29//     CHECK:   %[[AC:.+]] = spirv.AccessChain %[[ADDR]][%[[C0]], %[[DIV]], %[[MOD]]]
30//     CHECK:   spirv.Load "StorageBuffer" %[[AC]]
31//     CHECK:   spirv.Store "StorageBuffer" %[[AC]]
32
33// -----
34
35spirv.module Logical GLSL450 {
36  spirv.GlobalVariable @var01s bind(0, 1) {aliased} : !spirv.ptr<!spirv.struct<(!spirv.rtarray<f32, stride=4> [0])>, StorageBuffer>
37  spirv.GlobalVariable @var01v bind(0, 1) {aliased} : !spirv.ptr<!spirv.struct<(!spirv.rtarray<vector<4xf32>, stride=16> [0])>, StorageBuffer>
38
39  spirv.func @load_store_scalar_64bit(%index: i64) -> f32 "None" {
40    %c0 = spirv.Constant 0 : i64
41    %addr = spirv.mlir.addressof @var01s : !spirv.ptr<!spirv.struct<(!spirv.rtarray<f32, stride=4> [0])>, StorageBuffer>
42    %ac = spirv.AccessChain %addr[%c0, %index] : !spirv.ptr<!spirv.struct<(!spirv.rtarray<f32, stride=4> [0])>, StorageBuffer>, i64, i64 -> !spirv.ptr<f32, StorageBuffer>
43    %value = spirv.Load "StorageBuffer" %ac : f32
44    spirv.Store "StorageBuffer" %ac, %value : f32
45    spirv.ReturnValue %value : f32
46  }
47}
48
49// CHECK-LABEL: spirv.module
50
51// CHECK-NOT: @var01s
52//     CHECK: spirv.GlobalVariable @var01v bind(0, 1) : !spirv.ptr<!spirv.struct<(!spirv.rtarray<vector<4xf32>, stride=16> [0])>, StorageBuffer>
53// CHECK-NOT: @var01s
54
55//     CHECK: spirv.func @load_store_scalar_64bit(%[[INDEX:.+]]: i64)
56// CHECK-DAG:   %[[C4:.+]] = spirv.Constant 4 : i64
57//     CHECK:   spirv.SDiv %[[INDEX]], %[[C4]] : i64
58//     CHECK:   spirv.SMod %[[INDEX]], %[[C4]] : i64
59
60// -----
61
62spirv.module Logical GLSL450 {
63  spirv.GlobalVariable @var01s bind(0, 1) {aliased} : !spirv.ptr<!spirv.struct<(!spirv.rtarray<f32, stride=4> [0])>, StorageBuffer>
64  spirv.GlobalVariable @var01v bind(0, 1) {aliased} : !spirv.ptr<!spirv.struct<(!spirv.rtarray<vector<4xf32>, stride=16> [0])>, StorageBuffer>
65
66  spirv.func @multiple_uses(%i0: i32, %i1: i32) -> f32 "None" {
67    %c0 = spirv.Constant 0 : i32
68    %addr = spirv.mlir.addressof @var01s : !spirv.ptr<!spirv.struct<(!spirv.rtarray<f32, stride=4> [0])>, StorageBuffer>
69    %ac0 = spirv.AccessChain %addr[%c0, %i0] : !spirv.ptr<!spirv.struct<(!spirv.rtarray<f32, stride=4> [0])>, StorageBuffer>, i32, i32 -> !spirv.ptr<f32, StorageBuffer>
70    %val0 = spirv.Load "StorageBuffer" %ac0 : f32
71    %ac1 = spirv.AccessChain %addr[%c0, %i1] : !spirv.ptr<!spirv.struct<(!spirv.rtarray<f32, stride=4> [0])>, StorageBuffer>, i32, i32 -> !spirv.ptr<f32, StorageBuffer>
72    %val1 = spirv.Load "StorageBuffer" %ac1 : f32
73    %value = spirv.FAdd %val0, %val1 : f32
74    spirv.ReturnValue %value : f32
75  }
76}
77
78// CHECK-LABEL: spirv.module
79
80// CHECK-NOT: @var01s
81//     CHECK: spirv.GlobalVariable @var01v bind(0, 1) : !spirv.ptr<!spirv.struct<(!spirv.rtarray<vector<4xf32>, stride=16> [0])>, StorageBuffer>
82// CHECK-NOT: @var01s
83
84//     CHECK: spirv.func @multiple_uses
85//     CHECK:   %[[ADDR:.+]] = spirv.mlir.addressof @var01v
86//     CHECK:   spirv.AccessChain %[[ADDR]][%{{.+}}, %{{.+}}, %{{.+}}]
87//     CHECK:   spirv.AccessChain %[[ADDR]][%{{.+}}, %{{.+}}, %{{.+}}]
88
89// -----
90
91spirv.module Logical GLSL450 {
92  spirv.GlobalVariable @var01s bind(0, 1) {aliased} : !spirv.ptr<!spirv.struct<(!spirv.rtarray<f32, stride=4> [0])>, StorageBuffer>
93  spirv.GlobalVariable @var01v bind(0, 1) {aliased} : !spirv.ptr<!spirv.struct<(!spirv.rtarray<vector<3xf32>, stride=16> [0])>, StorageBuffer>
94
95  spirv.func @vector3(%index: i32) -> f32 "None" {
96    %c0 = spirv.Constant 0 : i32
97    %addr = spirv.mlir.addressof @var01s : !spirv.ptr<!spirv.struct<(!spirv.rtarray<f32, stride=4> [0])>, StorageBuffer>
98    %ac = spirv.AccessChain %addr[%c0, %index] : !spirv.ptr<!spirv.struct<(!spirv.rtarray<f32, stride=4> [0])>, StorageBuffer>, i32, i32 -> !spirv.ptr<f32, StorageBuffer>
99    %value = spirv.Load "StorageBuffer" %ac : f32
100    spirv.ReturnValue %value : f32
101  }
102}
103
104// CHECK-LABEL: spirv.module
105
106// CHECK: spirv.GlobalVariable @var01s bind(0, 1) {aliased}
107// CHECK: spirv.GlobalVariable @var01v bind(0, 1) {aliased}
108// CHECK: spirv.func @vector3
109
110// -----
111
112spirv.module Logical GLSL450 {
113  spirv.GlobalVariable @var01s bind(0, 1) {aliased} : !spirv.ptr<!spirv.struct<(!spirv.rtarray<f32, stride=4> [0])>, StorageBuffer>
114  spirv.GlobalVariable @var01v bind(1, 0) {aliased} : !spirv.ptr<!spirv.struct<(!spirv.rtarray<vector<4xf32>, stride=16> [0])>, StorageBuffer>
115
116  spirv.func @not_aliased(%index: i32) -> f32 "None" {
117    %c0 = spirv.Constant 0 : i32
118    %addr = spirv.mlir.addressof @var01s : !spirv.ptr<!spirv.struct<(!spirv.rtarray<f32, stride=4> [0])>, StorageBuffer>
119    %ac = spirv.AccessChain %addr[%c0, %index] : !spirv.ptr<!spirv.struct<(!spirv.rtarray<f32, stride=4> [0])>, StorageBuffer>, i32, i32 -> !spirv.ptr<f32, StorageBuffer>
120    %value = spirv.Load "StorageBuffer" %ac : f32
121    spirv.Store "StorageBuffer" %ac, %value : f32
122    spirv.ReturnValue %value : f32
123  }
124}
125
126// CHECK-LABEL: spirv.module
127
128// CHECK: spirv.GlobalVariable @var01s bind(0, 1) : !spirv.ptr<!spirv.struct<(!spirv.rtarray<f32, stride=4> [0])>, StorageBuffer>
129// CHECK: spirv.GlobalVariable @var01v bind(1, 0) : !spirv.ptr<!spirv.struct<(!spirv.rtarray<vector<4xf32>, stride=16> [0])>, StorageBuffer>
130// CHECK: spirv.func @not_aliased
131
132// -----
133
134spirv.module Logical GLSL450 {
135  spirv.GlobalVariable @var01s bind(0, 1) {aliased} : !spirv.ptr<!spirv.struct<(!spirv.rtarray<f32, stride=4> [0])>, StorageBuffer>
136  spirv.GlobalVariable @var01s_1 bind(0, 1) {aliased} : !spirv.ptr<!spirv.struct<(!spirv.rtarray<f32, stride=4> [0])>, StorageBuffer>
137  spirv.GlobalVariable @var01v bind(0, 1) {aliased} : !spirv.ptr<!spirv.struct<(!spirv.rtarray<vector<4xf32>, stride=16> [0])>, StorageBuffer>
138  spirv.GlobalVariable @var01v_1 bind(0, 1) {aliased} : !spirv.ptr<!spirv.struct<(!spirv.rtarray<vector<4xf32>, stride=16> [0])>, StorageBuffer>
139
140  spirv.func @multiple_aliases(%index: i32) -> f32 "None" {
141    %c0 = spirv.Constant 0 : i32
142
143    %addr0 = spirv.mlir.addressof @var01s : !spirv.ptr<!spirv.struct<(!spirv.rtarray<f32, stride=4> [0])>, StorageBuffer>
144    %ac0 = spirv.AccessChain %addr0[%c0, %index] : !spirv.ptr<!spirv.struct<(!spirv.rtarray<f32, stride=4> [0])>, StorageBuffer>, i32, i32 -> !spirv.ptr<f32, StorageBuffer>
145    %val0 = spirv.Load "StorageBuffer" %ac0 : f32
146
147    %addr1 = spirv.mlir.addressof @var01s_1 : !spirv.ptr<!spirv.struct<(!spirv.rtarray<f32, stride=4> [0])>, StorageBuffer>
148    %ac1 = spirv.AccessChain %addr1[%c0, %index] : !spirv.ptr<!spirv.struct<(!spirv.rtarray<f32, stride=4> [0])>, StorageBuffer>, i32, i32 -> !spirv.ptr<f32, StorageBuffer>
149    %val1 = spirv.Load "StorageBuffer" %ac1 : f32
150
151    %addr2 = spirv.mlir.addressof @var01v_1 : !spirv.ptr<!spirv.struct<(!spirv.rtarray<vector<4xf32>, stride=16> [0])>, StorageBuffer>
152    %ac2 = spirv.AccessChain %addr2[%c0, %index, %c0] : !spirv.ptr<!spirv.struct<(!spirv.rtarray<vector<4xf32>, stride=16> [0])>, StorageBuffer>, i32, i32, i32 -> !spirv.ptr<f32, StorageBuffer>
153    %val2 = spirv.Load "StorageBuffer" %ac2 : f32
154
155    %add0 = spirv.FAdd %val0, %val1 : f32
156    %add1 = spirv.FAdd %add0, %val2 : f32
157    spirv.ReturnValue %add1 : f32
158  }
159}
160
161// CHECK-LABEL: spirv.module
162
163// CHECK-NOT: @var01s
164//     CHECK: spirv.GlobalVariable @var01v bind(0, 1) : !spirv.ptr<!spirv.struct<(!spirv.rtarray<vector<4xf32>, stride=16> [0])>, StorageBuffer>
165// CHECK-NOT: @var01v_1
166
167//     CHECK: spirv.func @multiple_aliases
168//     CHECK:   %[[ADDR0:.+]] = spirv.mlir.addressof @var01v :
169//     CHECK:   spirv.AccessChain %[[ADDR0]][%{{.+}}, %{{.+}}, %{{.+}}]
170//     CHECK:   %[[ADDR1:.+]] = spirv.mlir.addressof @var01v :
171//     CHECK:   spirv.AccessChain %[[ADDR1]][%{{.+}}, %{{.+}}, %{{.+}}]
172//     CHECK:   %[[ADDR2:.+]] = spirv.mlir.addressof @var01v :
173//     CHECK:   spirv.AccessChain %[[ADDR2]][%{{.+}}, %{{.+}}, %{{.+}}]
174
175// -----
176
177spirv.module Logical GLSL450 {
178  spirv.GlobalVariable @var01s_i32 bind(0, 1) {aliased} : !spirv.ptr<!spirv.struct<(!spirv.rtarray<i32, stride=4> [0])>, StorageBuffer>
179  spirv.GlobalVariable @var01s_f32 bind(0, 1) {aliased} : !spirv.ptr<!spirv.struct<(!spirv.rtarray<f32, stride=4> [0])>, StorageBuffer>
180
181  spirv.func @different_scalar_type(%index: i32, %val1: f32) -> i32 "None" {
182    %c0 = spirv.Constant 0 : i32
183
184    %addr0 = spirv.mlir.addressof @var01s_i32 : !spirv.ptr<!spirv.struct<(!spirv.rtarray<i32, stride=4> [0])>, StorageBuffer>
185    %ac0 = spirv.AccessChain %addr0[%c0, %index] : !spirv.ptr<!spirv.struct<(!spirv.rtarray<i32, stride=4> [0])>, StorageBuffer>, i32, i32 -> !spirv.ptr<i32, StorageBuffer>
186    %val0 = spirv.Load "StorageBuffer" %ac0 : i32
187
188    %addr1 = spirv.mlir.addressof @var01s_f32 : !spirv.ptr<!spirv.struct<(!spirv.rtarray<f32, stride=4> [0])>, StorageBuffer>
189    %ac1 = spirv.AccessChain %addr1[%c0, %index] : !spirv.ptr<!spirv.struct<(!spirv.rtarray<f32, stride=4> [0])>, StorageBuffer>, i32, i32 -> !spirv.ptr<f32, StorageBuffer>
190    spirv.Store "StorageBuffer" %ac1, %val1 : f32
191
192    spirv.ReturnValue %val0 : i32
193  }
194}
195
196// CHECK-LABEL: spirv.module
197
198// CHECK-NOT: @var01s_f32
199//     CHECK: spirv.GlobalVariable @var01s_i32 bind(0, 1) : !spirv.ptr<!spirv.struct<(!spirv.rtarray<i32, stride=4> [0])>, StorageBuffer>
200// CHECK-NOT: @var01s_f32
201
202//     CHECK: spirv.func @different_scalar_type(%[[INDEX:.+]]: i32, %[[VAL1:.+]]: f32)
203
204//     CHECK:   %[[IADDR:.+]] = spirv.mlir.addressof @var01s_i32
205//     CHECK:   %[[IAC:.+]] = spirv.AccessChain %[[IADDR]][%{{.+}}, %[[INDEX]]]
206//     CHECK:   spirv.Load "StorageBuffer" %[[IAC]] : i32
207
208//     CHECK:   %[[FADDR:.+]] = spirv.mlir.addressof @var01s_i32
209//     CHECK:   %[[FAC:.+]] = spirv.AccessChain %[[FADDR]][%cst0_i32, %[[INDEX]]]
210//     CHECK:   %[[CAST:.+]] = spirv.Bitcast %[[VAL1]] : f32 to i32
211//     CHECK:   spirv.Store "StorageBuffer" %[[FAC]], %[[CAST]] : i32
212
213// -----
214
215spirv.module Logical GLSL450 {
216  spirv.GlobalVariable @var01s bind(0, 1) {aliased} : !spirv.ptr<!spirv.struct<(!spirv.rtarray<i32, stride=4> [0])>, StorageBuffer>
217  spirv.GlobalVariable @var01v bind(0, 1) {aliased} : !spirv.ptr<!spirv.struct<(!spirv.rtarray<vector<4xf32>, stride=16> [0])>, StorageBuffer>
218
219  spirv.func @different_primitive_type(%index: i32, %val0: i32) -> i32 "None" {
220    %c0 = spirv.Constant 0 : i32
221    %addr = spirv.mlir.addressof @var01s : !spirv.ptr<!spirv.struct<(!spirv.rtarray<i32, stride=4> [0])>, StorageBuffer>
222    %ac = spirv.AccessChain %addr[%c0, %index] : !spirv.ptr<!spirv.struct<(!spirv.rtarray<i32, stride=4> [0])>, StorageBuffer>, i32, i32 -> !spirv.ptr<i32, StorageBuffer>
223    %val1 = spirv.Load "StorageBuffer" %ac : i32
224    spirv.Store "StorageBuffer" %ac, %val0 : i32
225    spirv.ReturnValue %val1 : i32
226  }
227}
228
229// CHECK-LABEL: spirv.module
230
231// CHECK-NOT: @var01s
232//     CHECK: spirv.GlobalVariable @var01v bind(0, 1) : !spirv.ptr<!spirv.struct<(!spirv.rtarray<vector<4xf32>, stride=16> [0])>, StorageBuffer>
233// CHECK-NOT: @var01s
234
235//     CHECK: spirv.func @different_primitive_type(%{{.+}}: i32, %[[VAL0:.+]]: i32)
236//     CHECK:   %[[ADDR:.+]] = spirv.mlir.addressof @var01v
237//     CHECK:   %[[AC:.+]] = spirv.AccessChain %[[ADDR]][%{{.+}}, %{{.+}}, %{{.+}}]
238//     CHECK:   %[[VAL1:.+]] = spirv.Load "StorageBuffer" %[[AC]] : f32
239//     CHECK:   %[[CAST1:.+]] = spirv.Bitcast %[[VAL1]] : f32 to i32
240//     CHECK:   %[[CAST2:.+]] = spirv.Bitcast %[[VAL0]] : i32 to f32
241//     CHECK:   spirv.Store "StorageBuffer" %[[AC]], %[[CAST2]] : f32
242//     CHECK:   spirv.ReturnValue %[[CAST1]] : i32
243
244// -----
245
246spirv.module Logical GLSL450 {
247  spirv.GlobalVariable @var01s_i64 bind(0, 1) {aliased} : !spirv.ptr<!spirv.struct<(!spirv.rtarray<i64, stride=4> [0])>, StorageBuffer>
248  spirv.GlobalVariable @var01s_f32 bind(0, 1) {aliased} : !spirv.ptr<!spirv.struct<(!spirv.rtarray<f32, stride=4> [0])>, StorageBuffer>
249
250  spirv.func @load_different_scalar_bitwidth(%index: i32) -> i64 "None" {
251    %c0 = spirv.Constant 0 : i32
252
253    %addr0 = spirv.mlir.addressof @var01s_i64 : !spirv.ptr<!spirv.struct<(!spirv.rtarray<i64, stride=4> [0])>, StorageBuffer>
254    %ac0 = spirv.AccessChain %addr0[%c0, %index] : !spirv.ptr<!spirv.struct<(!spirv.rtarray<i64, stride=4> [0])>, StorageBuffer>, i32, i32 -> !spirv.ptr<i64, StorageBuffer>
255    %val0 = spirv.Load "StorageBuffer" %ac0 : i64
256
257    spirv.ReturnValue %val0 : i64
258  }
259}
260
261// CHECK-LABEL: spirv.module
262
263// CHECK-NOT: @var01s_i64
264//     CHECK: spirv.GlobalVariable @var01s_f32 bind(0, 1) : !spirv.ptr<!spirv.struct<(!spirv.rtarray<f32, stride=4> [0])>, StorageBuffer>
265// CHECK-NOT: @var01s_i64
266
267//     CHECK: spirv.func @load_different_scalar_bitwidth(%[[INDEX:.+]]: i32)
268//     CHECK:   %[[ZERO:.+]] = spirv.Constant 0 : i32
269//     CHECK:   %[[ADDR:.+]] = spirv.mlir.addressof @var01s_f32
270
271//     CHECK:   %[[TWO:.+]] = spirv.Constant 2 : i32
272//     CHECK:   %[[BASE:.+]] = spirv.IMul %[[INDEX]], %[[TWO]] : i32
273//     CHECK:   %[[AC0:.+]] = spirv.AccessChain %[[ADDR]][%[[ZERO]], %[[BASE]]]
274//     CHECK:   %[[LOAD0:.+]] = spirv.Load "StorageBuffer" %[[AC0]] : f32
275
276//     CHECK:   %[[ONE:.+]] = spirv.Constant 1 : i32
277//     CHECK:   %[[ADD:.+]] = spirv.IAdd %[[BASE]], %[[ONE]] : i32
278//     CHECK:   %[[AC1:.+]] = spirv.AccessChain %[[ADDR]][%[[ZERO]], %[[ADD]]]
279//     CHECK:   %[[LOAD1:.+]] = spirv.Load "StorageBuffer" %[[AC1]] : f32
280
281//     CHECK:   %[[CC:.+]] = spirv.CompositeConstruct %[[LOAD0]], %[[LOAD1]]
282//     CHECK:   %[[CAST:.+]] = spirv.Bitcast %[[CC]] : vector<2xf32> to i64
283//     CHECK:   spirv.ReturnValue %[[CAST]]
284
285// -----
286
287spirv.module Logical GLSL450 {
288  spirv.GlobalVariable @var01s_i64 bind(0, 1) {aliased} : !spirv.ptr<!spirv.struct<(!spirv.rtarray<i64, stride=4> [0])>, StorageBuffer>
289  spirv.GlobalVariable @var01s_f32 bind(0, 1) {aliased} : !spirv.ptr<!spirv.struct<(!spirv.rtarray<f32, stride=4> [0])>, StorageBuffer>
290
291  spirv.func @store_different_scalar_bitwidth(%i0: i32, %i1: i32) "None" {
292    %c0 = spirv.Constant 0 : i32
293
294    %addr0 = spirv.mlir.addressof @var01s_f32 : !spirv.ptr<!spirv.struct<(!spirv.rtarray<f32, stride=4> [0])>, StorageBuffer>
295    %ac0 = spirv.AccessChain %addr0[%c0, %i0] : !spirv.ptr<!spirv.struct<(!spirv.rtarray<f32, stride=4> [0])>, StorageBuffer>, i32, i32 -> !spirv.ptr<f32, StorageBuffer>
296    %f32val = spirv.Load "StorageBuffer" %ac0 : f32
297    %f64val = spirv.FConvert %f32val : f32 to f64
298    %i64val = spirv.Bitcast %f64val : f64 to i64
299
300    %addr1 = spirv.mlir.addressof @var01s_i64 : !spirv.ptr<!spirv.struct<(!spirv.rtarray<i64, stride=4> [0])>, StorageBuffer>
301    %ac1 = spirv.AccessChain %addr1[%c0, %i1] : !spirv.ptr<!spirv.struct<(!spirv.rtarray<i64, stride=4> [0])>, StorageBuffer>, i32, i32 -> !spirv.ptr<i64, StorageBuffer>
302    // expected-error@+1 {{failed to legalize operation 'spirv.Store'}}
303    spirv.Store "StorageBuffer" %ac1, %i64val : i64
304
305    spirv.Return
306  }
307}
308
309// -----
310
311spirv.module Logical GLSL450 {
312  spirv.GlobalVariable @var01_scalar bind(0, 1) {aliased} : !spirv.ptr<!spirv.struct<(!spirv.rtarray<f32, stride=4> [0])>, StorageBuffer>
313  spirv.GlobalVariable @var01_vec2 bind(0, 1) {aliased} : !spirv.ptr<!spirv.struct<(!spirv.rtarray<vector<2xf32>, stride=8> [0])>, StorageBuffer>
314  spirv.GlobalVariable @var01_vec4 bind(0, 1) {aliased} : !spirv.ptr<!spirv.struct<(!spirv.rtarray<vector<4xf32>, stride=16> [0])>, StorageBuffer>
315
316  spirv.func @load_different_vector_sizes(%i0: i32) -> vector<4xf32> "None" {
317    %c0 = spirv.Constant 0 : i32
318
319    %addr0 = spirv.mlir.addressof @var01_vec4 : !spirv.ptr<!spirv.struct<(!spirv.rtarray<vector<4xf32>, stride=16> [0])>, StorageBuffer>
320    %ac0 = spirv.AccessChain %addr0[%c0, %i0] : !spirv.ptr<!spirv.struct<(!spirv.rtarray<vector<4xf32>, stride=16> [0])>, StorageBuffer>, i32, i32 -> !spirv.ptr<vector<4xf32>, StorageBuffer>
321    %vec4val = spirv.Load "StorageBuffer" %ac0 : vector<4xf32>
322
323    %addr1 = spirv.mlir.addressof @var01_scalar : !spirv.ptr<!spirv.struct<(!spirv.rtarray<f32, stride=4> [0])>, StorageBuffer>
324    %ac1 = spirv.AccessChain %addr1[%c0, %i0] : !spirv.ptr<!spirv.struct<(!spirv.rtarray<f32, stride=4> [0])>, StorageBuffer>, i32, i32 -> !spirv.ptr<f32, StorageBuffer>
325    %scalarval = spirv.Load "StorageBuffer" %ac1 : f32
326
327    %val = spirv.CompositeInsert %scalarval, %vec4val[0 : i32] : f32 into vector<4xf32>
328    spirv.ReturnValue %val : vector<4xf32>
329  }
330}
331
332// CHECK-LABEL: spirv.module
333
334// CHECK-NOT: @var01_scalar
335// CHECK-NOT: @var01_vec4
336//     CHECK: spirv.GlobalVariable @var01_vec2 bind(0, 1) : !spirv.ptr<{{.+}}>
337// CHECK-NOT: @var01_scalar
338// CHECK-NOT: @var01_vec4
339
340//     CHECK: spirv.func @load_different_vector_sizes(%[[IDX:.+]]: i32)
341//     CHECK:   %[[ZERO:.+]] = spirv.Constant 0 : i32
342//     CHECK:   %[[ADDR:.+]] = spirv.mlir.addressof @var01_vec2
343//     CHECK:   %[[TWO:.+]] = spirv.Constant 2 : i32
344//     CHECK:   %[[IDX0:.+]] = spirv.IMul %[[IDX]], %[[TWO]] : i32
345//     CHECK:   %[[AC0:.+]] = spirv.AccessChain %[[ADDR]][%[[ZERO]], %[[IDX0]]]
346//     CHECK:   %[[LD0:.+]] = spirv.Load "StorageBuffer" %[[AC0]] : vector<2xf32>
347//     CHECK:   %[[ONE:.+]] = spirv.Constant 1 : i32
348//     CHECK:   %[[IDX1:.+]] = spirv.IAdd %0, %[[ONE]] : i32
349//     CHECK:   %[[AC1:.+]] = spirv.AccessChain %[[ADDR]][%[[ZERO]], %[[IDX1]]]
350//     CHECK:   %[[LD1:.+]] = spirv.Load "StorageBuffer" %[[AC1]] : vector<2xf32>
351//     CHECK:   spirv.CompositeConstruct %[[LD0]], %[[LD1]] : (vector<2xf32>, vector<2xf32>) -> vector<4xf32>
352
353//     CHECK:   %[[ADDR:.+]] = spirv.mlir.addressof @var01_vec2
354//     CHECK:   %[[TWO:.+]] = spirv.Constant 2 : i32
355//     CHECK:   %[[DIV:.+]] = spirv.SDiv %[[IDX]], %[[TWO]] : i32
356//     CHECK:   %[[MOD:.+]] = spirv.SMod %[[IDX]], %[[TWO]] : i32
357//     CHECK:   %[[AC:.+]] = spirv.AccessChain %[[ADDR]][%[[ZERO]], %[[DIV]], %[[MOD]]]
358//     CHECK:   %[[LD:.+]] = spirv.Load "StorageBuffer" %[[AC]] : f32
359
360// -----
361
362spirv.module Logical GLSL450 {
363  spirv.GlobalVariable @var01_v4f32 bind(0, 1) {aliased} : !spirv.ptr<!spirv.struct<(!spirv.rtarray<vector<4xf32>, stride=16> [0])>, StorageBuffer>
364  spirv.GlobalVariable @var01_f32 bind(0, 1) {aliased} : !spirv.ptr<!spirv.struct<(!spirv.rtarray<f32, stride=4> [0])>, StorageBuffer>
365  spirv.GlobalVariable @var01_i64 bind(0, 1) {aliased} : !spirv.ptr<!spirv.struct<(!spirv.rtarray<i64, stride=8> [0])>, StorageBuffer>
366
367  spirv.func @load_mixed_scalar_vector_primitive_types(%i0: i32) -> vector<4xf32> "None" {
368    %c0 = spirv.Constant 0 : i32
369
370    %addr0 = spirv.mlir.addressof @var01_v4f32 : !spirv.ptr<!spirv.struct<(!spirv.rtarray<vector<4xf32>, stride=16> [0])>, StorageBuffer>
371    %ac0 = spirv.AccessChain %addr0[%c0, %i0] : !spirv.ptr<!spirv.struct<(!spirv.rtarray<vector<4xf32>, stride=16> [0])>, StorageBuffer>, i32, i32 -> !spirv.ptr<vector<4xf32>, StorageBuffer>
372    %vec4val = spirv.Load "StorageBuffer" %ac0 : vector<4xf32>
373
374    %addr1 = spirv.mlir.addressof @var01_f32 : !spirv.ptr<!spirv.struct<(!spirv.rtarray<f32, stride=4> [0])>, StorageBuffer>
375    %ac1 = spirv.AccessChain %addr1[%c0, %i0] : !spirv.ptr<!spirv.struct<(!spirv.rtarray<f32, stride=4> [0])>, StorageBuffer>, i32, i32 -> !spirv.ptr<f32, StorageBuffer>
376    %f32val = spirv.Load "StorageBuffer" %ac1 : f32
377
378    %addr2 = spirv.mlir.addressof @var01_i64 : !spirv.ptr<!spirv.struct<(!spirv.rtarray<i64, stride=8> [0])>, StorageBuffer>
379    %ac2 = spirv.AccessChain %addr2[%c0, %i0] : !spirv.ptr<!spirv.struct<(!spirv.rtarray<i64, stride=8> [0])>, StorageBuffer>, i32, i32 -> !spirv.ptr<i64, StorageBuffer>
380    %i64val = spirv.Load "StorageBuffer" %ac2 : i64
381    %i32val = spirv.SConvert %i64val : i64 to i32
382    %castval = spirv.Bitcast %i32val : i32 to f32
383
384    %val1 = spirv.CompositeInsert %f32val, %vec4val[0 : i32] : f32 into vector<4xf32>
385    %val2 = spirv.CompositeInsert %castval, %val1[1 : i32] : f32 into vector<4xf32>
386    spirv.ReturnValue %val2 : vector<4xf32>
387  }
388}
389
390// CHECK-LABEL: spirv.module
391
392// CHECK-NOT: @var01_f32
393// CHECK-NOT: @var01_i64
394//     CHECK: spirv.GlobalVariable @var01_v4f32 bind(0, 1) : !spirv.ptr<{{.+}}>
395// CHECK-NOT: @var01_f32
396// CHECK-NOT: @var01_i64
397
398// CHECK:  spirv.func @load_mixed_scalar_vector_primitive_types(%[[IDX:.+]]: i32)
399
400// CHECK:    %[[ZERO:.+]] = spirv.Constant 0 : i32
401// CHECK:    %[[ADDR0:.+]] = spirv.mlir.addressof @var01_v4f32
402// CHECK:    %[[AC0:.+]] = spirv.AccessChain %[[ADDR0]][%[[ZERO]], %[[IDX]]]
403// CHECK:    spirv.Load "StorageBuffer" %[[AC0]] : vector<4xf32>
404
405// CHECK:    %[[ADDR1:.+]] = spirv.mlir.addressof @var01_v4f32
406// CHECK:    %[[FOUR:.+]] = spirv.Constant 4 : i32
407// CHECK:    %[[DIV:.+]] = spirv.SDiv %[[IDX]], %[[FOUR]] : i32
408// CHECK:    %[[MOD:.+]] = spirv.SMod %[[IDX]], %[[FOUR]] : i32
409// CHECK:    %[[AC1:.+]] = spirv.AccessChain %[[ADDR1]][%[[ZERO]], %[[DIV]], %[[MOD]]]
410// CHECK:    spirv.Load "StorageBuffer" %[[AC1]] : f32
411
412// CHECK:    %[[ADDR2:.+]] = spirv.mlir.addressof @var01_v4f32
413// CHECK:    %[[TWO:.+]] = spirv.Constant 2 : i32
414// CHECK:    %[[DIV0:.+]] = spirv.SDiv %[[IDX]], %[[TWO]] : i32
415// CHECK:    %[[MOD0:.+]] = spirv.SMod %[[IDX]], %[[TWO]] : i32
416// CHECK:    %[[AC2:.+]] = spirv.AccessChain %[[ADDR2]][%[[ZERO]], %[[DIV0]], %[[MOD0]]]
417// CHECK:    %[[LD0:.+]] = spirv.Load "StorageBuffer" %[[AC2]] : f32
418
419// CHECK:    %[[ONE:.+]] = spirv.Constant 1 : i32
420// CHECK:    %[[MOD1:.+]] = spirv.IAdd %[[MOD0]], %[[ONE]]
421// CHECK:    %[[AC3:.+]] = spirv.AccessChain %[[ADDR2]][%[[ZERO]], %[[DIV0]], %[[MOD1]]]
422// CHECK:    %[[LD1:.+]] = spirv.Load "StorageBuffer" %[[AC3]] : f32
423// CHECK:    %[[CC:.+]] = spirv.CompositeConstruct %[[LD0]], %[[LD1]]
424// CHECK:    %[[BC:.+]] = spirv.Bitcast %[[CC]] : vector<2xf32> to i64
425
426// -----
427
428spirv.module Logical GLSL450 {
429  spirv.GlobalVariable @var01_v2f2 bind(0, 1) {aliased} : !spirv.ptr<!spirv.struct<(!spirv.rtarray<vector<2xf32>, stride=16> [0])>, StorageBuffer>
430  spirv.GlobalVariable @var01_i64 bind(0, 1) {aliased} : !spirv.ptr<!spirv.struct<(!spirv.rtarray<i64, stride=8> [0])>, StorageBuffer>
431
432  spirv.func @load_mixed_scalar_vector_primitive_types(%i0: i32) -> i64 "None" {
433    %c0 = spirv.Constant 0 : i32
434
435    %addr = spirv.mlir.addressof @var01_i64 : !spirv.ptr<!spirv.struct<(!spirv.rtarray<i64, stride=8> [0])>, StorageBuffer>
436    %ac = spirv.AccessChain %addr[%c0, %i0] : !spirv.ptr<!spirv.struct<(!spirv.rtarray<i64, stride=8> [0])>, StorageBuffer>, i32, i32 -> !spirv.ptr<i64, StorageBuffer>
437    %val = spirv.Load "StorageBuffer" %ac : i64
438
439    spirv.ReturnValue %val : i64
440  }
441}
442
443// CHECK-LABEL: spirv.module
444
445// CHECK:  spirv.func @load_mixed_scalar_vector_primitive_types(%[[IDX:.+]]: i32)
446
447// CHECK:    %[[ADDR:.+]] = spirv.mlir.addressof @var01_v2f2
448// CHECK:    %[[ONE:.+]] = spirv.Constant 1 : i32
449// CHECK:    %[[DIV:.+]] = spirv.SDiv %[[IDX]], %[[ONE]] : i32
450// CHECK:    %[[MOD:.+]] = spirv.SMod %[[IDX]], %[[ONE]] : i32
451// CHECK:    spirv.AccessChain %[[ADDR]][%{{.+}}, %[[DIV]], %[[MOD]]]
452// CHECK:    spirv.Load
453// CHECK:    spirv.Load
454
455// -----
456
457spirv.module Logical GLSL450 {
458  spirv.GlobalVariable @var01_v2f2 bind(0, 1) {aliased} : !spirv.ptr<!spirv.struct<(!spirv.rtarray<vector<2xf32>, stride=16> [0])>, StorageBuffer>
459  spirv.GlobalVariable @var01_i16 bind(0, 1) {aliased} : !spirv.ptr<!spirv.struct<(!spirv.rtarray<i16, stride=2> [0])>, StorageBuffer>
460
461  spirv.func @scalar_type_bitwidth_smaller_than_vector(%i0: i32) -> i16 "None" {
462    %c0 = spirv.Constant 0 : i32
463
464    %addr = spirv.mlir.addressof @var01_i16 : !spirv.ptr<!spirv.struct<(!spirv.rtarray<i16, stride=2> [0])>, StorageBuffer>
465    %ac = spirv.AccessChain %addr[%c0, %i0] : !spirv.ptr<!spirv.struct<(!spirv.rtarray<i16, stride=2> [0])>, StorageBuffer>, i32, i32 -> !spirv.ptr<i16, StorageBuffer>
466    %val = spirv.Load "StorageBuffer" %ac : i16
467
468    spirv.ReturnValue %val : i16
469  }
470}
471
472// CHECK-LABEL: spirv.module
473
474// CHECK: spirv.GlobalVariable @var01_v2f2 bind(0, 1) {aliased}
475// CHECK: spirv.GlobalVariable @var01_i16 bind(0, 1) {aliased}
476
477// CHECK: spirv.func @scalar_type_bitwidth_smaller_than_vector
478
479// -----
480
481spirv.module Logical GLSL450 {
482  spirv.GlobalVariable @var00_v4f32 bind(0, 0) {aliased} : !spirv.ptr<!spirv.struct<(!spirv.rtarray<vector<4xf32>, stride=16> [0])>, StorageBuffer>
483  spirv.GlobalVariable @var00_v4f16 bind(0, 0) {aliased} : !spirv.ptr<!spirv.struct<(!spirv.rtarray<vector<4xf16>, stride=8> [0])>, StorageBuffer>
484
485  spirv.func @vector_type_same_size_different_element_type(%i0: i32) -> vector<4xf32> "None" {
486    %c0 = spirv.Constant 0 : i32
487
488    %addr = spirv.mlir.addressof @var00_v4f32 : !spirv.ptr<!spirv.struct<(!spirv.rtarray<vector<4xf32>, stride=16> [0])>, StorageBuffer>
489    %ac = spirv.AccessChain %addr[%c0, %i0] : !spirv.ptr<!spirv.struct<(!spirv.rtarray<vector<4xf32>, stride=16> [0])>, StorageBuffer>, i32, i32 -> !spirv.ptr<vector<4xf32>, StorageBuffer>
490    %val = spirv.Load "StorageBuffer" %ac :  vector<4xf32>
491
492    spirv.ReturnValue %val : vector<4xf32>
493  }
494}
495
496// CHECK-LABEL: spirv.module
497
498// CHECK: spirv.GlobalVariable @var00_v4f16 bind(0, 0) : !spirv.ptr<!spirv.struct<(!spirv.rtarray<vector<4xf16>, stride=8> [0])>, StorageBuffer>
499
500// CHECK: spirv.func @vector_type_same_size_different_element_type
501
502// CHECK:   %[[LD0:.+]] = spirv.Load "StorageBuffer" %{{.+}} : vector<4xf16>
503// CHECK:   %[[LD1:.+]] = spirv.Load "StorageBuffer" %{{.+}} : vector<4xf16>
504// CHECK:   %[[BC0:.+]] = spirv.Bitcast %[[LD0]] : vector<4xf16> to vector<2xf32>
505// CHECK:   %[[BC1:.+]] = spirv.Bitcast %[[LD1]] : vector<4xf16> to vector<2xf32>
506// CHECK:   %[[CC:.+]] = spirv.CompositeConstruct %[[BC0]], %[[BC1]] : (vector<2xf32>, vector<2xf32>) -> vector<4xf32>
507// CHECK:   spirv.ReturnValue %[[CC]]
508
509// -----
510
511spirv.module Logical GLSL450 {
512  spirv.GlobalVariable @var01_v2f16 bind(0, 1) {aliased} : !spirv.ptr<!spirv.struct<(!spirv.rtarray<vector<2xf16>, stride=4> [0])>, StorageBuffer>
513  spirv.GlobalVariable @var01_v2f32 bind(0, 1) {aliased} : !spirv.ptr<!spirv.struct<(!spirv.rtarray<vector<2xf32>, stride=8> [0])>, StorageBuffer>
514
515  spirv.func @aliased(%index: i32) -> vector<3xf32> "None" {
516    %c0 = spirv.Constant 0 : i32
517    %v0 = spirv.Constant dense<0.0> : vector<3xf32>
518    %addr0 = spirv.mlir.addressof @var01_v2f16 : !spirv.ptr<!spirv.struct<(!spirv.rtarray<vector<2xf16>, stride=4> [0])>, StorageBuffer>
519    %ac0 = spirv.AccessChain %addr0[%c0, %index] : !spirv.ptr<!spirv.struct<(!spirv.rtarray<vector<2xf16>, stride=4> [0])>, StorageBuffer>, i32, i32 -> !spirv.ptr<vector<2xf16>, StorageBuffer>
520    %value0 = spirv.Load "StorageBuffer" %ac0 : vector<2xf16>
521
522    %addr1 = spirv.mlir.addressof @var01_v2f32 : !spirv.ptr<!spirv.struct<(!spirv.rtarray<vector<2xf32>, stride=8> [0])>, StorageBuffer>
523    %ac1 = spirv.AccessChain %addr1[%c0, %index] : !spirv.ptr<!spirv.struct<(!spirv.rtarray<vector<2xf32>, stride=8> [0])>, StorageBuffer>, i32, i32 -> !spirv.ptr<vector<2xf32>, StorageBuffer>
524    %value1 = spirv.Load "StorageBuffer" %ac1 : vector<2xf32>
525
526    %val0_as_f32 = spirv.Bitcast %value0 : vector<2xf16> to f32
527
528    %res = spirv.CompositeConstruct %val0_as_f32, %value1 : (f32, vector<2xf32>) -> vector<3xf32>
529
530    spirv.ReturnValue %res : vector<3xf32>
531  }
532}
533
534// CHECK-LABEL: spirv.module
535
536// CHECK: spirv.GlobalVariable @var01_v2f16 bind(0, 1) : !spirv.ptr<!spirv.struct<(!spirv.rtarray<vector<2xf16>, stride=4> [0])>, StorageBuffer>
537// CHECK: spirv.func @aliased
538
539// CHECK:     %[[LD0:.+]] = spirv.Load "StorageBuffer" %{{.+}} : vector<2xf16>
540// CHECK:     %[[LD1:.+]] = spirv.Load "StorageBuffer" %{{.+}} : vector<2xf16>
541// CHECK:     %[[LD2:.+]] = spirv.Load "StorageBuffer" %{{.+}} : vector<2xf16>
542
543// CHECK-DAG: %[[ELEM0:.+]] = spirv.Bitcast %[[LD0]] : vector<2xf16> to f32
544// CHECK-DAG: %[[ELEM1:.+]] = spirv.Bitcast %[[LD1]] : vector<2xf16> to f32
545// CHECK-DAG: %[[ELEM2:.+]] = spirv.Bitcast %[[LD2]] : vector<2xf16> to f32
546
547// CHECK:     %[[RES:.+]] = spirv.CompositeConstruct %[[ELEM0]], %{{.+}} : (f32, vector<2xf32>) -> vector<3xf32>
548// CHECK:     spirv.ReturnValue %[[RES]] : vector<3xf32>
549
550// -----
551
552// Make sure we do not crash on function arguments.
553
554spirv.module Logical GLSL450 {
555  spirv.func @main(%arg0: !spirv.ptr<!spirv.struct<(!spirv.rtarray<f32, stride=4> [0])>, StorageBuffer>) "None" {
556    %cst0_i32 = spirv.Constant 0 : i32
557    %0 = spirv.AccessChain %arg0[%cst0_i32, %cst0_i32] : !spirv.ptr<!spirv.struct<(!spirv.rtarray<f32, stride=4> [0])>, StorageBuffer>, i32, i32 -> !spirv.ptr<f32, StorageBuffer>
558    spirv.Return
559  }
560}
561
562// CHECK-LABEL: spirv.module
563// CHECK-LABEL: spirv.func @main
564// CHECK-SAME:  (%{{.+}}: !spirv.ptr<!spirv.struct<(!spirv.rtarray<f32, stride=4> [0])>, StorageBuffer>) "None"
565// CHECK:       spirv.Return
566