• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 #include <vector>
17 
18 #include "gmock/gmock.h"
19 #include "test/opt/assembly_builder.h"
20 #include "test/opt/pass_fixture.h"
21 #include "test/opt/pass_utils.h"
22 
23 namespace spvtools {
24 namespace opt {
25 namespace {
26 
27 using ::testing::HasSubstr;
28 using EliminateDeadFunctionsBasicTest = PassTest<::testing::Test>;
29 
TEST_F(EliminateDeadFunctionsBasicTest,BasicDeleteDeadFunction)30 TEST_F(EliminateDeadFunctionsBasicTest, BasicDeleteDeadFunction) {
31   // The function Dead should be removed because it is never called.
32   const std::vector<const char*> common_code = {
33       // clang-format off
34                "OpCapability Shader",
35                "OpMemoryModel Logical GLSL450",
36                "OpEntryPoint Fragment %main \"main\"",
37                "OpName %main \"main\"",
38                "OpName %Live \"Live\"",
39        "%void = OpTypeVoid",
40           "%7 = OpTypeFunction %void",
41        "%main = OpFunction %void None %7",
42          "%15 = OpLabel",
43          "%16 = OpFunctionCall %void %Live",
44          "%17 = OpFunctionCall %void %Live",
45                "OpReturn",
46                "OpFunctionEnd",
47   "%Live = OpFunction %void None %7",
48          "%20 = OpLabel",
49                "OpReturn",
50                "OpFunctionEnd"
51       // clang-format on
52   };
53 
54   const std::vector<const char*> dead_function = {
55       // clang-format off
56       "%Dead = OpFunction %void None %7",
57          "%19 = OpLabel",
58                "OpReturn",
59                "OpFunctionEnd",
60       // clang-format on
61   };
62 
63   SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
64   SinglePassRunAndCheck<EliminateDeadFunctionsPass>(
65       JoinAllInsts(Concat(common_code, dead_function)),
66       JoinAllInsts(common_code), /* skip_nop = */ true);
67 }
68 
TEST_F(EliminateDeadFunctionsBasicTest,BasicKeepLiveFunction)69 TEST_F(EliminateDeadFunctionsBasicTest, BasicKeepLiveFunction) {
70   // Everything is reachable from an entry point, so no functions should be
71   // deleted.
72   const std::vector<const char*> text = {
73       // clang-format off
74                "OpCapability Shader",
75                "OpMemoryModel Logical GLSL450",
76                "OpEntryPoint Fragment %main \"main\"",
77                "OpName %main \"main\"",
78                "OpName %Live1 \"Live1\"",
79                "OpName %Live2 \"Live2\"",
80        "%void = OpTypeVoid",
81           "%7 = OpTypeFunction %void",
82        "%main = OpFunction %void None %7",
83          "%15 = OpLabel",
84          "%16 = OpFunctionCall %void %Live2",
85          "%17 = OpFunctionCall %void %Live1",
86                "OpReturn",
87                "OpFunctionEnd",
88       "%Live1 = OpFunction %void None %7",
89          "%19 = OpLabel",
90                "OpReturn",
91                "OpFunctionEnd",
92       "%Live2 = OpFunction %void None %7",
93          "%20 = OpLabel",
94                "OpReturn",
95                "OpFunctionEnd"
96       // clang-format on
97   };
98 
99   SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
100   std::string assembly = JoinAllInsts(text);
101   auto result = SinglePassRunAndDisassemble<EliminateDeadFunctionsPass>(
102       assembly, /* skip_nop = */ true, /* do_validation = */ false);
103   EXPECT_EQ(Pass::Status::SuccessWithoutChange, std::get<1>(result));
104   EXPECT_EQ(assembly, std::get<0>(result));
105 }
106 
TEST_F(EliminateDeadFunctionsBasicTest,BasicKeepExportFunctions)107 TEST_F(EliminateDeadFunctionsBasicTest, BasicKeepExportFunctions) {
108   // All functions are reachable.  In particular, ExportedFunc and Constant are
109   // reachable because ExportedFunc is exported.  Nothing should be removed.
110   const std::vector<const char*> text = {
111       // clang-format off
112                "OpCapability Shader",
113                "OpCapability Linkage",
114                "OpMemoryModel Logical GLSL450",
115                "OpEntryPoint Fragment %main \"main\"",
116                "OpName %main \"main\"",
117                "OpName %ExportedFunc \"ExportedFunc\"",
118                "OpName %Live \"Live\"",
119                "OpDecorate %ExportedFunc LinkageAttributes \"ExportedFunc\" Export",
120        "%void = OpTypeVoid",
121           "%7 = OpTypeFunction %void",
122        "%main = OpFunction %void None %7",
123          "%15 = OpLabel",
124                "OpReturn",
125                "OpFunctionEnd",
126 "%ExportedFunc = OpFunction %void None %7",
127          "%19 = OpLabel",
128          "%16 = OpFunctionCall %void %Live",
129                "OpReturn",
130                "OpFunctionEnd",
131   "%Live = OpFunction %void None %7",
132          "%20 = OpLabel",
133                "OpReturn",
134                "OpFunctionEnd"
135       // clang-format on
136   };
137 
138   SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
139   std::string assembly = JoinAllInsts(text);
140   auto result = SinglePassRunAndDisassemble<EliminateDeadFunctionsPass>(
141       assembly, /* skip_nop = */ true, /* do_validation = */ false);
142   EXPECT_EQ(Pass::Status::SuccessWithoutChange, std::get<1>(result));
143   EXPECT_EQ(assembly, std::get<0>(result));
144 }
145 
TEST_F(EliminateDeadFunctionsBasicTest,BasicRemoveDecorationsAndNames)146 TEST_F(EliminateDeadFunctionsBasicTest, BasicRemoveDecorationsAndNames) {
147   // We want to remove the names and decorations associated with results that
148   // are removed.  This test will check for that.
149   const std::string text = R"(
150                OpCapability Shader
151                OpMemoryModel Logical GLSL450
152                OpEntryPoint Vertex %main "main"
153                OpName %main "main"
154                OpName %Dead "Dead"
155                OpName %x "x"
156                OpName %y "y"
157                OpName %z "z"
158                OpDecorate %x RelaxedPrecision
159                OpDecorate %y RelaxedPrecision
160                OpDecorate %z RelaxedPrecision
161                OpDecorate %6 RelaxedPrecision
162                OpDecorate %7 RelaxedPrecision
163                OpDecorate %8 RelaxedPrecision
164        %void = OpTypeVoid
165          %10 = OpTypeFunction %void
166       %float = OpTypeFloat 32
167 %_ptr_Function_float = OpTypePointer Function %float
168     %float_1 = OpConstant %float 1
169        %main = OpFunction %void None %10
170          %14 = OpLabel
171                OpReturn
172                OpFunctionEnd
173        %Dead = OpFunction %void None %10
174          %15 = OpLabel
175           %x = OpVariable %_ptr_Function_float Function
176           %y = OpVariable %_ptr_Function_float Function
177           %z = OpVariable %_ptr_Function_float Function
178                OpStore %x %float_1
179                OpStore %y %float_1
180           %6 = OpLoad %float %x
181           %7 = OpLoad %float %y
182           %8 = OpFAdd %float %6 %7
183                OpStore %z %8
184                OpReturn
185                OpFunctionEnd)";
186 
187   const std::string expected_output = R"(OpCapability Shader
188 OpMemoryModel Logical GLSL450
189 OpEntryPoint Vertex %main "main"
190 OpName %main "main"
191 %void = OpTypeVoid
192 %10 = OpTypeFunction %void
193 %float = OpTypeFloat 32
194 %_ptr_Function_float = OpTypePointer Function %float
195 %float_1 = OpConstant %float 1
196 %main = OpFunction %void None %10
197 %14 = OpLabel
198 OpReturn
199 OpFunctionEnd
200 )";
201 
202   SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
203   SinglePassRunAndCheck<EliminateDeadFunctionsPass>(text, expected_output,
204                                                     /* skip_nop = */ true);
205 }
206 
207 }  // namespace
208 }  // namespace opt
209 }  // namespace spvtools
210