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#include <vector>
17fd4e5da5Sopenharmony_ci
18fd4e5da5Sopenharmony_ci#include "gmock/gmock.h"
19fd4e5da5Sopenharmony_ci#include "test/opt/assembly_builder.h"
20fd4e5da5Sopenharmony_ci#include "test/opt/pass_fixture.h"
21fd4e5da5Sopenharmony_ci#include "test/opt/pass_utils.h"
22fd4e5da5Sopenharmony_ci
23fd4e5da5Sopenharmony_cinamespace spvtools {
24fd4e5da5Sopenharmony_cinamespace opt {
25fd4e5da5Sopenharmony_cinamespace {
26fd4e5da5Sopenharmony_ci
27fd4e5da5Sopenharmony_ciusing ::testing::HasSubstr;
28fd4e5da5Sopenharmony_ciusing EliminateDeadFunctionsBasicTest = PassTest<::testing::Test>;
29fd4e5da5Sopenharmony_ci
30fd4e5da5Sopenharmony_ciTEST_F(EliminateDeadFunctionsBasicTest, BasicDeleteDeadFunction) {
31fd4e5da5Sopenharmony_ci  // The function Dead should be removed because it is never called.
32fd4e5da5Sopenharmony_ci  const std::vector<const char*> common_code = {
33fd4e5da5Sopenharmony_ci      // clang-format off
34fd4e5da5Sopenharmony_ci               "OpCapability Shader",
35fd4e5da5Sopenharmony_ci               "OpMemoryModel Logical GLSL450",
36fd4e5da5Sopenharmony_ci               "OpEntryPoint Fragment %main \"main\"",
37fd4e5da5Sopenharmony_ci               "OpName %main \"main\"",
38fd4e5da5Sopenharmony_ci               "OpName %Live \"Live\"",
39fd4e5da5Sopenharmony_ci       "%void = OpTypeVoid",
40fd4e5da5Sopenharmony_ci          "%7 = OpTypeFunction %void",
41fd4e5da5Sopenharmony_ci       "%main = OpFunction %void None %7",
42fd4e5da5Sopenharmony_ci         "%15 = OpLabel",
43fd4e5da5Sopenharmony_ci         "%16 = OpFunctionCall %void %Live",
44fd4e5da5Sopenharmony_ci         "%17 = OpFunctionCall %void %Live",
45fd4e5da5Sopenharmony_ci               "OpReturn",
46fd4e5da5Sopenharmony_ci               "OpFunctionEnd",
47fd4e5da5Sopenharmony_ci  "%Live = OpFunction %void None %7",
48fd4e5da5Sopenharmony_ci         "%20 = OpLabel",
49fd4e5da5Sopenharmony_ci               "OpReturn",
50fd4e5da5Sopenharmony_ci               "OpFunctionEnd"
51fd4e5da5Sopenharmony_ci      // clang-format on
52fd4e5da5Sopenharmony_ci  };
53fd4e5da5Sopenharmony_ci
54fd4e5da5Sopenharmony_ci  const std::vector<const char*> dead_function = {
55fd4e5da5Sopenharmony_ci      // clang-format off
56fd4e5da5Sopenharmony_ci      "%Dead = OpFunction %void None %7",
57fd4e5da5Sopenharmony_ci         "%19 = OpLabel",
58fd4e5da5Sopenharmony_ci               "OpReturn",
59fd4e5da5Sopenharmony_ci               "OpFunctionEnd",
60fd4e5da5Sopenharmony_ci      // clang-format on
61fd4e5da5Sopenharmony_ci  };
62fd4e5da5Sopenharmony_ci
63fd4e5da5Sopenharmony_ci  SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
64fd4e5da5Sopenharmony_ci  SinglePassRunAndCheck<EliminateDeadFunctionsPass>(
65fd4e5da5Sopenharmony_ci      JoinAllInsts(Concat(common_code, dead_function)),
66fd4e5da5Sopenharmony_ci      JoinAllInsts(common_code), /* skip_nop = */ true);
67fd4e5da5Sopenharmony_ci}
68fd4e5da5Sopenharmony_ci
69fd4e5da5Sopenharmony_ciTEST_F(EliminateDeadFunctionsBasicTest, BasicKeepLiveFunction) {
70fd4e5da5Sopenharmony_ci  // Everything is reachable from an entry point, so no functions should be
71fd4e5da5Sopenharmony_ci  // deleted.
72fd4e5da5Sopenharmony_ci  const std::vector<const char*> text = {
73fd4e5da5Sopenharmony_ci      // clang-format off
74fd4e5da5Sopenharmony_ci               "OpCapability Shader",
75fd4e5da5Sopenharmony_ci               "OpMemoryModel Logical GLSL450",
76fd4e5da5Sopenharmony_ci               "OpEntryPoint Fragment %main \"main\"",
77fd4e5da5Sopenharmony_ci               "OpName %main \"main\"",
78fd4e5da5Sopenharmony_ci               "OpName %Live1 \"Live1\"",
79fd4e5da5Sopenharmony_ci               "OpName %Live2 \"Live2\"",
80fd4e5da5Sopenharmony_ci       "%void = OpTypeVoid",
81fd4e5da5Sopenharmony_ci          "%7 = OpTypeFunction %void",
82fd4e5da5Sopenharmony_ci       "%main = OpFunction %void None %7",
83fd4e5da5Sopenharmony_ci         "%15 = OpLabel",
84fd4e5da5Sopenharmony_ci         "%16 = OpFunctionCall %void %Live2",
85fd4e5da5Sopenharmony_ci         "%17 = OpFunctionCall %void %Live1",
86fd4e5da5Sopenharmony_ci               "OpReturn",
87fd4e5da5Sopenharmony_ci               "OpFunctionEnd",
88fd4e5da5Sopenharmony_ci      "%Live1 = OpFunction %void None %7",
89fd4e5da5Sopenharmony_ci         "%19 = OpLabel",
90fd4e5da5Sopenharmony_ci               "OpReturn",
91fd4e5da5Sopenharmony_ci               "OpFunctionEnd",
92fd4e5da5Sopenharmony_ci      "%Live2 = OpFunction %void None %7",
93fd4e5da5Sopenharmony_ci         "%20 = OpLabel",
94fd4e5da5Sopenharmony_ci               "OpReturn",
95fd4e5da5Sopenharmony_ci               "OpFunctionEnd"
96fd4e5da5Sopenharmony_ci      // clang-format on
97fd4e5da5Sopenharmony_ci  };
98fd4e5da5Sopenharmony_ci
99fd4e5da5Sopenharmony_ci  SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
100fd4e5da5Sopenharmony_ci  std::string assembly = JoinAllInsts(text);
101fd4e5da5Sopenharmony_ci  auto result = SinglePassRunAndDisassemble<EliminateDeadFunctionsPass>(
102fd4e5da5Sopenharmony_ci      assembly, /* skip_nop = */ true, /* do_validation = */ false);
103fd4e5da5Sopenharmony_ci  EXPECT_EQ(Pass::Status::SuccessWithoutChange, std::get<1>(result));
104fd4e5da5Sopenharmony_ci  EXPECT_EQ(assembly, std::get<0>(result));
105fd4e5da5Sopenharmony_ci}
106fd4e5da5Sopenharmony_ci
107fd4e5da5Sopenharmony_ciTEST_F(EliminateDeadFunctionsBasicTest, BasicKeepExportFunctions) {
108fd4e5da5Sopenharmony_ci  // All functions are reachable.  In particular, ExportedFunc and Constant are
109fd4e5da5Sopenharmony_ci  // reachable because ExportedFunc is exported.  Nothing should be removed.
110fd4e5da5Sopenharmony_ci  const std::vector<const char*> text = {
111fd4e5da5Sopenharmony_ci      // clang-format off
112fd4e5da5Sopenharmony_ci               "OpCapability Shader",
113fd4e5da5Sopenharmony_ci               "OpCapability Linkage",
114fd4e5da5Sopenharmony_ci               "OpMemoryModel Logical GLSL450",
115fd4e5da5Sopenharmony_ci               "OpEntryPoint Fragment %main \"main\"",
116fd4e5da5Sopenharmony_ci               "OpName %main \"main\"",
117fd4e5da5Sopenharmony_ci               "OpName %ExportedFunc \"ExportedFunc\"",
118fd4e5da5Sopenharmony_ci               "OpName %Live \"Live\"",
119fd4e5da5Sopenharmony_ci               "OpDecorate %ExportedFunc LinkageAttributes \"ExportedFunc\" Export",
120fd4e5da5Sopenharmony_ci       "%void = OpTypeVoid",
121fd4e5da5Sopenharmony_ci          "%7 = OpTypeFunction %void",
122fd4e5da5Sopenharmony_ci       "%main = OpFunction %void None %7",
123fd4e5da5Sopenharmony_ci         "%15 = OpLabel",
124fd4e5da5Sopenharmony_ci               "OpReturn",
125fd4e5da5Sopenharmony_ci               "OpFunctionEnd",
126fd4e5da5Sopenharmony_ci"%ExportedFunc = OpFunction %void None %7",
127fd4e5da5Sopenharmony_ci         "%19 = OpLabel",
128fd4e5da5Sopenharmony_ci         "%16 = OpFunctionCall %void %Live",
129fd4e5da5Sopenharmony_ci               "OpReturn",
130fd4e5da5Sopenharmony_ci               "OpFunctionEnd",
131fd4e5da5Sopenharmony_ci  "%Live = OpFunction %void None %7",
132fd4e5da5Sopenharmony_ci         "%20 = OpLabel",
133fd4e5da5Sopenharmony_ci               "OpReturn",
134fd4e5da5Sopenharmony_ci               "OpFunctionEnd"
135fd4e5da5Sopenharmony_ci      // clang-format on
136fd4e5da5Sopenharmony_ci  };
137fd4e5da5Sopenharmony_ci
138fd4e5da5Sopenharmony_ci  SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
139fd4e5da5Sopenharmony_ci  std::string assembly = JoinAllInsts(text);
140fd4e5da5Sopenharmony_ci  auto result = SinglePassRunAndDisassemble<EliminateDeadFunctionsPass>(
141fd4e5da5Sopenharmony_ci      assembly, /* skip_nop = */ true, /* do_validation = */ false);
142fd4e5da5Sopenharmony_ci  EXPECT_EQ(Pass::Status::SuccessWithoutChange, std::get<1>(result));
143fd4e5da5Sopenharmony_ci  EXPECT_EQ(assembly, std::get<0>(result));
144fd4e5da5Sopenharmony_ci}
145fd4e5da5Sopenharmony_ci
146fd4e5da5Sopenharmony_ciTEST_F(EliminateDeadFunctionsBasicTest, BasicRemoveDecorationsAndNames) {
147fd4e5da5Sopenharmony_ci  // We want to remove the names and decorations associated with results that
148fd4e5da5Sopenharmony_ci  // are removed.  This test will check for that.
149fd4e5da5Sopenharmony_ci  const std::string text = R"(
150fd4e5da5Sopenharmony_ci               OpCapability Shader
151fd4e5da5Sopenharmony_ci               OpMemoryModel Logical GLSL450
152fd4e5da5Sopenharmony_ci               OpEntryPoint Vertex %main "main"
153fd4e5da5Sopenharmony_ci               OpName %main "main"
154fd4e5da5Sopenharmony_ci               OpName %Dead "Dead"
155fd4e5da5Sopenharmony_ci               OpName %x "x"
156fd4e5da5Sopenharmony_ci               OpName %y "y"
157fd4e5da5Sopenharmony_ci               OpName %z "z"
158fd4e5da5Sopenharmony_ci               OpDecorate %x RelaxedPrecision
159fd4e5da5Sopenharmony_ci               OpDecorate %y RelaxedPrecision
160fd4e5da5Sopenharmony_ci               OpDecorate %z RelaxedPrecision
161fd4e5da5Sopenharmony_ci               OpDecorate %6 RelaxedPrecision
162fd4e5da5Sopenharmony_ci               OpDecorate %7 RelaxedPrecision
163fd4e5da5Sopenharmony_ci               OpDecorate %8 RelaxedPrecision
164fd4e5da5Sopenharmony_ci       %void = OpTypeVoid
165fd4e5da5Sopenharmony_ci         %10 = OpTypeFunction %void
166fd4e5da5Sopenharmony_ci      %float = OpTypeFloat 32
167fd4e5da5Sopenharmony_ci%_ptr_Function_float = OpTypePointer Function %float
168fd4e5da5Sopenharmony_ci    %float_1 = OpConstant %float 1
169fd4e5da5Sopenharmony_ci       %main = OpFunction %void None %10
170fd4e5da5Sopenharmony_ci         %14 = OpLabel
171fd4e5da5Sopenharmony_ci               OpReturn
172fd4e5da5Sopenharmony_ci               OpFunctionEnd
173fd4e5da5Sopenharmony_ci       %Dead = OpFunction %void None %10
174fd4e5da5Sopenharmony_ci         %15 = OpLabel
175fd4e5da5Sopenharmony_ci          %x = OpVariable %_ptr_Function_float Function
176fd4e5da5Sopenharmony_ci          %y = OpVariable %_ptr_Function_float Function
177fd4e5da5Sopenharmony_ci          %z = OpVariable %_ptr_Function_float Function
178fd4e5da5Sopenharmony_ci               OpStore %x %float_1
179fd4e5da5Sopenharmony_ci               OpStore %y %float_1
180fd4e5da5Sopenharmony_ci          %6 = OpLoad %float %x
181fd4e5da5Sopenharmony_ci          %7 = OpLoad %float %y
182fd4e5da5Sopenharmony_ci          %8 = OpFAdd %float %6 %7
183fd4e5da5Sopenharmony_ci               OpStore %z %8
184fd4e5da5Sopenharmony_ci               OpReturn
185fd4e5da5Sopenharmony_ci               OpFunctionEnd)";
186fd4e5da5Sopenharmony_ci
187fd4e5da5Sopenharmony_ci  const std::string expected_output = R"(OpCapability Shader
188fd4e5da5Sopenharmony_ciOpMemoryModel Logical GLSL450
189fd4e5da5Sopenharmony_ciOpEntryPoint Vertex %main "main"
190fd4e5da5Sopenharmony_ciOpName %main "main"
191fd4e5da5Sopenharmony_ci%void = OpTypeVoid
192fd4e5da5Sopenharmony_ci%10 = OpTypeFunction %void
193fd4e5da5Sopenharmony_ci%float = OpTypeFloat 32
194fd4e5da5Sopenharmony_ci%_ptr_Function_float = OpTypePointer Function %float
195fd4e5da5Sopenharmony_ci%float_1 = OpConstant %float 1
196fd4e5da5Sopenharmony_ci%main = OpFunction %void None %10
197fd4e5da5Sopenharmony_ci%14 = OpLabel
198fd4e5da5Sopenharmony_ciOpReturn
199fd4e5da5Sopenharmony_ciOpFunctionEnd
200fd4e5da5Sopenharmony_ci)";
201fd4e5da5Sopenharmony_ci
202fd4e5da5Sopenharmony_ci  SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
203fd4e5da5Sopenharmony_ci  SinglePassRunAndCheck<EliminateDeadFunctionsPass>(text, expected_output,
204fd4e5da5Sopenharmony_ci                                                    /* skip_nop = */ true);
205fd4e5da5Sopenharmony_ci}
206fd4e5da5Sopenharmony_ci
207fd4e5da5Sopenharmony_ciTEST_F(EliminateDeadFunctionsBasicTest, DebugRemoveFunctionFromDebugFunction) {
208fd4e5da5Sopenharmony_ci  // We want to remove id of OpFunction from DebugFunction.
209fd4e5da5Sopenharmony_ci  const std::string text = R"(OpCapability Shader
210fd4e5da5Sopenharmony_ci%1 = OpExtInstImport "OpenCL.DebugInfo.100"
211fd4e5da5Sopenharmony_ciOpMemoryModel Logical GLSL450
212fd4e5da5Sopenharmony_ciOpEntryPoint Fragment %2 "main" %3 %4
213fd4e5da5Sopenharmony_ciOpExecutionMode %2 OriginUpperLeft
214fd4e5da5Sopenharmony_ci%5 = OpString "ps.hlsl"
215fd4e5da5Sopenharmony_ciOpSource HLSL 600 %5 "float4 foo() {
216fd4e5da5Sopenharmony_ci  return 1;
217fd4e5da5Sopenharmony_ci}
218fd4e5da5Sopenharmony_cifloat4 main(float4 color : COLOR) : SV_TARGET {
219fd4e5da5Sopenharmony_ci  return foo() + color;
220fd4e5da5Sopenharmony_ci}
221fd4e5da5Sopenharmony_ci"
222fd4e5da5Sopenharmony_ci%6 = OpString "float"
223fd4e5da5Sopenharmony_ci%7 = OpString "main"
224fd4e5da5Sopenharmony_ci%8 = OpString "foo"
225fd4e5da5Sopenharmony_ci; CHECK: [[foo:%\d+]] = OpString "foo"
226fd4e5da5Sopenharmony_ciOpDecorate %3 Location 0
227fd4e5da5Sopenharmony_ciOpDecorate %4 Location 0
228fd4e5da5Sopenharmony_ci%uint = OpTypeInt 32 0
229fd4e5da5Sopenharmony_ci%uint_32 = OpConstant %uint 32
230fd4e5da5Sopenharmony_ci%float = OpTypeFloat 32
231fd4e5da5Sopenharmony_ci%float_1 = OpConstant %float 1
232fd4e5da5Sopenharmony_ci%v4float = OpTypeVector %float 4
233fd4e5da5Sopenharmony_ci%14 = OpConstantComposite %v4float %float_1 %float_1 %float_1 %float_1
234fd4e5da5Sopenharmony_ci%_ptr_Input_v4float = OpTypePointer Input %v4float
235fd4e5da5Sopenharmony_ci%_ptr_Output_v4float = OpTypePointer Output %v4float
236fd4e5da5Sopenharmony_ci%void = OpTypeVoid
237fd4e5da5Sopenharmony_ci%18 = OpTypeFunction %void
238fd4e5da5Sopenharmony_ci%19 = OpTypeFunction %v4float
239fd4e5da5Sopenharmony_ci%3 = OpVariable %_ptr_Input_v4float Input
240fd4e5da5Sopenharmony_ci%4 = OpVariable %_ptr_Output_v4float Output
241fd4e5da5Sopenharmony_ci%_ptr_Function_v4float = OpTypePointer Function %v4float
242fd4e5da5Sopenharmony_ci; CHECK: [[info_none:%\d+]] = OpExtInst %void %1 DebugInfoNone
243fd4e5da5Sopenharmony_ci%20 = OpExtInst %void %1 DebugSource %5
244fd4e5da5Sopenharmony_ci%21 = OpExtInst %void %1 DebugCompilationUnit 1 4 %20 HLSL
245fd4e5da5Sopenharmony_ci%22 = OpExtInst %void %1 DebugTypeBasic %6 %uint_32 Float
246fd4e5da5Sopenharmony_ci%23 = OpExtInst %void %1 DebugTypeVector %22 4
247fd4e5da5Sopenharmony_ci%24 = OpExtInst %void %1 DebugTypeFunction FlagIsProtected|FlagIsPrivate %23 %23
248fd4e5da5Sopenharmony_ci%25 = OpExtInst %void %1 DebugTypeFunction FlagIsProtected|FlagIsPrivate %23
249fd4e5da5Sopenharmony_ci%26 = OpExtInst %void %1 DebugFunction %7 %24 %20 4 1 %21 %7 FlagIsProtected|FlagIsPrivate 4 %2
250fd4e5da5Sopenharmony_ci%27 = OpExtInst %void %1 DebugFunction %8 %25 %20 1 1 %21 %8 FlagIsProtected|FlagIsPrivate 1 %28
251fd4e5da5Sopenharmony_ci; CHECK: {{%\d+}} = OpExtInst %void %1 DebugFunction [[foo]] {{%\d+}} {{%\d+}} 1 1 {{%\d+}} {{%\d+}} FlagIsProtected|FlagIsPrivate 1 [[info_none]]
252fd4e5da5Sopenharmony_ci%29 = OpExtInst %void %1 DebugLexicalBlock %20 1 14 %27
253fd4e5da5Sopenharmony_ci%40 = OpExtInst %void %1 DebugInlinedAt 4 %26
254fd4e5da5Sopenharmony_ci%2 = OpFunction %void None %18
255fd4e5da5Sopenharmony_ci%30 = OpLabel
256fd4e5da5Sopenharmony_ci%39 = OpVariable %_ptr_Function_v4float Function
257fd4e5da5Sopenharmony_ci%41 = OpExtInst %void %1 DebugScope %27 %40
258fd4e5da5Sopenharmony_ciOpStore %39 %14
259fd4e5da5Sopenharmony_ci%32 = OpLoad %v4float %39
260fd4e5da5Sopenharmony_ci%42 = OpExtInst %void %1 DebugScope %26
261fd4e5da5Sopenharmony_ci%33 = OpLoad %v4float %3
262fd4e5da5Sopenharmony_ci%34 = OpFAdd %v4float %32 %33
263fd4e5da5Sopenharmony_ciOpStore %4 %34
264fd4e5da5Sopenharmony_ci%43 = OpExtInst %void %1 DebugNoScope
265fd4e5da5Sopenharmony_ciOpReturn
266fd4e5da5Sopenharmony_ciOpFunctionEnd
267fd4e5da5Sopenharmony_ci%28 = OpFunction %v4float None %19
268fd4e5da5Sopenharmony_ci%36 = OpLabel
269fd4e5da5Sopenharmony_ciOpReturnValue %14
270fd4e5da5Sopenharmony_ciOpFunctionEnd
271fd4e5da5Sopenharmony_ci)";
272fd4e5da5Sopenharmony_ci
273fd4e5da5Sopenharmony_ci  SinglePassRunAndMatch<EliminateDeadFunctionsPass>(text, false);
274fd4e5da5Sopenharmony_ci}
275fd4e5da5Sopenharmony_ci
276fd4e5da5Sopenharmony_ciTEST_F(EliminateDeadFunctionsBasicTest,
277fd4e5da5Sopenharmony_ci       DebugRemoveFunctionUsingExistingDebugInfoNone) {
278fd4e5da5Sopenharmony_ci  // We want to remove id of OpFunction from DebugFunction.
279fd4e5da5Sopenharmony_ci  const std::string text = R"(OpCapability Shader
280fd4e5da5Sopenharmony_ci%1 = OpExtInstImport "OpenCL.DebugInfo.100"
281fd4e5da5Sopenharmony_ciOpMemoryModel Logical GLSL450
282fd4e5da5Sopenharmony_ciOpEntryPoint Fragment %2 "main" %3 %4
283fd4e5da5Sopenharmony_ciOpExecutionMode %2 OriginUpperLeft
284fd4e5da5Sopenharmony_ci%5 = OpString "ps.hlsl"
285fd4e5da5Sopenharmony_ciOpSource HLSL 600 %5 "float4 foo() {
286fd4e5da5Sopenharmony_ci  return 1;
287fd4e5da5Sopenharmony_ci}
288fd4e5da5Sopenharmony_cifloat4 main(float4 color : COLOR) : SV_TARGET {
289fd4e5da5Sopenharmony_ci  return foo() + color;
290fd4e5da5Sopenharmony_ci}
291fd4e5da5Sopenharmony_ci"
292fd4e5da5Sopenharmony_ci%6 = OpString "float"
293fd4e5da5Sopenharmony_ci%7 = OpString "main"
294fd4e5da5Sopenharmony_ci%8 = OpString "foo"
295fd4e5da5Sopenharmony_ci; CHECK: [[foo:%\d+]] = OpString "foo"
296fd4e5da5Sopenharmony_ciOpDecorate %3 Location 0
297fd4e5da5Sopenharmony_ciOpDecorate %4 Location 0
298fd4e5da5Sopenharmony_ci%uint = OpTypeInt 32 0
299fd4e5da5Sopenharmony_ci%uint_32 = OpConstant %uint 32
300fd4e5da5Sopenharmony_ci%float = OpTypeFloat 32
301fd4e5da5Sopenharmony_ci%float_1 = OpConstant %float 1
302fd4e5da5Sopenharmony_ci%v4float = OpTypeVector %float 4
303fd4e5da5Sopenharmony_ci%14 = OpConstantComposite %v4float %float_1 %float_1 %float_1 %float_1
304fd4e5da5Sopenharmony_ci%_ptr_Input_v4float = OpTypePointer Input %v4float
305fd4e5da5Sopenharmony_ci%_ptr_Output_v4float = OpTypePointer Output %v4float
306fd4e5da5Sopenharmony_ci%void = OpTypeVoid
307fd4e5da5Sopenharmony_ci%18 = OpTypeFunction %void
308fd4e5da5Sopenharmony_ci%19 = OpTypeFunction %v4float
309fd4e5da5Sopenharmony_ci%3 = OpVariable %_ptr_Input_v4float Input
310fd4e5da5Sopenharmony_ci%4 = OpVariable %_ptr_Output_v4float Output
311fd4e5da5Sopenharmony_ci%_ptr_Function_v4float = OpTypePointer Function %v4float
312fd4e5da5Sopenharmony_ci; CHECK: [[info_none:%\d+]] = OpExtInst %void %1 DebugInfoNone
313fd4e5da5Sopenharmony_ci%20 = OpExtInst %void %1 DebugSource %5
314fd4e5da5Sopenharmony_ci%21 = OpExtInst %void %1 DebugCompilationUnit 1 4 %20 HLSL
315fd4e5da5Sopenharmony_ci%22 = OpExtInst %void %1 DebugTypeBasic %6 %uint_32 Float
316fd4e5da5Sopenharmony_ci%23 = OpExtInst %void %1 DebugTypeVector %22 4
317fd4e5da5Sopenharmony_ci%24 = OpExtInst %void %1 DebugTypeFunction FlagIsProtected|FlagIsPrivate %23 %23
318fd4e5da5Sopenharmony_ci%25 = OpExtInst %void %1 DebugTypeFunction FlagIsProtected|FlagIsPrivate %23
319fd4e5da5Sopenharmony_ci%26 = OpExtInst %void %1 DebugFunction %7 %24 %20 4 1 %21 %7 FlagIsProtected|FlagIsPrivate 4 %2
320fd4e5da5Sopenharmony_ci%27 = OpExtInst %void %1 DebugFunction %8 %25 %20 1 1 %21 %8 FlagIsProtected|FlagIsPrivate 1 %28
321fd4e5da5Sopenharmony_ci; CHECK: {{%\d+}} = OpExtInst %void %1 DebugFunction [[foo]] {{%\d+}} {{%\d+}} 1 1 {{%\d+}} {{%\d+}} FlagIsProtected|FlagIsPrivate 1 [[info_none]]
322fd4e5da5Sopenharmony_ci%29 = OpExtInst %void %1 DebugLexicalBlock %20 1 14 %27
323fd4e5da5Sopenharmony_ci%35 = OpExtInst %void %1 DebugInfoNone
324fd4e5da5Sopenharmony_ci%40 = OpExtInst %void %1 DebugInlinedAt 4 %26
325fd4e5da5Sopenharmony_ci%2 = OpFunction %void None %18
326fd4e5da5Sopenharmony_ci%30 = OpLabel
327fd4e5da5Sopenharmony_ci%39 = OpVariable %_ptr_Function_v4float Function
328fd4e5da5Sopenharmony_ci%41 = OpExtInst %void %1 DebugScope %27 %40
329fd4e5da5Sopenharmony_ciOpStore %39 %14
330fd4e5da5Sopenharmony_ci%32 = OpLoad %v4float %39
331fd4e5da5Sopenharmony_ci%42 = OpExtInst %void %1 DebugScope %26
332fd4e5da5Sopenharmony_ci%33 = OpLoad %v4float %3
333fd4e5da5Sopenharmony_ci%34 = OpFAdd %v4float %32 %33
334fd4e5da5Sopenharmony_ciOpStore %4 %34
335fd4e5da5Sopenharmony_ci%43 = OpExtInst %void %1 DebugNoScope
336fd4e5da5Sopenharmony_ciOpReturn
337fd4e5da5Sopenharmony_ciOpFunctionEnd
338fd4e5da5Sopenharmony_ci%28 = OpFunction %v4float None %19
339fd4e5da5Sopenharmony_ci%36 = OpLabel
340fd4e5da5Sopenharmony_ciOpReturnValue %14
341fd4e5da5Sopenharmony_ciOpFunctionEnd
342fd4e5da5Sopenharmony_ci)";
343fd4e5da5Sopenharmony_ci
344fd4e5da5Sopenharmony_ci  SinglePassRunAndMatch<EliminateDeadFunctionsPass>(text, false);
345fd4e5da5Sopenharmony_ci}
346fd4e5da5Sopenharmony_ci
347fd4e5da5Sopenharmony_ciTEST_F(EliminateDeadFunctionsBasicTest, NonSemanticInfoPersists) {
348fd4e5da5Sopenharmony_ci  const std::string text = R"(
349fd4e5da5Sopenharmony_ci; CHECK: [[import:%\w+]] = OpExtInstImport
350fd4e5da5Sopenharmony_ci; CHECK: [[void:%\w+]] = OpTypeVoid
351fd4e5da5Sopenharmony_ci; CHECK-NOT: OpExtInst [[void]] [[import]] 1
352fd4e5da5Sopenharmony_ci; CHECK: OpExtInst [[void]] [[import]] 2
353fd4e5da5Sopenharmony_ciOpCapability Shader
354fd4e5da5Sopenharmony_ciOpExtension "SPV_KHR_non_semantic_info"
355fd4e5da5Sopenharmony_ci%ext = OpExtInstImport "NonSemantic.Test"
356fd4e5da5Sopenharmony_ciOpMemoryModel Logical GLSL450
357fd4e5da5Sopenharmony_ciOpEntryPoint GLCompute %main "main"
358fd4e5da5Sopenharmony_ciOpExecutionMode %main LocalSize 1 1 1
359fd4e5da5Sopenharmony_ci%void = OpTypeVoid
360fd4e5da5Sopenharmony_ci%void_fn = OpTypeFunction %void
361fd4e5da5Sopenharmony_ci%main = OpFunction %void None %void_fn
362fd4e5da5Sopenharmony_ci%entry = OpLabel
363fd4e5da5Sopenharmony_ciOpReturn
364fd4e5da5Sopenharmony_ciOpFunctionEnd
365fd4e5da5Sopenharmony_ci%foo = OpFunction %void None %void_fn
366fd4e5da5Sopenharmony_ci%foo_entry = OpLabel
367fd4e5da5Sopenharmony_ci%non_semantic1 = OpExtInst %void %ext 1
368fd4e5da5Sopenharmony_ciOpReturn
369fd4e5da5Sopenharmony_ciOpFunctionEnd
370fd4e5da5Sopenharmony_ci%non_semantic2 = OpExtInst %void %ext 2
371fd4e5da5Sopenharmony_ci)";
372fd4e5da5Sopenharmony_ci
373fd4e5da5Sopenharmony_ci  SinglePassRunAndMatch<EliminateDeadFunctionsPass>(text, true);
374fd4e5da5Sopenharmony_ci}
375fd4e5da5Sopenharmony_ci
376fd4e5da5Sopenharmony_ciTEST_F(EliminateDeadFunctionsBasicTest, NonSemanticInfoRemoveDependent) {
377fd4e5da5Sopenharmony_ci  const std::string text = R"(
378fd4e5da5Sopenharmony_ci; CHECK: [[import:%\w+]] = OpExtInstImport
379fd4e5da5Sopenharmony_ci; CHECK: [[void:%\w+]] = OpTypeVoid
380fd4e5da5Sopenharmony_ci; CHECK-NOT: OpExtInst [[void]] [[import]] 1
381fd4e5da5Sopenharmony_ci; CHECK-NOT: OpExtInst [[void]] [[import]] 2
382fd4e5da5Sopenharmony_ci; CHECK: OpExtInst [[void]] [[import]] 3
383fd4e5da5Sopenharmony_ciOpCapability Shader
384fd4e5da5Sopenharmony_ciOpExtension "SPV_KHR_non_semantic_info"
385fd4e5da5Sopenharmony_ci%ext = OpExtInstImport "NonSemantic.Test"
386fd4e5da5Sopenharmony_ciOpMemoryModel Logical GLSL450
387fd4e5da5Sopenharmony_ciOpEntryPoint GLCompute %main "main"
388fd4e5da5Sopenharmony_ciOpExecutionMode %main LocalSize 1 1 1
389fd4e5da5Sopenharmony_ci%void = OpTypeVoid
390fd4e5da5Sopenharmony_ci%void_fn = OpTypeFunction %void
391fd4e5da5Sopenharmony_ci%main = OpFunction %void None %void_fn
392fd4e5da5Sopenharmony_ci%entry = OpLabel
393fd4e5da5Sopenharmony_ciOpReturn
394fd4e5da5Sopenharmony_ciOpFunctionEnd
395fd4e5da5Sopenharmony_ci%foo = OpFunction %void None %void_fn
396fd4e5da5Sopenharmony_ci%foo_entry = OpLabel
397fd4e5da5Sopenharmony_ci%non_semantic1 = OpExtInst %void %ext 1
398fd4e5da5Sopenharmony_ciOpReturn
399fd4e5da5Sopenharmony_ciOpFunctionEnd
400fd4e5da5Sopenharmony_ci%non_semantic2 = OpExtInst %void %ext 2 %foo
401fd4e5da5Sopenharmony_ci%non_semantic3 = OpExtInst %void %ext 3
402fd4e5da5Sopenharmony_ci)";
403fd4e5da5Sopenharmony_ci
404fd4e5da5Sopenharmony_ci  SinglePassRunAndMatch<EliminateDeadFunctionsPass>(text, true);
405fd4e5da5Sopenharmony_ci}
406fd4e5da5Sopenharmony_ci
407fd4e5da5Sopenharmony_ciTEST_F(EliminateDeadFunctionsBasicTest, NonSemanticInfoRemoveDependentTree) {
408fd4e5da5Sopenharmony_ci  const std::string text = R"(
409fd4e5da5Sopenharmony_ci; CHECK: [[import:%\w+]] = OpExtInstImport
410fd4e5da5Sopenharmony_ci; CHECK: [[void:%\w+]] = OpTypeVoid
411fd4e5da5Sopenharmony_ci; CHECK-NOT: OpExtInst [[void]] [[import]] 1
412fd4e5da5Sopenharmony_ci; CHECK-NOT: OpExtInst [[void]] [[import]] 2
413fd4e5da5Sopenharmony_ci; CHECK: OpExtInst [[void]] [[import]] 3
414fd4e5da5Sopenharmony_ci; CHECK-NOT: OpExtInst [[void]] [[import]] 4
415fd4e5da5Sopenharmony_ci; CHECK-NOT: OpExtInst [[void]] [[import]] 5
416fd4e5da5Sopenharmony_ciOpCapability Shader
417fd4e5da5Sopenharmony_ciOpExtension "SPV_KHR_non_semantic_info"
418fd4e5da5Sopenharmony_ci%ext = OpExtInstImport "NonSemantic.Test"
419fd4e5da5Sopenharmony_ciOpMemoryModel Logical GLSL450
420fd4e5da5Sopenharmony_ciOpEntryPoint GLCompute %main "main"
421fd4e5da5Sopenharmony_ciOpExecutionMode %main LocalSize 1 1 1
422fd4e5da5Sopenharmony_ci%void = OpTypeVoid
423fd4e5da5Sopenharmony_ci%void_fn = OpTypeFunction %void
424fd4e5da5Sopenharmony_ci%main = OpFunction %void None %void_fn
425fd4e5da5Sopenharmony_ci%entry = OpLabel
426fd4e5da5Sopenharmony_ciOpReturn
427fd4e5da5Sopenharmony_ciOpFunctionEnd
428fd4e5da5Sopenharmony_ci%foo = OpFunction %void None %void_fn
429fd4e5da5Sopenharmony_ci%foo_entry = OpLabel
430fd4e5da5Sopenharmony_ci%non_semantic1 = OpExtInst %void %ext 1
431fd4e5da5Sopenharmony_ciOpReturn
432fd4e5da5Sopenharmony_ciOpFunctionEnd
433fd4e5da5Sopenharmony_ci%non_semantic2 = OpExtInst %void %ext 2 %foo
434fd4e5da5Sopenharmony_ci%non_semantic3 = OpExtInst %void %ext 3
435fd4e5da5Sopenharmony_ci%non_semantic4 = OpExtInst %void %ext 4 %non_semantic2
436fd4e5da5Sopenharmony_ci%non_semantic5 = OpExtInst %void %ext 5 %non_semantic4
437fd4e5da5Sopenharmony_ci)";
438fd4e5da5Sopenharmony_ci
439fd4e5da5Sopenharmony_ci  SinglePassRunAndMatch<EliminateDeadFunctionsPass>(text, true);
440fd4e5da5Sopenharmony_ci}
441fd4e5da5Sopenharmony_ci
442fd4e5da5Sopenharmony_ciTEST_F(EliminateDeadFunctionsBasicTest, NonSemanticInfoRemoveDebugPrintf) {
443fd4e5da5Sopenharmony_ci  const std::string text = R"(
444fd4e5da5Sopenharmony_ci; CHECK-NOT: %foo_ = OpFunction %void None % 3
445fd4e5da5Sopenharmony_ci; CHECK-NOT: % 7 = OpLabel
446fd4e5da5Sopenharmony_ci; CHECK-NOT: %c = OpVariable %_ptr_Function_v4float Function
447fd4e5da5Sopenharmony_ci; CHECK-NOT: % 22 = OpAccessChain %_ptr_UniformConstant_13 %samplers %int_0
448fd4e5da5Sopenharmony_ci; CHECK-NOT: % 23 = OpLoad % 13 % 22
449fd4e5da5Sopenharmony_ci; CHECK-NOT: % 27 = OpImageSampleExplicitLod %v4float % 23 % 26 Lod %float_0
450fd4e5da5Sopenharmony_ci; CHECK-NOT: OpStore %c % 27
451fd4e5da5Sopenharmony_ci; CHECK-NOT: % 31 = OpAccessChain %_ptr_Function_float %c %uint_0
452fd4e5da5Sopenharmony_ci; CHECK-NOT: % 32 = OpLoad %float %31
453fd4e5da5Sopenharmony_ci; CHECK-NOT: % 34 = OpExtInst %void %33 1 % 28 % 32
454fd4e5da5Sopenharmony_ciOpCapability RayTracingKHR
455fd4e5da5Sopenharmony_ciOpExtension "SPV_KHR_non_semantic_info"
456fd4e5da5Sopenharmony_ciOpExtension "SPV_KHR_ray_tracing"
457fd4e5da5Sopenharmony_ci%1 = OpExtInstImport "GLSL.std.450"
458fd4e5da5Sopenharmony_ci%33 = OpExtInstImport "NonSemantic.DebugPrintf"
459fd4e5da5Sopenharmony_ciOpMemoryModel Logical GLSL450
460fd4e5da5Sopenharmony_ciOpEntryPoint ClosestHitNV %main "main" %samplers
461fd4e5da5Sopenharmony_ci%28 = OpString "%f"
462fd4e5da5Sopenharmony_ciOpSource GLSL 460
463fd4e5da5Sopenharmony_ciOpSourceExtension "GL_EXT_debug_printf"
464fd4e5da5Sopenharmony_ciOpName %main "main"
465fd4e5da5Sopenharmony_ciOpName %foo_ "foo("
466fd4e5da5Sopenharmony_ciOpName %c "c"
467fd4e5da5Sopenharmony_ciOpName %samplers "samplers"
468fd4e5da5Sopenharmony_ciOpDecorate %samplers DescriptorSet 0
469fd4e5da5Sopenharmony_ciOpDecorate %samplers Binding 0
470fd4e5da5Sopenharmony_ci%void = OpTypeVoid
471fd4e5da5Sopenharmony_ci%3 = OpTypeFunction %void
472fd4e5da5Sopenharmony_ci%float = OpTypeFloat 32
473fd4e5da5Sopenharmony_ci%v4float = OpTypeVector %float 4
474fd4e5da5Sopenharmony_ci%_ptr_Function_v4float = OpTypePointer Function %v4float
475fd4e5da5Sopenharmony_ci%12 = OpTypeImage %float 3D 0 0 0 1 Unknown
476fd4e5da5Sopenharmony_ci%13 = OpTypeSampledImage %12
477fd4e5da5Sopenharmony_ci%uint = OpTypeInt 32 0
478fd4e5da5Sopenharmony_ci%uint_1 = OpConstant %uint 1
479fd4e5da5Sopenharmony_ci%_arr_13_uint_1 = OpTypeArray %13 %uint_1
480fd4e5da5Sopenharmony_ci%_ptr_UniformConstant__arr_13_uint_1 = OpTypePointer UniformConstant %_arr_13_uint_1
481fd4e5da5Sopenharmony_ci%samplers = OpVariable %_ptr_UniformConstant__arr_13_uint_1 UniformConstant
482fd4e5da5Sopenharmony_ci%int = OpTypeInt 32 1
483fd4e5da5Sopenharmony_ci%int_0 = OpConstant %int 0
484fd4e5da5Sopenharmony_ci%_ptr_UniformConstant_13 = OpTypePointer UniformConstant %13
485fd4e5da5Sopenharmony_ci%v3float = OpTypeVector %float 3
486fd4e5da5Sopenharmony_ci%float_0 = OpConstant %float 0
487fd4e5da5Sopenharmony_ci%26 = OpConstantComposite %v3float %float_0 %float_0 %float_0
488fd4e5da5Sopenharmony_ci%uint_0 = OpConstant %uint 0
489fd4e5da5Sopenharmony_ci%_ptr_Function_float = OpTypePointer Function %float
490fd4e5da5Sopenharmony_ci%main = OpFunction %void None %3
491fd4e5da5Sopenharmony_ci%5 = OpLabel
492fd4e5da5Sopenharmony_ci%36 = OpVariable %_ptr_Function_v4float Function
493fd4e5da5Sopenharmony_ci%38 = OpAccessChain %_ptr_UniformConstant_13 %samplers %int_0
494fd4e5da5Sopenharmony_ci%39 = OpLoad %13 %38
495fd4e5da5Sopenharmony_ci%40 = OpImageSampleExplicitLod %v4float %39 %26 Lod %float_0
496fd4e5da5Sopenharmony_ciOpStore %36 %40
497fd4e5da5Sopenharmony_ci%41 = OpAccessChain %_ptr_Function_float %36 %uint_0
498fd4e5da5Sopenharmony_ci%42 = OpLoad %float %41
499fd4e5da5Sopenharmony_ci%43 = OpExtInst %void %33 1 %28 %42
500fd4e5da5Sopenharmony_ciOpReturn
501fd4e5da5Sopenharmony_ciOpFunctionEnd
502fd4e5da5Sopenharmony_ci%foo_ = OpFunction %void None %3
503fd4e5da5Sopenharmony_ci%7 = OpLabel
504fd4e5da5Sopenharmony_ci%c = OpVariable %_ptr_Function_v4float Function
505fd4e5da5Sopenharmony_ci%22 = OpAccessChain %_ptr_UniformConstant_13 %samplers %int_0
506fd4e5da5Sopenharmony_ci%23 = OpLoad %13 %22
507fd4e5da5Sopenharmony_ci%27 = OpImageSampleExplicitLod %v4float %23 %26 Lod %float_0
508fd4e5da5Sopenharmony_ciOpStore %c %27
509fd4e5da5Sopenharmony_ci%31 = OpAccessChain %_ptr_Function_float %c %uint_0
510fd4e5da5Sopenharmony_ci%32 = OpLoad %float %31
511fd4e5da5Sopenharmony_ci%34 = OpExtInst %void %33 1 %28 %32
512fd4e5da5Sopenharmony_ciOpReturn
513fd4e5da5Sopenharmony_ciOpFunctionEnd
514fd4e5da5Sopenharmony_ci)";
515fd4e5da5Sopenharmony_ci
516fd4e5da5Sopenharmony_ci  SetTargetEnv(SPV_ENV_VULKAN_1_2);
517fd4e5da5Sopenharmony_ci  SinglePassRunAndMatch<EliminateDeadFunctionsPass>(text, true);
518fd4e5da5Sopenharmony_ci}
519fd4e5da5Sopenharmony_ci
520fd4e5da5Sopenharmony_ciTEST_F(EliminateDeadFunctionsBasicTest, DependentNonSemanticChain) {
521fd4e5da5Sopenharmony_ci  const std::string text = R"(
522fd4e5da5Sopenharmony_ci; CHECK: OpEntryPoint GLCompute [[main:%\w+]]
523fd4e5da5Sopenharmony_ci; CHECK: [[main]] = OpFunction
524fd4e5da5Sopenharmony_ci; CHECK-NOT: = OpFunction
525fd4e5da5Sopenharmony_ci; CHECK: [[ext1:%\w+]] = OpExtInst %void {{%\w+}} 1 [[main]]
526fd4e5da5Sopenharmony_ci; CHECK: [[ext2:%\w+]] = OpExtInst %void {{%\w+}} 2 [[ext1]]
527fd4e5da5Sopenharmony_ci; CHECK: [[ext3:%\w+]] = OpExtInst %void {{%\w+}} 3 [[ext1]] [[ext2]]
528fd4e5da5Sopenharmony_ciOpCapability Shader
529fd4e5da5Sopenharmony_ciOpExtension "SPV_KHR_non_semantic_info"
530fd4e5da5Sopenharmony_ci%1 = OpExtInstImport "NonSemantic.Test"
531fd4e5da5Sopenharmony_ciOpMemoryModel Logical GLSL450
532fd4e5da5Sopenharmony_ciOpEntryPoint GLCompute %main "main"
533fd4e5da5Sopenharmony_ciOpExecutionMode %main LocalSize 1 1 1
534fd4e5da5Sopenharmony_ci%void = OpTypeVoid
535fd4e5da5Sopenharmony_ci%void_fn = OpTypeFunction %void
536fd4e5da5Sopenharmony_ci%main = OpFunction %void None %void_fn
537fd4e5da5Sopenharmony_ci%main_entry = OpLabel
538fd4e5da5Sopenharmony_ciOpReturn
539fd4e5da5Sopenharmony_ciOpFunctionEnd
540fd4e5da5Sopenharmony_ci%dead = OpFunction %void None %void_fn
541fd4e5da5Sopenharmony_ci%dead_entry = OpLabel
542fd4e5da5Sopenharmony_ciOpReturn
543fd4e5da5Sopenharmony_ciOpFunctionEnd
544fd4e5da5Sopenharmony_ci%2 = OpExtInst %void %1 1 %main
545fd4e5da5Sopenharmony_ci%3 = OpExtInst %void %1 2 %2
546fd4e5da5Sopenharmony_ci%4 = OpExtInst %void %1 3 %2 %3
547fd4e5da5Sopenharmony_ci)";
548fd4e5da5Sopenharmony_ci
549fd4e5da5Sopenharmony_ci  SetTargetEnv(SPV_ENV_VULKAN_1_0);
550fd4e5da5Sopenharmony_ci  SinglePassRunAndMatch<EliminateDeadFunctionsPass>(text, true);
551fd4e5da5Sopenharmony_ci}
552fd4e5da5Sopenharmony_ci
553fd4e5da5Sopenharmony_ci}  // namespace
554fd4e5da5Sopenharmony_ci}  // namespace opt
555fd4e5da5Sopenharmony_ci}  // namespace spvtools
556