1fd4e5da5Sopenharmony_ci// Copyright (c) 2017 Google Inc.
2fd4e5da5Sopenharmony_ci//
3fd4e5da5Sopenharmony_ci// Licensed under the Apache License, Version 2.0 (the "License");
4fd4e5da5Sopenharmony_ci// you may not use this file except in compliance with the License.
5fd4e5da5Sopenharmony_ci// You may obtain a copy of the License at
6fd4e5da5Sopenharmony_ci//
7fd4e5da5Sopenharmony_ci//     http://www.apache.org/licenses/LICENSE-2.0
8fd4e5da5Sopenharmony_ci//
9fd4e5da5Sopenharmony_ci// Unless required by applicable law or agreed to in writing, software
10fd4e5da5Sopenharmony_ci// distributed under the License is distributed on an "AS IS" BASIS,
11fd4e5da5Sopenharmony_ci// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12fd4e5da5Sopenharmony_ci// See the License for the specific language governing permissions and
13fd4e5da5Sopenharmony_ci// limitations under the License.
14fd4e5da5Sopenharmony_ci
15fd4e5da5Sopenharmony_ci#include <string>
16fd4e5da5Sopenharmony_ci
17fd4e5da5Sopenharmony_ci#include "test/opt/pass_fixture.h"
18fd4e5da5Sopenharmony_ci#include "test/opt/pass_utils.h"
19fd4e5da5Sopenharmony_ci
20fd4e5da5Sopenharmony_cinamespace spvtools {
21fd4e5da5Sopenharmony_cinamespace opt {
22fd4e5da5Sopenharmony_cinamespace {
23fd4e5da5Sopenharmony_ci
24fd4e5da5Sopenharmony_ciusing DeadVariableElimTest = PassTest<::testing::Test>;
25fd4e5da5Sopenharmony_ci
26fd4e5da5Sopenharmony_ci// %dead is unused.  Make sure we remove it along with its name.
27fd4e5da5Sopenharmony_ciTEST_F(DeadVariableElimTest, RemoveUnreferenced) {
28fd4e5da5Sopenharmony_ci  const std::string before =
29fd4e5da5Sopenharmony_ci      R"(OpCapability Shader
30fd4e5da5Sopenharmony_ciOpCapability Linkage
31fd4e5da5Sopenharmony_ci%1 = OpExtInstImport "GLSL.std.450"
32fd4e5da5Sopenharmony_ciOpMemoryModel Logical GLSL450
33fd4e5da5Sopenharmony_ciOpEntryPoint Fragment %main "main"
34fd4e5da5Sopenharmony_ciOpExecutionMode %main OriginUpperLeft
35fd4e5da5Sopenharmony_ciOpSource GLSL 150
36fd4e5da5Sopenharmony_ciOpName %main "main"
37fd4e5da5Sopenharmony_ciOpName %dead "dead"
38fd4e5da5Sopenharmony_ci%void = OpTypeVoid
39fd4e5da5Sopenharmony_ci%5 = OpTypeFunction %void
40fd4e5da5Sopenharmony_ci%float = OpTypeFloat 32
41fd4e5da5Sopenharmony_ci%_ptr_Private_float = OpTypePointer Private %float
42fd4e5da5Sopenharmony_ci%dead = OpVariable %_ptr_Private_float Private
43fd4e5da5Sopenharmony_ci%main = OpFunction %void None %5
44fd4e5da5Sopenharmony_ci%8 = OpLabel
45fd4e5da5Sopenharmony_ciOpReturn
46fd4e5da5Sopenharmony_ciOpFunctionEnd
47fd4e5da5Sopenharmony_ci)";
48fd4e5da5Sopenharmony_ci
49fd4e5da5Sopenharmony_ci  const std::string after =
50fd4e5da5Sopenharmony_ci      R"(OpCapability Shader
51fd4e5da5Sopenharmony_ciOpCapability Linkage
52fd4e5da5Sopenharmony_ci%1 = OpExtInstImport "GLSL.std.450"
53fd4e5da5Sopenharmony_ciOpMemoryModel Logical GLSL450
54fd4e5da5Sopenharmony_ciOpEntryPoint Fragment %main "main"
55fd4e5da5Sopenharmony_ciOpExecutionMode %main OriginUpperLeft
56fd4e5da5Sopenharmony_ciOpSource GLSL 150
57fd4e5da5Sopenharmony_ciOpName %main "main"
58fd4e5da5Sopenharmony_ci%void = OpTypeVoid
59fd4e5da5Sopenharmony_ci%5 = OpTypeFunction %void
60fd4e5da5Sopenharmony_ci%float = OpTypeFloat 32
61fd4e5da5Sopenharmony_ci%_ptr_Private_float = OpTypePointer Private %float
62fd4e5da5Sopenharmony_ci%main = OpFunction %void None %5
63fd4e5da5Sopenharmony_ci%8 = OpLabel
64fd4e5da5Sopenharmony_ciOpReturn
65fd4e5da5Sopenharmony_ciOpFunctionEnd
66fd4e5da5Sopenharmony_ci)";
67fd4e5da5Sopenharmony_ci
68fd4e5da5Sopenharmony_ci  SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
69fd4e5da5Sopenharmony_ci  SinglePassRunAndCheck<DeadVariableElimination>(before, after, true, true);
70fd4e5da5Sopenharmony_ci}
71fd4e5da5Sopenharmony_ci
72fd4e5da5Sopenharmony_ci// Since %dead is exported, make sure we keep it.  It could be referenced
73fd4e5da5Sopenharmony_ci// somewhere else.
74fd4e5da5Sopenharmony_ciTEST_F(DeadVariableElimTest, KeepExported) {
75fd4e5da5Sopenharmony_ci  const std::string before =
76fd4e5da5Sopenharmony_ci      R"(OpCapability Shader
77fd4e5da5Sopenharmony_ciOpCapability Linkage
78fd4e5da5Sopenharmony_ci%1 = OpExtInstImport "GLSL.std.450"
79fd4e5da5Sopenharmony_ciOpMemoryModel Logical GLSL450
80fd4e5da5Sopenharmony_ciOpEntryPoint Fragment %main "main"
81fd4e5da5Sopenharmony_ciOpExecutionMode %main OriginUpperLeft
82fd4e5da5Sopenharmony_ciOpSource GLSL 150
83fd4e5da5Sopenharmony_ciOpName %main "main"
84fd4e5da5Sopenharmony_ciOpName %dead "dead"
85fd4e5da5Sopenharmony_ciOpDecorate %dead LinkageAttributes "dead" Export
86fd4e5da5Sopenharmony_ci%void = OpTypeVoid
87fd4e5da5Sopenharmony_ci%5 = OpTypeFunction %void
88fd4e5da5Sopenharmony_ci%float = OpTypeFloat 32
89fd4e5da5Sopenharmony_ci%_ptr_Private_float = OpTypePointer Private %float
90fd4e5da5Sopenharmony_ci%dead = OpVariable %_ptr_Private_float Private
91fd4e5da5Sopenharmony_ci%main = OpFunction %void None %5
92fd4e5da5Sopenharmony_ci%8 = OpLabel
93fd4e5da5Sopenharmony_ciOpReturn
94fd4e5da5Sopenharmony_ciOpFunctionEnd
95fd4e5da5Sopenharmony_ci)";
96fd4e5da5Sopenharmony_ci
97fd4e5da5Sopenharmony_ci  SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
98fd4e5da5Sopenharmony_ci  SinglePassRunAndCheck<DeadVariableElimination>(before, before, true, true);
99fd4e5da5Sopenharmony_ci}
100fd4e5da5Sopenharmony_ci
101fd4e5da5Sopenharmony_ci// Delete %dead because it is unreferenced.  Then %initializer becomes
102fd4e5da5Sopenharmony_ci// unreferenced, so remove it as well.
103fd4e5da5Sopenharmony_ciTEST_F(DeadVariableElimTest, RemoveUnreferencedWithInit1) {
104fd4e5da5Sopenharmony_ci  const std::string before =
105fd4e5da5Sopenharmony_ci      R"(OpCapability Shader
106fd4e5da5Sopenharmony_ciOpCapability Linkage
107fd4e5da5Sopenharmony_ci%1 = OpExtInstImport "GLSL.std.450"
108fd4e5da5Sopenharmony_ciOpMemoryModel Logical GLSL450
109fd4e5da5Sopenharmony_ciOpEntryPoint Fragment %main "main"
110fd4e5da5Sopenharmony_ciOpExecutionMode %main OriginUpperLeft
111fd4e5da5Sopenharmony_ciOpSource GLSL 150
112fd4e5da5Sopenharmony_ciOpName %main "main"
113fd4e5da5Sopenharmony_ciOpName %dead "dead"
114fd4e5da5Sopenharmony_ciOpName %initializer "initializer"
115fd4e5da5Sopenharmony_ci%void = OpTypeVoid
116fd4e5da5Sopenharmony_ci%6 = OpTypeFunction %void
117fd4e5da5Sopenharmony_ci%float = OpTypeFloat 32
118fd4e5da5Sopenharmony_ci%_ptr_Private_float = OpTypePointer Private %float
119fd4e5da5Sopenharmony_ci%initializer = OpVariable %_ptr_Private_float Private
120fd4e5da5Sopenharmony_ci%dead = OpVariable %_ptr_Private_float Private %initializer
121fd4e5da5Sopenharmony_ci%main = OpFunction %void None %6
122fd4e5da5Sopenharmony_ci%9 = OpLabel
123fd4e5da5Sopenharmony_ciOpReturn
124fd4e5da5Sopenharmony_ciOpFunctionEnd
125fd4e5da5Sopenharmony_ci)";
126fd4e5da5Sopenharmony_ci
127fd4e5da5Sopenharmony_ci  const std::string after =
128fd4e5da5Sopenharmony_ci      R"(OpCapability Shader
129fd4e5da5Sopenharmony_ciOpCapability Linkage
130fd4e5da5Sopenharmony_ci%1 = OpExtInstImport "GLSL.std.450"
131fd4e5da5Sopenharmony_ciOpMemoryModel Logical GLSL450
132fd4e5da5Sopenharmony_ciOpEntryPoint Fragment %main "main"
133fd4e5da5Sopenharmony_ciOpExecutionMode %main OriginUpperLeft
134fd4e5da5Sopenharmony_ciOpSource GLSL 150
135fd4e5da5Sopenharmony_ciOpName %main "main"
136fd4e5da5Sopenharmony_ci%void = OpTypeVoid
137fd4e5da5Sopenharmony_ci%6 = OpTypeFunction %void
138fd4e5da5Sopenharmony_ci%float = OpTypeFloat 32
139fd4e5da5Sopenharmony_ci%_ptr_Private_float = OpTypePointer Private %float
140fd4e5da5Sopenharmony_ci%main = OpFunction %void None %6
141fd4e5da5Sopenharmony_ci%9 = OpLabel
142fd4e5da5Sopenharmony_ciOpReturn
143fd4e5da5Sopenharmony_ciOpFunctionEnd
144fd4e5da5Sopenharmony_ci)";
145fd4e5da5Sopenharmony_ci
146fd4e5da5Sopenharmony_ci  SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
147fd4e5da5Sopenharmony_ci  SinglePassRunAndCheck<DeadVariableElimination>(before, after, true, true);
148fd4e5da5Sopenharmony_ci}
149fd4e5da5Sopenharmony_ci
150fd4e5da5Sopenharmony_ci// Delete %dead because it is unreferenced.  In this case, the initialized has
151fd4e5da5Sopenharmony_ci// another reference, and should not be removed.
152fd4e5da5Sopenharmony_ciTEST_F(DeadVariableElimTest, RemoveUnreferencedWithInit2) {
153fd4e5da5Sopenharmony_ci  const std::string before =
154fd4e5da5Sopenharmony_ci      R"(OpCapability Shader
155fd4e5da5Sopenharmony_ciOpCapability Linkage
156fd4e5da5Sopenharmony_ci%1 = OpExtInstImport "GLSL.std.450"
157fd4e5da5Sopenharmony_ciOpMemoryModel Logical GLSL450
158fd4e5da5Sopenharmony_ciOpEntryPoint Fragment %main "main"
159fd4e5da5Sopenharmony_ciOpExecutionMode %main OriginUpperLeft
160fd4e5da5Sopenharmony_ciOpSource GLSL 150
161fd4e5da5Sopenharmony_ciOpName %main "main"
162fd4e5da5Sopenharmony_ciOpName %dead "dead"
163fd4e5da5Sopenharmony_ciOpName %initializer "initializer"
164fd4e5da5Sopenharmony_ci%void = OpTypeVoid
165fd4e5da5Sopenharmony_ci%6 = OpTypeFunction %void
166fd4e5da5Sopenharmony_ci%float = OpTypeFloat 32
167fd4e5da5Sopenharmony_ci%_ptr_Private_float = OpTypePointer Private %float
168fd4e5da5Sopenharmony_ci%initializer = OpVariable %_ptr_Private_float Private
169fd4e5da5Sopenharmony_ci%dead = OpVariable %_ptr_Private_float Private %initializer
170fd4e5da5Sopenharmony_ci%main = OpFunction %void None %6
171fd4e5da5Sopenharmony_ci%9 = OpLabel
172fd4e5da5Sopenharmony_ci%10 = OpLoad %float %initializer
173fd4e5da5Sopenharmony_ciOpReturn
174fd4e5da5Sopenharmony_ciOpFunctionEnd
175fd4e5da5Sopenharmony_ci)";
176fd4e5da5Sopenharmony_ci
177fd4e5da5Sopenharmony_ci  const std::string after =
178fd4e5da5Sopenharmony_ci      R"(OpCapability Shader
179fd4e5da5Sopenharmony_ciOpCapability Linkage
180fd4e5da5Sopenharmony_ci%1 = OpExtInstImport "GLSL.std.450"
181fd4e5da5Sopenharmony_ciOpMemoryModel Logical GLSL450
182fd4e5da5Sopenharmony_ciOpEntryPoint Fragment %main "main"
183fd4e5da5Sopenharmony_ciOpExecutionMode %main OriginUpperLeft
184fd4e5da5Sopenharmony_ciOpSource GLSL 150
185fd4e5da5Sopenharmony_ciOpName %main "main"
186fd4e5da5Sopenharmony_ciOpName %initializer "initializer"
187fd4e5da5Sopenharmony_ci%void = OpTypeVoid
188fd4e5da5Sopenharmony_ci%6 = OpTypeFunction %void
189fd4e5da5Sopenharmony_ci%float = OpTypeFloat 32
190fd4e5da5Sopenharmony_ci%_ptr_Private_float = OpTypePointer Private %float
191fd4e5da5Sopenharmony_ci%initializer = OpVariable %_ptr_Private_float Private
192fd4e5da5Sopenharmony_ci%main = OpFunction %void None %6
193fd4e5da5Sopenharmony_ci%9 = OpLabel
194fd4e5da5Sopenharmony_ci%10 = OpLoad %float %initializer
195fd4e5da5Sopenharmony_ciOpReturn
196fd4e5da5Sopenharmony_ciOpFunctionEnd
197fd4e5da5Sopenharmony_ci)";
198fd4e5da5Sopenharmony_ci
199fd4e5da5Sopenharmony_ci  SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
200fd4e5da5Sopenharmony_ci  SinglePassRunAndCheck<DeadVariableElimination>(before, after, true, true);
201fd4e5da5Sopenharmony_ci}
202fd4e5da5Sopenharmony_ci
203fd4e5da5Sopenharmony_ci// Keep %live because it is used, and its initializer.
204fd4e5da5Sopenharmony_ciTEST_F(DeadVariableElimTest, KeepReferenced) {
205fd4e5da5Sopenharmony_ci  const std::string before =
206fd4e5da5Sopenharmony_ci      R"(OpCapability Shader
207fd4e5da5Sopenharmony_ciOpCapability Linkage
208fd4e5da5Sopenharmony_ci%1 = OpExtInstImport "GLSL.std.450"
209fd4e5da5Sopenharmony_ciOpMemoryModel Logical GLSL450
210fd4e5da5Sopenharmony_ciOpEntryPoint Fragment %main "main"
211fd4e5da5Sopenharmony_ciOpExecutionMode %main OriginUpperLeft
212fd4e5da5Sopenharmony_ciOpSource GLSL 150
213fd4e5da5Sopenharmony_ciOpName %main "main"
214fd4e5da5Sopenharmony_ciOpName %live "live"
215fd4e5da5Sopenharmony_ciOpName %initializer "initializer"
216fd4e5da5Sopenharmony_ci%void = OpTypeVoid
217fd4e5da5Sopenharmony_ci%6 = OpTypeFunction %void
218fd4e5da5Sopenharmony_ci%float = OpTypeFloat 32
219fd4e5da5Sopenharmony_ci%_ptr_Private_float = OpTypePointer Private %float
220fd4e5da5Sopenharmony_ci%initializer = OpConstant %float 0
221fd4e5da5Sopenharmony_ci%live = OpVariable %_ptr_Private_float Private %initializer
222fd4e5da5Sopenharmony_ci%main = OpFunction %void None %6
223fd4e5da5Sopenharmony_ci%9 = OpLabel
224fd4e5da5Sopenharmony_ci%10 = OpLoad %float %live
225fd4e5da5Sopenharmony_ciOpReturn
226fd4e5da5Sopenharmony_ciOpFunctionEnd
227fd4e5da5Sopenharmony_ci)";
228fd4e5da5Sopenharmony_ci
229fd4e5da5Sopenharmony_ci  SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
230fd4e5da5Sopenharmony_ci  SinglePassRunAndCheck<DeadVariableElimination>(before, before, true, true);
231fd4e5da5Sopenharmony_ci}
232fd4e5da5Sopenharmony_ci
233fd4e5da5Sopenharmony_ci// This test that the decoration associated with a variable are removed when the
234fd4e5da5Sopenharmony_ci// variable is removed.
235fd4e5da5Sopenharmony_ciTEST_F(DeadVariableElimTest, RemoveVariableAndDecorations) {
236fd4e5da5Sopenharmony_ci  const std::string before =
237fd4e5da5Sopenharmony_ci      R"(OpCapability Shader
238fd4e5da5Sopenharmony_ci%1 = OpExtInstImport "GLSL.std.450"
239fd4e5da5Sopenharmony_ciOpMemoryModel Logical GLSL450
240fd4e5da5Sopenharmony_ciOpEntryPoint Vertex %main "main"
241fd4e5da5Sopenharmony_ciOpSource GLSL 450
242fd4e5da5Sopenharmony_ciOpName %main "main"
243fd4e5da5Sopenharmony_ciOpName %B "B"
244fd4e5da5Sopenharmony_ciOpMemberName %B 0 "a"
245fd4e5da5Sopenharmony_ciOpName %Bdat "Bdat"
246fd4e5da5Sopenharmony_ciOpMemberDecorate %B 0 Offset 0
247fd4e5da5Sopenharmony_ciOpDecorate %B BufferBlock
248fd4e5da5Sopenharmony_ciOpDecorate %Bdat DescriptorSet 0
249fd4e5da5Sopenharmony_ciOpDecorate %Bdat Binding 0
250fd4e5da5Sopenharmony_ci%void = OpTypeVoid
251fd4e5da5Sopenharmony_ci%6 = OpTypeFunction %void
252fd4e5da5Sopenharmony_ci%uint = OpTypeInt 32 0
253fd4e5da5Sopenharmony_ci%B = OpTypeStruct %uint
254fd4e5da5Sopenharmony_ci%_ptr_Uniform_B = OpTypePointer Uniform %B
255fd4e5da5Sopenharmony_ci%Bdat = OpVariable %_ptr_Uniform_B Uniform
256fd4e5da5Sopenharmony_ci%int = OpTypeInt 32 1
257fd4e5da5Sopenharmony_ci%int_0 = OpConstant %int 0
258fd4e5da5Sopenharmony_ci%uint_1 = OpConstant %uint 1
259fd4e5da5Sopenharmony_ci%_ptr_Uniform_uint = OpTypePointer Uniform %uint
260fd4e5da5Sopenharmony_ci%main = OpFunction %void None %6
261fd4e5da5Sopenharmony_ci%13 = OpLabel
262fd4e5da5Sopenharmony_ciOpReturn
263fd4e5da5Sopenharmony_ciOpFunctionEnd
264fd4e5da5Sopenharmony_ci)";
265fd4e5da5Sopenharmony_ci
266fd4e5da5Sopenharmony_ci  const std::string after =
267fd4e5da5Sopenharmony_ci      R"(OpCapability Shader
268fd4e5da5Sopenharmony_ci%1 = OpExtInstImport "GLSL.std.450"
269fd4e5da5Sopenharmony_ciOpMemoryModel Logical GLSL450
270fd4e5da5Sopenharmony_ciOpEntryPoint Vertex %main "main"
271fd4e5da5Sopenharmony_ciOpSource GLSL 450
272fd4e5da5Sopenharmony_ciOpName %main "main"
273fd4e5da5Sopenharmony_ciOpName %B "B"
274fd4e5da5Sopenharmony_ciOpMemberName %B 0 "a"
275fd4e5da5Sopenharmony_ciOpMemberDecorate %B 0 Offset 0
276fd4e5da5Sopenharmony_ciOpDecorate %B BufferBlock
277fd4e5da5Sopenharmony_ci%void = OpTypeVoid
278fd4e5da5Sopenharmony_ci%6 = OpTypeFunction %void
279fd4e5da5Sopenharmony_ci%uint = OpTypeInt 32 0
280fd4e5da5Sopenharmony_ci%B = OpTypeStruct %uint
281fd4e5da5Sopenharmony_ci%_ptr_Uniform_B = OpTypePointer Uniform %B
282fd4e5da5Sopenharmony_ci%int = OpTypeInt 32 1
283fd4e5da5Sopenharmony_ci%int_0 = OpConstant %int 0
284fd4e5da5Sopenharmony_ci%uint_1 = OpConstant %uint 1
285fd4e5da5Sopenharmony_ci%_ptr_Uniform_uint = OpTypePointer Uniform %uint
286fd4e5da5Sopenharmony_ci%main = OpFunction %void None %6
287fd4e5da5Sopenharmony_ci%13 = OpLabel
288fd4e5da5Sopenharmony_ciOpReturn
289fd4e5da5Sopenharmony_ciOpFunctionEnd
290fd4e5da5Sopenharmony_ci)";
291fd4e5da5Sopenharmony_ci
292fd4e5da5Sopenharmony_ci  SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
293fd4e5da5Sopenharmony_ci  SinglePassRunAndCheck<DeadVariableElimination>(before, after, true, true);
294fd4e5da5Sopenharmony_ci}
295fd4e5da5Sopenharmony_ci
296fd4e5da5Sopenharmony_ci}  // namespace
297fd4e5da5Sopenharmony_ci}  // namespace opt
298fd4e5da5Sopenharmony_ci}  // namespace spvtools
299