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 = OpVariable %_ptr_Private_float Private
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