1 // Copyright (c) 2022 The Khronos Group Inc.
2 // Copyright (c) 2022 LunarG Inc.
3 //
4 // Licensed under the Apache License, Version 2.0 (the "License");
5 // you may not use this file except in compliance with the License.
6 // You may obtain a copy of the License at
7 //
8 //     http://www.apache.org/licenses/LICENSE-2.0
9 //
10 // Unless required by applicable law or agreed to in writing, software
11 // distributed under the License is distributed on an "AS IS" BASIS,
12 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 // See the License for the specific language governing permissions and
14 // limitations under the License.
15 
16 #include <vector>
17 
18 #include "test/opt/pass_fixture.h"
19 #include "test/opt/pass_utils.h"
20 
21 namespace spvtools {
22 namespace opt {
23 namespace {
24 
25 using ElimDeadIOComponentsTest = PassTest<::testing::Test>;
26 
TEST_F(ElimDeadIOComponentsTest, ElimOneConstantIndex)27 TEST_F(ElimDeadIOComponentsTest, ElimOneConstantIndex) {
28   // Should reduce to uv[2]
29   //
30   // #version 450
31   //
32   // layout(location = 0) in vec4 uv[8];
33   //
34   // out gl_PerVertex {
35   //     vec4 gl_Position;
36   // };
37   //
38   // void main()
39   // {
40   //     gl_Position = uv[1];
41   // }
42   const std::string text = R"(
43                OpCapability Shader
44           %1 = OpExtInstImport "GLSL.std.450"
45                OpMemoryModel Logical GLSL450
46                OpEntryPoint Vertex %main "main" %_ %uv
47                OpSource GLSL 450
48                OpName %main "main"
49                OpName %gl_PerVertex "gl_PerVertex"
50                OpMemberName %gl_PerVertex 0 "gl_Position"
51                OpName %_ ""
52                OpName %uv "uv"
53                OpMemberDecorate %gl_PerVertex 0 BuiltIn Position
54                OpDecorate %gl_PerVertex Block
55                OpDecorate %uv Location 0
56        %void = OpTypeVoid
57           %3 = OpTypeFunction %void
58       %float = OpTypeFloat 32
59     %v4float = OpTypeVector %float 4
60 %gl_PerVertex = OpTypeStruct %v4float
61 %_ptr_Output_gl_PerVertex = OpTypePointer Output %gl_PerVertex
62           %_ = OpVariable %_ptr_Output_gl_PerVertex Output
63         %int = OpTypeInt 32 1
64       %int_0 = OpConstant %int 0
65        %uint = OpTypeInt 32 0
66      %uint_8 = OpConstant %uint 8
67 %_arr_v4float_uint_8 = OpTypeArray %v4float %uint_8
68 %_ptr_Input__arr_v4float_uint_8 = OpTypePointer Input %_arr_v4float_uint_8
69            %uv = OpVariable %_ptr_Input__arr_v4float_uint_8 Input
70       %int_1 = OpConstant %int 1
71 %_ptr_Input_v4float = OpTypePointer Input %v4float
72 %_ptr_Output_v4float = OpTypePointer Output %v4float
73 ;CHECK-NOT: %uv = OpVariable %_ptr_Input__arr_v4float_uint_8 Input
74 ;CHECK:     %uv = OpVariable %_ptr_Input__arr_v4float_uint_2 Input
75        %main = OpFunction %void None %3
76           %5 = OpLabel
77          %20 = OpAccessChain %_ptr_Input_v4float %uv %int_1
78          %21 = OpLoad %v4float %20
79          %23 = OpAccessChain %_ptr_Output_v4float %_ %int_0
80                OpStore %23 %21
81                OpReturn
82                OpFunctionEnd
83 )";
84 
85   SetTargetEnv(SPV_ENV_VULKAN_1_3);
86   SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
87   SinglePassRunAndMatch<EliminateDeadIOComponentsPass>(
88       text, true, spv::StorageClass::Input, false);
89 }
90 
TEST_F(ElimDeadIOComponentsTest, ElimOneConstantIndexInBounds)91 TEST_F(ElimDeadIOComponentsTest, ElimOneConstantIndexInBounds) {
92   // Same as ElimOneConstantIndex but with OpInBoundsAccessChain
93   const std::string text = R"(
94                OpCapability Shader
95           %1 = OpExtInstImport "GLSL.std.450"
96                OpMemoryModel Logical GLSL450
97                OpEntryPoint Vertex %main "main" %_ %uv
98                OpSource GLSL 450
99                OpName %main "main"
100                OpName %gl_PerVertex "gl_PerVertex"
101                OpMemberName %gl_PerVertex 0 "gl_Position"
102                OpName %_ ""
103                OpName %uv "uv"
104                OpMemberDecorate %gl_PerVertex 0 BuiltIn Position
105                OpDecorate %gl_PerVertex Block
106                OpDecorate %uv Location 0
107        %void = OpTypeVoid
108           %3 = OpTypeFunction %void
109       %float = OpTypeFloat 32
110     %v4float = OpTypeVector %float 4
111 %gl_PerVertex = OpTypeStruct %v4float
112 %_ptr_Output_gl_PerVertex = OpTypePointer Output %gl_PerVertex
113           %_ = OpVariable %_ptr_Output_gl_PerVertex Output
114         %int = OpTypeInt 32 1
115       %int_0 = OpConstant %int 0
116        %uint = OpTypeInt 32 0
117      %uint_8 = OpConstant %uint 8
118 %_arr_v4float_uint_8 = OpTypeArray %v4float %uint_8
119 %_ptr_Input__arr_v4float_uint_8 = OpTypePointer Input %_arr_v4float_uint_8
120            %uv = OpVariable %_ptr_Input__arr_v4float_uint_8 Input
121       %int_1 = OpConstant %int 1
122 %_ptr_Input_v4float = OpTypePointer Input %v4float
123 %_ptr_Output_v4float = OpTypePointer Output %v4float
124 ;CHECK-NOT: %uv = OpVariable %_ptr_Input__arr_v4float_uint_8 Input
125 ;CHECK:     %uv = OpVariable %_ptr_Input__arr_v4float_uint_2 Input
126        %main = OpFunction %void None %3
127           %5 = OpLabel
128          %20 = OpInBoundsAccessChain %_ptr_Input_v4float %uv %int_1
129          %21 = OpLoad %v4float %20
130          %23 = OpAccessChain %_ptr_Output_v4float %_ %int_0
131                OpStore %23 %21
132                OpReturn
133                OpFunctionEnd
134 )";
135 
136   SetTargetEnv(SPV_ENV_VULKAN_1_3);
137   SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
138   SinglePassRunAndMatch<EliminateDeadIOComponentsPass>(
139       text, true, spv::StorageClass::Input, false);
140 }
141 
TEST_F(ElimDeadIOComponentsTest, ElimTwoConstantIndices)142 TEST_F(ElimDeadIOComponentsTest, ElimTwoConstantIndices) {
143   // Should reduce to uv[4]
144   //
145   // #version 450
146   //
147   // layout(location = 0) in vec4 uv[8];
148   //
149   // out gl_PerVertex {
150   //     vec4 gl_Position;
151   // };
152   //
153   // void main()
154   // {
155   //     gl_Position = uv[1] + uv[3];
156   // }
157   const std::string text = R"(
158                OpCapability Shader
159           %1 = OpExtInstImport "GLSL.std.450"
160                OpMemoryModel Logical GLSL450
161                OpEntryPoint Vertex %main "main" %_ %uv
162                OpSource GLSL 450
163                OpName %main "main"
164                OpName %gl_PerVertex "gl_PerVertex"
165                OpMemberName %gl_PerVertex 0 "gl_Position"
166                OpName %_ ""
167                OpName %uv "uv"
168                OpMemberDecorate %gl_PerVertex 0 BuiltIn Position
169                OpDecorate %gl_PerVertex Block
170                OpDecorate %uv Location 0
171        %void = OpTypeVoid
172           %3 = OpTypeFunction %void
173       %float = OpTypeFloat 32
174     %v4float = OpTypeVector %float 4
175 %gl_PerVertex = OpTypeStruct %v4float
176 %_ptr_Output_gl_PerVertex = OpTypePointer Output %gl_PerVertex
177           %_ = OpVariable %_ptr_Output_gl_PerVertex Output
178         %int = OpTypeInt 32 1
179       %int_0 = OpConstant %int 0
180        %uint = OpTypeInt 32 0
181      %uint_8 = OpConstant %uint 8
182 %_arr_v4float_uint_8 = OpTypeArray %v4float %uint_8
183 %_ptr_Input__arr_v4float_uint_8 = OpTypePointer Input %_arr_v4float_uint_8
184          %uv = OpVariable %_ptr_Input__arr_v4float_uint_8 Input
185       %int_1 = OpConstant %int 1
186 %_ptr_Input_v4float = OpTypePointer Input %v4float
187       %int_3 = OpConstant %int 3
188 %_ptr_Output_v4float = OpTypePointer Output %v4float
189 ;CHECK-NOT: %uv = OpVariable %_ptr_Input__arr_v4float_uint_8 Input
190 ;CHECK:     %uv = OpVariable %_ptr_Input__arr_v4float_uint_4 Input
191        %main = OpFunction %void None %3
192           %5 = OpLabel
193          %20 = OpAccessChain %_ptr_Input_v4float %uv %int_1
194          %21 = OpLoad %v4float %20
195          %23 = OpAccessChain %_ptr_Input_v4float %uv %int_3
196          %24 = OpLoad %v4float %23
197          %25 = OpFAdd %v4float %21 %24
198          %27 = OpAccessChain %_ptr_Output_v4float %_ %int_0
199                OpStore %27 %25
200                OpReturn
201                OpFunctionEnd
202 )";
203 
204   SetTargetEnv(SPV_ENV_VULKAN_1_3);
205   SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
206   SinglePassRunAndMatch<EliminateDeadIOComponentsPass>(
207       text, true, spv::StorageClass::Input, false);
208 }
209 
TEST_F(ElimDeadIOComponentsTest, NoElimMaxConstantIndex)210 TEST_F(ElimDeadIOComponentsTest, NoElimMaxConstantIndex) {
211   // Should not reduce uv[8] because of max index of 7
212   //
213   // #version 450
214   //
215   // layout(location = 0) in vec4 uv[8];
216   //
217   // out gl_PerVertex {
218   //     vec4 gl_Position;
219   // };
220   //
221   // void main()
222   // {
223   //     gl_Position = uv[1] + uv[7];
224   // }
225   const std::string text = R"(
226                OpCapability Shader
227           %1 = OpExtInstImport "GLSL.std.450"
228                OpMemoryModel Logical GLSL450
229                OpEntryPoint Vertex %main "main" %_ %uv
230                OpSource GLSL 450
231                OpName %main "main"
232                OpName %gl_PerVertex "gl_PerVertex"
233                OpMemberName %gl_PerVertex 0 "gl_Position"
234                OpName %_ ""
235                OpName %uv "uv"
236                OpMemberDecorate %gl_PerVertex 0 BuiltIn Position
237                OpDecorate %gl_PerVertex Block
238                OpDecorate %uv Location 0
239        %void = OpTypeVoid
240           %3 = OpTypeFunction %void
241       %float = OpTypeFloat 32
242     %v4float = OpTypeVector %float 4
243 %gl_PerVertex = OpTypeStruct %v4float
244 %_ptr_Output_gl_PerVertex = OpTypePointer Output %gl_PerVertex
245           %_ = OpVariable %_ptr_Output_gl_PerVertex Output
246         %int = OpTypeInt 32 1
247       %int_0 = OpConstant %int 0
248        %uint = OpTypeInt 32 0
249      %uint_8 = OpConstant %uint 8
250 %_arr_v4float_uint_8 = OpTypeArray %v4float %uint_8
251 %_ptr_Input__arr_v4float_uint_8 = OpTypePointer Input %_arr_v4float_uint_8
252          %uv = OpVariable %_ptr_Input__arr_v4float_uint_8 Input
253       %int_1 = OpConstant %int 1
254 %_ptr_Input_v4float = OpTypePointer Input %v4float
255       %int_7 = OpConstant %int 7
256 %_ptr_Output_v4float = OpTypePointer Output %v4float
257 ;CHECK:     %uv = OpVariable %_ptr_Input__arr_v4float_uint_8 Input
258        %main = OpFunction %void None %3
259           %5 = OpLabel
260          %20 = OpAccessChain %_ptr_Input_v4float %uv %int_1
261          %21 = OpLoad %v4float %20
262          %23 = OpAccessChain %_ptr_Input_v4float %uv %int_7
263          %24 = OpLoad %v4float %23
264          %25 = OpFAdd %v4float %21 %24
265          %27 = OpAccessChain %_ptr_Output_v4float %_ %int_0
266                OpStore %27 %25
267                OpReturn
268                OpFunctionEnd
269 )";
270 
271   SetTargetEnv(SPV_ENV_VULKAN_1_3);
272   SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
273   SinglePassRunAndMatch<EliminateDeadIOComponentsPass>(
274       text, true, spv::StorageClass::Input, false);
275 }
276 
TEST_F(ElimDeadIOComponentsTest, NoElimNonConstantIndex)277 TEST_F(ElimDeadIOComponentsTest, NoElimNonConstantIndex) {
278   // Should not reduce uv[8] because of non-constant index of ui
279   //
280   // #version 450
281   //
282   // layout(location = 0) in vec4 uv[8];
283   //
284   // out gl_PerVertex {
285   //     vec4 gl_Position;
286   // };
287   //
288   // uniform ubname {
289   //     int ui;
290   // } ubinst;
291   //
292   // void main()
293   // {
294   //     gl_Position = uv[1] + uv[ubinst.ui];
295   // }
296   const std::string text = R"(
297                OpCapability Shader
298           %1 = OpExtInstImport "GLSL.std.450"
299                OpMemoryModel Logical GLSL450
300                OpEntryPoint Vertex %main "main" %_ %uv %ubinst
301                OpSource GLSL 450
302                OpName %main "main"
303                OpName %gl_PerVertex "gl_PerVertex"
304                OpMemberName %gl_PerVertex 0 "gl_Position"
305                OpName %_ ""
306                OpName %uv "uv"
307                OpName %ubname "ubname"
308                OpMemberName %ubname 0 "ui"
309                OpName %ubinst "ubinst"
310                OpMemberDecorate %gl_PerVertex 0 BuiltIn Position
311                OpDecorate %gl_PerVertex Block
312                OpDecorate %uv Location 0
313                OpMemberDecorate %ubname 0 Offset 0
314                OpDecorate %ubname Block
315                OpDecorate %ubinst DescriptorSet 0
316                OpDecorate %ubinst Binding 0
317        %void = OpTypeVoid
318           %3 = OpTypeFunction %void
319       %float = OpTypeFloat 32
320     %v4float = OpTypeVector %float 4
321 %gl_PerVertex = OpTypeStruct %v4float
322 %_ptr_Output_gl_PerVertex = OpTypePointer Output %gl_PerVertex
323           %_ = OpVariable %_ptr_Output_gl_PerVertex Output
324         %int = OpTypeInt 32 1
325       %int_0 = OpConstant %int 0
326        %uint = OpTypeInt 32 0
327      %uint_8 = OpConstant %uint 8
328 %_arr_v4float_uint_8 = OpTypeArray %v4float %uint_8
329 %_ptr_Input__arr_v4float_uint_8 = OpTypePointer Input %_arr_v4float_uint_8
330          %uv = OpVariable %_ptr_Input__arr_v4float_uint_8 Input
331       %int_1 = OpConstant %int 1
332 %_ptr_Input_v4float = OpTypePointer Input %v4float
333      %ubname = OpTypeStruct %int
334 %_ptr_Uniform_ubname = OpTypePointer Uniform %ubname
335      %ubinst = OpVariable %_ptr_Uniform_ubname Uniform
336 %_ptr_Uniform_int = OpTypePointer Uniform %int
337 %_ptr_Output_v4float = OpTypePointer Output %v4float
338 ;CHECK:  %uv = OpVariable %_ptr_Input__arr_v4float_uint_8 Input
339        %main = OpFunction %void None %3
340           %5 = OpLabel
341          %20 = OpAccessChain %_ptr_Input_v4float %uv %int_1
342          %21 = OpLoad %v4float %20
343          %26 = OpAccessChain %_ptr_Uniform_int %ubinst %int_0
344          %27 = OpLoad %int %26
345          %28 = OpAccessChain %_ptr_Input_v4float %uv %27
346          %29 = OpLoad %v4float %28
347          %30 = OpFAdd %v4float %21 %29
348          %32 = OpAccessChain %_ptr_Output_v4float %_ %int_0
349                OpStore %32 %30
350                OpReturn
351                OpFunctionEnd
352 )";
353 
354   SetTargetEnv(SPV_ENV_VULKAN_1_3);
355   SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
356   SinglePassRunAndMatch<EliminateDeadIOComponentsPass>(
357       text, true, spv::StorageClass::Input, false);
358 }
359 
TEST_F(ElimDeadIOComponentsTest, NoElimNonIndexedAccessChain)360 TEST_F(ElimDeadIOComponentsTest, NoElimNonIndexedAccessChain) {
361   // Should not change due to non-indexed access chain
362   const std::string text = R"(
363                OpCapability Shader
364           %1 = OpExtInstImport "GLSL.std.450"
365                OpMemoryModel Logical GLSL450
366                OpEntryPoint Vertex %main "main" %_ %uv
367                OpSource GLSL 450
368                OpName %main "main"
369                OpName %gl_PerVertex "gl_PerVertex"
370                OpMemberName %gl_PerVertex 0 "gl_Position"
371                OpName %_ ""
372                OpName %uv "uv"
373                OpMemberDecorate %gl_PerVertex 0 BuiltIn Position
374                OpDecorate %gl_PerVertex Block
375                OpDecorate %uv Location 0
376        %void = OpTypeVoid
377           %3 = OpTypeFunction %void
378       %float = OpTypeFloat 32
379     %v4float = OpTypeVector %float 4
380 %gl_PerVertex = OpTypeStruct %v4float
381 %_ptr_Output_gl_PerVertex = OpTypePointer Output %gl_PerVertex
382           %_ = OpVariable %_ptr_Output_gl_PerVertex Output
383         %int = OpTypeInt 32 1
384       %int_0 = OpConstant %int 0
385        %uint = OpTypeInt 32 0
386      %uint_8 = OpConstant %uint 8
387 %_arr_v4float_uint_8 = OpTypeArray %v4float %uint_8
388 %_ptr_Input__arr_v4float_uint_8 = OpTypePointer Input %_arr_v4float_uint_8
389            %uv = OpVariable %_ptr_Input__arr_v4float_uint_8 Input
390       %int_1 = OpConstant %int 1
391 %_ptr_Input_v4float = OpTypePointer Input %v4float
392 %_ptr_Output_v4float = OpTypePointer Output %v4float
393 ;CHECK:  %uv = OpVariable %_ptr_Input__arr_v4float_uint_8 Input
394        %main = OpFunction %void None %3
395           %5 = OpLabel
396          %20 = OpAccessChain %_ptr_Input__arr_v4float_uint_8 %uv
397                OpReturn
398                OpFunctionEnd
399 )";
400 
401   SetTargetEnv(SPV_ENV_VULKAN_1_3);
402   SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
403   SinglePassRunAndMatch<EliminateDeadIOComponentsPass>(
404       text, true, spv::StorageClass::Input, false);
405 }
406 
TEST_F(ElimDeadIOComponentsTest, ElimStructMember)407 TEST_F(ElimDeadIOComponentsTest, ElimStructMember) {
408   // Should eliminate uv
409   //
410   // #version 450
411   //
412   // in Vertex {
413   //   vec4 Cd;
414   //   vec2 uv;
415   // } iVert;
416   //
417   // out vec4 fragColor;
418   //
419   // void main()
420   // {
421   //   vec4 color = vec4(iVert.Cd);
422   //   fragColor = color;
423   // }
424   const std::string text = R"(
425                OpCapability Shader
426           %1 = OpExtInstImport "GLSL.std.450"
427                OpMemoryModel Logical GLSL450
428                OpEntryPoint Fragment %main "main" %iVert %fragColor
429                OpExecutionMode %main OriginUpperLeft
430                OpSource GLSL 450
431                OpName %main "main"
432                OpName %Vertex "Vertex"
433                OpMemberName %Vertex 0 "Cd"
434                OpMemberName %Vertex 1 "uv"
435                OpName %iVert "iVert"
436                OpName %fragColor "fragColor"
437                OpDecorate %Vertex Block
438                OpDecorate %iVert Location 0
439                OpDecorate %fragColor Location 0
440        %void = OpTypeVoid
441           %3 = OpTypeFunction %void
442       %float = OpTypeFloat 32
443     %v4float = OpTypeVector %float 4
444     %v2float = OpTypeVector %float 2
445      %Vertex = OpTypeStruct %v4float %v2float
446 ; CHECK: %Vertex = OpTypeStruct %v4float %v2float
447 ; CHECK: %Vertex_0 = OpTypeStruct %v4float
448 %_ptr_Input_Vertex = OpTypePointer Input %Vertex
449 ; CHECK: [[pty:%\w+]] = OpTypePointer Input %Vertex_0
450       %iVert = OpVariable %_ptr_Input_Vertex Input
451 ; CHECK: %iVert = OpVariable [[pty]] Input
452         %int = OpTypeInt 32 1
453       %int_0 = OpConstant %int 0
454 %_ptr_Input_v4float = OpTypePointer Input %v4float
455 %_ptr_Output_v4float = OpTypePointer Output %v4float
456   %fragColor = OpVariable %_ptr_Output_v4float Output
457        %main = OpFunction %void None %3
458           %5 = OpLabel
459          %17 = OpAccessChain %_ptr_Input_v4float %iVert %int_0
460          %18 = OpLoad %v4float %17
461                OpStore %fragColor %18
462                OpReturn
463                OpFunctionEnd
464 )";
465 
466   SetTargetEnv(SPV_ENV_VULKAN_1_3);
467   SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
468   SinglePassRunAndMatch<EliminateDeadIOComponentsPass>(
469       text, true, spv::StorageClass::Input, false);
470 }
471 
TEST_F(ElimDeadIOComponentsTest, ElimOutputStructMember)472 TEST_F(ElimDeadIOComponentsTest, ElimOutputStructMember) {
473   // Should eliminate uv from Vertex and all but gl_Position from gl_PerVertex
474   //
475   // #version 450
476   //
477   // out Vertex {
478   //   vec4 Cd;
479   //   vec2 uv;
480   // } oVert;
481   //
482   // in vec3 P;
483   //
484   // void main()
485   // {
486   //   vec4 worldSpacePos = vec4(P, 1);
487   //   oVert.Cd = vec4(1, 0.5, 0, 1);
488   //   gl_Position = worldSpacePos;
489   // }
490 
491   const std::string text = R"(
492                OpCapability Shader
493           %1 = OpExtInstImport "GLSL.std.450"
494                OpMemoryModel Logical GLSL450
495                OpEntryPoint Vertex %main "main" %P %oVert %_
496                OpSource GLSL 450
497                OpName %main "main"
498                OpName %P "P"
499                OpName %Vertex "Vertex"
500                OpMemberName %Vertex 0 "Cd"
501                OpMemberName %Vertex 1 "uv"
502                OpName %oVert "oVert"
503                OpName %gl_PerVertex "gl_PerVertex"
504                OpMemberName %gl_PerVertex 0 "gl_Position"
505                OpMemberName %gl_PerVertex 1 "gl_PointSize"
506                OpMemberName %gl_PerVertex 2 "gl_ClipDistance"
507                OpMemberName %gl_PerVertex 3 "gl_CullDistance"
508                OpName %_ ""
509                OpDecorate %P Location 0
510                OpDecorate %Vertex Block
511                OpDecorate %oVert Location 0
512                OpMemberDecorate %gl_PerVertex 0 BuiltIn Position
513                OpMemberDecorate %gl_PerVertex 1 BuiltIn PointSize
514                OpMemberDecorate %gl_PerVertex 2 BuiltIn ClipDistance
515                OpMemberDecorate %gl_PerVertex 3 BuiltIn CullDistance
516                OpDecorate %gl_PerVertex Block
517        %void = OpTypeVoid
518           %3 = OpTypeFunction %void
519       %float = OpTypeFloat 32
520     %v4float = OpTypeVector %float 4
521     %v3float = OpTypeVector %float 3
522 %_ptr_Input_v3float = OpTypePointer Input %v3float
523           %P = OpVariable %_ptr_Input_v3float Input
524     %float_1 = OpConstant %float 1
525     %v2float = OpTypeVector %float 2
526      %Vertex = OpTypeStruct %v4float %v2float
527 %_ptr_Output_Vertex = OpTypePointer Output %Vertex
528       %oVert = OpVariable %_ptr_Output_Vertex Output
529         %int = OpTypeInt 32 1
530       %int_0 = OpConstant %int 0
531   %float_0_5 = OpConstant %float 0.5
532     %float_0 = OpConstant %float 0
533          %27 = OpConstantComposite %v4float %float_1 %float_0_5 %float_0 %float_1
534 %_ptr_Output_v4float = OpTypePointer Output %v4float
535        %uint = OpTypeInt 32 0
536      %uint_1 = OpConstant %uint 1
537 %_arr_float_uint_1 = OpTypeArray %float %uint_1
538 %gl_PerVertex = OpTypeStruct %v4float %float %_arr_float_uint_1 %_arr_float_uint_1
539 %_ptr_Output_gl_PerVertex = OpTypePointer Output %gl_PerVertex
540           %_ = OpVariable %_ptr_Output_gl_PerVertex Output
541 ; CHECK: %Vertex = OpTypeStruct %v4float %v2float
542 ; CHECK: %gl_PerVertex = OpTypeStruct %v4float %float %_arr_float_uint_1 %_arr_float_uint_1
543 ; CHECK: %_ptr_Output_gl_PerVertex = OpTypePointer Output %gl_PerVertex
544 ; CHECK: [[sty:%\w+]] = OpTypeStruct %v4float
545 ; CHECK: [[pty:%\w+]] = OpTypePointer Output [[sty]]
546 ; CHECK: %oVert = OpVariable [[pty]] Output
547 ; CHECK: [[sty2:%\w+]] = OpTypeStruct %v4float
548 ; CHECK: [[pty2:%\w+]] = OpTypePointer Output [[sty2]]
549 ; CHECK: %_ = OpVariable [[pty2]] Output
550        %main = OpFunction %void None %3
551           %5 = OpLabel
552          %13 = OpLoad %v3float %P
553          %15 = OpCompositeExtract %float %13 0
554          %16 = OpCompositeExtract %float %13 1
555          %17 = OpCompositeExtract %float %13 2
556          %18 = OpCompositeConstruct %v4float %15 %16 %17 %float_1
557          %29 = OpAccessChain %_ptr_Output_v4float %oVert %int_0
558                OpStore %29 %27
559          %37 = OpAccessChain %_ptr_Output_v4float %_ %int_0
560                OpStore %37 %18
561                OpReturn
562                OpFunctionEnd
563 )";
564 
565   SetTargetEnv(SPV_ENV_VULKAN_1_3);
566   SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
567   SinglePassRunAndMatch<EliminateDeadIOComponentsPass>(
568       text, true, spv::StorageClass::Output, false);
569 }
570 
TEST_F(ElimDeadIOComponentsTest, ElimOutputArrayMembers)571 TEST_F(ElimDeadIOComponentsTest, ElimOutputArrayMembers) {
572   // Should reduce to uv[2]
573   //
574   // #version 450
575   //
576   // layout(location = 0) out vec2 uv[8];
577   //
578   // void main()
579   // {
580   //     uv[1] = vec2(1, 0.5);
581   // }
582 
583   const std::string text = R"(
584                OpCapability Shader
585           %1 = OpExtInstImport "GLSL.std.450"
586                OpMemoryModel Logical GLSL450
587                OpEntryPoint Fragment %main "main" %uv
588                OpExecutionMode %main OriginUpperLeft
589                OpSource GLSL 450
590                OpName %main "main"
591                OpName %uv "uv"
592                OpDecorate %uv Location 0
593        %void = OpTypeVoid
594           %3 = OpTypeFunction %void
595       %float = OpTypeFloat 32
596     %v2float = OpTypeVector %float 2
597        %uint = OpTypeInt 32 0
598      %uint_8 = OpConstant %uint 8
599 %_arr_v2float_uint_8 = OpTypeArray %v2float %uint_8
600 %_ptr_Output__arr_v2float_uint_8 = OpTypePointer Output %_arr_v2float_uint_8
601          %uv = OpVariable %_ptr_Output__arr_v2float_uint_8 Output
602 ;CHECK-NOT:         %uv = OpVariable %_ptr_Output__arr_v2float_uint_8 Output
603 ;CHECK:             %uv = OpVariable %_ptr_Output__arr_v2float_uint_2 Output
604         %int = OpTypeInt 32 1
605       %int_1 = OpConstant %int 1
606     %float_1 = OpConstant %float 1
607   %float_0_5 = OpConstant %float 0.5
608          %17 = OpConstantComposite %v2float %float_1 %float_0_5
609 %_ptr_Output_v2float = OpTypePointer Output %v2float
610        %main = OpFunction %void None %3
611           %5 = OpLabel
612          %19 = OpAccessChain %_ptr_Output_v2float %uv %int_1
613                OpStore %19 %17
614                OpReturn
615                OpFunctionEnd
616 )";
617 
618   SetTargetEnv(SPV_ENV_VULKAN_1_3);
619   SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
620   SinglePassRunAndMatch<EliminateDeadIOComponentsPass>(
621       text, true, spv::StorageClass::Output, false);
622 }
623 
TEST_F(ElimDeadIOComponentsTest, VertexOnly)624 TEST_F(ElimDeadIOComponentsTest, VertexOnly) {
625   // Should NOT eliminate uv
626   //
627   // #version 450
628   //
629   // in Vertex {
630   //   vec4 Cd;
631   //   vec2 uv;
632   // } iVert;
633   //
634   // out vec4 fragColor;
635   //
636   // void main()
637   // {
638   //   vec4 color = vec4(iVert.Cd);
639   //   fragColor = color;
640   // }
641   const std::string text = R"(
642                OpCapability Shader
643           %1 = OpExtInstImport "GLSL.std.450"
644                OpMemoryModel Logical GLSL450
645                OpEntryPoint Fragment %main "main" %iVert %fragColor
646                OpExecutionMode %main OriginUpperLeft
647                OpSource GLSL 450
648                OpName %main "main"
649                OpName %Vertex "Vertex"
650                OpMemberName %Vertex 0 "Cd"
651                OpMemberName %Vertex 1 "uv"
652                OpName %iVert "iVert"
653                OpName %fragColor "fragColor"
654                OpDecorate %Vertex Block
655                OpDecorate %iVert Location 0
656                OpDecorate %fragColor Location 0
657        %void = OpTypeVoid
658           %3 = OpTypeFunction %void
659       %float = OpTypeFloat 32
660     %v4float = OpTypeVector %float 4
661     %v2float = OpTypeVector %float 2
662      %Vertex = OpTypeStruct %v4float %v2float
663 ; CHECK: %Vertex = OpTypeStruct %v4float %v2float
664 %_ptr_Input_Vertex = OpTypePointer Input %Vertex
665 ; CHECK: %_ptr_Input_Vertex = OpTypePointer Input %Vertex
666       %iVert = OpVariable %_ptr_Input_Vertex Input
667 ; CHECK: %iVert = OpVariable %_ptr_Input_Vertex Input
668         %int = OpTypeInt 32 1
669       %int_0 = OpConstant %int 0
670 %_ptr_Input_v4float = OpTypePointer Input %v4float
671 %_ptr_Output_v4float = OpTypePointer Output %v4float
672   %fragColor = OpVariable %_ptr_Output_v4float Output
673        %main = OpFunction %void None %3
674           %5 = OpLabel
675          %17 = OpAccessChain %_ptr_Input_v4float %iVert %int_0
676          %18 = OpLoad %v4float %17
677                OpStore %fragColor %18
678                OpReturn
679                OpFunctionEnd
680 )";
681 
682   SetTargetEnv(SPV_ENV_VULKAN_1_3);
683   SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
684   SinglePassRunAndMatch<EliminateDeadIOComponentsPass>(
685       text, true, spv::StorageClass::Input, true);
686 }
687 
TEST_F(ElimDeadIOComponentsTest, TescInput)688 TEST_F(ElimDeadIOComponentsTest, TescInput) {
689   // Eliminate PointSize, ClipDistance, CullDistance from gl_in[]
690   //
691   // #version 450
692   //
693   // layout (vertices = 4) out;
694   //
695   // void main()
696   // {
697   //     vec4 pos = gl_in[gl_InvocationID].gl_Position;
698   //     gl_out[gl_InvocationID].gl_Position = pos;
699   // }
700   const std::string text = R"(
701                OpCapability Tessellation
702           %1 = OpExtInstImport "GLSL.std.450"
703                OpMemoryModel Logical GLSL450
704                OpEntryPoint TessellationControl %main "main" %gl_in %gl_InvocationID %gl_out
705                OpExecutionMode %main OutputVertices 4
706                OpSource GLSL 450
707                OpName %main "main"
708                OpName %pos "pos"
709                OpName %gl_PerVertex "gl_PerVertex"
710                OpMemberName %gl_PerVertex 0 "gl_Position"
711                OpMemberName %gl_PerVertex 1 "gl_PointSize"
712                OpMemberName %gl_PerVertex 2 "gl_ClipDistance"
713                OpMemberName %gl_PerVertex 3 "gl_CullDistance"
714                OpName %gl_in "gl_in"
715                OpName %gl_InvocationID "gl_InvocationID"
716                OpName %gl_PerVertex_0 "gl_PerVertex"
717                OpMemberName %gl_PerVertex_0 0 "gl_Position"
718                OpName %gl_out "gl_out"
719                OpMemberDecorate %gl_PerVertex 0 BuiltIn Position
720                OpMemberDecorate %gl_PerVertex 1 BuiltIn PointSize
721                OpMemberDecorate %gl_PerVertex 2 BuiltIn ClipDistance
722                OpMemberDecorate %gl_PerVertex 3 BuiltIn CullDistance
723                OpDecorate %gl_PerVertex Block
724                OpDecorate %gl_InvocationID BuiltIn InvocationId
725                OpMemberDecorate %gl_PerVertex_0 0 BuiltIn Position
726                OpDecorate %gl_PerVertex_0 Block
727        %void = OpTypeVoid
728           %3 = OpTypeFunction %void
729       %float = OpTypeFloat 32
730     %v4float = OpTypeVector %float 4
731 %_ptr_Function_v4float = OpTypePointer Function %v4float
732        %uint = OpTypeInt 32 0
733      %uint_1 = OpConstant %uint 1
734 %_arr_float_uint_1 = OpTypeArray %float %uint_1
735 %gl_PerVertex = OpTypeStruct %v4float %float %_arr_float_uint_1 %_arr_float_uint_1
736     %uint_32 = OpConstant %uint 32
737 %_arr_gl_PerVertex_uint_32 = OpTypeArray %gl_PerVertex %uint_32
738 %_ptr_Input__arr_gl_PerVertex_uint_32 = OpTypePointer Input %_arr_gl_PerVertex_uint_32
739       %gl_in = OpVariable %_ptr_Input__arr_gl_PerVertex_uint_32 Input
740         %int = OpTypeInt 32 1
741 %_ptr_Input_int = OpTypePointer Input %int
742 %gl_InvocationID = OpVariable %_ptr_Input_int Input
743       %int_0 = OpConstant %int 0
744 %_ptr_Input_v4float = OpTypePointer Input %v4float
745 %gl_PerVertex_0 = OpTypeStruct %v4float
746      %uint_4 = OpConstant %uint 4
747 %_arr_gl_PerVertex_0_uint_4 = OpTypeArray %gl_PerVertex_0 %uint_4
748 %_ptr_Output__arr_gl_PerVertex_0_uint_4 = OpTypePointer Output %_arr_gl_PerVertex_0_uint_4
749      %gl_out = OpVariable %_ptr_Output__arr_gl_PerVertex_0_uint_4 Output
750 %_ptr_Output_v4float = OpTypePointer Output %v4float
751 ; CHECK: %gl_PerVertex = OpTypeStruct %v4float %float %_arr_float_uint_1 %_arr_float_uint_1
752 ; CHECK: [[sty:%\w+]] = OpTypeStruct %v4float
753 ; CHECK: [[asty:%\w+]] = OpTypeArray [[sty]] %uint_32
754 ; CHECK: [[pasty:%\w+]] = OpTypePointer Input [[asty]]
755 ; CHECK: %gl_in = OpVariable [[pasty]] Input
756        %main = OpFunction %void None %3
757           %5 = OpLabel
758         %pos = OpVariable %_ptr_Function_v4float Function
759          %21 = OpLoad %int %gl_InvocationID
760          %24 = OpAccessChain %_ptr_Input_v4float %gl_in %21 %int_0
761          %25 = OpLoad %v4float %24
762                OpStore %pos %25
763          %31 = OpLoad %int %gl_InvocationID
764          %32 = OpLoad %v4float %pos
765          %34 = OpAccessChain %_ptr_Output_v4float %gl_out %31 %int_0
766                OpStore %34 %32
767                OpReturn
768                OpFunctionEnd
769 )";
770 
771   SetTargetEnv(SPV_ENV_VULKAN_1_3);
772   SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
773   SinglePassRunAndMatch<EliminateDeadIOComponentsPass>(
774       text, true, spv::StorageClass::Input, false);
775 }
776 
TEST_F(ElimDeadIOComponentsTest, TescOutput)777 TEST_F(ElimDeadIOComponentsTest, TescOutput) {
778   // Eliminate PointSize, ClipDistance, CullDistance from gl_out[]
779   //
780   // #version 450
781   //
782   // layout (vertices = 4) out;
783   //
784   // void main()
785   // {
786   //     vec4 pos = gl_in[gl_InvocationID].gl_Position;
787   //     gl_out[gl_InvocationID].gl_Position = pos;
788   // }
789   const std::string text = R"(
790                OpCapability Tessellation
791           %1 = OpExtInstImport "GLSL.std.450"
792                OpMemoryModel Logical GLSL450
793                OpEntryPoint TessellationControl %main "main" %gl_in %gl_InvocationID %gl_out
794                OpExecutionMode %main OutputVertices 4
795                OpSource GLSL 450
796                OpName %main "main"
797                OpName %pos "pos"
798                OpName %gl_PerVertex "gl_PerVertex"
799                OpMemberName %gl_PerVertex 0 "gl_Position"
800                OpName %gl_in "gl_in"
801                OpName %gl_InvocationID "gl_InvocationID"
802                OpName %gl_PerVertex_0 "gl_PerVertex"
803                OpMemberName %gl_PerVertex_0 0 "gl_Position"
804                OpMemberName %gl_PerVertex_0 1 "gl_PointSize"
805                OpMemberName %gl_PerVertex_0 2 "gl_ClipDistance"
806                OpMemberName %gl_PerVertex_0 3 "gl_CullDistance"
807                OpName %gl_out "gl_out"
808                OpMemberDecorate %gl_PerVertex 0 BuiltIn Position
809                OpDecorate %gl_PerVertex Block
810                OpDecorate %gl_InvocationID BuiltIn InvocationId
811                OpMemberDecorate %gl_PerVertex_0 0 BuiltIn Position
812                OpMemberDecorate %gl_PerVertex_0 1 BuiltIn PointSize
813                OpMemberDecorate %gl_PerVertex_0 2 BuiltIn ClipDistance
814                OpMemberDecorate %gl_PerVertex_0 3 BuiltIn CullDistance
815                OpDecorate %gl_PerVertex_0 Block
816        %void = OpTypeVoid
817           %3 = OpTypeFunction %void
818       %float = OpTypeFloat 32
819     %v4float = OpTypeVector %float 4
820 %_ptr_Function_v4float = OpTypePointer Function %v4float
821        %uint = OpTypeInt 32 0
822      %uint_1 = OpConstant %uint 1
823 %_arr_float_uint_1 = OpTypeArray %float %uint_1
824 %gl_PerVertex = OpTypeStruct %v4float
825     %uint_32 = OpConstant %uint 32
826 %_arr_gl_PerVertex_uint_32 = OpTypeArray %gl_PerVertex %uint_32
827 %_ptr_Input__arr_gl_PerVertex_uint_32 = OpTypePointer Input %_arr_gl_PerVertex_uint_32
828       %gl_in = OpVariable %_ptr_Input__arr_gl_PerVertex_uint_32 Input
829         %int = OpTypeInt 32 1
830 %_ptr_Input_int = OpTypePointer Input %int
831 %gl_InvocationID = OpVariable %_ptr_Input_int Input
832       %int_0 = OpConstant %int 0
833 %_ptr_Input_v4float = OpTypePointer Input %v4float
834 %gl_PerVertex_0 = OpTypeStruct %v4float %float %_arr_float_uint_1 %_arr_float_uint_1
835      %uint_4 = OpConstant %uint 4
836 %_arr_gl_PerVertex_0_uint_4 = OpTypeArray %gl_PerVertex_0 %uint_4
837 %_ptr_Output__arr_gl_PerVertex_0_uint_4 = OpTypePointer Output %_arr_gl_PerVertex_0_uint_4
838      %gl_out = OpVariable %_ptr_Output__arr_gl_PerVertex_0_uint_4 Output
839 %_ptr_Output_v4float = OpTypePointer Output %v4float
840 ; CHECK: [[sty:%\w+]] = OpTypeStruct %v4float
841 ; CHECK: [[asty:%\w+]] = OpTypeArray [[sty]] %uint_4
842 ; CHECK: [[pasty:%\w+]] = OpTypePointer Output [[asty]]
843 ; CHECK: %gl_out = OpVariable [[pasty]] Output
844        %main = OpFunction %void None %3
845           %5 = OpLabel
846         %pos = OpVariable %_ptr_Function_v4float Function
847          %21 = OpLoad %int %gl_InvocationID
848          %24 = OpAccessChain %_ptr_Input_v4float %gl_in %21 %int_0
849          %25 = OpLoad %v4float %24
850                OpStore %pos %25
851          %31 = OpLoad %int %gl_InvocationID
852          %32 = OpLoad %v4float %pos
853          %34 = OpAccessChain %_ptr_Output_v4float %gl_out %31 %int_0
854                OpStore %34 %32
855                OpReturn
856                OpFunctionEnd
857 )";
858 
859   SetTargetEnv(SPV_ENV_VULKAN_1_3);
860   SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
861   SinglePassRunAndMatch<EliminateDeadIOComponentsPass>(
862       text, true, spv::StorageClass::Output, false);
863 }
864 
TEST_F(ElimDeadIOComponentsTest, TeseInput)865 TEST_F(ElimDeadIOComponentsTest, TeseInput) {
866   // Eliminate PointSize, ClipDistance, CullDistance from gl_in[]
867   //
868   // #version 450
869   //
870   // layout(triangles, ccw) in;
871   // layout(fractional_odd_spacing) in;
872   // layout(point_mode) in;
873   //
874   // void main()
875   // {
876   //     vec4 p = gl_in[1].gl_Position;
877   //     gl_Position = p;
878   // }
879   const std::string text = R"(
880                OpCapability Tessellation
881           %1 = OpExtInstImport "GLSL.std.450"
882                OpMemoryModel Logical GLSL450
883                OpEntryPoint TessellationEvaluation %main "main" %gl_in %_
884                OpExecutionMode %main Triangles
885                OpExecutionMode %main SpacingFractionalOdd
886                OpExecutionMode %main VertexOrderCcw
887                OpExecutionMode %main PointMode
888                OpSource GLSL 450
889                OpName %main "main"
890                OpName %p "p"
891                OpName %gl_PerVertex "gl_PerVertex"
892                OpMemberName %gl_PerVertex 0 "gl_Position"
893                OpMemberName %gl_PerVertex 1 "gl_PointSize"
894                OpMemberName %gl_PerVertex 2 "gl_ClipDistance"
895                OpMemberName %gl_PerVertex 3 "gl_CullDistance"
896                OpName %gl_in "gl_in"
897                OpName %gl_PerVertex_0 "gl_PerVertex"
898                OpMemberName %gl_PerVertex_0 0 "gl_Position"
899                OpName %_ ""
900                OpMemberDecorate %gl_PerVertex 0 BuiltIn Position
901                OpMemberDecorate %gl_PerVertex 1 BuiltIn PointSize
902                OpMemberDecorate %gl_PerVertex 2 BuiltIn ClipDistance
903                OpMemberDecorate %gl_PerVertex 3 BuiltIn CullDistance
904                OpDecorate %gl_PerVertex Block
905                OpMemberDecorate %gl_PerVertex_0 0 BuiltIn Position
906                OpDecorate %gl_PerVertex_0 Block
907        %void = OpTypeVoid
908           %3 = OpTypeFunction %void
909       %float = OpTypeFloat 32
910     %v4float = OpTypeVector %float 4
911 %_ptr_Function_v4float = OpTypePointer Function %v4float
912        %uint = OpTypeInt 32 0
913      %uint_1 = OpConstant %uint 1
914 %_arr_float_uint_1 = OpTypeArray %float %uint_1
915 %gl_PerVertex = OpTypeStruct %v4float %float %_arr_float_uint_1 %_arr_float_uint_1
916     %uint_32 = OpConstant %uint 32
917 %_arr_gl_PerVertex_uint_32 = OpTypeArray %gl_PerVertex %uint_32
918 %_ptr_Input__arr_gl_PerVertex_uint_32 = OpTypePointer Input %_arr_gl_PerVertex_uint_32
919       %gl_in = OpVariable %_ptr_Input__arr_gl_PerVertex_uint_32 Input
920         %int = OpTypeInt 32 1
921       %int_1 = OpConstant %int 1
922       %int_0 = OpConstant %int 0
923 %_ptr_Input_v4float = OpTypePointer Input %v4float
924 %gl_PerVertex_0 = OpTypeStruct %v4float
925 %_ptr_Output_gl_PerVertex_0 = OpTypePointer Output %gl_PerVertex_0
926           %_ = OpVariable %_ptr_Output_gl_PerVertex_0 Output
927 %_ptr_Output_v4float = OpTypePointer Output %v4float
928 ; CHECK: %gl_PerVertex = OpTypeStruct %v4float %float %_arr_float_uint_1 %_arr_float_uint_1
929 ; CHECK: [[sty:%\w+]] = OpTypeStruct %v4float
930 ; CHECK: [[asty:%\w+]] = OpTypeArray [[sty]] %uint_32
931 ; CHECK: [[pasty:%\w+]] = OpTypePointer Input [[asty]]
932 ; CHECK: %gl_in = OpVariable [[pasty]] Input
933        %main = OpFunction %void None %3
934           %5 = OpLabel
935           %p = OpVariable %_ptr_Function_v4float Function
936          %22 = OpAccessChain %_ptr_Input_v4float %gl_in %int_1 %int_0
937          %23 = OpLoad %v4float %22
938                OpStore %p %23
939          %27 = OpLoad %v4float %p
940          %29 = OpAccessChain %_ptr_Output_v4float %_ %int_0
941                OpStore %29 %27
942                OpReturn
943                OpFunctionEnd
944 )";
945 
946   SetTargetEnv(SPV_ENV_VULKAN_1_3);
947   SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
948   SinglePassRunAndMatch<EliminateDeadIOComponentsPass>(
949       text, true, spv::StorageClass::Input, false);
950 }
951 
TEST_F(ElimDeadIOComponentsTest, TeseOutput)952 TEST_F(ElimDeadIOComponentsTest, TeseOutput) {
953   // Eliminate PointSize, ClipDistance, CullDistance from gl_out
954   //
955   // #version 450
956   //
957   // layout(triangles, ccw) in;
958   // layout(fractional_odd_spacing) in;
959   // layout(point_mode) in;
960   //
961   // void main()
962   // {
963   //     vec4 p = gl_in[1].gl_Position;
964   //     gl_Position = p;
965   // }
966   const std::string text = R"(
967                OpCapability Tessellation
968           %1 = OpExtInstImport "GLSL.std.450"
969                OpMemoryModel Logical GLSL450
970                OpEntryPoint TessellationEvaluation %main "main" %gl_in %_
971                OpExecutionMode %main Triangles
972                OpExecutionMode %main SpacingFractionalOdd
973                OpExecutionMode %main VertexOrderCcw
974                OpExecutionMode %main PointMode
975                OpSource GLSL 450
976                OpName %main "main"
977                OpName %p "p"
978                OpName %gl_PerVertex "gl_PerVertex"
979                OpMemberName %gl_PerVertex 0 "gl_Position"
980                OpName %gl_in "gl_in"
981                OpName %gl_PerVertex_0 "gl_PerVertex"
982                OpMemberName %gl_PerVertex_0 0 "gl_Position"
983                OpMemberName %gl_PerVertex_0 1 "gl_PointSize"
984                OpMemberName %gl_PerVertex_0 2 "gl_ClipDistance"
985                OpMemberName %gl_PerVertex_0 3 "gl_CullDistance"
986                OpName %_ ""
987                OpMemberDecorate %gl_PerVertex 0 BuiltIn Position
988                OpDecorate %gl_PerVertex Block
989                OpMemberDecorate %gl_PerVertex_0 0 BuiltIn Position
990                OpMemberDecorate %gl_PerVertex_0 1 BuiltIn PointSize
991                OpMemberDecorate %gl_PerVertex_0 2 BuiltIn ClipDistance
992                OpMemberDecorate %gl_PerVertex_0 3 BuiltIn CullDistance
993                OpDecorate %gl_PerVertex_0 Block
994        %void = OpTypeVoid
995           %3 = OpTypeFunction %void
996       %float = OpTypeFloat 32
997     %v4float = OpTypeVector %float 4
998 %_ptr_Function_v4float = OpTypePointer Function %v4float
999        %uint = OpTypeInt 32 0
1000      %uint_1 = OpConstant %uint 1
1001 %_arr_float_uint_1 = OpTypeArray %float %uint_1
1002 %gl_PerVertex = OpTypeStruct %v4float
1003     %uint_32 = OpConstant %uint 32
1004 %_arr_gl_PerVertex_uint_32 = OpTypeArray %gl_PerVertex %uint_32
1005 %_ptr_Input__arr_gl_PerVertex_uint_32 = OpTypePointer Input %_arr_gl_PerVertex_uint_32
1006       %gl_in = OpVariable %_ptr_Input__arr_gl_PerVertex_uint_32 Input
1007         %int = OpTypeInt 32 1
1008       %int_1 = OpConstant %int 1
1009       %int_0 = OpConstant %int 0
1010 %_ptr_Input_v4float = OpTypePointer Input %v4float
1011 %gl_PerVertex_0 = OpTypeStruct %v4float %float %_arr_float_uint_1 %_arr_float_uint_1
1012 %_ptr_Output_gl_PerVertex_0 = OpTypePointer Output %gl_PerVertex_0
1013           %_ = OpVariable %_ptr_Output_gl_PerVertex_0 Output
1014 %_ptr_Output_v4float = OpTypePointer Output %v4float
1015 ; CHECK: %_ptr_Output_gl_PerVertex = OpTypePointer Output %gl_PerVertex
1016 ; CHECK: %_ = OpVariable %_ptr_Output_gl_PerVertex Output
1017        %main = OpFunction %void None %3
1018           %5 = OpLabel
1019           %p = OpVariable %_ptr_Function_v4float Function
1020          %22 = OpAccessChain %_ptr_Input_v4float %gl_in %int_1 %int_0
1021          %23 = OpLoad %v4float %22
1022                OpStore %p %23
1023          %27 = OpLoad %v4float %p
1024          %29 = OpAccessChain %_ptr_Output_v4float %_ %int_0
1025                OpStore %29 %27
1026                OpReturn
1027                OpFunctionEnd
1028 )";
1029 
1030   SetTargetEnv(SPV_ENV_VULKAN_1_3);
1031   SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
1032   SinglePassRunAndMatch<EliminateDeadIOComponentsPass>(
1033       text, true, spv::StorageClass::Output, false);
1034 }
1035 
TEST_F(ElimDeadIOComponentsTest, GeomInput)1036 TEST_F(ElimDeadIOComponentsTest, GeomInput) {
1037   // Eliminate PointSize, ClipDistance, CullDistance from gl_in[]
1038   //
1039   // #version 450
1040   //
1041   // layout(triangle_strip, max_vertices = 3) out;
1042   // layout(triangles) in;
1043   //
1044   // void main()
1045   // {
1046   //         for (int i = 0; i < 3; i++)
1047   //         {
1048   //                 gl_Position = gl_in[i].gl_Position;
1049   //                 EmitVertex();
1050   //         }
1051   //         EndPrimitive();
1052   // }
1053   const std::string text = R"(
1054                OpCapability Geometry
1055           %1 = OpExtInstImport "GLSL.std.450"
1056                OpMemoryModel Logical GLSL450
1057                OpEntryPoint Geometry %main "main" %_ %gl_in
1058                OpExecutionMode %main Triangles
1059                OpExecutionMode %main Invocations 1
1060                OpExecutionMode %main OutputTriangleStrip
1061                OpExecutionMode %main OutputVertices 3
1062                OpSource GLSL 460
1063                OpName %main "main"
1064                OpName %i "i"
1065                OpName %gl_PerVertex "gl_PerVertex"
1066                OpMemberName %gl_PerVertex 0 "gl_Position"
1067                OpName %_ ""
1068                OpName %gl_PerVertex_0 "gl_PerVertex"
1069                OpMemberName %gl_PerVertex_0 0 "gl_Position"
1070                OpMemberName %gl_PerVertex_0 1 "gl_PointSize"
1071                OpMemberName %gl_PerVertex_0 2 "gl_ClipDistance"
1072                OpMemberName %gl_PerVertex_0 3 "gl_CullDistance"
1073                OpName %gl_in "gl_in"
1074                OpMemberDecorate %gl_PerVertex 0 BuiltIn Position
1075                OpDecorate %gl_PerVertex Block
1076                OpMemberDecorate %gl_PerVertex_0 0 BuiltIn Position
1077                OpMemberDecorate %gl_PerVertex_0 1 BuiltIn PointSize
1078                OpMemberDecorate %gl_PerVertex_0 2 BuiltIn ClipDistance
1079                OpMemberDecorate %gl_PerVertex_0 3 BuiltIn CullDistance
1080                OpDecorate %gl_PerVertex_0 Block
1081        %void = OpTypeVoid
1082           %3 = OpTypeFunction %void
1083         %int = OpTypeInt 32 1
1084 %_ptr_Function_int = OpTypePointer Function %int
1085       %int_0 = OpConstant %int 0
1086       %int_3 = OpConstant %int 3
1087        %bool = OpTypeBool
1088       %float = OpTypeFloat 32
1089     %v4float = OpTypeVector %float 4
1090        %uint = OpTypeInt 32 0
1091      %uint_1 = OpConstant %uint 1
1092 %_arr_float_uint_1 = OpTypeArray %float %uint_1
1093 %gl_PerVertex = OpTypeStruct %v4float
1094 %_ptr_Output_gl_PerVertex = OpTypePointer Output %gl_PerVertex
1095           %_ = OpVariable %_ptr_Output_gl_PerVertex Output
1096 %gl_PerVertex_0 = OpTypeStruct %v4float %float %_arr_float_uint_1 %_arr_float_uint_1
1097      %uint_3 = OpConstant %uint 3
1098 %_arr_gl_PerVertex_0_uint_3 = OpTypeArray %gl_PerVertex_0 %uint_3
1099 %_ptr_Input__arr_gl_PerVertex_0_uint_3 = OpTypePointer Input %_arr_gl_PerVertex_0_uint_3
1100       %gl_in = OpVariable %_ptr_Input__arr_gl_PerVertex_0_uint_3 Input
1101 %_ptr_Input_v4float = OpTypePointer Input %v4float
1102 %_ptr_Output_v4float = OpTypePointer Output %v4float
1103       %int_1 = OpConstant %int 1
1104 ; CHECK: [[asty:%\w+]] = OpTypeArray %gl_PerVertex %uint_3
1105 ; CHECK: [[pasty:%\w+]] = OpTypePointer Input [[asty]]
1106 ; CHECK: %gl_in = OpVariable [[pasty]] Input
1107        %main = OpFunction %void None %3
1108           %5 = OpLabel
1109           %i = OpVariable %_ptr_Function_int Function
1110                OpStore %i %int_0
1111                OpBranch %10
1112          %10 = OpLabel
1113                OpLoopMerge %12 %13 None
1114                OpBranch %14
1115          %14 = OpLabel
1116          %15 = OpLoad %int %i
1117          %18 = OpSLessThan %bool %15 %int_3
1118                OpBranchConditional %18 %11 %12
1119          %11 = OpLabel
1120          %32 = OpLoad %int %i
1121          %34 = OpAccessChain %_ptr_Input_v4float %gl_in %32 %int_0
1122          %35 = OpLoad %v4float %34
1123          %37 = OpAccessChain %_ptr_Output_v4float %_ %int_0
1124                OpStore %37 %35
1125                OpEmitVertex
1126                OpBranch %13
1127          %13 = OpLabel
1128          %38 = OpLoad %int %i
1129          %40 = OpIAdd %int %38 %int_1
1130                OpStore %i %40
1131                OpBranch %10
1132          %12 = OpLabel
1133                OpEndPrimitive
1134                OpReturn
1135                OpFunctionEnd
1136 )";
1137 
1138   SetTargetEnv(SPV_ENV_VULKAN_1_3);
1139   SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
1140   SinglePassRunAndMatch<EliminateDeadIOComponentsPass>(
1141       text, true, spv::StorageClass::Input, false);
1142 }
1143 
TEST_F(ElimDeadIOComponentsTest, GeomOutput)1144 TEST_F(ElimDeadIOComponentsTest, GeomOutput) {
1145   // Eliminate PointSize, ClipDistance, CullDistance from gl_out
1146   //
1147   // #version 450
1148   //
1149   // layout(triangle_strip, max_vertices = 3) out;
1150   // layout(triangles) in;
1151   //
1152   // void main()
1153   // {
1154   //         for (int i = 0; i < 3; i++)
1155   //         {
1156   //                 gl_Position = gl_in[i].gl_Position;
1157   //                 EmitVertex();
1158   //         }
1159   //         EndPrimitive();
1160   // }
1161   const std::string text = R"(
1162                OpCapability Geometry
1163           %1 = OpExtInstImport "GLSL.std.450"
1164                OpMemoryModel Logical GLSL450
1165                OpEntryPoint Geometry %main "main" %_ %gl_in
1166                OpExecutionMode %main Triangles
1167                OpExecutionMode %main Invocations 1
1168                OpExecutionMode %main OutputTriangleStrip
1169                OpExecutionMode %main OutputVertices 3
1170                OpSource GLSL 460
1171                OpName %main "main"
1172                OpName %i "i"
1173                OpName %gl_PerVertex "gl_PerVertex"
1174                OpMemberName %gl_PerVertex 0 "gl_Position"
1175                OpMemberName %gl_PerVertex 1 "gl_PointSize"
1176                OpMemberName %gl_PerVertex 2 "gl_ClipDistance"
1177                OpMemberName %gl_PerVertex 3 "gl_CullDistance"
1178                OpName %_ ""
1179                OpName %gl_PerVertex_0 "gl_PerVertex"
1180                OpMemberName %gl_PerVertex_0 0 "gl_Position"
1181                OpName %gl_in "gl_in"
1182                OpMemberDecorate %gl_PerVertex 0 BuiltIn Position
1183                OpMemberDecorate %gl_PerVertex 1 BuiltIn PointSize
1184                OpMemberDecorate %gl_PerVertex 2 BuiltIn ClipDistance
1185                OpMemberDecorate %gl_PerVertex 3 BuiltIn CullDistance
1186                OpDecorate %gl_PerVertex Block
1187                OpMemberDecorate %gl_PerVertex_0 0 BuiltIn Position
1188                OpDecorate %gl_PerVertex_0 Block
1189        %void = OpTypeVoid
1190           %3 = OpTypeFunction %void
1191         %int = OpTypeInt 32 1
1192 %_ptr_Function_int = OpTypePointer Function %int
1193       %int_0 = OpConstant %int 0
1194       %int_3 = OpConstant %int 3
1195        %bool = OpTypeBool
1196       %float = OpTypeFloat 32
1197     %v4float = OpTypeVector %float 4
1198        %uint = OpTypeInt 32 0
1199      %uint_1 = OpConstant %uint 1
1200 %_arr_float_uint_1 = OpTypeArray %float %uint_1
1201 %gl_PerVertex = OpTypeStruct %v4float %float %_arr_float_uint_1 %_arr_float_uint_1
1202 %_ptr_Output_gl_PerVertex = OpTypePointer Output %gl_PerVertex
1203           %_ = OpVariable %_ptr_Output_gl_PerVertex Output
1204 %gl_PerVertex_0 = OpTypeStruct %v4float
1205      %uint_3 = OpConstant %uint 3
1206 %_arr_gl_PerVertex_0_uint_3 = OpTypeArray %gl_PerVertex_0 %uint_3
1207 %_ptr_Input__arr_gl_PerVertex_0_uint_3 = OpTypePointer Input %_arr_gl_PerVertex_0_uint_3
1208       %gl_in = OpVariable %_ptr_Input__arr_gl_PerVertex_0_uint_3 Input
1209 %_ptr_Input_v4float = OpTypePointer Input %v4float
1210 %_ptr_Output_v4float = OpTypePointer Output %v4float
1211       %int_1 = OpConstant %int 1
1212 ; CHECK: %_ptr_Output_gl_PerVertex_0 = OpTypePointer Output %gl_PerVertex_0
1213 ; CHECK: %_ = OpVariable %_ptr_Output_gl_PerVertex_0 Output
1214        %main = OpFunction %void None %3
1215           %5 = OpLabel
1216           %i = OpVariable %_ptr_Function_int Function
1217                OpStore %i %int_0
1218                OpBranch %10
1219          %10 = OpLabel
1220                OpLoopMerge %12 %13 None
1221                OpBranch %14
1222          %14 = OpLabel
1223          %15 = OpLoad %int %i
1224          %18 = OpSLessThan %bool %15 %int_3
1225                OpBranchConditional %18 %11 %12
1226          %11 = OpLabel
1227          %32 = OpLoad %int %i
1228          %34 = OpAccessChain %_ptr_Input_v4float %gl_in %32 %int_0
1229          %35 = OpLoad %v4float %34
1230          %37 = OpAccessChain %_ptr_Output_v4float %_ %int_0
1231                OpStore %37 %35
1232                OpEmitVertex
1233                OpBranch %13
1234          %13 = OpLabel
1235          %38 = OpLoad %int %i
1236          %40 = OpIAdd %int %38 %int_1
1237                OpStore %i %40
1238                OpBranch %10
1239          %12 = OpLabel
1240                OpEndPrimitive
1241                OpReturn
1242                OpFunctionEnd
1243 )";
1244 
1245   SetTargetEnv(SPV_ENV_VULKAN_1_3);
1246   SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
1247   SinglePassRunAndMatch<EliminateDeadIOComponentsPass>(
1248       text, true, spv::StorageClass::Output, false);
1249 }
1250 
1251 }  // namespace
1252 }  // namespace opt
1253 }  // namespace spvtools
1254