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 "gmock/gmock.h"
18fd4e5da5Sopenharmony_ci#include "test/opt/assembly_builder.h"
19fd4e5da5Sopenharmony_ci#include "test/opt/pass_fixture.h"
20fd4e5da5Sopenharmony_ci#include "test/opt/pass_utils.h"
21fd4e5da5Sopenharmony_ci
22fd4e5da5Sopenharmony_cinamespace spvtools {
23fd4e5da5Sopenharmony_cinamespace opt {
24fd4e5da5Sopenharmony_cinamespace {
25fd4e5da5Sopenharmony_ci
26fd4e5da5Sopenharmony_ciusing ::testing::HasSubstr;
27fd4e5da5Sopenharmony_ciusing ::testing::MatchesRegex;
28fd4e5da5Sopenharmony_ciusing RedundancyEliminationTest = PassTest<::testing::Test>;
29fd4e5da5Sopenharmony_ci
30fd4e5da5Sopenharmony_ci// Test that it can get a simple case of local redundancy elimination.
31fd4e5da5Sopenharmony_ci// The rest of the test check for extra functionality.
32fd4e5da5Sopenharmony_ciTEST_F(RedundancyEliminationTest, RemoveRedundantLocalAdd) {
33fd4e5da5Sopenharmony_ci  const std::string text = R"(
34fd4e5da5Sopenharmony_ci               OpCapability Shader
35fd4e5da5Sopenharmony_ci          %1 = OpExtInstImport "GLSL.std.450"
36fd4e5da5Sopenharmony_ci               OpMemoryModel Logical GLSL450
37fd4e5da5Sopenharmony_ci               OpEntryPoint Fragment %2 "main"
38fd4e5da5Sopenharmony_ci               OpExecutionMode %2 OriginUpperLeft
39fd4e5da5Sopenharmony_ci               OpSource GLSL 430
40fd4e5da5Sopenharmony_ci          %3 = OpTypeVoid
41fd4e5da5Sopenharmony_ci          %4 = OpTypeFunction %3
42fd4e5da5Sopenharmony_ci          %5 = OpTypeFloat 32
43fd4e5da5Sopenharmony_ci          %6 = OpTypePointer Function %5
44fd4e5da5Sopenharmony_ci          %2 = OpFunction %3 None %4
45fd4e5da5Sopenharmony_ci          %7 = OpLabel
46fd4e5da5Sopenharmony_ci          %8 = OpVariable %6 Function
47fd4e5da5Sopenharmony_ci          %9 = OpLoad %5 %8
48fd4e5da5Sopenharmony_ci         %10 = OpFAdd %5 %9 %9
49fd4e5da5Sopenharmony_ci; CHECK: OpFAdd
50fd4e5da5Sopenharmony_ci; CHECK-NOT: OpFAdd
51fd4e5da5Sopenharmony_ci         %11 = OpFAdd %5 %9 %9
52fd4e5da5Sopenharmony_ci               OpReturn
53fd4e5da5Sopenharmony_ci               OpFunctionEnd
54fd4e5da5Sopenharmony_ci  )";
55fd4e5da5Sopenharmony_ci  SinglePassRunAndMatch<RedundancyEliminationPass>(text, false);
56fd4e5da5Sopenharmony_ci}
57fd4e5da5Sopenharmony_ci
58fd4e5da5Sopenharmony_ci// Remove a redundant add across basic blocks.
59fd4e5da5Sopenharmony_ciTEST_F(RedundancyEliminationTest, RemoveRedundantAdd) {
60fd4e5da5Sopenharmony_ci  const std::string text = R"(
61fd4e5da5Sopenharmony_ci               OpCapability Shader
62fd4e5da5Sopenharmony_ci          %1 = OpExtInstImport "GLSL.std.450"
63fd4e5da5Sopenharmony_ci               OpMemoryModel Logical GLSL450
64fd4e5da5Sopenharmony_ci               OpEntryPoint Fragment %2 "main"
65fd4e5da5Sopenharmony_ci               OpExecutionMode %2 OriginUpperLeft
66fd4e5da5Sopenharmony_ci               OpSource GLSL 430
67fd4e5da5Sopenharmony_ci          %3 = OpTypeVoid
68fd4e5da5Sopenharmony_ci          %4 = OpTypeFunction %3
69fd4e5da5Sopenharmony_ci          %5 = OpTypeFloat 32
70fd4e5da5Sopenharmony_ci          %6 = OpTypePointer Function %5
71fd4e5da5Sopenharmony_ci          %2 = OpFunction %3 None %4
72fd4e5da5Sopenharmony_ci          %7 = OpLabel
73fd4e5da5Sopenharmony_ci          %8 = OpVariable %6 Function
74fd4e5da5Sopenharmony_ci          %9 = OpLoad %5 %8
75fd4e5da5Sopenharmony_ci         %10 = OpFAdd %5 %9 %9
76fd4e5da5Sopenharmony_ci               OpBranch %11
77fd4e5da5Sopenharmony_ci         %11 = OpLabel
78fd4e5da5Sopenharmony_ci; CHECK: OpFAdd
79fd4e5da5Sopenharmony_ci; CHECK-NOT: OpFAdd
80fd4e5da5Sopenharmony_ci         %12 = OpFAdd %5 %9 %9
81fd4e5da5Sopenharmony_ci               OpReturn
82fd4e5da5Sopenharmony_ci               OpFunctionEnd
83fd4e5da5Sopenharmony_ci  )";
84fd4e5da5Sopenharmony_ci  SinglePassRunAndMatch<RedundancyEliminationPass>(text, false);
85fd4e5da5Sopenharmony_ci}
86fd4e5da5Sopenharmony_ci
87fd4e5da5Sopenharmony_ci// Remove a redundant add going through a multiple basic blocks.
88fd4e5da5Sopenharmony_ciTEST_F(RedundancyEliminationTest, RemoveRedundantAddDiamond) {
89fd4e5da5Sopenharmony_ci  const std::string text = R"(
90fd4e5da5Sopenharmony_ci               OpCapability Shader
91fd4e5da5Sopenharmony_ci          %1 = OpExtInstImport "GLSL.std.450"
92fd4e5da5Sopenharmony_ci               OpMemoryModel Logical GLSL450
93fd4e5da5Sopenharmony_ci               OpEntryPoint Fragment %2 "main"
94fd4e5da5Sopenharmony_ci               OpExecutionMode %2 OriginUpperLeft
95fd4e5da5Sopenharmony_ci               OpSource GLSL 430
96fd4e5da5Sopenharmony_ci          %3 = OpTypeVoid
97fd4e5da5Sopenharmony_ci          %4 = OpTypeFunction %3
98fd4e5da5Sopenharmony_ci          %5 = OpTypeFloat 32
99fd4e5da5Sopenharmony_ci          %6 = OpTypePointer Function %5
100fd4e5da5Sopenharmony_ci          %7 = OpTypeBool
101fd4e5da5Sopenharmony_ci          %8 = OpConstantTrue %7
102fd4e5da5Sopenharmony_ci          %2 = OpFunction %3 None %4
103fd4e5da5Sopenharmony_ci          %9 = OpLabel
104fd4e5da5Sopenharmony_ci         %10 = OpVariable %6 Function
105fd4e5da5Sopenharmony_ci         %11 = OpLoad %5 %10
106fd4e5da5Sopenharmony_ci         %12 = OpFAdd %5 %11 %11
107fd4e5da5Sopenharmony_ci; CHECK: OpFAdd
108fd4e5da5Sopenharmony_ci; CHECK-NOT: OpFAdd
109fd4e5da5Sopenharmony_ci               OpBranchConditional %8 %13 %14
110fd4e5da5Sopenharmony_ci         %13 = OpLabel
111fd4e5da5Sopenharmony_ci               OpBranch %15
112fd4e5da5Sopenharmony_ci         %14 = OpLabel
113fd4e5da5Sopenharmony_ci               OpBranch %15
114fd4e5da5Sopenharmony_ci         %15 = OpLabel
115fd4e5da5Sopenharmony_ci         %16 = OpFAdd %5 %11 %11
116fd4e5da5Sopenharmony_ci               OpReturn
117fd4e5da5Sopenharmony_ci               OpFunctionEnd
118fd4e5da5Sopenharmony_ci
119fd4e5da5Sopenharmony_ci  )";
120fd4e5da5Sopenharmony_ci  SinglePassRunAndMatch<RedundancyEliminationPass>(text, false);
121fd4e5da5Sopenharmony_ci}
122fd4e5da5Sopenharmony_ci
123fd4e5da5Sopenharmony_ci// Remove a redundant add in a side node.
124fd4e5da5Sopenharmony_ciTEST_F(RedundancyEliminationTest, RemoveRedundantAddInSideNode) {
125fd4e5da5Sopenharmony_ci  const std::string text = R"(
126fd4e5da5Sopenharmony_ci               OpCapability Shader
127fd4e5da5Sopenharmony_ci          %1 = OpExtInstImport "GLSL.std.450"
128fd4e5da5Sopenharmony_ci               OpMemoryModel Logical GLSL450
129fd4e5da5Sopenharmony_ci               OpEntryPoint Fragment %2 "main"
130fd4e5da5Sopenharmony_ci               OpExecutionMode %2 OriginUpperLeft
131fd4e5da5Sopenharmony_ci               OpSource GLSL 430
132fd4e5da5Sopenharmony_ci          %3 = OpTypeVoid
133fd4e5da5Sopenharmony_ci          %4 = OpTypeFunction %3
134fd4e5da5Sopenharmony_ci          %5 = OpTypeFloat 32
135fd4e5da5Sopenharmony_ci          %6 = OpTypePointer Function %5
136fd4e5da5Sopenharmony_ci          %7 = OpTypeBool
137fd4e5da5Sopenharmony_ci          %8 = OpConstantTrue %7
138fd4e5da5Sopenharmony_ci          %2 = OpFunction %3 None %4
139fd4e5da5Sopenharmony_ci          %9 = OpLabel
140fd4e5da5Sopenharmony_ci         %10 = OpVariable %6 Function
141fd4e5da5Sopenharmony_ci         %11 = OpLoad %5 %10
142fd4e5da5Sopenharmony_ci         %12 = OpFAdd %5 %11 %11
143fd4e5da5Sopenharmony_ci; CHECK: OpFAdd
144fd4e5da5Sopenharmony_ci; CHECK-NOT: OpFAdd
145fd4e5da5Sopenharmony_ci               OpBranchConditional %8 %13 %14
146fd4e5da5Sopenharmony_ci         %13 = OpLabel
147fd4e5da5Sopenharmony_ci               OpBranch %15
148fd4e5da5Sopenharmony_ci         %14 = OpLabel
149fd4e5da5Sopenharmony_ci         %16 = OpFAdd %5 %11 %11
150fd4e5da5Sopenharmony_ci               OpBranch %15
151fd4e5da5Sopenharmony_ci         %15 = OpLabel
152fd4e5da5Sopenharmony_ci               OpReturn
153fd4e5da5Sopenharmony_ci               OpFunctionEnd
154fd4e5da5Sopenharmony_ci
155fd4e5da5Sopenharmony_ci  )";
156fd4e5da5Sopenharmony_ci  SinglePassRunAndMatch<RedundancyEliminationPass>(text, false);
157fd4e5da5Sopenharmony_ci}
158fd4e5da5Sopenharmony_ci
159fd4e5da5Sopenharmony_ci// Remove a redundant add whose value is in the result of a phi node.
160fd4e5da5Sopenharmony_ciTEST_F(RedundancyEliminationTest, RemoveRedundantAddWithPhi) {
161fd4e5da5Sopenharmony_ci  const std::string text = R"(
162fd4e5da5Sopenharmony_ci               OpCapability Shader
163fd4e5da5Sopenharmony_ci          %1 = OpExtInstImport "GLSL.std.450"
164fd4e5da5Sopenharmony_ci               OpMemoryModel Logical GLSL450
165fd4e5da5Sopenharmony_ci               OpEntryPoint Fragment %2 "main"
166fd4e5da5Sopenharmony_ci               OpExecutionMode %2 OriginUpperLeft
167fd4e5da5Sopenharmony_ci               OpSource GLSL 430
168fd4e5da5Sopenharmony_ci          %3 = OpTypeVoid
169fd4e5da5Sopenharmony_ci          %4 = OpTypeFunction %3
170fd4e5da5Sopenharmony_ci          %5 = OpTypeFloat 32
171fd4e5da5Sopenharmony_ci          %6 = OpTypePointer Function %5
172fd4e5da5Sopenharmony_ci          %7 = OpTypeBool
173fd4e5da5Sopenharmony_ci          %8 = OpConstantTrue %7
174fd4e5da5Sopenharmony_ci          %2 = OpFunction %3 None %4
175fd4e5da5Sopenharmony_ci          %9 = OpLabel
176fd4e5da5Sopenharmony_ci         %10 = OpVariable %6 Function
177fd4e5da5Sopenharmony_ci         %11 = OpLoad %5 %10
178fd4e5da5Sopenharmony_ci               OpBranchConditional %8 %13 %14
179fd4e5da5Sopenharmony_ci         %13 = OpLabel
180fd4e5da5Sopenharmony_ci         %add1 = OpFAdd %5 %11 %11
181fd4e5da5Sopenharmony_ci; CHECK: OpFAdd
182fd4e5da5Sopenharmony_ci               OpBranch %15
183fd4e5da5Sopenharmony_ci         %14 = OpLabel
184fd4e5da5Sopenharmony_ci         %add2 = OpFAdd %5 %11 %11
185fd4e5da5Sopenharmony_ci; CHECK: OpFAdd
186fd4e5da5Sopenharmony_ci               OpBranch %15
187fd4e5da5Sopenharmony_ci         %15 = OpLabel
188fd4e5da5Sopenharmony_ci; CHECK: OpPhi
189fd4e5da5Sopenharmony_ci          %phi = OpPhi %5 %add1 %13 %add2 %14
190fd4e5da5Sopenharmony_ci; CHECK-NOT: OpFAdd
191fd4e5da5Sopenharmony_ci         %16 = OpFAdd %5 %11 %11
192fd4e5da5Sopenharmony_ci               OpReturn
193fd4e5da5Sopenharmony_ci               OpFunctionEnd
194fd4e5da5Sopenharmony_ci
195fd4e5da5Sopenharmony_ci  )";
196fd4e5da5Sopenharmony_ci  SinglePassRunAndMatch<RedundancyEliminationPass>(text, false);
197fd4e5da5Sopenharmony_ci}
198fd4e5da5Sopenharmony_ci
199fd4e5da5Sopenharmony_ci// Keep the add because it is redundant on some paths, but not all paths.
200fd4e5da5Sopenharmony_ciTEST_F(RedundancyEliminationTest, KeepPartiallyRedundantAdd) {
201fd4e5da5Sopenharmony_ci  const std::string text = R"(
202fd4e5da5Sopenharmony_ci               OpCapability Shader
203fd4e5da5Sopenharmony_ci          %1 = OpExtInstImport "GLSL.std.450"
204fd4e5da5Sopenharmony_ci               OpMemoryModel Logical GLSL450
205fd4e5da5Sopenharmony_ci               OpEntryPoint Fragment %2 "main"
206fd4e5da5Sopenharmony_ci               OpExecutionMode %2 OriginUpperLeft
207fd4e5da5Sopenharmony_ci               OpSource GLSL 430
208fd4e5da5Sopenharmony_ci          %3 = OpTypeVoid
209fd4e5da5Sopenharmony_ci          %4 = OpTypeFunction %3
210fd4e5da5Sopenharmony_ci          %5 = OpTypeFloat 32
211fd4e5da5Sopenharmony_ci          %6 = OpTypePointer Function %5
212fd4e5da5Sopenharmony_ci          %7 = OpTypeBool
213fd4e5da5Sopenharmony_ci          %8 = OpConstantTrue %7
214fd4e5da5Sopenharmony_ci          %2 = OpFunction %3 None %4
215fd4e5da5Sopenharmony_ci          %9 = OpLabel
216fd4e5da5Sopenharmony_ci         %10 = OpVariable %6 Function
217fd4e5da5Sopenharmony_ci         %11 = OpLoad %5 %10
218fd4e5da5Sopenharmony_ci               OpBranchConditional %8 %13 %14
219fd4e5da5Sopenharmony_ci         %13 = OpLabel
220fd4e5da5Sopenharmony_ci        %add = OpFAdd %5 %11 %11
221fd4e5da5Sopenharmony_ci               OpBranch %15
222fd4e5da5Sopenharmony_ci         %14 = OpLabel
223fd4e5da5Sopenharmony_ci               OpBranch %15
224fd4e5da5Sopenharmony_ci         %15 = OpLabel
225fd4e5da5Sopenharmony_ci         %16 = OpFAdd %5 %11 %11
226fd4e5da5Sopenharmony_ci               OpReturn
227fd4e5da5Sopenharmony_ci               OpFunctionEnd
228fd4e5da5Sopenharmony_ci
229fd4e5da5Sopenharmony_ci  )";
230fd4e5da5Sopenharmony_ci  auto result = SinglePassRunAndDisassemble<RedundancyEliminationPass>(
231fd4e5da5Sopenharmony_ci      text, /* skip_nop = */ true, /* do_validation = */ false);
232fd4e5da5Sopenharmony_ci  EXPECT_EQ(Pass::Status::SuccessWithoutChange, std::get<1>(result));
233fd4e5da5Sopenharmony_ci}
234fd4e5da5Sopenharmony_ci
235fd4e5da5Sopenharmony_ci// Keep the add.  Even if it is redundant on all paths, there is no single id
236fd4e5da5Sopenharmony_ci// whose definition dominates the add and contains the same value.
237fd4e5da5Sopenharmony_ciTEST_F(RedundancyEliminationTest, KeepRedundantAddWithoutPhi) {
238fd4e5da5Sopenharmony_ci  const std::string text = R"(
239fd4e5da5Sopenharmony_ci               OpCapability Shader
240fd4e5da5Sopenharmony_ci          %1 = OpExtInstImport "GLSL.std.450"
241fd4e5da5Sopenharmony_ci               OpMemoryModel Logical GLSL450
242fd4e5da5Sopenharmony_ci               OpEntryPoint Fragment %2 "main"
243fd4e5da5Sopenharmony_ci               OpExecutionMode %2 OriginUpperLeft
244fd4e5da5Sopenharmony_ci               OpSource GLSL 430
245fd4e5da5Sopenharmony_ci          %3 = OpTypeVoid
246fd4e5da5Sopenharmony_ci          %4 = OpTypeFunction %3
247fd4e5da5Sopenharmony_ci          %5 = OpTypeFloat 32
248fd4e5da5Sopenharmony_ci          %6 = OpTypePointer Function %5
249fd4e5da5Sopenharmony_ci          %7 = OpTypeBool
250fd4e5da5Sopenharmony_ci          %8 = OpConstantTrue %7
251fd4e5da5Sopenharmony_ci          %2 = OpFunction %3 None %4
252fd4e5da5Sopenharmony_ci          %9 = OpLabel
253fd4e5da5Sopenharmony_ci         %10 = OpVariable %6 Function
254fd4e5da5Sopenharmony_ci         %11 = OpLoad %5 %10
255fd4e5da5Sopenharmony_ci               OpBranchConditional %8 %13 %14
256fd4e5da5Sopenharmony_ci         %13 = OpLabel
257fd4e5da5Sopenharmony_ci         %add1 = OpFAdd %5 %11 %11
258fd4e5da5Sopenharmony_ci               OpBranch %15
259fd4e5da5Sopenharmony_ci         %14 = OpLabel
260fd4e5da5Sopenharmony_ci         %add2 = OpFAdd %5 %11 %11
261fd4e5da5Sopenharmony_ci               OpBranch %15
262fd4e5da5Sopenharmony_ci         %15 = OpLabel
263fd4e5da5Sopenharmony_ci         %16 = OpFAdd %5 %11 %11
264fd4e5da5Sopenharmony_ci               OpReturn
265fd4e5da5Sopenharmony_ci               OpFunctionEnd
266fd4e5da5Sopenharmony_ci
267fd4e5da5Sopenharmony_ci  )";
268fd4e5da5Sopenharmony_ci  auto result = SinglePassRunAndDisassemble<RedundancyEliminationPass>(
269fd4e5da5Sopenharmony_ci      text, /* skip_nop = */ true, /* do_validation = */ false);
270fd4e5da5Sopenharmony_ci  EXPECT_EQ(Pass::Status::SuccessWithoutChange, std::get<1>(result));
271fd4e5da5Sopenharmony_ci}
272fd4e5da5Sopenharmony_ci
273fd4e5da5Sopenharmony_ci// Test that it can get a simple case of local redundancy elimination
274fd4e5da5Sopenharmony_ci// when it has OpenCL.DebugInfo.100 instructions.
275fd4e5da5Sopenharmony_ciTEST_F(RedundancyEliminationTest, OpenCLDebugInfo100) {
276fd4e5da5Sopenharmony_ci  // When three redundant DebugValues exist, only one DebugValue must remain.
277fd4e5da5Sopenharmony_ci  const std::string text = R"(
278fd4e5da5Sopenharmony_ci               OpCapability Shader
279fd4e5da5Sopenharmony_ci          %1 = OpExtInstImport "OpenCL.DebugInfo.100"
280fd4e5da5Sopenharmony_ci          %2 = OpExtInstImport "GLSL.std.450"
281fd4e5da5Sopenharmony_ci               OpMemoryModel Logical GLSL450
282fd4e5da5Sopenharmony_ci               OpEntryPoint Fragment %3 "main"
283fd4e5da5Sopenharmony_ci               OpExecutionMode %3 OriginUpperLeft
284fd4e5da5Sopenharmony_ci               OpSource GLSL 430
285fd4e5da5Sopenharmony_ci          %4 = OpString "ps.hlsl"
286fd4e5da5Sopenharmony_ci          %5 = OpString "float"
287fd4e5da5Sopenharmony_ci          %6 = OpString "s0"
288fd4e5da5Sopenharmony_ci          %7 = OpString "main"
289fd4e5da5Sopenharmony_ci       %void = OpTypeVoid
290fd4e5da5Sopenharmony_ci          %9 = OpTypeFunction %void
291fd4e5da5Sopenharmony_ci      %float = OpTypeFloat 32
292fd4e5da5Sopenharmony_ci       %uint = OpTypeInt 32 0
293fd4e5da5Sopenharmony_ci     %uint_0 = OpConstant %uint 0
294fd4e5da5Sopenharmony_ci    %uint_32 = OpConstant %uint 32
295fd4e5da5Sopenharmony_ci%_ptr_Function_float = OpTypePointer Function %float
296fd4e5da5Sopenharmony_ci         %15 = OpExtInst %void %1 DebugExpression
297fd4e5da5Sopenharmony_ci         %16 = OpExtInst %void %1 DebugSource %4
298fd4e5da5Sopenharmony_ci         %17 = OpExtInst %void %1 DebugCompilationUnit 1 4 %16 HLSL
299fd4e5da5Sopenharmony_ci         %18 = OpExtInst %void %1 DebugTypeBasic %5 %uint_32 Float
300fd4e5da5Sopenharmony_ci         %19 = OpExtInst %void %1 DebugTypeVector %18 4
301fd4e5da5Sopenharmony_ci         %20 = OpExtInst %void %1 DebugTypeFunction FlagIsProtected|FlagIsPrivate %19
302fd4e5da5Sopenharmony_ci         %21 = OpExtInst %void %1 DebugFunction %7 %20 %16 4 1 %17 %7 FlagIsProtected|FlagIsPrivate 4 %3
303fd4e5da5Sopenharmony_ci; CHECK:     [[dbg_local_var:%\w+]] = OpExtInst %void {{%\w+}} DebugLocalVariable
304fd4e5da5Sopenharmony_ci         %22 = OpExtInst %void %1 DebugLocalVariable %6 %19 %16 0 0 %21 FlagIsLocal
305fd4e5da5Sopenharmony_ci         %14 = OpExtInst %void %1 DebugLocalVariable %6 %19 %16 0 0 %21 FlagIsLocal
306fd4e5da5Sopenharmony_ci          %3 = OpFunction %void None %9
307fd4e5da5Sopenharmony_ci         %23 = OpLabel
308fd4e5da5Sopenharmony_ci         %24 = OpExtInst %void %1 DebugScope %21
309fd4e5da5Sopenharmony_ci         %25 = OpVariable %_ptr_Function_float Function
310fd4e5da5Sopenharmony_ci         %26 = OpLoad %float %25
311fd4e5da5Sopenharmony_ci               OpLine %4 0 0
312fd4e5da5Sopenharmony_ci; Two `OpFAdd %float %26 %26` are the same. One must be removed.
313fd4e5da5Sopenharmony_ci; After removing one `OpFAdd %float %26 %26`, two DebugValues are the same.
314fd4e5da5Sopenharmony_ci; One must be removed.
315fd4e5da5Sopenharmony_ci;
316fd4e5da5Sopenharmony_ci; CHECK:      OpLine {{%\w+}} 0 0
317fd4e5da5Sopenharmony_ci; CHECK-NEXT: [[add:%\w+]] = OpFAdd %float [[value:%\w+]]
318fd4e5da5Sopenharmony_ci; CHECK-NEXT: DebugValue [[dbg_local_var]] [[add]]
319fd4e5da5Sopenharmony_ci; CHECK-NEXT: OpLine {{%\w+}} 1 0
320fd4e5da5Sopenharmony_ci; CHECK-NEXT: OpFAdd %float [[add]] [[value]]
321fd4e5da5Sopenharmony_ci; CHECK-NEXT: OpReturn
322fd4e5da5Sopenharmony_ci         %27 = OpFAdd %float %26 %26
323fd4e5da5Sopenharmony_ci         %28 = OpExtInst %void %1 DebugValue %22 %27 %15 %uint_0
324fd4e5da5Sopenharmony_ci               OpLine %4 1 0
325fd4e5da5Sopenharmony_ci         %29 = OpFAdd %float %26 %26
326fd4e5da5Sopenharmony_ci         %30 = OpExtInst %void %1 DebugValue %14 %29 %15 %uint_0
327fd4e5da5Sopenharmony_ci         %31 = OpExtInst %void %1 DebugValue %22 %29 %15 %uint_0
328fd4e5da5Sopenharmony_ci         %32 = OpFAdd %float %29 %26
329fd4e5da5Sopenharmony_ci         %33 = OpFAdd %float %27 %26
330fd4e5da5Sopenharmony_ci               OpReturn
331fd4e5da5Sopenharmony_ci               OpFunctionEnd
332fd4e5da5Sopenharmony_ci  )";
333fd4e5da5Sopenharmony_ci  SinglePassRunAndMatch<RedundancyEliminationPass>(text, false);
334fd4e5da5Sopenharmony_ci}
335fd4e5da5Sopenharmony_ci
336fd4e5da5Sopenharmony_ciTEST_F(RedundancyEliminationTest, FunctionDeclaration) {
337fd4e5da5Sopenharmony_ci  // Make sure the pass works with a function declaration that is called.
338fd4e5da5Sopenharmony_ci  const std::string text = R"(OpCapability Addresses
339fd4e5da5Sopenharmony_ciOpCapability Linkage
340fd4e5da5Sopenharmony_ciOpCapability Kernel
341fd4e5da5Sopenharmony_ciOpCapability Int8
342fd4e5da5Sopenharmony_ci%1 = OpExtInstImport "OpenCL.std"
343fd4e5da5Sopenharmony_ciOpMemoryModel Physical64 OpenCL
344fd4e5da5Sopenharmony_ciOpEntryPoint Kernel %2 "_Z23julia__1166_kernel_77094Bool"
345fd4e5da5Sopenharmony_ciOpExecutionMode %2 ContractionOff
346fd4e5da5Sopenharmony_ciOpSource Unknown 0
347fd4e5da5Sopenharmony_ciOpDecorate %3 LinkageAttributes "julia_error_7712" Import
348fd4e5da5Sopenharmony_ci%void = OpTypeVoid
349fd4e5da5Sopenharmony_ci%5 = OpTypeFunction %void
350fd4e5da5Sopenharmony_ci%3 = OpFunction %void None %5
351fd4e5da5Sopenharmony_ciOpFunctionEnd
352fd4e5da5Sopenharmony_ci%2 = OpFunction %void None %5
353fd4e5da5Sopenharmony_ci%6 = OpLabel
354fd4e5da5Sopenharmony_ci%7 = OpFunctionCall %void %3
355fd4e5da5Sopenharmony_ciOpReturn
356fd4e5da5Sopenharmony_ciOpFunctionEnd
357fd4e5da5Sopenharmony_ci)";
358fd4e5da5Sopenharmony_ci
359fd4e5da5Sopenharmony_ci  SinglePassRunAndCheck<RedundancyEliminationPass>(text, text, false);
360fd4e5da5Sopenharmony_ci}
361fd4e5da5Sopenharmony_ci
362fd4e5da5Sopenharmony_ci}  // namespace
363fd4e5da5Sopenharmony_ci}  // namespace opt
364fd4e5da5Sopenharmony_ci}  // namespace spvtools