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