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