1// RUN: mlir-opt -test-spirv-module-combiner -split-input-file -verify-diagnostics %s | FileCheck %s
2
3// Deduplicate 2 global variables with the same descriptor set and binding.
4
5// CHECK:      module {
6// CHECK-NEXT:   spv.module Logical GLSL450 {
7// CHECK-NEXT:     spv.GlobalVariable @foo
8
9// CHECK-NEXT:     spv.func @use_foo
10// CHECK-NEXT:       spv.mlir.addressof @foo
11// CHECK-NEXT:       spv.Load
12// CHECK-NEXT:       spv.ReturnValue
13// CHECK-NEXT:     }
14
15// CHECK-NEXT:     spv.func @use_bar
16// CHECK-NEXT:       spv.mlir.addressof @foo
17// CHECK-NEXT:       spv.Load
18// CHECK-NEXT:       spv.FAdd
19// CHECK-NEXT:       spv.ReturnValue
20// CHECK-NEXT:     }
21// CHECK-NEXT:   }
22// CHECK-NEXT: }
23
24spv.module Logical GLSL450 {
25  spv.GlobalVariable @foo bind(1, 0) : !spv.ptr<f32, Input>
26
27  spv.func @use_foo() -> f32 "None" {
28    %0 = spv.mlir.addressof @foo : !spv.ptr<f32, Input>
29    %1 = spv.Load "Input" %0 : f32
30    spv.ReturnValue %1 : f32
31  }
32}
33
34spv.module Logical GLSL450 {
35  spv.GlobalVariable @bar bind(1, 0) : !spv.ptr<f32, Input>
36
37  spv.func @use_bar() -> f32 "None" {
38    %0 = spv.mlir.addressof @bar : !spv.ptr<f32, Input>
39    %1 = spv.Load "Input" %0 : f32
40    %2 = spv.FAdd %1, %1 : f32
41    spv.ReturnValue %2 : f32
42  }
43}
44
45// -----
46
47// Deduplicate 2 global variables with the same descriptor set and binding but different types.
48
49// CHECK:      module {
50// CHECK-NEXT: spv.module Logical GLSL450 {
51// CHECK-NEXT:   spv.GlobalVariable @foo bind(1, 0)
52
53// CHECK-NEXT:   spv.GlobalVariable @bar bind(1, 0)
54
55// CHECK-NEXT:   spv.func @use_bar
56// CHECK-NEXT:     spv.mlir.addressof @bar
57// CHECK-NEXT:     spv.Load
58// CHECK-NEXT:     spv.ReturnValue
59// CHECK-NEXT:   }
60// CHECK-NEXT: }
61// CHECK-NEXT: }
62
63spv.module Logical GLSL450 {
64  spv.GlobalVariable @foo bind(1, 0) : !spv.ptr<i32, Input>
65}
66
67spv.module Logical GLSL450 {
68  spv.GlobalVariable @bar bind(1, 0) : !spv.ptr<f32, Input>
69
70  spv.func @use_bar() -> f32 "None" {
71    %0 = spv.mlir.addressof @bar : !spv.ptr<f32, Input>
72    %1 = spv.Load "Input" %0 : f32
73    spv.ReturnValue %1 : f32
74  }
75}
76
77// -----
78
79// Deduplicate 2 global variables with the same built-in attribute.
80
81// CHECK:      module {
82// CHECK-NEXT:   spv.module Logical GLSL450 {
83// CHECK-NEXT:     spv.GlobalVariable @foo built_in("GlobalInvocationId")
84// CHECK-NEXT:     spv.func @use_bar
85// CHECK-NEXT:       spv.mlir.addressof @foo
86// CHECK-NEXT:       spv.Load
87// CHECK-NEXT:       spv.ReturnValue
88// CHECK-NEXT:     }
89// CHECK-NEXT:   }
90// CHECK-NEXT: }
91
92spv.module Logical GLSL450 {
93  spv.GlobalVariable @foo built_in("GlobalInvocationId") : !spv.ptr<vector<3xi32>, Input>
94}
95
96spv.module Logical GLSL450 {
97  spv.GlobalVariable @bar built_in("GlobalInvocationId") : !spv.ptr<vector<3xi32>, Input>
98
99  spv.func @use_bar() -> vector<3xi32> "None" {
100    %0 = spv.mlir.addressof @bar : !spv.ptr<vector<3xi32>, Input>
101    %1 = spv.Load "Input" %0 : vector<3xi32>
102    spv.ReturnValue %1 : vector<3xi32>
103  }
104}
105
106// -----
107
108// Deduplicate 2 spec constants with the same spec ID.
109
110// CHECK:      module {
111// CHECK-NEXT:   spv.module Logical GLSL450 {
112// CHECK-NEXT:     spv.SpecConstant @foo spec_id(5)
113
114// CHECK-NEXT:     spv.func @use_foo()
115// CHECK-NEXT:       %0 = spv.mlir.referenceof @foo
116// CHECK-NEXT:       spv.ReturnValue
117// CHECK-NEXT:     }
118
119// CHECK-NEXT:     spv.func @use_bar()
120// CHECK-NEXT:       %0 = spv.mlir.referenceof @foo
121// CHECK-NEXT:       spv.FAdd
122// CHECK-NEXT:       spv.ReturnValue
123// CHECK-NEXT:     }
124// CHECK-NEXT:   }
125// CHECK-NEXT: }
126
127spv.module Logical GLSL450 {
128  spv.SpecConstant @foo spec_id(5) = 1. : f32
129
130  spv.func @use_foo() -> (f32) "None" {
131    %0 = spv.mlir.referenceof @foo : f32
132    spv.ReturnValue %0 : f32
133  }
134}
135
136spv.module Logical GLSL450 {
137  spv.SpecConstant @bar spec_id(5) = 1. : f32
138
139  spv.func @use_bar() -> (f32) "None" {
140    %0 = spv.mlir.referenceof @bar : f32
141    %1 = spv.FAdd %0, %0 : f32
142    spv.ReturnValue %1 : f32
143  }
144}
145
146// -----
147
148// Don't deduplicate functions with similar ops but different operands.
149
150//       CHECK: spv.module Logical GLSL450 {
151//  CHECK-NEXT:   spv.func @foo(%[[ARG0:.+]]: f32, %[[ARG1:.+]]: f32, %[[ARG2:.+]]: f32)
152//  CHECK-NEXT:     %[[ADD:.+]] = spv.FAdd %[[ARG0]], %[[ARG1]] : f32
153//  CHECK-NEXT:     %[[MUL:.+]] = spv.FMul %[[ADD]], %[[ARG2]] : f32
154//  CHECK-NEXT:     spv.ReturnValue %[[MUL]] : f32
155//  CHECK-NEXT:   }
156//  CHECK-NEXT:   spv.func @foo_1(%[[ARG0:.+]]: f32, %[[ARG1:.+]]: f32, %[[ARG2:.+]]: f32)
157//  CHECK-NEXT:     %[[ADD:.+]] = spv.FAdd %[[ARG0]], %[[ARG2]] : f32
158//  CHECK-NEXT:     %[[MUL:.+]] = spv.FMul %[[ADD]], %[[ARG1]] : f32
159//  CHECK-NEXT:     spv.ReturnValue %[[MUL]] : f32
160//  CHECK-NEXT:   }
161//  CHECK-NEXT: }
162
163spv.module Logical GLSL450 {
164  spv.func @foo(%a: f32, %b: f32, %c: f32) -> f32 "None" {
165    %add = spv.FAdd %a, %b: f32
166    %mul = spv.FMul %add, %c: f32
167    spv.ReturnValue %mul: f32
168  }
169}
170
171spv.module Logical GLSL450 {
172  spv.func @foo(%a: f32, %b: f32, %c: f32) -> f32 "None" {
173    %add = spv.FAdd %a, %c: f32
174    %mul = spv.FMul %add, %b: f32
175    spv.ReturnValue %mul: f32
176  }
177}
178
179// -----
180
181// TODO: re-enable this test once we have better function deduplication.
182
183// XXXXX:      module {
184// XXXXX-NEXT:   spv.module Logical GLSL450 {
185// XXXXX-NEXT:     spv.SpecConstant @bar spec_id(5)
186
187// XXXXX-NEXT:     spv.func @foo(%arg0: f32)
188// XXXXX-NEXT:       spv.ReturnValue
189// XXXXX-NEXT:     }
190
191// XXXXX-NEXT:     spv.func @foo_different_body(%arg0: f32)
192// XXXXX-NEXT:       spv.mlir.referenceof
193// XXXXX-NEXT:       spv.ReturnValue
194// XXXXX-NEXT:     }
195
196// XXXXX-NEXT:     spv.func @baz(%arg0: i32)
197// XXXXX-NEXT:       spv.ReturnValue
198// XXXXX-NEXT:     }
199
200// XXXXX-NEXT:     spv.func @baz_no_return(%arg0: i32)
201// XXXXX-NEXT:       spv.Return
202// XXXXX-NEXT:     }
203
204// XXXXX-NEXT:     spv.func @baz_no_return_different_control
205// XXXXX-NEXT:       spv.Return
206// XXXXX-NEXT:     }
207
208// XXXXX-NEXT:     spv.func @baz_no_return_another_control
209// XXXXX-NEXT:       spv.Return
210// XXXXX-NEXT:     }
211
212// XXXXX-NEXT:     spv.func @kernel
213// XXXXX-NEXT:       spv.Return
214// XXXXX-NEXT:     }
215
216// XXXXX-NEXT:     spv.func @kernel_different_attr
217// XXXXX-NEXT:       spv.Return
218// XXXXX-NEXT:     }
219// XXXXX-NEXT:   }
220// XXXXX-NEXT:   }
221
222module {
223spv.module Logical GLSL450 {
224  spv.SpecConstant @bar spec_id(5) = 1. : f32
225
226  spv.func @foo(%arg0: f32) -> (f32) "None" {
227    spv.ReturnValue %arg0 : f32
228  }
229
230  spv.func @foo_duplicate(%arg0: f32) -> (f32) "None" {
231    spv.ReturnValue %arg0 : f32
232  }
233
234  spv.func @foo_different_body(%arg0: f32) -> (f32) "None" {
235    %0 = spv.mlir.referenceof @bar : f32
236    spv.ReturnValue %arg0 : f32
237  }
238
239  spv.func @baz(%arg0: i32) -> (i32) "None" {
240    spv.ReturnValue %arg0 : i32
241  }
242
243  spv.func @baz_no_return(%arg0: i32) "None" {
244    spv.Return
245  }
246
247  spv.func @baz_no_return_duplicate(%arg0: i32) -> () "None" {
248    spv.Return
249  }
250
251  spv.func @baz_no_return_different_control(%arg0: i32) -> () "Inline" {
252    spv.Return
253  }
254
255  spv.func @baz_no_return_another_control(%arg0: i32) -> () "Inline|Pure" {
256    spv.Return
257  }
258
259  spv.func @kernel(
260    %arg0: f32,
261    %arg1: !spv.ptr<!spv.struct<(!spv.array<12 x f32>)>, CrossWorkgroup>) "None"
262  attributes {spv.entry_point_abi = #spv.entry_point_abi<local_size = dense<[32, 1, 1]> : vector<3xi32>>} {
263    spv.Return
264  }
265
266  spv.func @kernel_different_attr(
267    %arg0: f32,
268    %arg1: !spv.ptr<!spv.struct<(!spv.array<12 x f32>)>, CrossWorkgroup>) "None"
269  attributes {spv.entry_point_abi = #spv.entry_point_abi<local_size = dense<[64, 1, 1]> : vector<3xi32>>} {
270    spv.Return
271  }
272}
273}
274