1fd4e5da5Sopenharmony_ci// Copyright (c) 2019 Google LLC
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 "source/reduce/merge_blocks_reduction_opportunity_finder.h"
16fd4e5da5Sopenharmony_ci
17fd4e5da5Sopenharmony_ci#include "source/opt/build_module.h"
18fd4e5da5Sopenharmony_ci#include "source/reduce/reduction_opportunity.h"
19fd4e5da5Sopenharmony_ci#include "test/reduce/reduce_test_util.h"
20fd4e5da5Sopenharmony_ci
21fd4e5da5Sopenharmony_cinamespace spvtools {
22fd4e5da5Sopenharmony_cinamespace reduce {
23fd4e5da5Sopenharmony_cinamespace {
24fd4e5da5Sopenharmony_ci
25fd4e5da5Sopenharmony_ciTEST(MergeBlocksReductionPassTest, BasicCheck) {
26fd4e5da5Sopenharmony_ci  std::string shader = R"(
27fd4e5da5Sopenharmony_ci               OpCapability Shader
28fd4e5da5Sopenharmony_ci          %1 = OpExtInstImport "GLSL.std.450"
29fd4e5da5Sopenharmony_ci               OpMemoryModel Logical GLSL450
30fd4e5da5Sopenharmony_ci               OpEntryPoint Fragment %4 "main"
31fd4e5da5Sopenharmony_ci               OpExecutionMode %4 OriginUpperLeft
32fd4e5da5Sopenharmony_ci               OpSource ESSL 310
33fd4e5da5Sopenharmony_ci               OpName %4 "main"
34fd4e5da5Sopenharmony_ci               OpName %8 "x"
35fd4e5da5Sopenharmony_ci          %2 = OpTypeVoid
36fd4e5da5Sopenharmony_ci          %3 = OpTypeFunction %2
37fd4e5da5Sopenharmony_ci          %6 = OpTypeInt 32 1
38fd4e5da5Sopenharmony_ci          %7 = OpTypePointer Function %6
39fd4e5da5Sopenharmony_ci          %9 = OpConstant %6 1
40fd4e5da5Sopenharmony_ci         %10 = OpConstant %6 2
41fd4e5da5Sopenharmony_ci         %11 = OpConstant %6 3
42fd4e5da5Sopenharmony_ci         %12 = OpConstant %6 4
43fd4e5da5Sopenharmony_ci          %4 = OpFunction %2 None %3
44fd4e5da5Sopenharmony_ci          %5 = OpLabel
45fd4e5da5Sopenharmony_ci          %8 = OpVariable %7 Function
46fd4e5da5Sopenharmony_ci               OpBranch %13
47fd4e5da5Sopenharmony_ci         %13 = OpLabel
48fd4e5da5Sopenharmony_ci               OpStore %8 %9
49fd4e5da5Sopenharmony_ci               OpBranch %14
50fd4e5da5Sopenharmony_ci         %14 = OpLabel
51fd4e5da5Sopenharmony_ci               OpStore %8 %10
52fd4e5da5Sopenharmony_ci               OpBranch %15
53fd4e5da5Sopenharmony_ci         %15 = OpLabel
54fd4e5da5Sopenharmony_ci               OpStore %8 %11
55fd4e5da5Sopenharmony_ci               OpBranch %16
56fd4e5da5Sopenharmony_ci         %16 = OpLabel
57fd4e5da5Sopenharmony_ci               OpStore %8 %12
58fd4e5da5Sopenharmony_ci               OpBranch %17
59fd4e5da5Sopenharmony_ci         %17 = OpLabel
60fd4e5da5Sopenharmony_ci               OpReturn
61fd4e5da5Sopenharmony_ci               OpFunctionEnd
62fd4e5da5Sopenharmony_ci  )";
63fd4e5da5Sopenharmony_ci  const auto env = SPV_ENV_UNIVERSAL_1_3;
64fd4e5da5Sopenharmony_ci  const auto consumer = nullptr;
65fd4e5da5Sopenharmony_ci  const auto context =
66fd4e5da5Sopenharmony_ci      BuildModule(env, consumer, shader, kReduceAssembleOption);
67fd4e5da5Sopenharmony_ci  const auto ops =
68fd4e5da5Sopenharmony_ci      MergeBlocksReductionOpportunityFinder().GetAvailableOpportunities(
69fd4e5da5Sopenharmony_ci          context.get(), 0);
70fd4e5da5Sopenharmony_ci  ASSERT_EQ(5, ops.size());
71fd4e5da5Sopenharmony_ci
72fd4e5da5Sopenharmony_ci  // Try order 3, 0, 2, 4, 1
73fd4e5da5Sopenharmony_ci
74fd4e5da5Sopenharmony_ci  ASSERT_TRUE(ops[3]->PreconditionHolds());
75fd4e5da5Sopenharmony_ci  ops[3]->TryToApply();
76fd4e5da5Sopenharmony_ci
77fd4e5da5Sopenharmony_ci  std::string after_op_3 = R"(
78fd4e5da5Sopenharmony_ci               OpCapability Shader
79fd4e5da5Sopenharmony_ci          %1 = OpExtInstImport "GLSL.std.450"
80fd4e5da5Sopenharmony_ci               OpMemoryModel Logical GLSL450
81fd4e5da5Sopenharmony_ci               OpEntryPoint Fragment %4 "main"
82fd4e5da5Sopenharmony_ci               OpExecutionMode %4 OriginUpperLeft
83fd4e5da5Sopenharmony_ci               OpSource ESSL 310
84fd4e5da5Sopenharmony_ci               OpName %4 "main"
85fd4e5da5Sopenharmony_ci               OpName %8 "x"
86fd4e5da5Sopenharmony_ci          %2 = OpTypeVoid
87fd4e5da5Sopenharmony_ci          %3 = OpTypeFunction %2
88fd4e5da5Sopenharmony_ci          %6 = OpTypeInt 32 1
89fd4e5da5Sopenharmony_ci          %7 = OpTypePointer Function %6
90fd4e5da5Sopenharmony_ci          %9 = OpConstant %6 1
91fd4e5da5Sopenharmony_ci         %10 = OpConstant %6 2
92fd4e5da5Sopenharmony_ci         %11 = OpConstant %6 3
93fd4e5da5Sopenharmony_ci         %12 = OpConstant %6 4
94fd4e5da5Sopenharmony_ci          %4 = OpFunction %2 None %3
95fd4e5da5Sopenharmony_ci          %5 = OpLabel
96fd4e5da5Sopenharmony_ci          %8 = OpVariable %7 Function
97fd4e5da5Sopenharmony_ci               OpBranch %13
98fd4e5da5Sopenharmony_ci         %13 = OpLabel
99fd4e5da5Sopenharmony_ci               OpStore %8 %9
100fd4e5da5Sopenharmony_ci               OpBranch %14
101fd4e5da5Sopenharmony_ci         %14 = OpLabel
102fd4e5da5Sopenharmony_ci               OpStore %8 %10
103fd4e5da5Sopenharmony_ci               OpBranch %15
104fd4e5da5Sopenharmony_ci         %15 = OpLabel
105fd4e5da5Sopenharmony_ci               OpStore %8 %11
106fd4e5da5Sopenharmony_ci               OpStore %8 %12
107fd4e5da5Sopenharmony_ci               OpBranch %17
108fd4e5da5Sopenharmony_ci         %17 = OpLabel
109fd4e5da5Sopenharmony_ci               OpReturn
110fd4e5da5Sopenharmony_ci               OpFunctionEnd
111fd4e5da5Sopenharmony_ci  )";
112fd4e5da5Sopenharmony_ci
113fd4e5da5Sopenharmony_ci  CheckEqual(env, after_op_3, context.get());
114fd4e5da5Sopenharmony_ci
115fd4e5da5Sopenharmony_ci  ASSERT_TRUE(ops[0]->PreconditionHolds());
116fd4e5da5Sopenharmony_ci  ops[0]->TryToApply();
117fd4e5da5Sopenharmony_ci
118fd4e5da5Sopenharmony_ci  std::string after_op_0 = R"(
119fd4e5da5Sopenharmony_ci               OpCapability Shader
120fd4e5da5Sopenharmony_ci          %1 = OpExtInstImport "GLSL.std.450"
121fd4e5da5Sopenharmony_ci               OpMemoryModel Logical GLSL450
122fd4e5da5Sopenharmony_ci               OpEntryPoint Fragment %4 "main"
123fd4e5da5Sopenharmony_ci               OpExecutionMode %4 OriginUpperLeft
124fd4e5da5Sopenharmony_ci               OpSource ESSL 310
125fd4e5da5Sopenharmony_ci               OpName %4 "main"
126fd4e5da5Sopenharmony_ci               OpName %8 "x"
127fd4e5da5Sopenharmony_ci          %2 = OpTypeVoid
128fd4e5da5Sopenharmony_ci          %3 = OpTypeFunction %2
129fd4e5da5Sopenharmony_ci          %6 = OpTypeInt 32 1
130fd4e5da5Sopenharmony_ci          %7 = OpTypePointer Function %6
131fd4e5da5Sopenharmony_ci          %9 = OpConstant %6 1
132fd4e5da5Sopenharmony_ci         %10 = OpConstant %6 2
133fd4e5da5Sopenharmony_ci         %11 = OpConstant %6 3
134fd4e5da5Sopenharmony_ci         %12 = OpConstant %6 4
135fd4e5da5Sopenharmony_ci          %4 = OpFunction %2 None %3
136fd4e5da5Sopenharmony_ci          %5 = OpLabel
137fd4e5da5Sopenharmony_ci          %8 = OpVariable %7 Function
138fd4e5da5Sopenharmony_ci               OpStore %8 %9
139fd4e5da5Sopenharmony_ci               OpBranch %14
140fd4e5da5Sopenharmony_ci         %14 = OpLabel
141fd4e5da5Sopenharmony_ci               OpStore %8 %10
142fd4e5da5Sopenharmony_ci               OpBranch %15
143fd4e5da5Sopenharmony_ci         %15 = OpLabel
144fd4e5da5Sopenharmony_ci               OpStore %8 %11
145fd4e5da5Sopenharmony_ci               OpStore %8 %12
146fd4e5da5Sopenharmony_ci               OpBranch %17
147fd4e5da5Sopenharmony_ci         %17 = OpLabel
148fd4e5da5Sopenharmony_ci               OpReturn
149fd4e5da5Sopenharmony_ci               OpFunctionEnd
150fd4e5da5Sopenharmony_ci  )";
151fd4e5da5Sopenharmony_ci
152fd4e5da5Sopenharmony_ci  CheckEqual(env, after_op_0, context.get());
153fd4e5da5Sopenharmony_ci
154fd4e5da5Sopenharmony_ci  ASSERT_TRUE(ops[2]->PreconditionHolds());
155fd4e5da5Sopenharmony_ci  ops[2]->TryToApply();
156fd4e5da5Sopenharmony_ci
157fd4e5da5Sopenharmony_ci  std::string after_op_2 = R"(
158fd4e5da5Sopenharmony_ci               OpCapability Shader
159fd4e5da5Sopenharmony_ci          %1 = OpExtInstImport "GLSL.std.450"
160fd4e5da5Sopenharmony_ci               OpMemoryModel Logical GLSL450
161fd4e5da5Sopenharmony_ci               OpEntryPoint Fragment %4 "main"
162fd4e5da5Sopenharmony_ci               OpExecutionMode %4 OriginUpperLeft
163fd4e5da5Sopenharmony_ci               OpSource ESSL 310
164fd4e5da5Sopenharmony_ci               OpName %4 "main"
165fd4e5da5Sopenharmony_ci               OpName %8 "x"
166fd4e5da5Sopenharmony_ci          %2 = OpTypeVoid
167fd4e5da5Sopenharmony_ci          %3 = OpTypeFunction %2
168fd4e5da5Sopenharmony_ci          %6 = OpTypeInt 32 1
169fd4e5da5Sopenharmony_ci          %7 = OpTypePointer Function %6
170fd4e5da5Sopenharmony_ci          %9 = OpConstant %6 1
171fd4e5da5Sopenharmony_ci         %10 = OpConstant %6 2
172fd4e5da5Sopenharmony_ci         %11 = OpConstant %6 3
173fd4e5da5Sopenharmony_ci         %12 = OpConstant %6 4
174fd4e5da5Sopenharmony_ci          %4 = OpFunction %2 None %3
175fd4e5da5Sopenharmony_ci          %5 = OpLabel
176fd4e5da5Sopenharmony_ci          %8 = OpVariable %7 Function
177fd4e5da5Sopenharmony_ci               OpStore %8 %9
178fd4e5da5Sopenharmony_ci               OpBranch %14
179fd4e5da5Sopenharmony_ci         %14 = OpLabel
180fd4e5da5Sopenharmony_ci               OpStore %8 %10
181fd4e5da5Sopenharmony_ci               OpStore %8 %11
182fd4e5da5Sopenharmony_ci               OpStore %8 %12
183fd4e5da5Sopenharmony_ci               OpBranch %17
184fd4e5da5Sopenharmony_ci         %17 = OpLabel
185fd4e5da5Sopenharmony_ci               OpReturn
186fd4e5da5Sopenharmony_ci               OpFunctionEnd
187fd4e5da5Sopenharmony_ci  )";
188fd4e5da5Sopenharmony_ci
189fd4e5da5Sopenharmony_ci  CheckEqual(env, after_op_2, context.get());
190fd4e5da5Sopenharmony_ci
191fd4e5da5Sopenharmony_ci  ASSERT_TRUE(ops[4]->PreconditionHolds());
192fd4e5da5Sopenharmony_ci  ops[4]->TryToApply();
193fd4e5da5Sopenharmony_ci
194fd4e5da5Sopenharmony_ci  std::string after_op_4 = R"(
195fd4e5da5Sopenharmony_ci               OpCapability Shader
196fd4e5da5Sopenharmony_ci          %1 = OpExtInstImport "GLSL.std.450"
197fd4e5da5Sopenharmony_ci               OpMemoryModel Logical GLSL450
198fd4e5da5Sopenharmony_ci               OpEntryPoint Fragment %4 "main"
199fd4e5da5Sopenharmony_ci               OpExecutionMode %4 OriginUpperLeft
200fd4e5da5Sopenharmony_ci               OpSource ESSL 310
201fd4e5da5Sopenharmony_ci               OpName %4 "main"
202fd4e5da5Sopenharmony_ci               OpName %8 "x"
203fd4e5da5Sopenharmony_ci          %2 = OpTypeVoid
204fd4e5da5Sopenharmony_ci          %3 = OpTypeFunction %2
205fd4e5da5Sopenharmony_ci          %6 = OpTypeInt 32 1
206fd4e5da5Sopenharmony_ci          %7 = OpTypePointer Function %6
207fd4e5da5Sopenharmony_ci          %9 = OpConstant %6 1
208fd4e5da5Sopenharmony_ci         %10 = OpConstant %6 2
209fd4e5da5Sopenharmony_ci         %11 = OpConstant %6 3
210fd4e5da5Sopenharmony_ci         %12 = OpConstant %6 4
211fd4e5da5Sopenharmony_ci          %4 = OpFunction %2 None %3
212fd4e5da5Sopenharmony_ci          %5 = OpLabel
213fd4e5da5Sopenharmony_ci          %8 = OpVariable %7 Function
214fd4e5da5Sopenharmony_ci               OpStore %8 %9
215fd4e5da5Sopenharmony_ci               OpBranch %14
216fd4e5da5Sopenharmony_ci         %14 = OpLabel
217fd4e5da5Sopenharmony_ci               OpStore %8 %10
218fd4e5da5Sopenharmony_ci               OpStore %8 %11
219fd4e5da5Sopenharmony_ci               OpStore %8 %12
220fd4e5da5Sopenharmony_ci               OpReturn
221fd4e5da5Sopenharmony_ci               OpFunctionEnd
222fd4e5da5Sopenharmony_ci  )";
223fd4e5da5Sopenharmony_ci
224fd4e5da5Sopenharmony_ci  CheckEqual(env, after_op_4, context.get());
225fd4e5da5Sopenharmony_ci
226fd4e5da5Sopenharmony_ci  ASSERT_TRUE(ops[1]->PreconditionHolds());
227fd4e5da5Sopenharmony_ci  ops[1]->TryToApply();
228fd4e5da5Sopenharmony_ci
229fd4e5da5Sopenharmony_ci  std::string after_op_1 = R"(
230fd4e5da5Sopenharmony_ci               OpCapability Shader
231fd4e5da5Sopenharmony_ci          %1 = OpExtInstImport "GLSL.std.450"
232fd4e5da5Sopenharmony_ci               OpMemoryModel Logical GLSL450
233fd4e5da5Sopenharmony_ci               OpEntryPoint Fragment %4 "main"
234fd4e5da5Sopenharmony_ci               OpExecutionMode %4 OriginUpperLeft
235fd4e5da5Sopenharmony_ci               OpSource ESSL 310
236fd4e5da5Sopenharmony_ci               OpName %4 "main"
237fd4e5da5Sopenharmony_ci               OpName %8 "x"
238fd4e5da5Sopenharmony_ci          %2 = OpTypeVoid
239fd4e5da5Sopenharmony_ci          %3 = OpTypeFunction %2
240fd4e5da5Sopenharmony_ci          %6 = OpTypeInt 32 1
241fd4e5da5Sopenharmony_ci          %7 = OpTypePointer Function %6
242fd4e5da5Sopenharmony_ci          %9 = OpConstant %6 1
243fd4e5da5Sopenharmony_ci         %10 = OpConstant %6 2
244fd4e5da5Sopenharmony_ci         %11 = OpConstant %6 3
245fd4e5da5Sopenharmony_ci         %12 = OpConstant %6 4
246fd4e5da5Sopenharmony_ci          %4 = OpFunction %2 None %3
247fd4e5da5Sopenharmony_ci          %5 = OpLabel
248fd4e5da5Sopenharmony_ci          %8 = OpVariable %7 Function
249fd4e5da5Sopenharmony_ci               OpStore %8 %9
250fd4e5da5Sopenharmony_ci               OpStore %8 %10
251fd4e5da5Sopenharmony_ci               OpStore %8 %11
252fd4e5da5Sopenharmony_ci               OpStore %8 %12
253fd4e5da5Sopenharmony_ci               OpReturn
254fd4e5da5Sopenharmony_ci               OpFunctionEnd
255fd4e5da5Sopenharmony_ci  )";
256fd4e5da5Sopenharmony_ci
257fd4e5da5Sopenharmony_ci  CheckEqual(env, after_op_1, context.get());
258fd4e5da5Sopenharmony_ci}
259fd4e5da5Sopenharmony_ci
260fd4e5da5Sopenharmony_ciTEST(MergeBlocksReductionPassTest, Loops) {
261fd4e5da5Sopenharmony_ci  std::string shader = R"(
262fd4e5da5Sopenharmony_ci               OpCapability Shader
263fd4e5da5Sopenharmony_ci          %1 = OpExtInstImport "GLSL.std.450"
264fd4e5da5Sopenharmony_ci               OpMemoryModel Logical GLSL450
265fd4e5da5Sopenharmony_ci               OpEntryPoint Fragment %4 "main"
266fd4e5da5Sopenharmony_ci               OpExecutionMode %4 OriginUpperLeft
267fd4e5da5Sopenharmony_ci               OpSource ESSL 310
268fd4e5da5Sopenharmony_ci               OpName %4 "main"
269fd4e5da5Sopenharmony_ci               OpName %8 "x"
270fd4e5da5Sopenharmony_ci               OpName %10 "i"
271fd4e5da5Sopenharmony_ci               OpName %29 "i"
272fd4e5da5Sopenharmony_ci          %2 = OpTypeVoid
273fd4e5da5Sopenharmony_ci          %3 = OpTypeFunction %2
274fd4e5da5Sopenharmony_ci          %6 = OpTypeInt 32 1
275fd4e5da5Sopenharmony_ci          %7 = OpTypePointer Function %6
276fd4e5da5Sopenharmony_ci          %9 = OpConstant %6 1
277fd4e5da5Sopenharmony_ci         %11 = OpConstant %6 0
278fd4e5da5Sopenharmony_ci         %18 = OpConstant %6 10
279fd4e5da5Sopenharmony_ci         %19 = OpTypeBool
280fd4e5da5Sopenharmony_ci          %4 = OpFunction %2 None %3
281fd4e5da5Sopenharmony_ci          %5 = OpLabel
282fd4e5da5Sopenharmony_ci          %8 = OpVariable %7 Function
283fd4e5da5Sopenharmony_ci         %10 = OpVariable %7 Function
284fd4e5da5Sopenharmony_ci         %29 = OpVariable %7 Function
285fd4e5da5Sopenharmony_ci               OpStore %8 %9
286fd4e5da5Sopenharmony_ci               OpBranch %45
287fd4e5da5Sopenharmony_ci         %45 = OpLabel
288fd4e5da5Sopenharmony_ci               OpStore %10 %11
289fd4e5da5Sopenharmony_ci               OpBranch %12
290fd4e5da5Sopenharmony_ci         %12 = OpLabel
291fd4e5da5Sopenharmony_ci               OpLoopMerge %14 %15 None
292fd4e5da5Sopenharmony_ci               OpBranch %16
293fd4e5da5Sopenharmony_ci         %16 = OpLabel
294fd4e5da5Sopenharmony_ci         %17 = OpLoad %6 %10
295fd4e5da5Sopenharmony_ci               OpBranch %46
296fd4e5da5Sopenharmony_ci         %46 = OpLabel
297fd4e5da5Sopenharmony_ci         %20 = OpSLessThan %19 %17 %18
298fd4e5da5Sopenharmony_ci               OpBranchConditional %20 %13 %14
299fd4e5da5Sopenharmony_ci         %13 = OpLabel
300fd4e5da5Sopenharmony_ci         %21 = OpLoad %6 %10
301fd4e5da5Sopenharmony_ci               OpBranch %47
302fd4e5da5Sopenharmony_ci         %47 = OpLabel
303fd4e5da5Sopenharmony_ci         %22 = OpLoad %6 %8
304fd4e5da5Sopenharmony_ci         %23 = OpIAdd %6 %22 %21
305fd4e5da5Sopenharmony_ci               OpStore %8 %23
306fd4e5da5Sopenharmony_ci         %24 = OpLoad %6 %10
307fd4e5da5Sopenharmony_ci         %25 = OpLoad %6 %8
308fd4e5da5Sopenharmony_ci         %26 = OpIAdd %6 %25 %24
309fd4e5da5Sopenharmony_ci               OpStore %8 %26
310fd4e5da5Sopenharmony_ci               OpBranch %48
311fd4e5da5Sopenharmony_ci         %48 = OpLabel
312fd4e5da5Sopenharmony_ci               OpBranch %15
313fd4e5da5Sopenharmony_ci         %15 = OpLabel
314fd4e5da5Sopenharmony_ci         %27 = OpLoad %6 %10
315fd4e5da5Sopenharmony_ci         %28 = OpIAdd %6 %27 %9
316fd4e5da5Sopenharmony_ci               OpStore %10 %28
317fd4e5da5Sopenharmony_ci               OpBranch %12
318fd4e5da5Sopenharmony_ci         %14 = OpLabel
319fd4e5da5Sopenharmony_ci               OpStore %29 %11
320fd4e5da5Sopenharmony_ci               OpBranch %49
321fd4e5da5Sopenharmony_ci         %49 = OpLabel
322fd4e5da5Sopenharmony_ci               OpBranch %30
323fd4e5da5Sopenharmony_ci         %30 = OpLabel
324fd4e5da5Sopenharmony_ci               OpLoopMerge %32 %33 None
325fd4e5da5Sopenharmony_ci               OpBranch %34
326fd4e5da5Sopenharmony_ci         %34 = OpLabel
327fd4e5da5Sopenharmony_ci         %35 = OpLoad %6 %29
328fd4e5da5Sopenharmony_ci         %36 = OpSLessThan %19 %35 %18
329fd4e5da5Sopenharmony_ci               OpBranch %50
330fd4e5da5Sopenharmony_ci         %50 = OpLabel
331fd4e5da5Sopenharmony_ci               OpBranchConditional %36 %31 %32
332fd4e5da5Sopenharmony_ci         %31 = OpLabel
333fd4e5da5Sopenharmony_ci         %37 = OpLoad %6 %29
334fd4e5da5Sopenharmony_ci         %38 = OpLoad %6 %8
335fd4e5da5Sopenharmony_ci         %39 = OpIAdd %6 %38 %37
336fd4e5da5Sopenharmony_ci               OpStore %8 %39
337fd4e5da5Sopenharmony_ci         %40 = OpLoad %6 %29
338fd4e5da5Sopenharmony_ci         %41 = OpLoad %6 %8
339fd4e5da5Sopenharmony_ci         %42 = OpIAdd %6 %41 %40
340fd4e5da5Sopenharmony_ci               OpStore %8 %42
341fd4e5da5Sopenharmony_ci               OpBranch %33
342fd4e5da5Sopenharmony_ci         %33 = OpLabel
343fd4e5da5Sopenharmony_ci         %43 = OpLoad %6 %29
344fd4e5da5Sopenharmony_ci         %44 = OpIAdd %6 %43 %9
345fd4e5da5Sopenharmony_ci               OpBranch %51
346fd4e5da5Sopenharmony_ci         %51 = OpLabel
347fd4e5da5Sopenharmony_ci               OpStore %29 %44
348fd4e5da5Sopenharmony_ci               OpBranch %30
349fd4e5da5Sopenharmony_ci         %32 = OpLabel
350fd4e5da5Sopenharmony_ci               OpReturn
351fd4e5da5Sopenharmony_ci               OpFunctionEnd
352fd4e5da5Sopenharmony_ci  )";
353fd4e5da5Sopenharmony_ci  const auto env = SPV_ENV_UNIVERSAL_1_3;
354fd4e5da5Sopenharmony_ci  const auto consumer = nullptr;
355fd4e5da5Sopenharmony_ci  const auto context =
356fd4e5da5Sopenharmony_ci      BuildModule(env, consumer, shader, kReduceAssembleOption);
357fd4e5da5Sopenharmony_ci  const auto ops =
358fd4e5da5Sopenharmony_ci      MergeBlocksReductionOpportunityFinder().GetAvailableOpportunities(
359fd4e5da5Sopenharmony_ci          context.get(), 0);
360fd4e5da5Sopenharmony_ci  ASSERT_EQ(11, ops.size());
361fd4e5da5Sopenharmony_ci
362fd4e5da5Sopenharmony_ci  for (auto& ri : ops) {
363fd4e5da5Sopenharmony_ci    ASSERT_TRUE(ri->PreconditionHolds());
364fd4e5da5Sopenharmony_ci    ri->TryToApply();
365fd4e5da5Sopenharmony_ci  }
366fd4e5da5Sopenharmony_ci
367fd4e5da5Sopenharmony_ci  std::string after = R"(
368fd4e5da5Sopenharmony_ci               OpCapability Shader
369fd4e5da5Sopenharmony_ci          %1 = OpExtInstImport "GLSL.std.450"
370fd4e5da5Sopenharmony_ci               OpMemoryModel Logical GLSL450
371fd4e5da5Sopenharmony_ci               OpEntryPoint Fragment %4 "main"
372fd4e5da5Sopenharmony_ci               OpExecutionMode %4 OriginUpperLeft
373fd4e5da5Sopenharmony_ci               OpSource ESSL 310
374fd4e5da5Sopenharmony_ci               OpName %4 "main"
375fd4e5da5Sopenharmony_ci               OpName %8 "x"
376fd4e5da5Sopenharmony_ci               OpName %10 "i"
377fd4e5da5Sopenharmony_ci               OpName %29 "i"
378fd4e5da5Sopenharmony_ci          %2 = OpTypeVoid
379fd4e5da5Sopenharmony_ci          %3 = OpTypeFunction %2
380fd4e5da5Sopenharmony_ci          %6 = OpTypeInt 32 1
381fd4e5da5Sopenharmony_ci          %7 = OpTypePointer Function %6
382fd4e5da5Sopenharmony_ci          %9 = OpConstant %6 1
383fd4e5da5Sopenharmony_ci         %11 = OpConstant %6 0
384fd4e5da5Sopenharmony_ci         %18 = OpConstant %6 10
385fd4e5da5Sopenharmony_ci         %19 = OpTypeBool
386fd4e5da5Sopenharmony_ci          %4 = OpFunction %2 None %3
387fd4e5da5Sopenharmony_ci          %5 = OpLabel
388fd4e5da5Sopenharmony_ci          %8 = OpVariable %7 Function
389fd4e5da5Sopenharmony_ci         %10 = OpVariable %7 Function
390fd4e5da5Sopenharmony_ci         %29 = OpVariable %7 Function
391fd4e5da5Sopenharmony_ci               OpStore %8 %9
392fd4e5da5Sopenharmony_ci               OpStore %10 %11
393fd4e5da5Sopenharmony_ci               OpBranch %12
394fd4e5da5Sopenharmony_ci         %12 = OpLabel
395fd4e5da5Sopenharmony_ci         %17 = OpLoad %6 %10
396fd4e5da5Sopenharmony_ci         %20 = OpSLessThan %19 %17 %18
397fd4e5da5Sopenharmony_ci               OpLoopMerge %14 %13 None
398fd4e5da5Sopenharmony_ci               OpBranchConditional %20 %13 %14
399fd4e5da5Sopenharmony_ci         %13 = OpLabel
400fd4e5da5Sopenharmony_ci         %21 = OpLoad %6 %10
401fd4e5da5Sopenharmony_ci         %22 = OpLoad %6 %8
402fd4e5da5Sopenharmony_ci         %23 = OpIAdd %6 %22 %21
403fd4e5da5Sopenharmony_ci               OpStore %8 %23
404fd4e5da5Sopenharmony_ci         %24 = OpLoad %6 %10
405fd4e5da5Sopenharmony_ci         %25 = OpLoad %6 %8
406fd4e5da5Sopenharmony_ci         %26 = OpIAdd %6 %25 %24
407fd4e5da5Sopenharmony_ci               OpStore %8 %26
408fd4e5da5Sopenharmony_ci         %27 = OpLoad %6 %10
409fd4e5da5Sopenharmony_ci         %28 = OpIAdd %6 %27 %9
410fd4e5da5Sopenharmony_ci               OpStore %10 %28
411fd4e5da5Sopenharmony_ci               OpBranch %12
412fd4e5da5Sopenharmony_ci         %14 = OpLabel
413fd4e5da5Sopenharmony_ci               OpStore %29 %11
414fd4e5da5Sopenharmony_ci               OpBranch %30
415fd4e5da5Sopenharmony_ci         %30 = OpLabel
416fd4e5da5Sopenharmony_ci         %35 = OpLoad %6 %29
417fd4e5da5Sopenharmony_ci         %36 = OpSLessThan %19 %35 %18
418fd4e5da5Sopenharmony_ci               OpLoopMerge %32 %31 None
419fd4e5da5Sopenharmony_ci               OpBranchConditional %36 %31 %32
420fd4e5da5Sopenharmony_ci         %31 = OpLabel
421fd4e5da5Sopenharmony_ci         %37 = OpLoad %6 %29
422fd4e5da5Sopenharmony_ci         %38 = OpLoad %6 %8
423fd4e5da5Sopenharmony_ci         %39 = OpIAdd %6 %38 %37
424fd4e5da5Sopenharmony_ci               OpStore %8 %39
425fd4e5da5Sopenharmony_ci         %40 = OpLoad %6 %29
426fd4e5da5Sopenharmony_ci         %41 = OpLoad %6 %8
427fd4e5da5Sopenharmony_ci         %42 = OpIAdd %6 %41 %40
428fd4e5da5Sopenharmony_ci               OpStore %8 %42
429fd4e5da5Sopenharmony_ci         %43 = OpLoad %6 %29
430fd4e5da5Sopenharmony_ci         %44 = OpIAdd %6 %43 %9
431fd4e5da5Sopenharmony_ci               OpStore %29 %44
432fd4e5da5Sopenharmony_ci               OpBranch %30
433fd4e5da5Sopenharmony_ci         %32 = OpLabel
434fd4e5da5Sopenharmony_ci               OpReturn
435fd4e5da5Sopenharmony_ci               OpFunctionEnd
436fd4e5da5Sopenharmony_ci  )";
437fd4e5da5Sopenharmony_ci
438fd4e5da5Sopenharmony_ci  CheckEqual(env, after, context.get());
439fd4e5da5Sopenharmony_ci}
440fd4e5da5Sopenharmony_ci
441fd4e5da5Sopenharmony_ciTEST(MergeBlocksReductionPassTest, MergeWithOpPhi) {
442fd4e5da5Sopenharmony_ci  std::string shader = R"(
443fd4e5da5Sopenharmony_ci               OpCapability Shader
444fd4e5da5Sopenharmony_ci          %1 = OpExtInstImport "GLSL.std.450"
445fd4e5da5Sopenharmony_ci               OpMemoryModel Logical GLSL450
446fd4e5da5Sopenharmony_ci               OpEntryPoint Fragment %4 "main"
447fd4e5da5Sopenharmony_ci               OpExecutionMode %4 OriginUpperLeft
448fd4e5da5Sopenharmony_ci               OpSource ESSL 310
449fd4e5da5Sopenharmony_ci               OpName %4 "main"
450fd4e5da5Sopenharmony_ci               OpName %8 "x"
451fd4e5da5Sopenharmony_ci               OpName %10 "y"
452fd4e5da5Sopenharmony_ci          %2 = OpTypeVoid
453fd4e5da5Sopenharmony_ci          %3 = OpTypeFunction %2
454fd4e5da5Sopenharmony_ci          %6 = OpTypeInt 32 1
455fd4e5da5Sopenharmony_ci          %7 = OpTypePointer Function %6
456fd4e5da5Sopenharmony_ci          %9 = OpConstant %6 1
457fd4e5da5Sopenharmony_ci          %4 = OpFunction %2 None %3
458fd4e5da5Sopenharmony_ci          %5 = OpLabel
459fd4e5da5Sopenharmony_ci          %8 = OpVariable %7 Function
460fd4e5da5Sopenharmony_ci         %10 = OpVariable %7 Function
461fd4e5da5Sopenharmony_ci               OpStore %8 %9
462fd4e5da5Sopenharmony_ci         %11 = OpLoad %6 %8
463fd4e5da5Sopenharmony_ci               OpBranch %12
464fd4e5da5Sopenharmony_ci         %12 = OpLabel
465fd4e5da5Sopenharmony_ci         %13 = OpPhi %6 %11 %5
466fd4e5da5Sopenharmony_ci               OpStore %10 %13
467fd4e5da5Sopenharmony_ci               OpReturn
468fd4e5da5Sopenharmony_ci               OpFunctionEnd
469fd4e5da5Sopenharmony_ci  )";
470fd4e5da5Sopenharmony_ci
471fd4e5da5Sopenharmony_ci  const auto env = SPV_ENV_UNIVERSAL_1_3;
472fd4e5da5Sopenharmony_ci  const auto consumer = nullptr;
473fd4e5da5Sopenharmony_ci  const auto context =
474fd4e5da5Sopenharmony_ci      BuildModule(env, consumer, shader, kReduceAssembleOption);
475fd4e5da5Sopenharmony_ci  const auto ops =
476fd4e5da5Sopenharmony_ci      MergeBlocksReductionOpportunityFinder().GetAvailableOpportunities(
477fd4e5da5Sopenharmony_ci          context.get(), 0);
478fd4e5da5Sopenharmony_ci  ASSERT_EQ(1, ops.size());
479fd4e5da5Sopenharmony_ci
480fd4e5da5Sopenharmony_ci  ASSERT_TRUE(ops[0]->PreconditionHolds());
481fd4e5da5Sopenharmony_ci  ops[0]->TryToApply();
482fd4e5da5Sopenharmony_ci
483fd4e5da5Sopenharmony_ci  std::string after = R"(
484fd4e5da5Sopenharmony_ci               OpCapability Shader
485fd4e5da5Sopenharmony_ci          %1 = OpExtInstImport "GLSL.std.450"
486fd4e5da5Sopenharmony_ci               OpMemoryModel Logical GLSL450
487fd4e5da5Sopenharmony_ci               OpEntryPoint Fragment %4 "main"
488fd4e5da5Sopenharmony_ci               OpExecutionMode %4 OriginUpperLeft
489fd4e5da5Sopenharmony_ci               OpSource ESSL 310
490fd4e5da5Sopenharmony_ci               OpName %4 "main"
491fd4e5da5Sopenharmony_ci               OpName %8 "x"
492fd4e5da5Sopenharmony_ci               OpName %10 "y"
493fd4e5da5Sopenharmony_ci          %2 = OpTypeVoid
494fd4e5da5Sopenharmony_ci          %3 = OpTypeFunction %2
495fd4e5da5Sopenharmony_ci          %6 = OpTypeInt 32 1
496fd4e5da5Sopenharmony_ci          %7 = OpTypePointer Function %6
497fd4e5da5Sopenharmony_ci          %9 = OpConstant %6 1
498fd4e5da5Sopenharmony_ci          %4 = OpFunction %2 None %3
499fd4e5da5Sopenharmony_ci          %5 = OpLabel
500fd4e5da5Sopenharmony_ci          %8 = OpVariable %7 Function
501fd4e5da5Sopenharmony_ci         %10 = OpVariable %7 Function
502fd4e5da5Sopenharmony_ci               OpStore %8 %9
503fd4e5da5Sopenharmony_ci         %11 = OpLoad %6 %8
504fd4e5da5Sopenharmony_ci               OpStore %10 %11
505fd4e5da5Sopenharmony_ci               OpReturn
506fd4e5da5Sopenharmony_ci               OpFunctionEnd
507fd4e5da5Sopenharmony_ci  )";
508fd4e5da5Sopenharmony_ci
509fd4e5da5Sopenharmony_ci  CheckEqual(env, after, context.get());
510fd4e5da5Sopenharmony_ci}
511fd4e5da5Sopenharmony_ci
512fd4e5da5Sopenharmony_civoid MergeBlocksReductionPassTest_LoopReturn_Helper(bool reverse) {
513fd4e5da5Sopenharmony_ci  // A merge block opportunity stores a block that can be merged with its
514fd4e5da5Sopenharmony_ci  // predecessor.
515fd4e5da5Sopenharmony_ci  // Given blocks A -> B -> C:
516fd4e5da5Sopenharmony_ci  // This test demonstrates how merging B->C can invalidate
517fd4e5da5Sopenharmony_ci  // the opportunity of merging A->B, and vice-versa. E.g.
518fd4e5da5Sopenharmony_ci  // B->C are merged: B is now terminated with OpReturn.
519fd4e5da5Sopenharmony_ci  // A->B can now no longer be merged because A is a loop header, which
520fd4e5da5Sopenharmony_ci  // cannot be terminated with OpReturn.
521fd4e5da5Sopenharmony_ci
522fd4e5da5Sopenharmony_ci  std::string shader = R"(
523fd4e5da5Sopenharmony_ci               OpCapability Shader
524fd4e5da5Sopenharmony_ci          %1 = OpExtInstImport "GLSL.std.450"
525fd4e5da5Sopenharmony_ci               OpMemoryModel Logical GLSL450
526fd4e5da5Sopenharmony_ci               OpEntryPoint Fragment %2 "main"
527fd4e5da5Sopenharmony_ci               OpExecutionMode %2 OriginUpperLeft
528fd4e5da5Sopenharmony_ci               OpSource ESSL 310
529fd4e5da5Sopenharmony_ci               OpName %2 "main"
530fd4e5da5Sopenharmony_ci          %3 = OpTypeVoid
531fd4e5da5Sopenharmony_ci          %4 = OpTypeFunction %3
532fd4e5da5Sopenharmony_ci          %5 = OpTypeInt 32 1
533fd4e5da5Sopenharmony_ci          %6 = OpTypePointer Function %5
534fd4e5da5Sopenharmony_ci          %7 = OpTypeBool
535fd4e5da5Sopenharmony_ci          %8 = OpConstantFalse %7
536fd4e5da5Sopenharmony_ci          %2 = OpFunction %3 None %4
537fd4e5da5Sopenharmony_ci          %9 = OpLabel
538fd4e5da5Sopenharmony_ci               OpBranch %10
539fd4e5da5Sopenharmony_ci         %10 = OpLabel                   ; A (loop header)
540fd4e5da5Sopenharmony_ci               OpLoopMerge %13 %12 None
541fd4e5da5Sopenharmony_ci               OpBranch %11
542fd4e5da5Sopenharmony_ci         %12 = OpLabel                   ; (unreachable continue block)
543fd4e5da5Sopenharmony_ci               OpBranch %10
544fd4e5da5Sopenharmony_ci         %11 = OpLabel                   ; B
545fd4e5da5Sopenharmony_ci               OpBranch %15
546fd4e5da5Sopenharmony_ci         %15 = OpLabel                   ; C
547fd4e5da5Sopenharmony_ci               OpReturn
548fd4e5da5Sopenharmony_ci         %13 = OpLabel                   ; (unreachable merge block)
549fd4e5da5Sopenharmony_ci               OpReturn
550fd4e5da5Sopenharmony_ci               OpFunctionEnd
551fd4e5da5Sopenharmony_ci  )";
552fd4e5da5Sopenharmony_ci  const auto env = SPV_ENV_UNIVERSAL_1_3;
553fd4e5da5Sopenharmony_ci  const auto consumer = nullptr;
554fd4e5da5Sopenharmony_ci  const auto context =
555fd4e5da5Sopenharmony_ci      BuildModule(env, consumer, shader, kReduceAssembleOption);
556fd4e5da5Sopenharmony_ci  ASSERT_NE(context.get(), nullptr);
557fd4e5da5Sopenharmony_ci  auto opportunities =
558fd4e5da5Sopenharmony_ci      MergeBlocksReductionOpportunityFinder().GetAvailableOpportunities(
559fd4e5da5Sopenharmony_ci          context.get(), 0);
560fd4e5da5Sopenharmony_ci
561fd4e5da5Sopenharmony_ci  // A->B and B->C
562fd4e5da5Sopenharmony_ci  ASSERT_EQ(opportunities.size(), 2);
563fd4e5da5Sopenharmony_ci
564fd4e5da5Sopenharmony_ci  // Test applying opportunities in both orders.
565fd4e5da5Sopenharmony_ci  if (reverse) {
566fd4e5da5Sopenharmony_ci    std::reverse(opportunities.begin(), opportunities.end());
567fd4e5da5Sopenharmony_ci  }
568fd4e5da5Sopenharmony_ci
569fd4e5da5Sopenharmony_ci  size_t num_applied = 0;
570fd4e5da5Sopenharmony_ci  for (auto& ri : opportunities) {
571fd4e5da5Sopenharmony_ci    if (ri->PreconditionHolds()) {
572fd4e5da5Sopenharmony_ci      ri->TryToApply();
573fd4e5da5Sopenharmony_ci      ++num_applied;
574fd4e5da5Sopenharmony_ci    }
575fd4e5da5Sopenharmony_ci  }
576fd4e5da5Sopenharmony_ci
577fd4e5da5Sopenharmony_ci  // Only 1 opportunity can be applied, as both disable each other.
578fd4e5da5Sopenharmony_ci  ASSERT_EQ(num_applied, 1);
579fd4e5da5Sopenharmony_ci
580fd4e5da5Sopenharmony_ci  std::string after = R"(
581fd4e5da5Sopenharmony_ci               OpCapability Shader
582fd4e5da5Sopenharmony_ci          %1 = OpExtInstImport "GLSL.std.450"
583fd4e5da5Sopenharmony_ci               OpMemoryModel Logical GLSL450
584fd4e5da5Sopenharmony_ci               OpEntryPoint Fragment %2 "main"
585fd4e5da5Sopenharmony_ci               OpExecutionMode %2 OriginUpperLeft
586fd4e5da5Sopenharmony_ci               OpSource ESSL 310
587fd4e5da5Sopenharmony_ci               OpName %2 "main"
588fd4e5da5Sopenharmony_ci          %3 = OpTypeVoid
589fd4e5da5Sopenharmony_ci          %4 = OpTypeFunction %3
590fd4e5da5Sopenharmony_ci          %5 = OpTypeInt 32 1
591fd4e5da5Sopenharmony_ci          %6 = OpTypePointer Function %5
592fd4e5da5Sopenharmony_ci          %7 = OpTypeBool
593fd4e5da5Sopenharmony_ci          %8 = OpConstantFalse %7
594fd4e5da5Sopenharmony_ci          %2 = OpFunction %3 None %4
595fd4e5da5Sopenharmony_ci          %9 = OpLabel
596fd4e5da5Sopenharmony_ci               OpBranch %10
597fd4e5da5Sopenharmony_ci         %10 = OpLabel                   ; A-B (loop header)
598fd4e5da5Sopenharmony_ci               OpLoopMerge %13 %12 None
599fd4e5da5Sopenharmony_ci               OpBranch %15
600fd4e5da5Sopenharmony_ci         %12 = OpLabel                   ; (unreachable continue block)
601fd4e5da5Sopenharmony_ci               OpBranch %10
602fd4e5da5Sopenharmony_ci         %15 = OpLabel                   ; C
603fd4e5da5Sopenharmony_ci               OpReturn
604fd4e5da5Sopenharmony_ci         %13 = OpLabel                   ; (unreachable merge block)
605fd4e5da5Sopenharmony_ci               OpReturn
606fd4e5da5Sopenharmony_ci               OpFunctionEnd
607fd4e5da5Sopenharmony_ci  )";
608fd4e5da5Sopenharmony_ci
609fd4e5da5Sopenharmony_ci  // The only difference is the labels.
610fd4e5da5Sopenharmony_ci  std::string after_reversed = R"(
611fd4e5da5Sopenharmony_ci               OpCapability Shader
612fd4e5da5Sopenharmony_ci          %1 = OpExtInstImport "GLSL.std.450"
613fd4e5da5Sopenharmony_ci               OpMemoryModel Logical GLSL450
614fd4e5da5Sopenharmony_ci               OpEntryPoint Fragment %2 "main"
615fd4e5da5Sopenharmony_ci               OpExecutionMode %2 OriginUpperLeft
616fd4e5da5Sopenharmony_ci               OpSource ESSL 310
617fd4e5da5Sopenharmony_ci               OpName %2 "main"
618fd4e5da5Sopenharmony_ci          %3 = OpTypeVoid
619fd4e5da5Sopenharmony_ci          %4 = OpTypeFunction %3
620fd4e5da5Sopenharmony_ci          %5 = OpTypeInt 32 1
621fd4e5da5Sopenharmony_ci          %6 = OpTypePointer Function %5
622fd4e5da5Sopenharmony_ci          %7 = OpTypeBool
623fd4e5da5Sopenharmony_ci          %8 = OpConstantFalse %7
624fd4e5da5Sopenharmony_ci          %2 = OpFunction %3 None %4
625fd4e5da5Sopenharmony_ci          %9 = OpLabel
626fd4e5da5Sopenharmony_ci               OpBranch %10
627fd4e5da5Sopenharmony_ci         %10 = OpLabel                   ; A (loop header)
628fd4e5da5Sopenharmony_ci               OpLoopMerge %13 %12 None
629fd4e5da5Sopenharmony_ci               OpBranch %11
630fd4e5da5Sopenharmony_ci         %12 = OpLabel                   ; (unreachable continue block)
631fd4e5da5Sopenharmony_ci               OpBranch %10
632fd4e5da5Sopenharmony_ci         %11 = OpLabel                   ; B-C
633fd4e5da5Sopenharmony_ci               OpReturn
634fd4e5da5Sopenharmony_ci         %13 = OpLabel                   ; (unreachable merge block)
635fd4e5da5Sopenharmony_ci               OpReturn
636fd4e5da5Sopenharmony_ci               OpFunctionEnd
637fd4e5da5Sopenharmony_ci  )";
638fd4e5da5Sopenharmony_ci
639fd4e5da5Sopenharmony_ci  CheckEqual(env, reverse ? after_reversed : after, context.get());
640fd4e5da5Sopenharmony_ci}
641fd4e5da5Sopenharmony_ci
642fd4e5da5Sopenharmony_ciTEST(MergeBlocksReductionPassTest, LoopReturn) {
643fd4e5da5Sopenharmony_ci  MergeBlocksReductionPassTest_LoopReturn_Helper(false);
644fd4e5da5Sopenharmony_ci}
645fd4e5da5Sopenharmony_ci
646fd4e5da5Sopenharmony_ciTEST(MergeBlocksReductionPassTest, LoopReturnReverse) {
647fd4e5da5Sopenharmony_ci  MergeBlocksReductionPassTest_LoopReturn_Helper(true);
648fd4e5da5Sopenharmony_ci}
649fd4e5da5Sopenharmony_ci
650fd4e5da5Sopenharmony_ciTEST(MergeBlocksReductionPassTest, MergeUnreachable) {
651fd4e5da5Sopenharmony_ci  std::string shader = R"(
652fd4e5da5Sopenharmony_ci               OpCapability Shader
653fd4e5da5Sopenharmony_ci          %1 = OpExtInstImport "GLSL.std.450"
654fd4e5da5Sopenharmony_ci               OpMemoryModel Logical GLSL450
655fd4e5da5Sopenharmony_ci               OpEntryPoint Fragment %4 "main"
656fd4e5da5Sopenharmony_ci               OpExecutionMode %4 OriginUpperLeft
657fd4e5da5Sopenharmony_ci               OpSource ESSL 320
658fd4e5da5Sopenharmony_ci               OpName %4 "main"
659fd4e5da5Sopenharmony_ci          %2 = OpTypeVoid
660fd4e5da5Sopenharmony_ci          %3 = OpTypeFunction %2
661fd4e5da5Sopenharmony_ci         %11 = OpTypeBool
662fd4e5da5Sopenharmony_ci         %12 = OpConstantFalse %11
663fd4e5da5Sopenharmony_ci          %4 = OpFunction %2 None %3
664fd4e5da5Sopenharmony_ci          %5 = OpLabel
665fd4e5da5Sopenharmony_ci               OpReturn
666fd4e5da5Sopenharmony_ci          %9 = OpLabel
667fd4e5da5Sopenharmony_ci               OpBranch %100
668fd4e5da5Sopenharmony_ci        %100 = OpLabel
669fd4e5da5Sopenharmony_ci               OpReturn
670fd4e5da5Sopenharmony_ci               OpFunctionEnd
671fd4e5da5Sopenharmony_ci  )";
672fd4e5da5Sopenharmony_ci
673fd4e5da5Sopenharmony_ci  const auto env = SPV_ENV_UNIVERSAL_1_3;
674fd4e5da5Sopenharmony_ci  const auto consumer = nullptr;
675fd4e5da5Sopenharmony_ci  const auto context =
676fd4e5da5Sopenharmony_ci      BuildModule(env, consumer, shader, kReduceAssembleOption);
677fd4e5da5Sopenharmony_ci  const auto ops =
678fd4e5da5Sopenharmony_ci      MergeBlocksReductionOpportunityFinder().GetAvailableOpportunities(
679fd4e5da5Sopenharmony_ci          context.get(), 0);
680fd4e5da5Sopenharmony_ci  ASSERT_EQ(1, ops.size());
681fd4e5da5Sopenharmony_ci
682fd4e5da5Sopenharmony_ci  ASSERT_TRUE(ops[0]->PreconditionHolds());
683fd4e5da5Sopenharmony_ci  ops[0]->TryToApply();
684fd4e5da5Sopenharmony_ci
685fd4e5da5Sopenharmony_ci  std::string after = R"(
686fd4e5da5Sopenharmony_ci               OpCapability Shader
687fd4e5da5Sopenharmony_ci          %1 = OpExtInstImport "GLSL.std.450"
688fd4e5da5Sopenharmony_ci               OpMemoryModel Logical GLSL450
689fd4e5da5Sopenharmony_ci               OpEntryPoint Fragment %4 "main"
690fd4e5da5Sopenharmony_ci               OpExecutionMode %4 OriginUpperLeft
691fd4e5da5Sopenharmony_ci               OpSource ESSL 320
692fd4e5da5Sopenharmony_ci               OpName %4 "main"
693fd4e5da5Sopenharmony_ci          %2 = OpTypeVoid
694fd4e5da5Sopenharmony_ci          %3 = OpTypeFunction %2
695fd4e5da5Sopenharmony_ci         %11 = OpTypeBool
696fd4e5da5Sopenharmony_ci         %12 = OpConstantFalse %11
697fd4e5da5Sopenharmony_ci          %4 = OpFunction %2 None %3
698fd4e5da5Sopenharmony_ci          %5 = OpLabel
699fd4e5da5Sopenharmony_ci               OpReturn
700fd4e5da5Sopenharmony_ci          %9 = OpLabel
701fd4e5da5Sopenharmony_ci               OpReturn
702fd4e5da5Sopenharmony_ci               OpFunctionEnd
703fd4e5da5Sopenharmony_ci  )";
704fd4e5da5Sopenharmony_ci
705fd4e5da5Sopenharmony_ci  CheckEqual(env, after, context.get());
706fd4e5da5Sopenharmony_ci}
707fd4e5da5Sopenharmony_ci
708fd4e5da5Sopenharmony_ci}  // namespace
709fd4e5da5Sopenharmony_ci}  // namespace reduce
710fd4e5da5Sopenharmony_ci}  // namespace spvtools
711