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_outline_function.h"
16fd4e5da5Sopenharmony_ci
17fd4e5da5Sopenharmony_ci#include "gtest/gtest.h"
18fd4e5da5Sopenharmony_ci#include "source/fuzz/counter_overflow_id_source.h"
19fd4e5da5Sopenharmony_ci#include "source/fuzz/fuzzer_util.h"
20fd4e5da5Sopenharmony_ci#include "test/fuzz/fuzz_test_util.h"
21fd4e5da5Sopenharmony_ci
22fd4e5da5Sopenharmony_cinamespace spvtools {
23fd4e5da5Sopenharmony_cinamespace fuzz {
24fd4e5da5Sopenharmony_cinamespace {
25fd4e5da5Sopenharmony_ci
26fd4e5da5Sopenharmony_ciTEST(TransformationOutlineFunctionTest, TrivialOutline) {
27fd4e5da5Sopenharmony_ci  // This tests outlining of a single, empty basic block.
28fd4e5da5Sopenharmony_ci
29fd4e5da5Sopenharmony_ci  std::string shader = R"(
30fd4e5da5Sopenharmony_ci               OpCapability Shader
31fd4e5da5Sopenharmony_ci          %1 = OpExtInstImport "GLSL.std.450"
32fd4e5da5Sopenharmony_ci               OpMemoryModel Logical GLSL450
33fd4e5da5Sopenharmony_ci               OpEntryPoint Fragment %4 "main"
34fd4e5da5Sopenharmony_ci               OpExecutionMode %4 OriginUpperLeft
35fd4e5da5Sopenharmony_ci               OpSource ESSL 310
36fd4e5da5Sopenharmony_ci               OpName %4 "main"
37fd4e5da5Sopenharmony_ci          %2 = OpTypeVoid
38fd4e5da5Sopenharmony_ci          %3 = OpTypeFunction %2
39fd4e5da5Sopenharmony_ci          %4 = OpFunction %2 None %3
40fd4e5da5Sopenharmony_ci          %5 = OpLabel
41fd4e5da5Sopenharmony_ci               OpReturn
42fd4e5da5Sopenharmony_ci               OpFunctionEnd
43fd4e5da5Sopenharmony_ci  )";
44fd4e5da5Sopenharmony_ci
45fd4e5da5Sopenharmony_ci  const auto env = SPV_ENV_UNIVERSAL_1_4;
46fd4e5da5Sopenharmony_ci  const auto consumer = nullptr;
47fd4e5da5Sopenharmony_ci  const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption);
48fd4e5da5Sopenharmony_ci  spvtools::ValidatorOptions validator_options;
49fd4e5da5Sopenharmony_ci  ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
50fd4e5da5Sopenharmony_ci                                               kConsoleMessageConsumer));
51fd4e5da5Sopenharmony_ci  TransformationContext transformation_context(
52fd4e5da5Sopenharmony_ci      MakeUnique<FactManager>(context.get()), validator_options);
53fd4e5da5Sopenharmony_ci  TransformationOutlineFunction transformation(5, 5, /* not relevant */ 200,
54fd4e5da5Sopenharmony_ci                                               100, 101, 102, 103,
55fd4e5da5Sopenharmony_ci                                               /* not relevant */ 201, {}, {});
56fd4e5da5Sopenharmony_ci  ASSERT_TRUE(
57fd4e5da5Sopenharmony_ci      transformation.IsApplicable(context.get(), transformation_context));
58fd4e5da5Sopenharmony_ci  ApplyAndCheckFreshIds(transformation, context.get(), &transformation_context);
59fd4e5da5Sopenharmony_ci  ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
60fd4e5da5Sopenharmony_ci                                               kConsoleMessageConsumer));
61fd4e5da5Sopenharmony_ci
62fd4e5da5Sopenharmony_ci  std::string after_transformation = R"(
63fd4e5da5Sopenharmony_ci               OpCapability Shader
64fd4e5da5Sopenharmony_ci          %1 = OpExtInstImport "GLSL.std.450"
65fd4e5da5Sopenharmony_ci               OpMemoryModel Logical GLSL450
66fd4e5da5Sopenharmony_ci               OpEntryPoint Fragment %4 "main"
67fd4e5da5Sopenharmony_ci               OpExecutionMode %4 OriginUpperLeft
68fd4e5da5Sopenharmony_ci               OpSource ESSL 310
69fd4e5da5Sopenharmony_ci               OpName %4 "main"
70fd4e5da5Sopenharmony_ci          %2 = OpTypeVoid
71fd4e5da5Sopenharmony_ci          %3 = OpTypeFunction %2
72fd4e5da5Sopenharmony_ci          %4 = OpFunction %2 None %3
73fd4e5da5Sopenharmony_ci          %5 = OpLabel
74fd4e5da5Sopenharmony_ci        %103 = OpFunctionCall %2 %101
75fd4e5da5Sopenharmony_ci               OpReturn
76fd4e5da5Sopenharmony_ci               OpFunctionEnd
77fd4e5da5Sopenharmony_ci        %101 = OpFunction %2 None %3
78fd4e5da5Sopenharmony_ci        %102 = OpLabel
79fd4e5da5Sopenharmony_ci               OpReturn
80fd4e5da5Sopenharmony_ci               OpFunctionEnd
81fd4e5da5Sopenharmony_ci  )";
82fd4e5da5Sopenharmony_ci  ASSERT_TRUE(IsEqual(env, after_transformation, context.get()));
83fd4e5da5Sopenharmony_ci}
84fd4e5da5Sopenharmony_ci
85fd4e5da5Sopenharmony_ciTEST(TransformationOutlineFunctionTest,
86fd4e5da5Sopenharmony_ci     DoNotOutlineIfRegionStartsWithOpVariable) {
87fd4e5da5Sopenharmony_ci  // This checks that we do not outline the first block of a function if it
88fd4e5da5Sopenharmony_ci  // contains OpVariable.
89fd4e5da5Sopenharmony_ci
90fd4e5da5Sopenharmony_ci  std::string shader = R"(
91fd4e5da5Sopenharmony_ci               OpCapability Shader
92fd4e5da5Sopenharmony_ci          %1 = OpExtInstImport "GLSL.std.450"
93fd4e5da5Sopenharmony_ci               OpMemoryModel Logical GLSL450
94fd4e5da5Sopenharmony_ci               OpEntryPoint Fragment %4 "main"
95fd4e5da5Sopenharmony_ci               OpExecutionMode %4 OriginUpperLeft
96fd4e5da5Sopenharmony_ci               OpSource ESSL 310
97fd4e5da5Sopenharmony_ci               OpName %4 "main"
98fd4e5da5Sopenharmony_ci          %2 = OpTypeVoid
99fd4e5da5Sopenharmony_ci          %3 = OpTypeFunction %2
100fd4e5da5Sopenharmony_ci          %7 = OpTypeBool
101fd4e5da5Sopenharmony_ci          %8 = OpTypePointer Function %7
102fd4e5da5Sopenharmony_ci          %4 = OpFunction %2 None %3
103fd4e5da5Sopenharmony_ci          %5 = OpLabel
104fd4e5da5Sopenharmony_ci          %6 = OpVariable %8 Function
105fd4e5da5Sopenharmony_ci               OpReturn
106fd4e5da5Sopenharmony_ci               OpFunctionEnd
107fd4e5da5Sopenharmony_ci  )";
108fd4e5da5Sopenharmony_ci
109fd4e5da5Sopenharmony_ci  const auto env = SPV_ENV_UNIVERSAL_1_4;
110fd4e5da5Sopenharmony_ci  const auto consumer = nullptr;
111fd4e5da5Sopenharmony_ci  const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption);
112fd4e5da5Sopenharmony_ci  spvtools::ValidatorOptions validator_options;
113fd4e5da5Sopenharmony_ci  ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
114fd4e5da5Sopenharmony_ci                                               kConsoleMessageConsumer));
115fd4e5da5Sopenharmony_ci  TransformationContext transformation_context(
116fd4e5da5Sopenharmony_ci      MakeUnique<FactManager>(context.get()), validator_options);
117fd4e5da5Sopenharmony_ci  TransformationOutlineFunction transformation(5, 5, /* not relevant */ 200,
118fd4e5da5Sopenharmony_ci                                               100, 101, 102, 103,
119fd4e5da5Sopenharmony_ci                                               /* not relevant */ 201, {}, {});
120fd4e5da5Sopenharmony_ci  ASSERT_FALSE(
121fd4e5da5Sopenharmony_ci      transformation.IsApplicable(context.get(), transformation_context));
122fd4e5da5Sopenharmony_ci}
123fd4e5da5Sopenharmony_ci
124fd4e5da5Sopenharmony_ciTEST(TransformationOutlineFunctionTest, OutlineInterestingControlFlowNoState) {
125fd4e5da5Sopenharmony_ci  // This tests outlining of some non-trivial control flow, but such that the
126fd4e5da5Sopenharmony_ci  // basic blocks in the control flow do not actually do anything.
127fd4e5da5Sopenharmony_ci
128fd4e5da5Sopenharmony_ci  std::string shader = R"(
129fd4e5da5Sopenharmony_ci               OpCapability Shader
130fd4e5da5Sopenharmony_ci          %1 = OpExtInstImport "GLSL.std.450"
131fd4e5da5Sopenharmony_ci               OpMemoryModel Logical GLSL450
132fd4e5da5Sopenharmony_ci               OpEntryPoint Fragment %4 "main"
133fd4e5da5Sopenharmony_ci               OpExecutionMode %4 OriginUpperLeft
134fd4e5da5Sopenharmony_ci               OpSource ESSL 310
135fd4e5da5Sopenharmony_ci               OpName %4 "main"
136fd4e5da5Sopenharmony_ci          %2 = OpTypeVoid
137fd4e5da5Sopenharmony_ci         %20 = OpTypeBool
138fd4e5da5Sopenharmony_ci         %21 = OpConstantTrue %20
139fd4e5da5Sopenharmony_ci          %3 = OpTypeFunction %2
140fd4e5da5Sopenharmony_ci          %4 = OpFunction %2 None %3
141fd4e5da5Sopenharmony_ci          %5 = OpLabel
142fd4e5da5Sopenharmony_ci               OpBranch %6
143fd4e5da5Sopenharmony_ci          %6 = OpLabel
144fd4e5da5Sopenharmony_ci               OpBranch %7
145fd4e5da5Sopenharmony_ci          %7 = OpLabel
146fd4e5da5Sopenharmony_ci               OpSelectionMerge %9 None
147fd4e5da5Sopenharmony_ci               OpBranchConditional %21 %8 %9
148fd4e5da5Sopenharmony_ci          %8 = OpLabel
149fd4e5da5Sopenharmony_ci               OpBranch %9
150fd4e5da5Sopenharmony_ci          %9 = OpLabel
151fd4e5da5Sopenharmony_ci               OpLoopMerge %12 %11 None
152fd4e5da5Sopenharmony_ci               OpBranch %10
153fd4e5da5Sopenharmony_ci         %10 = OpLabel
154fd4e5da5Sopenharmony_ci               OpBranchConditional %21 %11 %12
155fd4e5da5Sopenharmony_ci         %11 = OpLabel
156fd4e5da5Sopenharmony_ci               OpBranch %9
157fd4e5da5Sopenharmony_ci         %12 = OpLabel
158fd4e5da5Sopenharmony_ci               OpBranch %13
159fd4e5da5Sopenharmony_ci         %13 = OpLabel
160fd4e5da5Sopenharmony_ci               OpReturn
161fd4e5da5Sopenharmony_ci               OpFunctionEnd
162fd4e5da5Sopenharmony_ci  )";
163fd4e5da5Sopenharmony_ci
164fd4e5da5Sopenharmony_ci  const auto env = SPV_ENV_UNIVERSAL_1_4;
165fd4e5da5Sopenharmony_ci  const auto consumer = nullptr;
166fd4e5da5Sopenharmony_ci  const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption);
167fd4e5da5Sopenharmony_ci  spvtools::ValidatorOptions validator_options;
168fd4e5da5Sopenharmony_ci  ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
169fd4e5da5Sopenharmony_ci                                               kConsoleMessageConsumer));
170fd4e5da5Sopenharmony_ci  TransformationContext transformation_context(
171fd4e5da5Sopenharmony_ci      MakeUnique<FactManager>(context.get()), validator_options);
172fd4e5da5Sopenharmony_ci  TransformationOutlineFunction transformation(6, 13, /* not relevant */
173fd4e5da5Sopenharmony_ci                                               200, 100, 101, 102, 103,
174fd4e5da5Sopenharmony_ci                                               /* not relevant */ 201, {}, {});
175fd4e5da5Sopenharmony_ci  ASSERT_TRUE(
176fd4e5da5Sopenharmony_ci      transformation.IsApplicable(context.get(), transformation_context));
177fd4e5da5Sopenharmony_ci  ApplyAndCheckFreshIds(transformation, context.get(), &transformation_context);
178fd4e5da5Sopenharmony_ci  ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
179fd4e5da5Sopenharmony_ci                                               kConsoleMessageConsumer));
180fd4e5da5Sopenharmony_ci
181fd4e5da5Sopenharmony_ci  std::string after_transformation = R"(
182fd4e5da5Sopenharmony_ci               OpCapability Shader
183fd4e5da5Sopenharmony_ci          %1 = OpExtInstImport "GLSL.std.450"
184fd4e5da5Sopenharmony_ci               OpMemoryModel Logical GLSL450
185fd4e5da5Sopenharmony_ci               OpEntryPoint Fragment %4 "main"
186fd4e5da5Sopenharmony_ci               OpExecutionMode %4 OriginUpperLeft
187fd4e5da5Sopenharmony_ci               OpSource ESSL 310
188fd4e5da5Sopenharmony_ci               OpName %4 "main"
189fd4e5da5Sopenharmony_ci          %2 = OpTypeVoid
190fd4e5da5Sopenharmony_ci         %20 = OpTypeBool
191fd4e5da5Sopenharmony_ci         %21 = OpConstantTrue %20
192fd4e5da5Sopenharmony_ci          %3 = OpTypeFunction %2
193fd4e5da5Sopenharmony_ci          %4 = OpFunction %2 None %3
194fd4e5da5Sopenharmony_ci          %5 = OpLabel
195fd4e5da5Sopenharmony_ci               OpBranch %6
196fd4e5da5Sopenharmony_ci          %6 = OpLabel
197fd4e5da5Sopenharmony_ci        %103 = OpFunctionCall %2 %101
198fd4e5da5Sopenharmony_ci               OpReturn
199fd4e5da5Sopenharmony_ci               OpFunctionEnd
200fd4e5da5Sopenharmony_ci        %101 = OpFunction %2 None %3
201fd4e5da5Sopenharmony_ci        %102 = OpLabel
202fd4e5da5Sopenharmony_ci               OpBranch %7
203fd4e5da5Sopenharmony_ci          %7 = OpLabel
204fd4e5da5Sopenharmony_ci               OpSelectionMerge %9 None
205fd4e5da5Sopenharmony_ci               OpBranchConditional %21 %8 %9
206fd4e5da5Sopenharmony_ci          %8 = OpLabel
207fd4e5da5Sopenharmony_ci               OpBranch %9
208fd4e5da5Sopenharmony_ci          %9 = OpLabel
209fd4e5da5Sopenharmony_ci               OpLoopMerge %12 %11 None
210fd4e5da5Sopenharmony_ci               OpBranch %10
211fd4e5da5Sopenharmony_ci         %10 = OpLabel
212fd4e5da5Sopenharmony_ci               OpBranchConditional %21 %11 %12
213fd4e5da5Sopenharmony_ci         %11 = OpLabel
214fd4e5da5Sopenharmony_ci               OpBranch %9
215fd4e5da5Sopenharmony_ci         %12 = OpLabel
216fd4e5da5Sopenharmony_ci               OpBranch %13
217fd4e5da5Sopenharmony_ci         %13 = OpLabel
218fd4e5da5Sopenharmony_ci               OpReturn
219fd4e5da5Sopenharmony_ci               OpFunctionEnd
220fd4e5da5Sopenharmony_ci  )";
221fd4e5da5Sopenharmony_ci  ASSERT_TRUE(IsEqual(env, after_transformation, context.get()));
222fd4e5da5Sopenharmony_ci}
223fd4e5da5Sopenharmony_ci
224fd4e5da5Sopenharmony_ciTEST(TransformationOutlineFunctionTest, OutlineCodeThatGeneratesUnusedIds) {
225fd4e5da5Sopenharmony_ci  // This tests outlining of a single basic block that does some computation,
226fd4e5da5Sopenharmony_ci  // but that does not use nor generate ids required outside of the outlined
227fd4e5da5Sopenharmony_ci  // region.
228fd4e5da5Sopenharmony_ci
229fd4e5da5Sopenharmony_ci  std::string shader = 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          %2 = OpTypeVoid
238fd4e5da5Sopenharmony_ci         %20 = OpTypeInt 32 1
239fd4e5da5Sopenharmony_ci         %21 = OpConstant %20 5
240fd4e5da5Sopenharmony_ci          %3 = OpTypeFunction %2
241fd4e5da5Sopenharmony_ci          %4 = OpFunction %2 None %3
242fd4e5da5Sopenharmony_ci          %5 = OpLabel
243fd4e5da5Sopenharmony_ci               OpBranch %6
244fd4e5da5Sopenharmony_ci          %6 = OpLabel
245fd4e5da5Sopenharmony_ci          %7 = OpCopyObject %20 %21
246fd4e5da5Sopenharmony_ci          %8 = OpCopyObject %20 %21
247fd4e5da5Sopenharmony_ci          %9 = OpIAdd %20 %7 %8
248fd4e5da5Sopenharmony_ci               OpReturn
249fd4e5da5Sopenharmony_ci               OpFunctionEnd
250fd4e5da5Sopenharmony_ci  )";
251fd4e5da5Sopenharmony_ci
252fd4e5da5Sopenharmony_ci  const auto env = SPV_ENV_UNIVERSAL_1_4;
253fd4e5da5Sopenharmony_ci  const auto consumer = nullptr;
254fd4e5da5Sopenharmony_ci  const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption);
255fd4e5da5Sopenharmony_ci  spvtools::ValidatorOptions validator_options;
256fd4e5da5Sopenharmony_ci  ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
257fd4e5da5Sopenharmony_ci                                               kConsoleMessageConsumer));
258fd4e5da5Sopenharmony_ci  TransformationContext transformation_context(
259fd4e5da5Sopenharmony_ci      MakeUnique<FactManager>(context.get()), validator_options);
260fd4e5da5Sopenharmony_ci  TransformationOutlineFunction transformation(6, 6, /* not relevant */ 200,
261fd4e5da5Sopenharmony_ci                                               100, 101, 102, 103,
262fd4e5da5Sopenharmony_ci                                               /* not relevant */ 201, {}, {});
263fd4e5da5Sopenharmony_ci  ASSERT_TRUE(
264fd4e5da5Sopenharmony_ci      transformation.IsApplicable(context.get(), transformation_context));
265fd4e5da5Sopenharmony_ci  ApplyAndCheckFreshIds(transformation, context.get(), &transformation_context);
266fd4e5da5Sopenharmony_ci  ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
267fd4e5da5Sopenharmony_ci                                               kConsoleMessageConsumer));
268fd4e5da5Sopenharmony_ci
269fd4e5da5Sopenharmony_ci  std::string after_transformation = R"(
270fd4e5da5Sopenharmony_ci               OpCapability Shader
271fd4e5da5Sopenharmony_ci          %1 = OpExtInstImport "GLSL.std.450"
272fd4e5da5Sopenharmony_ci               OpMemoryModel Logical GLSL450
273fd4e5da5Sopenharmony_ci               OpEntryPoint Fragment %4 "main"
274fd4e5da5Sopenharmony_ci               OpExecutionMode %4 OriginUpperLeft
275fd4e5da5Sopenharmony_ci               OpSource ESSL 310
276fd4e5da5Sopenharmony_ci               OpName %4 "main"
277fd4e5da5Sopenharmony_ci          %2 = OpTypeVoid
278fd4e5da5Sopenharmony_ci         %20 = OpTypeInt 32 1
279fd4e5da5Sopenharmony_ci         %21 = OpConstant %20 5
280fd4e5da5Sopenharmony_ci          %3 = OpTypeFunction %2
281fd4e5da5Sopenharmony_ci          %4 = OpFunction %2 None %3
282fd4e5da5Sopenharmony_ci          %5 = OpLabel
283fd4e5da5Sopenharmony_ci               OpBranch %6
284fd4e5da5Sopenharmony_ci          %6 = OpLabel
285fd4e5da5Sopenharmony_ci        %103 = OpFunctionCall %2 %101
286fd4e5da5Sopenharmony_ci               OpReturn
287fd4e5da5Sopenharmony_ci               OpFunctionEnd
288fd4e5da5Sopenharmony_ci        %101 = OpFunction %2 None %3
289fd4e5da5Sopenharmony_ci        %102 = OpLabel
290fd4e5da5Sopenharmony_ci          %7 = OpCopyObject %20 %21
291fd4e5da5Sopenharmony_ci          %8 = OpCopyObject %20 %21
292fd4e5da5Sopenharmony_ci          %9 = OpIAdd %20 %7 %8
293fd4e5da5Sopenharmony_ci               OpReturn
294fd4e5da5Sopenharmony_ci               OpFunctionEnd
295fd4e5da5Sopenharmony_ci  )";
296fd4e5da5Sopenharmony_ci  ASSERT_TRUE(IsEqual(env, after_transformation, context.get()));
297fd4e5da5Sopenharmony_ci}
298fd4e5da5Sopenharmony_ci
299fd4e5da5Sopenharmony_ciTEST(TransformationOutlineFunctionTest, OutlineCodeThatGeneratesSingleUsedId) {
300fd4e5da5Sopenharmony_ci  // This tests outlining of a block that generates an id that is used in a
301fd4e5da5Sopenharmony_ci  // later block.
302fd4e5da5Sopenharmony_ci
303fd4e5da5Sopenharmony_ci  std::string shader = R"(
304fd4e5da5Sopenharmony_ci               OpCapability Shader
305fd4e5da5Sopenharmony_ci          %1 = OpExtInstImport "GLSL.std.450"
306fd4e5da5Sopenharmony_ci               OpMemoryModel Logical GLSL450
307fd4e5da5Sopenharmony_ci               OpEntryPoint Fragment %4 "main"
308fd4e5da5Sopenharmony_ci               OpExecutionMode %4 OriginUpperLeft
309fd4e5da5Sopenharmony_ci               OpSource ESSL 310
310fd4e5da5Sopenharmony_ci               OpName %4 "main"
311fd4e5da5Sopenharmony_ci          %2 = OpTypeVoid
312fd4e5da5Sopenharmony_ci         %20 = OpTypeInt 32 1
313fd4e5da5Sopenharmony_ci         %21 = OpConstant %20 5
314fd4e5da5Sopenharmony_ci          %3 = OpTypeFunction %2
315fd4e5da5Sopenharmony_ci          %4 = OpFunction %2 None %3
316fd4e5da5Sopenharmony_ci          %5 = OpLabel
317fd4e5da5Sopenharmony_ci               OpBranch %6
318fd4e5da5Sopenharmony_ci          %6 = OpLabel
319fd4e5da5Sopenharmony_ci          %7 = OpCopyObject %20 %21
320fd4e5da5Sopenharmony_ci          %8 = OpCopyObject %20 %21
321fd4e5da5Sopenharmony_ci          %9 = OpIAdd %20 %7 %8
322fd4e5da5Sopenharmony_ci               OpBranch %10
323fd4e5da5Sopenharmony_ci         %10 = OpLabel
324fd4e5da5Sopenharmony_ci         %11 = OpCopyObject %20 %9
325fd4e5da5Sopenharmony_ci               OpReturn
326fd4e5da5Sopenharmony_ci               OpFunctionEnd
327fd4e5da5Sopenharmony_ci  )";
328fd4e5da5Sopenharmony_ci
329fd4e5da5Sopenharmony_ci  const auto env = SPV_ENV_UNIVERSAL_1_4;
330fd4e5da5Sopenharmony_ci  const auto consumer = nullptr;
331fd4e5da5Sopenharmony_ci  const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption);
332fd4e5da5Sopenharmony_ci  spvtools::ValidatorOptions validator_options;
333fd4e5da5Sopenharmony_ci  ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
334fd4e5da5Sopenharmony_ci                                               kConsoleMessageConsumer));
335fd4e5da5Sopenharmony_ci  TransformationContext transformation_context(
336fd4e5da5Sopenharmony_ci      MakeUnique<FactManager>(context.get()), validator_options);
337fd4e5da5Sopenharmony_ci  TransformationOutlineFunction transformation(6, 6, 99, 100, 101, 102, 103,
338fd4e5da5Sopenharmony_ci                                               105, {}, {{9, 104}});
339fd4e5da5Sopenharmony_ci  ASSERT_TRUE(
340fd4e5da5Sopenharmony_ci      transformation.IsApplicable(context.get(), transformation_context));
341fd4e5da5Sopenharmony_ci  ApplyAndCheckFreshIds(transformation, context.get(), &transformation_context);
342fd4e5da5Sopenharmony_ci  ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
343fd4e5da5Sopenharmony_ci                                               kConsoleMessageConsumer));
344fd4e5da5Sopenharmony_ci
345fd4e5da5Sopenharmony_ci  std::string after_transformation = R"(
346fd4e5da5Sopenharmony_ci               OpCapability Shader
347fd4e5da5Sopenharmony_ci          %1 = OpExtInstImport "GLSL.std.450"
348fd4e5da5Sopenharmony_ci               OpMemoryModel Logical GLSL450
349fd4e5da5Sopenharmony_ci               OpEntryPoint Fragment %4 "main"
350fd4e5da5Sopenharmony_ci               OpExecutionMode %4 OriginUpperLeft
351fd4e5da5Sopenharmony_ci               OpSource ESSL 310
352fd4e5da5Sopenharmony_ci               OpName %4 "main"
353fd4e5da5Sopenharmony_ci          %2 = OpTypeVoid
354fd4e5da5Sopenharmony_ci         %20 = OpTypeInt 32 1
355fd4e5da5Sopenharmony_ci         %21 = OpConstant %20 5
356fd4e5da5Sopenharmony_ci          %3 = OpTypeFunction %2
357fd4e5da5Sopenharmony_ci         %99 = OpTypeStruct %20
358fd4e5da5Sopenharmony_ci        %100 = OpTypeFunction %99
359fd4e5da5Sopenharmony_ci          %4 = OpFunction %2 None %3
360fd4e5da5Sopenharmony_ci          %5 = OpLabel
361fd4e5da5Sopenharmony_ci               OpBranch %6
362fd4e5da5Sopenharmony_ci          %6 = OpLabel
363fd4e5da5Sopenharmony_ci        %103 = OpFunctionCall %99 %101
364fd4e5da5Sopenharmony_ci          %9 = OpCompositeExtract %20 %103 0
365fd4e5da5Sopenharmony_ci               OpBranch %10
366fd4e5da5Sopenharmony_ci         %10 = OpLabel
367fd4e5da5Sopenharmony_ci         %11 = OpCopyObject %20 %9
368fd4e5da5Sopenharmony_ci               OpReturn
369fd4e5da5Sopenharmony_ci               OpFunctionEnd
370fd4e5da5Sopenharmony_ci        %101 = OpFunction %99 None %100
371fd4e5da5Sopenharmony_ci        %102 = OpLabel
372fd4e5da5Sopenharmony_ci          %7 = OpCopyObject %20 %21
373fd4e5da5Sopenharmony_ci          %8 = OpCopyObject %20 %21
374fd4e5da5Sopenharmony_ci        %104 = OpIAdd %20 %7 %8
375fd4e5da5Sopenharmony_ci        %105 = OpCompositeConstruct %99 %104
376fd4e5da5Sopenharmony_ci               OpReturnValue %105
377fd4e5da5Sopenharmony_ci               OpFunctionEnd
378fd4e5da5Sopenharmony_ci  )";
379fd4e5da5Sopenharmony_ci  ASSERT_TRUE(IsEqual(env, after_transformation, context.get()));
380fd4e5da5Sopenharmony_ci}
381fd4e5da5Sopenharmony_ci
382fd4e5da5Sopenharmony_ciTEST(TransformationOutlineFunctionTest, OutlineDiamondThatGeneratesSeveralIds) {
383fd4e5da5Sopenharmony_ci  // This tests outlining of several blocks that generate a number of ids that
384fd4e5da5Sopenharmony_ci  // are used in later blocks.
385fd4e5da5Sopenharmony_ci
386fd4e5da5Sopenharmony_ci  std::string shader = R"(
387fd4e5da5Sopenharmony_ci               OpCapability Shader
388fd4e5da5Sopenharmony_ci          %1 = OpExtInstImport "GLSL.std.450"
389fd4e5da5Sopenharmony_ci               OpMemoryModel Logical GLSL450
390fd4e5da5Sopenharmony_ci               OpEntryPoint Fragment %4 "main"
391fd4e5da5Sopenharmony_ci               OpExecutionMode %4 OriginUpperLeft
392fd4e5da5Sopenharmony_ci               OpSource ESSL 310
393fd4e5da5Sopenharmony_ci               OpName %4 "main"
394fd4e5da5Sopenharmony_ci          %2 = OpTypeVoid
395fd4e5da5Sopenharmony_ci         %20 = OpTypeInt 32 1
396fd4e5da5Sopenharmony_ci         %21 = OpConstant %20 5
397fd4e5da5Sopenharmony_ci         %22 = OpTypeBool
398fd4e5da5Sopenharmony_ci          %3 = OpTypeFunction %2
399fd4e5da5Sopenharmony_ci          %4 = OpFunction %2 None %3
400fd4e5da5Sopenharmony_ci          %5 = OpLabel
401fd4e5da5Sopenharmony_ci               OpBranch %6
402fd4e5da5Sopenharmony_ci          %6 = OpLabel
403fd4e5da5Sopenharmony_ci          %7 = OpCopyObject %20 %21
404fd4e5da5Sopenharmony_ci          %8 = OpCopyObject %20 %21
405fd4e5da5Sopenharmony_ci          %9 = OpSLessThan %22 %7 %8
406fd4e5da5Sopenharmony_ci               OpSelectionMerge %12 None
407fd4e5da5Sopenharmony_ci               OpBranchConditional %9 %10 %11
408fd4e5da5Sopenharmony_ci         %10 = OpLabel
409fd4e5da5Sopenharmony_ci         %13 = OpIAdd %20 %7 %8
410fd4e5da5Sopenharmony_ci               OpBranch %12
411fd4e5da5Sopenharmony_ci         %11 = OpLabel
412fd4e5da5Sopenharmony_ci         %14 = OpIAdd %20 %7 %7
413fd4e5da5Sopenharmony_ci               OpBranch %12
414fd4e5da5Sopenharmony_ci         %12 = OpLabel
415fd4e5da5Sopenharmony_ci         %15 = OpPhi %20 %13 %10 %14 %11
416fd4e5da5Sopenharmony_ci               OpBranch %80
417fd4e5da5Sopenharmony_ci         %80 = OpLabel
418fd4e5da5Sopenharmony_ci               OpBranch %16
419fd4e5da5Sopenharmony_ci         %16 = OpLabel
420fd4e5da5Sopenharmony_ci         %17 = OpCopyObject %20 %15
421fd4e5da5Sopenharmony_ci         %18 = OpCopyObject %22 %9
422fd4e5da5Sopenharmony_ci         %19 = OpIAdd %20 %7 %8
423fd4e5da5Sopenharmony_ci               OpReturn
424fd4e5da5Sopenharmony_ci               OpFunctionEnd
425fd4e5da5Sopenharmony_ci  )";
426fd4e5da5Sopenharmony_ci
427fd4e5da5Sopenharmony_ci  const auto env = SPV_ENV_UNIVERSAL_1_4;
428fd4e5da5Sopenharmony_ci  const auto consumer = nullptr;
429fd4e5da5Sopenharmony_ci  const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption);
430fd4e5da5Sopenharmony_ci  spvtools::ValidatorOptions validator_options;
431fd4e5da5Sopenharmony_ci  ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
432fd4e5da5Sopenharmony_ci                                               kConsoleMessageConsumer));
433fd4e5da5Sopenharmony_ci  TransformationContext transformation_context(
434fd4e5da5Sopenharmony_ci      MakeUnique<FactManager>(context.get()), validator_options);
435fd4e5da5Sopenharmony_ci  TransformationOutlineFunction transformation(
436fd4e5da5Sopenharmony_ci      6, 80, 100, 101, 102, 103, 104, 105, {},
437fd4e5da5Sopenharmony_ci      {{15, 106}, {9, 107}, {7, 108}, {8, 109}});
438fd4e5da5Sopenharmony_ci  ASSERT_TRUE(
439fd4e5da5Sopenharmony_ci      transformation.IsApplicable(context.get(), transformation_context));
440fd4e5da5Sopenharmony_ci  ApplyAndCheckFreshIds(transformation, context.get(), &transformation_context);
441fd4e5da5Sopenharmony_ci  ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
442fd4e5da5Sopenharmony_ci                                               kConsoleMessageConsumer));
443fd4e5da5Sopenharmony_ci
444fd4e5da5Sopenharmony_ci  std::string after_transformation = R"(
445fd4e5da5Sopenharmony_ci               OpCapability Shader
446fd4e5da5Sopenharmony_ci          %1 = OpExtInstImport "GLSL.std.450"
447fd4e5da5Sopenharmony_ci               OpMemoryModel Logical GLSL450
448fd4e5da5Sopenharmony_ci               OpEntryPoint Fragment %4 "main"
449fd4e5da5Sopenharmony_ci               OpExecutionMode %4 OriginUpperLeft
450fd4e5da5Sopenharmony_ci               OpSource ESSL 310
451fd4e5da5Sopenharmony_ci               OpName %4 "main"
452fd4e5da5Sopenharmony_ci          %2 = OpTypeVoid
453fd4e5da5Sopenharmony_ci         %20 = OpTypeInt 32 1
454fd4e5da5Sopenharmony_ci         %21 = OpConstant %20 5
455fd4e5da5Sopenharmony_ci         %22 = OpTypeBool
456fd4e5da5Sopenharmony_ci          %3 = OpTypeFunction %2
457fd4e5da5Sopenharmony_ci        %100 = OpTypeStruct %20 %20 %22 %20
458fd4e5da5Sopenharmony_ci        %101 = OpTypeFunction %100
459fd4e5da5Sopenharmony_ci          %4 = OpFunction %2 None %3
460fd4e5da5Sopenharmony_ci          %5 = OpLabel
461fd4e5da5Sopenharmony_ci               OpBranch %6
462fd4e5da5Sopenharmony_ci          %6 = OpLabel
463fd4e5da5Sopenharmony_ci        %104 = OpFunctionCall %100 %102
464fd4e5da5Sopenharmony_ci          %7 = OpCompositeExtract %20 %104 0
465fd4e5da5Sopenharmony_ci          %8 = OpCompositeExtract %20 %104 1
466fd4e5da5Sopenharmony_ci          %9 = OpCompositeExtract %22 %104 2
467fd4e5da5Sopenharmony_ci         %15 = OpCompositeExtract %20 %104 3
468fd4e5da5Sopenharmony_ci               OpBranch %16
469fd4e5da5Sopenharmony_ci         %16 = OpLabel
470fd4e5da5Sopenharmony_ci         %17 = OpCopyObject %20 %15
471fd4e5da5Sopenharmony_ci         %18 = OpCopyObject %22 %9
472fd4e5da5Sopenharmony_ci         %19 = OpIAdd %20 %7 %8
473fd4e5da5Sopenharmony_ci               OpReturn
474fd4e5da5Sopenharmony_ci               OpFunctionEnd
475fd4e5da5Sopenharmony_ci        %102 = OpFunction %100 None %101
476fd4e5da5Sopenharmony_ci        %103 = OpLabel
477fd4e5da5Sopenharmony_ci        %108 = OpCopyObject %20 %21
478fd4e5da5Sopenharmony_ci        %109 = OpCopyObject %20 %21
479fd4e5da5Sopenharmony_ci        %107 = OpSLessThan %22 %108 %109
480fd4e5da5Sopenharmony_ci               OpSelectionMerge %12 None
481fd4e5da5Sopenharmony_ci               OpBranchConditional %107 %10 %11
482fd4e5da5Sopenharmony_ci         %10 = OpLabel
483fd4e5da5Sopenharmony_ci         %13 = OpIAdd %20 %108 %109
484fd4e5da5Sopenharmony_ci               OpBranch %12
485fd4e5da5Sopenharmony_ci         %11 = OpLabel
486fd4e5da5Sopenharmony_ci         %14 = OpIAdd %20 %108 %108
487fd4e5da5Sopenharmony_ci               OpBranch %12
488fd4e5da5Sopenharmony_ci         %12 = OpLabel
489fd4e5da5Sopenharmony_ci        %106 = OpPhi %20 %13 %10 %14 %11
490fd4e5da5Sopenharmony_ci               OpBranch %80
491fd4e5da5Sopenharmony_ci         %80 = OpLabel
492fd4e5da5Sopenharmony_ci        %105 = OpCompositeConstruct %100 %108 %109 %107 %106
493fd4e5da5Sopenharmony_ci               OpReturnValue %105
494fd4e5da5Sopenharmony_ci               OpFunctionEnd
495fd4e5da5Sopenharmony_ci  )";
496fd4e5da5Sopenharmony_ci  ASSERT_TRUE(IsEqual(env, after_transformation, context.get()));
497fd4e5da5Sopenharmony_ci}
498fd4e5da5Sopenharmony_ci
499fd4e5da5Sopenharmony_ciTEST(TransformationOutlineFunctionTest, OutlineCodeThatUsesASingleId) {
500fd4e5da5Sopenharmony_ci  // This tests outlining of a block that uses an id defined earlier.
501fd4e5da5Sopenharmony_ci
502fd4e5da5Sopenharmony_ci  std::string shader = R"(
503fd4e5da5Sopenharmony_ci               OpCapability Shader
504fd4e5da5Sopenharmony_ci          %1 = OpExtInstImport "GLSL.std.450"
505fd4e5da5Sopenharmony_ci               OpMemoryModel Logical GLSL450
506fd4e5da5Sopenharmony_ci               OpEntryPoint Fragment %4 "main"
507fd4e5da5Sopenharmony_ci               OpExecutionMode %4 OriginUpperLeft
508fd4e5da5Sopenharmony_ci               OpSource ESSL 310
509fd4e5da5Sopenharmony_ci               OpName %4 "main"
510fd4e5da5Sopenharmony_ci          %2 = OpTypeVoid
511fd4e5da5Sopenharmony_ci         %20 = OpTypeInt 32 1
512fd4e5da5Sopenharmony_ci         %21 = OpConstant %20 5
513fd4e5da5Sopenharmony_ci          %3 = OpTypeFunction %2
514fd4e5da5Sopenharmony_ci          %4 = OpFunction %2 None %3
515fd4e5da5Sopenharmony_ci          %5 = OpLabel
516fd4e5da5Sopenharmony_ci          %7 = OpCopyObject %20 %21
517fd4e5da5Sopenharmony_ci               OpBranch %6
518fd4e5da5Sopenharmony_ci          %6 = OpLabel
519fd4e5da5Sopenharmony_ci          %8 = OpCopyObject %20 %7
520fd4e5da5Sopenharmony_ci               OpBranch %10
521fd4e5da5Sopenharmony_ci         %10 = OpLabel
522fd4e5da5Sopenharmony_ci               OpReturn
523fd4e5da5Sopenharmony_ci               OpFunctionEnd
524fd4e5da5Sopenharmony_ci  )";
525fd4e5da5Sopenharmony_ci
526fd4e5da5Sopenharmony_ci  const auto env = SPV_ENV_UNIVERSAL_1_4;
527fd4e5da5Sopenharmony_ci  const auto consumer = nullptr;
528fd4e5da5Sopenharmony_ci  const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption);
529fd4e5da5Sopenharmony_ci  spvtools::ValidatorOptions validator_options;
530fd4e5da5Sopenharmony_ci  ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
531fd4e5da5Sopenharmony_ci                                               kConsoleMessageConsumer));
532fd4e5da5Sopenharmony_ci  TransformationContext transformation_context(
533fd4e5da5Sopenharmony_ci      MakeUnique<FactManager>(context.get()), validator_options);
534fd4e5da5Sopenharmony_ci  TransformationOutlineFunction transformation(6, 6, 100, 101, 102, 103, 104,
535fd4e5da5Sopenharmony_ci                                               105, {{7, 106}}, {});
536fd4e5da5Sopenharmony_ci  ASSERT_TRUE(
537fd4e5da5Sopenharmony_ci      transformation.IsApplicable(context.get(), transformation_context));
538fd4e5da5Sopenharmony_ci  ApplyAndCheckFreshIds(transformation, context.get(), &transformation_context);
539fd4e5da5Sopenharmony_ci  ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
540fd4e5da5Sopenharmony_ci                                               kConsoleMessageConsumer));
541fd4e5da5Sopenharmony_ci
542fd4e5da5Sopenharmony_ci  std::string after_transformation = R"(
543fd4e5da5Sopenharmony_ci               OpCapability Shader
544fd4e5da5Sopenharmony_ci          %1 = OpExtInstImport "GLSL.std.450"
545fd4e5da5Sopenharmony_ci               OpMemoryModel Logical GLSL450
546fd4e5da5Sopenharmony_ci               OpEntryPoint Fragment %4 "main"
547fd4e5da5Sopenharmony_ci               OpExecutionMode %4 OriginUpperLeft
548fd4e5da5Sopenharmony_ci               OpSource ESSL 310
549fd4e5da5Sopenharmony_ci               OpName %4 "main"
550fd4e5da5Sopenharmony_ci          %2 = OpTypeVoid
551fd4e5da5Sopenharmony_ci         %20 = OpTypeInt 32 1
552fd4e5da5Sopenharmony_ci         %21 = OpConstant %20 5
553fd4e5da5Sopenharmony_ci          %3 = OpTypeFunction %2
554fd4e5da5Sopenharmony_ci        %101 = OpTypeFunction %2 %20
555fd4e5da5Sopenharmony_ci          %4 = OpFunction %2 None %3
556fd4e5da5Sopenharmony_ci          %5 = OpLabel
557fd4e5da5Sopenharmony_ci          %7 = OpCopyObject %20 %21
558fd4e5da5Sopenharmony_ci               OpBranch %6
559fd4e5da5Sopenharmony_ci          %6 = OpLabel
560fd4e5da5Sopenharmony_ci        %104 = OpFunctionCall %2 %102 %7
561fd4e5da5Sopenharmony_ci               OpBranch %10
562fd4e5da5Sopenharmony_ci         %10 = OpLabel
563fd4e5da5Sopenharmony_ci               OpReturn
564fd4e5da5Sopenharmony_ci               OpFunctionEnd
565fd4e5da5Sopenharmony_ci        %102 = OpFunction %2 None %101
566fd4e5da5Sopenharmony_ci        %106 = OpFunctionParameter %20
567fd4e5da5Sopenharmony_ci        %103 = OpLabel
568fd4e5da5Sopenharmony_ci          %8 = OpCopyObject %20 %106
569fd4e5da5Sopenharmony_ci               OpReturn
570fd4e5da5Sopenharmony_ci               OpFunctionEnd
571fd4e5da5Sopenharmony_ci  )";
572fd4e5da5Sopenharmony_ci  ASSERT_TRUE(IsEqual(env, after_transformation, context.get()));
573fd4e5da5Sopenharmony_ci}
574fd4e5da5Sopenharmony_ci
575fd4e5da5Sopenharmony_ciTEST(TransformationOutlineFunctionTest, OutlineCodeThatUsesAVariable) {
576fd4e5da5Sopenharmony_ci  // This tests outlining of a block that uses a variable.
577fd4e5da5Sopenharmony_ci
578fd4e5da5Sopenharmony_ci  std::string shader = 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               OpName %4 "main"
586fd4e5da5Sopenharmony_ci          %2 = OpTypeVoid
587fd4e5da5Sopenharmony_ci         %20 = OpTypeInt 32 1
588fd4e5da5Sopenharmony_ci         %21 = OpConstant %20 5
589fd4e5da5Sopenharmony_ci          %3 = OpTypeFunction %2
590fd4e5da5Sopenharmony_ci         %12 = OpTypePointer Function %20
591fd4e5da5Sopenharmony_ci          %4 = OpFunction %2 None %3
592fd4e5da5Sopenharmony_ci          %5 = OpLabel
593fd4e5da5Sopenharmony_ci         %13 = OpVariable %12 Function
594fd4e5da5Sopenharmony_ci               OpBranch %6
595fd4e5da5Sopenharmony_ci          %6 = OpLabel
596fd4e5da5Sopenharmony_ci          %8 = OpLoad %20 %13
597fd4e5da5Sopenharmony_ci               OpBranch %10
598fd4e5da5Sopenharmony_ci         %10 = OpLabel
599fd4e5da5Sopenharmony_ci               OpReturn
600fd4e5da5Sopenharmony_ci               OpFunctionEnd
601fd4e5da5Sopenharmony_ci  )";
602fd4e5da5Sopenharmony_ci
603fd4e5da5Sopenharmony_ci  const auto env = SPV_ENV_UNIVERSAL_1_4;
604fd4e5da5Sopenharmony_ci  const auto consumer = nullptr;
605fd4e5da5Sopenharmony_ci  const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption);
606fd4e5da5Sopenharmony_ci  spvtools::ValidatorOptions validator_options;
607fd4e5da5Sopenharmony_ci  ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
608fd4e5da5Sopenharmony_ci                                               kConsoleMessageConsumer));
609fd4e5da5Sopenharmony_ci  TransformationContext transformation_context(
610fd4e5da5Sopenharmony_ci      MakeUnique<FactManager>(context.get()), validator_options);
611fd4e5da5Sopenharmony_ci  TransformationOutlineFunction transformation(6, 6, 100, 101, 102, 103, 104,
612fd4e5da5Sopenharmony_ci                                               105, {{13, 106}}, {});
613fd4e5da5Sopenharmony_ci  ASSERT_TRUE(
614fd4e5da5Sopenharmony_ci      transformation.IsApplicable(context.get(), transformation_context));
615fd4e5da5Sopenharmony_ci  ApplyAndCheckFreshIds(transformation, context.get(), &transformation_context);
616fd4e5da5Sopenharmony_ci  ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
617fd4e5da5Sopenharmony_ci                                               kConsoleMessageConsumer));
618fd4e5da5Sopenharmony_ci
619fd4e5da5Sopenharmony_ci  std::string after_transformation = R"(
620fd4e5da5Sopenharmony_ci               OpCapability Shader
621fd4e5da5Sopenharmony_ci          %1 = OpExtInstImport "GLSL.std.450"
622fd4e5da5Sopenharmony_ci               OpMemoryModel Logical GLSL450
623fd4e5da5Sopenharmony_ci               OpEntryPoint Fragment %4 "main"
624fd4e5da5Sopenharmony_ci               OpExecutionMode %4 OriginUpperLeft
625fd4e5da5Sopenharmony_ci               OpSource ESSL 310
626fd4e5da5Sopenharmony_ci               OpName %4 "main"
627fd4e5da5Sopenharmony_ci          %2 = OpTypeVoid
628fd4e5da5Sopenharmony_ci         %20 = OpTypeInt 32 1
629fd4e5da5Sopenharmony_ci         %21 = OpConstant %20 5
630fd4e5da5Sopenharmony_ci          %3 = OpTypeFunction %2
631fd4e5da5Sopenharmony_ci         %12 = OpTypePointer Function %20
632fd4e5da5Sopenharmony_ci        %101 = OpTypeFunction %2 %12
633fd4e5da5Sopenharmony_ci          %4 = OpFunction %2 None %3
634fd4e5da5Sopenharmony_ci          %5 = OpLabel
635fd4e5da5Sopenharmony_ci         %13 = OpVariable %12 Function
636fd4e5da5Sopenharmony_ci               OpBranch %6
637fd4e5da5Sopenharmony_ci          %6 = OpLabel
638fd4e5da5Sopenharmony_ci        %104 = OpFunctionCall %2 %102 %13
639fd4e5da5Sopenharmony_ci               OpBranch %10
640fd4e5da5Sopenharmony_ci         %10 = OpLabel
641fd4e5da5Sopenharmony_ci               OpReturn
642fd4e5da5Sopenharmony_ci               OpFunctionEnd
643fd4e5da5Sopenharmony_ci        %102 = OpFunction %2 None %101
644fd4e5da5Sopenharmony_ci        %106 = OpFunctionParameter %12
645fd4e5da5Sopenharmony_ci        %103 = OpLabel
646fd4e5da5Sopenharmony_ci          %8 = OpLoad %20 %106
647fd4e5da5Sopenharmony_ci               OpReturn
648fd4e5da5Sopenharmony_ci               OpFunctionEnd
649fd4e5da5Sopenharmony_ci  )";
650fd4e5da5Sopenharmony_ci  ASSERT_TRUE(IsEqual(env, after_transformation, context.get()));
651fd4e5da5Sopenharmony_ci}
652fd4e5da5Sopenharmony_ci
653fd4e5da5Sopenharmony_ciTEST(TransformationOutlineFunctionTest, OutlineCodeThatUsesAParameter) {
654fd4e5da5Sopenharmony_ci  // This tests outlining of a block that uses a function parameter.
655fd4e5da5Sopenharmony_ci
656fd4e5da5Sopenharmony_ci  std::string shader = R"(
657fd4e5da5Sopenharmony_ci               OpCapability Shader
658fd4e5da5Sopenharmony_ci          %1 = OpExtInstImport "GLSL.std.450"
659fd4e5da5Sopenharmony_ci               OpMemoryModel Logical GLSL450
660fd4e5da5Sopenharmony_ci               OpEntryPoint Fragment %4 "main"
661fd4e5da5Sopenharmony_ci               OpExecutionMode %4 OriginUpperLeft
662fd4e5da5Sopenharmony_ci               OpSource ESSL 310
663fd4e5da5Sopenharmony_ci               OpName %4 "main"
664fd4e5da5Sopenharmony_ci               OpName %10 "foo(i1;"
665fd4e5da5Sopenharmony_ci               OpName %9 "x"
666fd4e5da5Sopenharmony_ci               OpName %18 "param"
667fd4e5da5Sopenharmony_ci          %2 = OpTypeVoid
668fd4e5da5Sopenharmony_ci          %3 = OpTypeFunction %2
669fd4e5da5Sopenharmony_ci          %6 = OpTypeInt 32 1
670fd4e5da5Sopenharmony_ci          %7 = OpTypePointer Function %6
671fd4e5da5Sopenharmony_ci          %8 = OpTypeFunction %6 %7
672fd4e5da5Sopenharmony_ci         %13 = OpConstant %6 1
673fd4e5da5Sopenharmony_ci         %17 = OpConstant %6 3
674fd4e5da5Sopenharmony_ci          %4 = OpFunction %2 None %3
675fd4e5da5Sopenharmony_ci          %5 = OpLabel
676fd4e5da5Sopenharmony_ci         %18 = OpVariable %7 Function
677fd4e5da5Sopenharmony_ci               OpStore %18 %17
678fd4e5da5Sopenharmony_ci         %19 = OpFunctionCall %6 %10 %18
679fd4e5da5Sopenharmony_ci               OpReturn
680fd4e5da5Sopenharmony_ci               OpFunctionEnd
681fd4e5da5Sopenharmony_ci         %10 = OpFunction %6 None %8
682fd4e5da5Sopenharmony_ci          %9 = OpFunctionParameter %7
683fd4e5da5Sopenharmony_ci         %11 = OpLabel
684fd4e5da5Sopenharmony_ci         %12 = OpLoad %6 %9
685fd4e5da5Sopenharmony_ci         %14 = OpIAdd %6 %12 %13
686fd4e5da5Sopenharmony_ci               OpReturnValue %14
687fd4e5da5Sopenharmony_ci               OpFunctionEnd
688fd4e5da5Sopenharmony_ci  )";
689fd4e5da5Sopenharmony_ci
690fd4e5da5Sopenharmony_ci  const auto env = SPV_ENV_UNIVERSAL_1_4;
691fd4e5da5Sopenharmony_ci  const auto consumer = nullptr;
692fd4e5da5Sopenharmony_ci  const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption);
693fd4e5da5Sopenharmony_ci  spvtools::ValidatorOptions validator_options;
694fd4e5da5Sopenharmony_ci  ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
695fd4e5da5Sopenharmony_ci                                               kConsoleMessageConsumer));
696fd4e5da5Sopenharmony_ci  TransformationContext transformation_context(
697fd4e5da5Sopenharmony_ci      MakeUnique<FactManager>(context.get()), validator_options);
698fd4e5da5Sopenharmony_ci  TransformationOutlineFunction transformation(11, 11, 100, 101, 102, 103, 104,
699fd4e5da5Sopenharmony_ci                                               105, {{9, 106}}, {{14, 107}});
700fd4e5da5Sopenharmony_ci  ASSERT_TRUE(
701fd4e5da5Sopenharmony_ci      transformation.IsApplicable(context.get(), transformation_context));
702fd4e5da5Sopenharmony_ci  ApplyAndCheckFreshIds(transformation, context.get(), &transformation_context);
703fd4e5da5Sopenharmony_ci  ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
704fd4e5da5Sopenharmony_ci                                               kConsoleMessageConsumer));
705fd4e5da5Sopenharmony_ci
706fd4e5da5Sopenharmony_ci  std::string after_transformation = R"(
707fd4e5da5Sopenharmony_ci               OpCapability Shader
708fd4e5da5Sopenharmony_ci          %1 = OpExtInstImport "GLSL.std.450"
709fd4e5da5Sopenharmony_ci               OpMemoryModel Logical GLSL450
710fd4e5da5Sopenharmony_ci               OpEntryPoint Fragment %4 "main"
711fd4e5da5Sopenharmony_ci               OpExecutionMode %4 OriginUpperLeft
712fd4e5da5Sopenharmony_ci               OpSource ESSL 310
713fd4e5da5Sopenharmony_ci               OpName %4 "main"
714fd4e5da5Sopenharmony_ci               OpName %10 "foo(i1;"
715fd4e5da5Sopenharmony_ci               OpName %9 "x"
716fd4e5da5Sopenharmony_ci               OpName %18 "param"
717fd4e5da5Sopenharmony_ci          %2 = OpTypeVoid
718fd4e5da5Sopenharmony_ci          %3 = OpTypeFunction %2
719fd4e5da5Sopenharmony_ci          %6 = OpTypeInt 32 1
720fd4e5da5Sopenharmony_ci          %7 = OpTypePointer Function %6
721fd4e5da5Sopenharmony_ci          %8 = OpTypeFunction %6 %7
722fd4e5da5Sopenharmony_ci         %13 = OpConstant %6 1
723fd4e5da5Sopenharmony_ci         %17 = OpConstant %6 3
724fd4e5da5Sopenharmony_ci        %100 = OpTypeStruct %6
725fd4e5da5Sopenharmony_ci        %101 = OpTypeFunction %100 %7
726fd4e5da5Sopenharmony_ci          %4 = OpFunction %2 None %3
727fd4e5da5Sopenharmony_ci          %5 = OpLabel
728fd4e5da5Sopenharmony_ci         %18 = OpVariable %7 Function
729fd4e5da5Sopenharmony_ci               OpStore %18 %17
730fd4e5da5Sopenharmony_ci         %19 = OpFunctionCall %6 %10 %18
731fd4e5da5Sopenharmony_ci               OpReturn
732fd4e5da5Sopenharmony_ci               OpFunctionEnd
733fd4e5da5Sopenharmony_ci         %10 = OpFunction %6 None %8
734fd4e5da5Sopenharmony_ci          %9 = OpFunctionParameter %7
735fd4e5da5Sopenharmony_ci         %11 = OpLabel
736fd4e5da5Sopenharmony_ci        %104 = OpFunctionCall %100 %102 %9
737fd4e5da5Sopenharmony_ci         %14 = OpCompositeExtract %6 %104 0
738fd4e5da5Sopenharmony_ci               OpReturnValue %14
739fd4e5da5Sopenharmony_ci               OpFunctionEnd
740fd4e5da5Sopenharmony_ci        %102 = OpFunction %100 None %101
741fd4e5da5Sopenharmony_ci        %106 = OpFunctionParameter %7
742fd4e5da5Sopenharmony_ci        %103 = OpLabel
743fd4e5da5Sopenharmony_ci         %12 = OpLoad %6 %106
744fd4e5da5Sopenharmony_ci        %107 = OpIAdd %6 %12 %13
745fd4e5da5Sopenharmony_ci        %105 = OpCompositeConstruct %100 %107
746fd4e5da5Sopenharmony_ci               OpReturnValue %105
747fd4e5da5Sopenharmony_ci               OpFunctionEnd
748fd4e5da5Sopenharmony_ci  )";
749fd4e5da5Sopenharmony_ci  ASSERT_TRUE(IsEqual(env, after_transformation, context.get()));
750fd4e5da5Sopenharmony_ci}
751fd4e5da5Sopenharmony_ci
752fd4e5da5Sopenharmony_ciTEST(TransformationOutlineFunctionTest,
753fd4e5da5Sopenharmony_ci     DoNotOutlineIfLoopMergeIsOutsideRegion) {
754fd4e5da5Sopenharmony_ci  std::string shader = R"(
755fd4e5da5Sopenharmony_ci               OpCapability Shader
756fd4e5da5Sopenharmony_ci          %1 = OpExtInstImport "GLSL.std.450"
757fd4e5da5Sopenharmony_ci               OpMemoryModel Logical GLSL450
758fd4e5da5Sopenharmony_ci               OpEntryPoint Fragment %4 "main"
759fd4e5da5Sopenharmony_ci               OpExecutionMode %4 OriginUpperLeft
760fd4e5da5Sopenharmony_ci               OpSource ESSL 310
761fd4e5da5Sopenharmony_ci               OpName %4 "main"
762fd4e5da5Sopenharmony_ci          %2 = OpTypeVoid
763fd4e5da5Sopenharmony_ci          %3 = OpTypeFunction %2
764fd4e5da5Sopenharmony_ci          %9 = OpTypeBool
765fd4e5da5Sopenharmony_ci         %10 = OpConstantTrue %9
766fd4e5da5Sopenharmony_ci          %4 = OpFunction %2 None %3
767fd4e5da5Sopenharmony_ci          %5 = OpLabel
768fd4e5da5Sopenharmony_ci               OpBranch %6
769fd4e5da5Sopenharmony_ci          %6 = OpLabel
770fd4e5da5Sopenharmony_ci               OpLoopMerge %7 %8 None
771fd4e5da5Sopenharmony_ci               OpBranch %8
772fd4e5da5Sopenharmony_ci          %8 = OpLabel
773fd4e5da5Sopenharmony_ci               OpBranchConditional %10 %6 %7
774fd4e5da5Sopenharmony_ci          %7 = OpLabel
775fd4e5da5Sopenharmony_ci               OpReturn
776fd4e5da5Sopenharmony_ci               OpFunctionEnd
777fd4e5da5Sopenharmony_ci  )";
778fd4e5da5Sopenharmony_ci
779fd4e5da5Sopenharmony_ci  const auto env = SPV_ENV_UNIVERSAL_1_4;
780fd4e5da5Sopenharmony_ci  const auto consumer = nullptr;
781fd4e5da5Sopenharmony_ci  const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption);
782fd4e5da5Sopenharmony_ci  spvtools::ValidatorOptions validator_options;
783fd4e5da5Sopenharmony_ci  ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
784fd4e5da5Sopenharmony_ci                                               kConsoleMessageConsumer));
785fd4e5da5Sopenharmony_ci  TransformationContext transformation_context(
786fd4e5da5Sopenharmony_ci      MakeUnique<FactManager>(context.get()), validator_options);
787fd4e5da5Sopenharmony_ci  TransformationOutlineFunction transformation(6, 8, 100, 101, 102, 103, 104,
788fd4e5da5Sopenharmony_ci                                               105, {}, {});
789fd4e5da5Sopenharmony_ci  ASSERT_FALSE(
790fd4e5da5Sopenharmony_ci      transformation.IsApplicable(context.get(), transformation_context));
791fd4e5da5Sopenharmony_ci}
792fd4e5da5Sopenharmony_ci
793fd4e5da5Sopenharmony_ciTEST(TransformationOutlineFunctionTest, DoNotOutlineIfRegionInvolvesReturn) {
794fd4e5da5Sopenharmony_ci  std::string shader = R"(
795fd4e5da5Sopenharmony_ci               OpCapability Shader
796fd4e5da5Sopenharmony_ci          %1 = OpExtInstImport "GLSL.std.450"
797fd4e5da5Sopenharmony_ci               OpMemoryModel Logical GLSL450
798fd4e5da5Sopenharmony_ci               OpEntryPoint Fragment %4 "main"
799fd4e5da5Sopenharmony_ci               OpExecutionMode %4 OriginUpperLeft
800fd4e5da5Sopenharmony_ci               OpSource ESSL 310
801fd4e5da5Sopenharmony_ci               OpName %4 "main"
802fd4e5da5Sopenharmony_ci          %2 = OpTypeVoid
803fd4e5da5Sopenharmony_ci         %20 = OpTypeBool
804fd4e5da5Sopenharmony_ci         %21 = OpConstantTrue %20
805fd4e5da5Sopenharmony_ci          %3 = OpTypeFunction %2
806fd4e5da5Sopenharmony_ci          %4 = OpFunction %2 None %3
807fd4e5da5Sopenharmony_ci          %5 = OpLabel
808fd4e5da5Sopenharmony_ci               OpBranch %6
809fd4e5da5Sopenharmony_ci          %6 = OpLabel
810fd4e5da5Sopenharmony_ci               OpBranch %7
811fd4e5da5Sopenharmony_ci          %7 = OpLabel
812fd4e5da5Sopenharmony_ci               OpSelectionMerge %10 None
813fd4e5da5Sopenharmony_ci               OpBranchConditional %21 %8 %9
814fd4e5da5Sopenharmony_ci          %8 = OpLabel
815fd4e5da5Sopenharmony_ci               OpReturn
816fd4e5da5Sopenharmony_ci          %9 = OpLabel
817fd4e5da5Sopenharmony_ci               OpBranch %10
818fd4e5da5Sopenharmony_ci         %10 = OpLabel
819fd4e5da5Sopenharmony_ci               OpBranch %11
820fd4e5da5Sopenharmony_ci         %11 = OpLabel
821fd4e5da5Sopenharmony_ci               OpBranch %12
822fd4e5da5Sopenharmony_ci         %12 = OpLabel
823fd4e5da5Sopenharmony_ci               OpReturn
824fd4e5da5Sopenharmony_ci               OpFunctionEnd
825fd4e5da5Sopenharmony_ci  )";
826fd4e5da5Sopenharmony_ci
827fd4e5da5Sopenharmony_ci  const auto env = SPV_ENV_UNIVERSAL_1_4;
828fd4e5da5Sopenharmony_ci  const auto consumer = nullptr;
829fd4e5da5Sopenharmony_ci  const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption);
830fd4e5da5Sopenharmony_ci  spvtools::ValidatorOptions validator_options;
831fd4e5da5Sopenharmony_ci  ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
832fd4e5da5Sopenharmony_ci                                               kConsoleMessageConsumer));
833fd4e5da5Sopenharmony_ci  TransformationContext transformation_context(
834fd4e5da5Sopenharmony_ci      MakeUnique<FactManager>(context.get()), validator_options);
835fd4e5da5Sopenharmony_ci  TransformationOutlineFunction transformation(6, 11, /* not relevant */ 200,
836fd4e5da5Sopenharmony_ci                                               100, 101, 102, 103,
837fd4e5da5Sopenharmony_ci                                               /* not relevant */ 201, {}, {});
838fd4e5da5Sopenharmony_ci  ASSERT_FALSE(
839fd4e5da5Sopenharmony_ci      transformation.IsApplicable(context.get(), transformation_context));
840fd4e5da5Sopenharmony_ci}
841fd4e5da5Sopenharmony_ci
842fd4e5da5Sopenharmony_ciTEST(TransformationOutlineFunctionTest, DoNotOutlineIfRegionInvolvesKill) {
843fd4e5da5Sopenharmony_ci  std::string shader = R"(
844fd4e5da5Sopenharmony_ci               OpCapability Shader
845fd4e5da5Sopenharmony_ci          %1 = OpExtInstImport "GLSL.std.450"
846fd4e5da5Sopenharmony_ci               OpMemoryModel Logical GLSL450
847fd4e5da5Sopenharmony_ci               OpEntryPoint Fragment %4 "main"
848fd4e5da5Sopenharmony_ci               OpExecutionMode %4 OriginUpperLeft
849fd4e5da5Sopenharmony_ci               OpSource ESSL 310
850fd4e5da5Sopenharmony_ci               OpName %4 "main"
851fd4e5da5Sopenharmony_ci          %2 = OpTypeVoid
852fd4e5da5Sopenharmony_ci         %20 = OpTypeBool
853fd4e5da5Sopenharmony_ci         %21 = OpConstantTrue %20
854fd4e5da5Sopenharmony_ci          %3 = OpTypeFunction %2
855fd4e5da5Sopenharmony_ci          %4 = OpFunction %2 None %3
856fd4e5da5Sopenharmony_ci          %5 = OpLabel
857fd4e5da5Sopenharmony_ci               OpBranch %6
858fd4e5da5Sopenharmony_ci          %6 = OpLabel
859fd4e5da5Sopenharmony_ci               OpBranch %7
860fd4e5da5Sopenharmony_ci          %7 = OpLabel
861fd4e5da5Sopenharmony_ci               OpSelectionMerge %10 None
862fd4e5da5Sopenharmony_ci               OpBranchConditional %21 %8 %9
863fd4e5da5Sopenharmony_ci          %8 = OpLabel
864fd4e5da5Sopenharmony_ci               OpKill
865fd4e5da5Sopenharmony_ci          %9 = OpLabel
866fd4e5da5Sopenharmony_ci               OpBranch %10
867fd4e5da5Sopenharmony_ci         %10 = OpLabel
868fd4e5da5Sopenharmony_ci               OpBranch %11
869fd4e5da5Sopenharmony_ci         %11 = OpLabel
870fd4e5da5Sopenharmony_ci               OpBranch %12
871fd4e5da5Sopenharmony_ci         %12 = OpLabel
872fd4e5da5Sopenharmony_ci               OpReturn
873fd4e5da5Sopenharmony_ci               OpFunctionEnd
874fd4e5da5Sopenharmony_ci  )";
875fd4e5da5Sopenharmony_ci
876fd4e5da5Sopenharmony_ci  const auto env = SPV_ENV_UNIVERSAL_1_4;
877fd4e5da5Sopenharmony_ci  const auto consumer = nullptr;
878fd4e5da5Sopenharmony_ci  const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption);
879fd4e5da5Sopenharmony_ci  spvtools::ValidatorOptions validator_options;
880fd4e5da5Sopenharmony_ci  ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
881fd4e5da5Sopenharmony_ci                                               kConsoleMessageConsumer));
882fd4e5da5Sopenharmony_ci  TransformationContext transformation_context(
883fd4e5da5Sopenharmony_ci      MakeUnique<FactManager>(context.get()), validator_options);
884fd4e5da5Sopenharmony_ci  TransformationOutlineFunction transformation(6, 11, /* not relevant */ 200,
885fd4e5da5Sopenharmony_ci                                               100, 101, 102, 103,
886fd4e5da5Sopenharmony_ci                                               /* not relevant */ 201, {}, {});
887fd4e5da5Sopenharmony_ci  ASSERT_FALSE(
888fd4e5da5Sopenharmony_ci      transformation.IsApplicable(context.get(), transformation_context));
889fd4e5da5Sopenharmony_ci}
890fd4e5da5Sopenharmony_ci
891fd4e5da5Sopenharmony_ciTEST(TransformationOutlineFunctionTest,
892fd4e5da5Sopenharmony_ci     DoNotOutlineIfRegionInvolvesUnreachable) {
893fd4e5da5Sopenharmony_ci  std::string shader = R"(
894fd4e5da5Sopenharmony_ci               OpCapability Shader
895fd4e5da5Sopenharmony_ci          %1 = OpExtInstImport "GLSL.std.450"
896fd4e5da5Sopenharmony_ci               OpMemoryModel Logical GLSL450
897fd4e5da5Sopenharmony_ci               OpEntryPoint Fragment %4 "main"
898fd4e5da5Sopenharmony_ci               OpExecutionMode %4 OriginUpperLeft
899fd4e5da5Sopenharmony_ci               OpSource ESSL 310
900fd4e5da5Sopenharmony_ci               OpName %4 "main"
901fd4e5da5Sopenharmony_ci          %2 = OpTypeVoid
902fd4e5da5Sopenharmony_ci         %20 = OpTypeBool
903fd4e5da5Sopenharmony_ci         %21 = OpConstantTrue %20
904fd4e5da5Sopenharmony_ci          %3 = OpTypeFunction %2
905fd4e5da5Sopenharmony_ci          %4 = OpFunction %2 None %3
906fd4e5da5Sopenharmony_ci          %5 = OpLabel
907fd4e5da5Sopenharmony_ci               OpBranch %6
908fd4e5da5Sopenharmony_ci          %6 = OpLabel
909fd4e5da5Sopenharmony_ci               OpBranch %7
910fd4e5da5Sopenharmony_ci          %7 = OpLabel
911fd4e5da5Sopenharmony_ci               OpSelectionMerge %10 None
912fd4e5da5Sopenharmony_ci               OpBranchConditional %21 %8 %9
913fd4e5da5Sopenharmony_ci          %8 = OpLabel
914fd4e5da5Sopenharmony_ci               OpBranch %10
915fd4e5da5Sopenharmony_ci          %9 = OpLabel
916fd4e5da5Sopenharmony_ci               OpUnreachable
917fd4e5da5Sopenharmony_ci         %10 = OpLabel
918fd4e5da5Sopenharmony_ci               OpBranch %11
919fd4e5da5Sopenharmony_ci         %11 = OpLabel
920fd4e5da5Sopenharmony_ci               OpBranch %12
921fd4e5da5Sopenharmony_ci         %12 = OpLabel
922fd4e5da5Sopenharmony_ci               OpReturn
923fd4e5da5Sopenharmony_ci               OpFunctionEnd
924fd4e5da5Sopenharmony_ci  )";
925fd4e5da5Sopenharmony_ci
926fd4e5da5Sopenharmony_ci  const auto env = SPV_ENV_UNIVERSAL_1_4;
927fd4e5da5Sopenharmony_ci  const auto consumer = nullptr;
928fd4e5da5Sopenharmony_ci  const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption);
929fd4e5da5Sopenharmony_ci  spvtools::ValidatorOptions validator_options;
930fd4e5da5Sopenharmony_ci  ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
931fd4e5da5Sopenharmony_ci                                               kConsoleMessageConsumer));
932fd4e5da5Sopenharmony_ci  TransformationContext transformation_context(
933fd4e5da5Sopenharmony_ci      MakeUnique<FactManager>(context.get()), validator_options);
934fd4e5da5Sopenharmony_ci  TransformationOutlineFunction transformation(6, 11, /* not relevant */ 200,
935fd4e5da5Sopenharmony_ci                                               100, 101, 102, 103,
936fd4e5da5Sopenharmony_ci                                               /* not relevant */ 201, {}, {});
937fd4e5da5Sopenharmony_ci  ASSERT_FALSE(
938fd4e5da5Sopenharmony_ci      transformation.IsApplicable(context.get(), transformation_context));
939fd4e5da5Sopenharmony_ci}
940fd4e5da5Sopenharmony_ci
941fd4e5da5Sopenharmony_ciTEST(TransformationOutlineFunctionTest,
942fd4e5da5Sopenharmony_ci     DoNotOutlineIfSelectionMergeIsOutsideRegion) {
943fd4e5da5Sopenharmony_ci  std::string shader = R"(
944fd4e5da5Sopenharmony_ci               OpCapability Shader
945fd4e5da5Sopenharmony_ci          %1 = OpExtInstImport "GLSL.std.450"
946fd4e5da5Sopenharmony_ci               OpMemoryModel Logical GLSL450
947fd4e5da5Sopenharmony_ci               OpEntryPoint Fragment %4 "main"
948fd4e5da5Sopenharmony_ci               OpExecutionMode %4 OriginUpperLeft
949fd4e5da5Sopenharmony_ci               OpSource ESSL 310
950fd4e5da5Sopenharmony_ci               OpName %4 "main"
951fd4e5da5Sopenharmony_ci          %2 = OpTypeVoid
952fd4e5da5Sopenharmony_ci          %3 = OpTypeFunction %2
953fd4e5da5Sopenharmony_ci          %9 = OpTypeBool
954fd4e5da5Sopenharmony_ci         %10 = OpConstantTrue %9
955fd4e5da5Sopenharmony_ci          %4 = OpFunction %2 None %3
956fd4e5da5Sopenharmony_ci          %5 = OpLabel
957fd4e5da5Sopenharmony_ci               OpBranch %6
958fd4e5da5Sopenharmony_ci          %6 = OpLabel
959fd4e5da5Sopenharmony_ci               OpSelectionMerge %7 None
960fd4e5da5Sopenharmony_ci               OpBranchConditional %10 %8 %7
961fd4e5da5Sopenharmony_ci          %8 = OpLabel
962fd4e5da5Sopenharmony_ci               OpBranch %7
963fd4e5da5Sopenharmony_ci          %7 = OpLabel
964fd4e5da5Sopenharmony_ci               OpReturn
965fd4e5da5Sopenharmony_ci               OpFunctionEnd
966fd4e5da5Sopenharmony_ci  )";
967fd4e5da5Sopenharmony_ci
968fd4e5da5Sopenharmony_ci  const auto env = SPV_ENV_UNIVERSAL_1_4;
969fd4e5da5Sopenharmony_ci  const auto consumer = nullptr;
970fd4e5da5Sopenharmony_ci  const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption);
971fd4e5da5Sopenharmony_ci  spvtools::ValidatorOptions validator_options;
972fd4e5da5Sopenharmony_ci  ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
973fd4e5da5Sopenharmony_ci                                               kConsoleMessageConsumer));
974fd4e5da5Sopenharmony_ci  TransformationContext transformation_context(
975fd4e5da5Sopenharmony_ci      MakeUnique<FactManager>(context.get()), validator_options);
976fd4e5da5Sopenharmony_ci  TransformationOutlineFunction transformation(6, 8, 100, 101, 102, 103, 104,
977fd4e5da5Sopenharmony_ci                                               105, {}, {});
978fd4e5da5Sopenharmony_ci  ASSERT_FALSE(
979fd4e5da5Sopenharmony_ci      transformation.IsApplicable(context.get(), transformation_context));
980fd4e5da5Sopenharmony_ci}
981fd4e5da5Sopenharmony_ci
982fd4e5da5Sopenharmony_ciTEST(TransformationOutlineFunctionTest, DoNotOutlineIfLoopHeadIsOutsideRegion) {
983fd4e5da5Sopenharmony_ci  std::string shader = R"(
984fd4e5da5Sopenharmony_ci               OpCapability Shader
985fd4e5da5Sopenharmony_ci          %1 = OpExtInstImport "GLSL.std.450"
986fd4e5da5Sopenharmony_ci               OpMemoryModel Logical GLSL450
987fd4e5da5Sopenharmony_ci               OpEntryPoint Fragment %4 "main"
988fd4e5da5Sopenharmony_ci               OpExecutionMode %4 OriginUpperLeft
989fd4e5da5Sopenharmony_ci               OpSource ESSL 310
990fd4e5da5Sopenharmony_ci               OpName %4 "main"
991fd4e5da5Sopenharmony_ci          %2 = OpTypeVoid
992fd4e5da5Sopenharmony_ci          %3 = OpTypeFunction %2
993fd4e5da5Sopenharmony_ci          %9 = OpTypeBool
994fd4e5da5Sopenharmony_ci         %10 = OpConstantTrue %9
995fd4e5da5Sopenharmony_ci          %4 = OpFunction %2 None %3
996fd4e5da5Sopenharmony_ci          %5 = OpLabel
997fd4e5da5Sopenharmony_ci               OpBranch %6
998fd4e5da5Sopenharmony_ci          %6 = OpLabel
999fd4e5da5Sopenharmony_ci               OpLoopMerge %8 %11 None
1000fd4e5da5Sopenharmony_ci               OpBranch %7
1001fd4e5da5Sopenharmony_ci          %7 = OpLabel
1002fd4e5da5Sopenharmony_ci               OpBranchConditional %10 %11 %8
1003fd4e5da5Sopenharmony_ci         %11 = OpLabel
1004fd4e5da5Sopenharmony_ci               OpBranch %6
1005fd4e5da5Sopenharmony_ci          %8 = OpLabel
1006fd4e5da5Sopenharmony_ci               OpReturn
1007fd4e5da5Sopenharmony_ci               OpFunctionEnd
1008fd4e5da5Sopenharmony_ci  )";
1009fd4e5da5Sopenharmony_ci
1010fd4e5da5Sopenharmony_ci  const auto env = SPV_ENV_UNIVERSAL_1_4;
1011fd4e5da5Sopenharmony_ci  const auto consumer = nullptr;
1012fd4e5da5Sopenharmony_ci  const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption);
1013fd4e5da5Sopenharmony_ci  spvtools::ValidatorOptions validator_options;
1014fd4e5da5Sopenharmony_ci  ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
1015fd4e5da5Sopenharmony_ci                                               kConsoleMessageConsumer));
1016fd4e5da5Sopenharmony_ci  TransformationContext transformation_context(
1017fd4e5da5Sopenharmony_ci      MakeUnique<FactManager>(context.get()), validator_options);
1018fd4e5da5Sopenharmony_ci  TransformationOutlineFunction transformation(7, 8, 100, 101, 102, 103, 104,
1019fd4e5da5Sopenharmony_ci                                               105, {}, {});
1020fd4e5da5Sopenharmony_ci  ASSERT_FALSE(
1021fd4e5da5Sopenharmony_ci      transformation.IsApplicable(context.get(), transformation_context));
1022fd4e5da5Sopenharmony_ci}
1023fd4e5da5Sopenharmony_ci
1024fd4e5da5Sopenharmony_ciTEST(TransformationOutlineFunctionTest,
1025fd4e5da5Sopenharmony_ci     DoNotOutlineIfLoopContinueIsOutsideRegion) {
1026fd4e5da5Sopenharmony_ci  std::string shader = R"(
1027fd4e5da5Sopenharmony_ci               OpCapability Shader
1028fd4e5da5Sopenharmony_ci          %1 = OpExtInstImport "GLSL.std.450"
1029fd4e5da5Sopenharmony_ci               OpMemoryModel Logical GLSL450
1030fd4e5da5Sopenharmony_ci               OpEntryPoint Fragment %4 "main"
1031fd4e5da5Sopenharmony_ci               OpExecutionMode %4 OriginUpperLeft
1032fd4e5da5Sopenharmony_ci               OpSource ESSL 310
1033fd4e5da5Sopenharmony_ci               OpName %4 "main"
1034fd4e5da5Sopenharmony_ci          %2 = OpTypeVoid
1035fd4e5da5Sopenharmony_ci          %3 = OpTypeFunction %2
1036fd4e5da5Sopenharmony_ci          %9 = OpTypeBool
1037fd4e5da5Sopenharmony_ci         %10 = OpConstantTrue %9
1038fd4e5da5Sopenharmony_ci          %4 = OpFunction %2 None %3
1039fd4e5da5Sopenharmony_ci          %5 = OpLabel
1040fd4e5da5Sopenharmony_ci               OpBranch %6
1041fd4e5da5Sopenharmony_ci          %6 = OpLabel
1042fd4e5da5Sopenharmony_ci               OpLoopMerge %7 %8 None
1043fd4e5da5Sopenharmony_ci               OpBranch %7
1044fd4e5da5Sopenharmony_ci          %8 = OpLabel
1045fd4e5da5Sopenharmony_ci               OpBranch %6
1046fd4e5da5Sopenharmony_ci          %7 = OpLabel
1047fd4e5da5Sopenharmony_ci               OpReturn
1048fd4e5da5Sopenharmony_ci               OpFunctionEnd
1049fd4e5da5Sopenharmony_ci  )";
1050fd4e5da5Sopenharmony_ci
1051fd4e5da5Sopenharmony_ci  const auto env = SPV_ENV_UNIVERSAL_1_4;
1052fd4e5da5Sopenharmony_ci  const auto consumer = nullptr;
1053fd4e5da5Sopenharmony_ci  const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption);
1054fd4e5da5Sopenharmony_ci  spvtools::ValidatorOptions validator_options;
1055fd4e5da5Sopenharmony_ci  ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
1056fd4e5da5Sopenharmony_ci                                               kConsoleMessageConsumer));
1057fd4e5da5Sopenharmony_ci  TransformationContext transformation_context(
1058fd4e5da5Sopenharmony_ci      MakeUnique<FactManager>(context.get()), validator_options);
1059fd4e5da5Sopenharmony_ci  TransformationOutlineFunction transformation(6, 7, 100, 101, 102, 103, 104,
1060fd4e5da5Sopenharmony_ci                                               105, {}, {});
1061fd4e5da5Sopenharmony_ci  ASSERT_FALSE(
1062fd4e5da5Sopenharmony_ci      transformation.IsApplicable(context.get(), transformation_context));
1063fd4e5da5Sopenharmony_ci}
1064fd4e5da5Sopenharmony_ci
1065fd4e5da5Sopenharmony_ciTEST(TransformationOutlineFunctionTest,
1066fd4e5da5Sopenharmony_ci     DoNotOutlineWithLoopCarriedPhiDependence) {
1067fd4e5da5Sopenharmony_ci  std::string shader = R"(
1068fd4e5da5Sopenharmony_ci               OpCapability Shader
1069fd4e5da5Sopenharmony_ci          %1 = OpExtInstImport "GLSL.std.450"
1070fd4e5da5Sopenharmony_ci               OpMemoryModel Logical GLSL450
1071fd4e5da5Sopenharmony_ci               OpEntryPoint Fragment %4 "main"
1072fd4e5da5Sopenharmony_ci               OpExecutionMode %4 OriginUpperLeft
1073fd4e5da5Sopenharmony_ci               OpSource ESSL 310
1074fd4e5da5Sopenharmony_ci               OpName %4 "main"
1075fd4e5da5Sopenharmony_ci          %2 = OpTypeVoid
1076fd4e5da5Sopenharmony_ci          %3 = OpTypeFunction %2
1077fd4e5da5Sopenharmony_ci          %9 = OpTypeBool
1078fd4e5da5Sopenharmony_ci         %10 = OpConstantTrue %9
1079fd4e5da5Sopenharmony_ci          %4 = OpFunction %2 None %3
1080fd4e5da5Sopenharmony_ci          %5 = OpLabel
1081fd4e5da5Sopenharmony_ci               OpBranch %6
1082fd4e5da5Sopenharmony_ci          %6 = OpLabel
1083fd4e5da5Sopenharmony_ci         %12 = OpPhi %9 %10 %5 %13 %8
1084fd4e5da5Sopenharmony_ci               OpLoopMerge %7 %8 None
1085fd4e5da5Sopenharmony_ci               OpBranch %8
1086fd4e5da5Sopenharmony_ci          %8 = OpLabel
1087fd4e5da5Sopenharmony_ci         %13 = OpCopyObject %9 %10
1088fd4e5da5Sopenharmony_ci               OpBranchConditional %10 %6 %7
1089fd4e5da5Sopenharmony_ci          %7 = OpLabel
1090fd4e5da5Sopenharmony_ci               OpReturn
1091fd4e5da5Sopenharmony_ci               OpFunctionEnd
1092fd4e5da5Sopenharmony_ci  )";
1093fd4e5da5Sopenharmony_ci
1094fd4e5da5Sopenharmony_ci  const auto env = SPV_ENV_UNIVERSAL_1_4;
1095fd4e5da5Sopenharmony_ci  const auto consumer = nullptr;
1096fd4e5da5Sopenharmony_ci  const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption);
1097fd4e5da5Sopenharmony_ci  spvtools::ValidatorOptions validator_options;
1098fd4e5da5Sopenharmony_ci  ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
1099fd4e5da5Sopenharmony_ci                                               kConsoleMessageConsumer));
1100fd4e5da5Sopenharmony_ci  TransformationContext transformation_context(
1101fd4e5da5Sopenharmony_ci      MakeUnique<FactManager>(context.get()), validator_options);
1102fd4e5da5Sopenharmony_ci  TransformationOutlineFunction transformation(6, 7, 100, 101, 102, 103, 104,
1103fd4e5da5Sopenharmony_ci                                               105, {}, {});
1104fd4e5da5Sopenharmony_ci  ASSERT_FALSE(
1105fd4e5da5Sopenharmony_ci      transformation.IsApplicable(context.get(), transformation_context));
1106fd4e5da5Sopenharmony_ci}
1107fd4e5da5Sopenharmony_ci
1108fd4e5da5Sopenharmony_ciTEST(TransformationOutlineFunctionTest,
1109fd4e5da5Sopenharmony_ci     DoNotOutlineSelectionHeaderNotInRegion) {
1110fd4e5da5Sopenharmony_ci  std::string shader = R"(
1111fd4e5da5Sopenharmony_ci               OpCapability Shader
1112fd4e5da5Sopenharmony_ci          %1 = OpExtInstImport "GLSL.std.450"
1113fd4e5da5Sopenharmony_ci               OpMemoryModel Logical GLSL450
1114fd4e5da5Sopenharmony_ci               OpEntryPoint Fragment %4 "main"
1115fd4e5da5Sopenharmony_ci               OpExecutionMode %4 OriginUpperLeft
1116fd4e5da5Sopenharmony_ci               OpSource ESSL 310
1117fd4e5da5Sopenharmony_ci               OpName %4 "main"
1118fd4e5da5Sopenharmony_ci          %2 = OpTypeVoid
1119fd4e5da5Sopenharmony_ci          %3 = OpTypeFunction %2
1120fd4e5da5Sopenharmony_ci          %6 = OpTypeBool
1121fd4e5da5Sopenharmony_ci          %7 = OpConstantTrue %6
1122fd4e5da5Sopenharmony_ci          %4 = OpFunction %2 None %3
1123fd4e5da5Sopenharmony_ci          %5 = OpLabel
1124fd4e5da5Sopenharmony_ci               OpSelectionMerge %10 None
1125fd4e5da5Sopenharmony_ci               OpBranchConditional %7 %8 %8
1126fd4e5da5Sopenharmony_ci          %8 = OpLabel
1127fd4e5da5Sopenharmony_ci               OpBranch %9
1128fd4e5da5Sopenharmony_ci          %9 = OpLabel
1129fd4e5da5Sopenharmony_ci               OpBranch %10
1130fd4e5da5Sopenharmony_ci         %10 = OpLabel
1131fd4e5da5Sopenharmony_ci               OpBranch %11
1132fd4e5da5Sopenharmony_ci         %11 = OpLabel
1133fd4e5da5Sopenharmony_ci               OpReturn
1134fd4e5da5Sopenharmony_ci               OpFunctionEnd
1135fd4e5da5Sopenharmony_ci  )";
1136fd4e5da5Sopenharmony_ci
1137fd4e5da5Sopenharmony_ci  const auto env = SPV_ENV_UNIVERSAL_1_4;
1138fd4e5da5Sopenharmony_ci  const auto consumer = nullptr;
1139fd4e5da5Sopenharmony_ci  const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption);
1140fd4e5da5Sopenharmony_ci  spvtools::ValidatorOptions validator_options;
1141fd4e5da5Sopenharmony_ci  ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
1142fd4e5da5Sopenharmony_ci                                               kConsoleMessageConsumer));
1143fd4e5da5Sopenharmony_ci  TransformationContext transformation_context(
1144fd4e5da5Sopenharmony_ci      MakeUnique<FactManager>(context.get()), validator_options);
1145fd4e5da5Sopenharmony_ci  TransformationOutlineFunction transformation(8, 11, 100, 101, 102, 103, 104,
1146fd4e5da5Sopenharmony_ci                                               105, {}, {});
1147fd4e5da5Sopenharmony_ci  ASSERT_FALSE(
1148fd4e5da5Sopenharmony_ci      transformation.IsApplicable(context.get(), transformation_context));
1149fd4e5da5Sopenharmony_ci}
1150fd4e5da5Sopenharmony_ci
1151fd4e5da5Sopenharmony_ciTEST(TransformationOutlineFunctionTest, OutlineRegionEndingWithReturnVoid) {
1152fd4e5da5Sopenharmony_ci  std::string shader = R"(
1153fd4e5da5Sopenharmony_ci               OpCapability Shader
1154fd4e5da5Sopenharmony_ci          %1 = OpExtInstImport "GLSL.std.450"
1155fd4e5da5Sopenharmony_ci               OpMemoryModel Logical GLSL450
1156fd4e5da5Sopenharmony_ci               OpEntryPoint Fragment %4 "main"
1157fd4e5da5Sopenharmony_ci               OpExecutionMode %4 OriginUpperLeft
1158fd4e5da5Sopenharmony_ci               OpSource ESSL 310
1159fd4e5da5Sopenharmony_ci         %20 = OpTypeInt 32 0
1160fd4e5da5Sopenharmony_ci         %21 = OpConstant %20 1
1161fd4e5da5Sopenharmony_ci          %2 = OpTypeVoid
1162fd4e5da5Sopenharmony_ci          %3 = OpTypeFunction %2
1163fd4e5da5Sopenharmony_ci          %4 = OpFunction %2 None %3
1164fd4e5da5Sopenharmony_ci          %5 = OpLabel
1165fd4e5da5Sopenharmony_ci         %22 = OpCopyObject %20 %21
1166fd4e5da5Sopenharmony_ci               OpBranch %54
1167fd4e5da5Sopenharmony_ci         %54 = OpLabel
1168fd4e5da5Sopenharmony_ci               OpBranch %57
1169fd4e5da5Sopenharmony_ci         %57 = OpLabel
1170fd4e5da5Sopenharmony_ci         %23 = OpCopyObject %20 %22
1171fd4e5da5Sopenharmony_ci               OpBranch %58
1172fd4e5da5Sopenharmony_ci         %58 = OpLabel
1173fd4e5da5Sopenharmony_ci               OpReturn
1174fd4e5da5Sopenharmony_ci               OpFunctionEnd
1175fd4e5da5Sopenharmony_ci  )";
1176fd4e5da5Sopenharmony_ci
1177fd4e5da5Sopenharmony_ci  const auto env = SPV_ENV_UNIVERSAL_1_5;
1178fd4e5da5Sopenharmony_ci  const auto consumer = nullptr;
1179fd4e5da5Sopenharmony_ci  const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption);
1180fd4e5da5Sopenharmony_ci  spvtools::ValidatorOptions validator_options;
1181fd4e5da5Sopenharmony_ci  ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
1182fd4e5da5Sopenharmony_ci                                               kConsoleMessageConsumer));
1183fd4e5da5Sopenharmony_ci  TransformationContext transformation_context(
1184fd4e5da5Sopenharmony_ci      MakeUnique<FactManager>(context.get()), validator_options);
1185fd4e5da5Sopenharmony_ci  TransformationOutlineFunction transformation(
1186fd4e5da5Sopenharmony_ci      /*entry_block*/ 54,
1187fd4e5da5Sopenharmony_ci      /*exit_block*/ 58,
1188fd4e5da5Sopenharmony_ci      /*new_function_struct_return_type_id*/ 200,
1189fd4e5da5Sopenharmony_ci      /*new_function_type_id*/ 201,
1190fd4e5da5Sopenharmony_ci      /*new_function_id*/ 202,
1191fd4e5da5Sopenharmony_ci      /*new_function_region_entry_block*/ 203,
1192fd4e5da5Sopenharmony_ci      /*new_caller_result_id*/ 204,
1193fd4e5da5Sopenharmony_ci      /*new_callee_result_id*/ 205,
1194fd4e5da5Sopenharmony_ci      /*input_id_to_fresh_id*/ {{22, 206}},
1195fd4e5da5Sopenharmony_ci      /*output_id_to_fresh_id*/ {});
1196fd4e5da5Sopenharmony_ci
1197fd4e5da5Sopenharmony_ci  ASSERT_TRUE(
1198fd4e5da5Sopenharmony_ci      transformation.IsApplicable(context.get(), transformation_context));
1199fd4e5da5Sopenharmony_ci  ApplyAndCheckFreshIds(transformation, context.get(), &transformation_context);
1200fd4e5da5Sopenharmony_ci  ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
1201fd4e5da5Sopenharmony_ci                                               kConsoleMessageConsumer));
1202fd4e5da5Sopenharmony_ci
1203fd4e5da5Sopenharmony_ci  std::string after_transformation = R"(
1204fd4e5da5Sopenharmony_ci               OpCapability Shader
1205fd4e5da5Sopenharmony_ci          %1 = OpExtInstImport "GLSL.std.450"
1206fd4e5da5Sopenharmony_ci               OpMemoryModel Logical GLSL450
1207fd4e5da5Sopenharmony_ci               OpEntryPoint Fragment %4 "main"
1208fd4e5da5Sopenharmony_ci               OpExecutionMode %4 OriginUpperLeft
1209fd4e5da5Sopenharmony_ci               OpSource ESSL 310
1210fd4e5da5Sopenharmony_ci         %20 = OpTypeInt 32 0
1211fd4e5da5Sopenharmony_ci         %21 = OpConstant %20 1
1212fd4e5da5Sopenharmony_ci          %2 = OpTypeVoid
1213fd4e5da5Sopenharmony_ci          %3 = OpTypeFunction %2
1214fd4e5da5Sopenharmony_ci        %201 = OpTypeFunction %2 %20
1215fd4e5da5Sopenharmony_ci          %4 = OpFunction %2 None %3
1216fd4e5da5Sopenharmony_ci          %5 = OpLabel
1217fd4e5da5Sopenharmony_ci         %22 = OpCopyObject %20 %21
1218fd4e5da5Sopenharmony_ci               OpBranch %54
1219fd4e5da5Sopenharmony_ci         %54 = OpLabel
1220fd4e5da5Sopenharmony_ci        %204 = OpFunctionCall %2 %202 %22
1221fd4e5da5Sopenharmony_ci               OpReturn
1222fd4e5da5Sopenharmony_ci               OpFunctionEnd
1223fd4e5da5Sopenharmony_ci        %202 = OpFunction %2 None %201
1224fd4e5da5Sopenharmony_ci        %206 = OpFunctionParameter %20
1225fd4e5da5Sopenharmony_ci        %203 = OpLabel
1226fd4e5da5Sopenharmony_ci               OpBranch %57
1227fd4e5da5Sopenharmony_ci         %57 = OpLabel
1228fd4e5da5Sopenharmony_ci         %23 = OpCopyObject %20 %206
1229fd4e5da5Sopenharmony_ci               OpBranch %58
1230fd4e5da5Sopenharmony_ci         %58 = OpLabel
1231fd4e5da5Sopenharmony_ci               OpReturn
1232fd4e5da5Sopenharmony_ci               OpFunctionEnd
1233fd4e5da5Sopenharmony_ci  )";
1234fd4e5da5Sopenharmony_ci  ASSERT_TRUE(IsEqual(env, after_transformation, context.get()));
1235fd4e5da5Sopenharmony_ci}
1236fd4e5da5Sopenharmony_ci
1237fd4e5da5Sopenharmony_ciTEST(TransformationOutlineFunctionTest, OutlineRegionEndingWithReturnValue) {
1238fd4e5da5Sopenharmony_ci  std::string shader = R"(
1239fd4e5da5Sopenharmony_ci               OpCapability Shader
1240fd4e5da5Sopenharmony_ci          %1 = OpExtInstImport "GLSL.std.450"
1241fd4e5da5Sopenharmony_ci               OpMemoryModel Logical GLSL450
1242fd4e5da5Sopenharmony_ci               OpEntryPoint Fragment %4 "main"
1243fd4e5da5Sopenharmony_ci               OpExecutionMode %4 OriginUpperLeft
1244fd4e5da5Sopenharmony_ci               OpSource ESSL 310
1245fd4e5da5Sopenharmony_ci         %20 = OpTypeInt 32 0
1246fd4e5da5Sopenharmony_ci         %21 = OpConstant %20 1
1247fd4e5da5Sopenharmony_ci          %2 = OpTypeVoid
1248fd4e5da5Sopenharmony_ci          %3 = OpTypeFunction %2
1249fd4e5da5Sopenharmony_ci         %30 = OpTypeFunction %20
1250fd4e5da5Sopenharmony_ci          %4 = OpFunction %2 None %3
1251fd4e5da5Sopenharmony_ci          %5 = OpLabel
1252fd4e5da5Sopenharmony_ci          %6 = OpFunctionCall %20 %100
1253fd4e5da5Sopenharmony_ci               OpReturn
1254fd4e5da5Sopenharmony_ci               OpFunctionEnd
1255fd4e5da5Sopenharmony_ci        %100 = OpFunction %20 None %30
1256fd4e5da5Sopenharmony_ci          %8 = OpLabel
1257fd4e5da5Sopenharmony_ci         %31 = OpCopyObject %20 %21
1258fd4e5da5Sopenharmony_ci               OpBranch %9
1259fd4e5da5Sopenharmony_ci          %9 = OpLabel
1260fd4e5da5Sopenharmony_ci         %32 = OpCopyObject %20 %31
1261fd4e5da5Sopenharmony_ci               OpBranch %10
1262fd4e5da5Sopenharmony_ci         %10 = OpLabel
1263fd4e5da5Sopenharmony_ci               OpReturnValue %32
1264fd4e5da5Sopenharmony_ci               OpFunctionEnd
1265fd4e5da5Sopenharmony_ci  )";
1266fd4e5da5Sopenharmony_ci
1267fd4e5da5Sopenharmony_ci  const auto env = SPV_ENV_UNIVERSAL_1_5;
1268fd4e5da5Sopenharmony_ci  const auto consumer = nullptr;
1269fd4e5da5Sopenharmony_ci  const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption);
1270fd4e5da5Sopenharmony_ci  spvtools::ValidatorOptions validator_options;
1271fd4e5da5Sopenharmony_ci  ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
1272fd4e5da5Sopenharmony_ci                                               kConsoleMessageConsumer));
1273fd4e5da5Sopenharmony_ci  TransformationContext transformation_context(
1274fd4e5da5Sopenharmony_ci      MakeUnique<FactManager>(context.get()), validator_options);
1275fd4e5da5Sopenharmony_ci  TransformationOutlineFunction transformation(
1276fd4e5da5Sopenharmony_ci      /*entry_block*/ 9,
1277fd4e5da5Sopenharmony_ci      /*exit_block*/ 10,
1278fd4e5da5Sopenharmony_ci      /*new_function_struct_return_type_id*/ 200,
1279fd4e5da5Sopenharmony_ci      /*new_function_type_id*/ 201,
1280fd4e5da5Sopenharmony_ci      /*new_function_id*/ 202,
1281fd4e5da5Sopenharmony_ci      /*new_function_region_entry_block*/ 203,
1282fd4e5da5Sopenharmony_ci      /*new_caller_result_id*/ 204,
1283fd4e5da5Sopenharmony_ci      /*new_callee_result_id*/ 205,
1284fd4e5da5Sopenharmony_ci      /*input_id_to_fresh_id*/ {{31, 206}},
1285fd4e5da5Sopenharmony_ci      /*output_id_to_fresh_id*/ {{32, 207}});
1286fd4e5da5Sopenharmony_ci
1287fd4e5da5Sopenharmony_ci  ASSERT_TRUE(
1288fd4e5da5Sopenharmony_ci      transformation.IsApplicable(context.get(), transformation_context));
1289fd4e5da5Sopenharmony_ci  ApplyAndCheckFreshIds(transformation, context.get(), &transformation_context);
1290fd4e5da5Sopenharmony_ci  ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
1291fd4e5da5Sopenharmony_ci                                               kConsoleMessageConsumer));
1292fd4e5da5Sopenharmony_ci
1293fd4e5da5Sopenharmony_ci  std::string after_transformation = R"(
1294fd4e5da5Sopenharmony_ci               OpCapability Shader
1295fd4e5da5Sopenharmony_ci          %1 = OpExtInstImport "GLSL.std.450"
1296fd4e5da5Sopenharmony_ci               OpMemoryModel Logical GLSL450
1297fd4e5da5Sopenharmony_ci               OpEntryPoint Fragment %4 "main"
1298fd4e5da5Sopenharmony_ci               OpExecutionMode %4 OriginUpperLeft
1299fd4e5da5Sopenharmony_ci               OpSource ESSL 310
1300fd4e5da5Sopenharmony_ci         %20 = OpTypeInt 32 0
1301fd4e5da5Sopenharmony_ci         %21 = OpConstant %20 1
1302fd4e5da5Sopenharmony_ci          %2 = OpTypeVoid
1303fd4e5da5Sopenharmony_ci          %3 = OpTypeFunction %2
1304fd4e5da5Sopenharmony_ci         %30 = OpTypeFunction %20
1305fd4e5da5Sopenharmony_ci        %200 = OpTypeStruct %20
1306fd4e5da5Sopenharmony_ci        %201 = OpTypeFunction %200 %20
1307fd4e5da5Sopenharmony_ci          %4 = OpFunction %2 None %3
1308fd4e5da5Sopenharmony_ci          %5 = OpLabel
1309fd4e5da5Sopenharmony_ci          %6 = OpFunctionCall %20 %100
1310fd4e5da5Sopenharmony_ci               OpReturn
1311fd4e5da5Sopenharmony_ci               OpFunctionEnd
1312fd4e5da5Sopenharmony_ci        %100 = OpFunction %20 None %30
1313fd4e5da5Sopenharmony_ci          %8 = OpLabel
1314fd4e5da5Sopenharmony_ci         %31 = OpCopyObject %20 %21
1315fd4e5da5Sopenharmony_ci               OpBranch %9
1316fd4e5da5Sopenharmony_ci          %9 = OpLabel
1317fd4e5da5Sopenharmony_ci        %204 = OpFunctionCall %200 %202 %31
1318fd4e5da5Sopenharmony_ci         %32 = OpCompositeExtract %20 %204 0
1319fd4e5da5Sopenharmony_ci               OpReturnValue %32
1320fd4e5da5Sopenharmony_ci               OpFunctionEnd
1321fd4e5da5Sopenharmony_ci        %202 = OpFunction %200 None %201
1322fd4e5da5Sopenharmony_ci        %206 = OpFunctionParameter %20
1323fd4e5da5Sopenharmony_ci        %203 = OpLabel
1324fd4e5da5Sopenharmony_ci        %207 = OpCopyObject %20 %206
1325fd4e5da5Sopenharmony_ci               OpBranch %10
1326fd4e5da5Sopenharmony_ci         %10 = OpLabel
1327fd4e5da5Sopenharmony_ci        %205 = OpCompositeConstruct %200 %207
1328fd4e5da5Sopenharmony_ci               OpReturnValue %205
1329fd4e5da5Sopenharmony_ci               OpFunctionEnd
1330fd4e5da5Sopenharmony_ci  )";
1331fd4e5da5Sopenharmony_ci  ASSERT_TRUE(IsEqual(env, after_transformation, context.get()));
1332fd4e5da5Sopenharmony_ci}
1333fd4e5da5Sopenharmony_ci
1334fd4e5da5Sopenharmony_ciTEST(TransformationOutlineFunctionTest,
1335fd4e5da5Sopenharmony_ci     OutlineRegionEndingWithConditionalBranch) {
1336fd4e5da5Sopenharmony_ci  std::string shader = R"(
1337fd4e5da5Sopenharmony_ci               OpCapability Shader
1338fd4e5da5Sopenharmony_ci          %1 = OpExtInstImport "GLSL.std.450"
1339fd4e5da5Sopenharmony_ci               OpMemoryModel Logical GLSL450
1340fd4e5da5Sopenharmony_ci               OpEntryPoint Fragment %4 "main"
1341fd4e5da5Sopenharmony_ci               OpExecutionMode %4 OriginUpperLeft
1342fd4e5da5Sopenharmony_ci               OpSource ESSL 310
1343fd4e5da5Sopenharmony_ci         %20 = OpTypeBool
1344fd4e5da5Sopenharmony_ci         %21 = OpConstantTrue %20
1345fd4e5da5Sopenharmony_ci          %2 = OpTypeVoid
1346fd4e5da5Sopenharmony_ci          %3 = OpTypeFunction %2
1347fd4e5da5Sopenharmony_ci          %4 = OpFunction %2 None %3
1348fd4e5da5Sopenharmony_ci          %5 = OpLabel
1349fd4e5da5Sopenharmony_ci               OpBranch %54
1350fd4e5da5Sopenharmony_ci         %54 = OpLabel
1351fd4e5da5Sopenharmony_ci          %6 = OpCopyObject %20 %21
1352fd4e5da5Sopenharmony_ci               OpSelectionMerge %8 None
1353fd4e5da5Sopenharmony_ci               OpBranchConditional %6 %7 %8
1354fd4e5da5Sopenharmony_ci          %7 = OpLabel
1355fd4e5da5Sopenharmony_ci               OpBranch %8
1356fd4e5da5Sopenharmony_ci          %8 = OpLabel
1357fd4e5da5Sopenharmony_ci               OpReturn
1358fd4e5da5Sopenharmony_ci               OpFunctionEnd
1359fd4e5da5Sopenharmony_ci  )";
1360fd4e5da5Sopenharmony_ci
1361fd4e5da5Sopenharmony_ci  const auto env = SPV_ENV_UNIVERSAL_1_5;
1362fd4e5da5Sopenharmony_ci  const auto consumer = nullptr;
1363fd4e5da5Sopenharmony_ci  const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption);
1364fd4e5da5Sopenharmony_ci  spvtools::ValidatorOptions validator_options;
1365fd4e5da5Sopenharmony_ci  ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
1366fd4e5da5Sopenharmony_ci                                               kConsoleMessageConsumer));
1367fd4e5da5Sopenharmony_ci  TransformationContext transformation_context(
1368fd4e5da5Sopenharmony_ci      MakeUnique<FactManager>(context.get()), validator_options);
1369fd4e5da5Sopenharmony_ci  TransformationOutlineFunction transformation(
1370fd4e5da5Sopenharmony_ci      /*entry_block*/ 54,
1371fd4e5da5Sopenharmony_ci      /*exit_block*/ 54,
1372fd4e5da5Sopenharmony_ci      /*new_function_struct_return_type_id*/ 200,
1373fd4e5da5Sopenharmony_ci      /*new_function_type_id*/ 201,
1374fd4e5da5Sopenharmony_ci      /*new_function_id*/ 202,
1375fd4e5da5Sopenharmony_ci      /*new_function_region_entry_block*/ 203,
1376fd4e5da5Sopenharmony_ci      /*new_caller_result_id*/ 204,
1377fd4e5da5Sopenharmony_ci      /*new_callee_result_id*/ 205,
1378fd4e5da5Sopenharmony_ci      /*input_id_to_fresh_id*/ {{}},
1379fd4e5da5Sopenharmony_ci      /*output_id_to_fresh_id*/ {{6, 206}});
1380fd4e5da5Sopenharmony_ci
1381fd4e5da5Sopenharmony_ci  ASSERT_TRUE(
1382fd4e5da5Sopenharmony_ci      transformation.IsApplicable(context.get(), transformation_context));
1383fd4e5da5Sopenharmony_ci  ApplyAndCheckFreshIds(transformation, context.get(), &transformation_context);
1384fd4e5da5Sopenharmony_ci  ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
1385fd4e5da5Sopenharmony_ci                                               kConsoleMessageConsumer));
1386fd4e5da5Sopenharmony_ci
1387fd4e5da5Sopenharmony_ci  std::string after_transformation = R"(
1388fd4e5da5Sopenharmony_ci               OpCapability Shader
1389fd4e5da5Sopenharmony_ci          %1 = OpExtInstImport "GLSL.std.450"
1390fd4e5da5Sopenharmony_ci               OpMemoryModel Logical GLSL450
1391fd4e5da5Sopenharmony_ci               OpEntryPoint Fragment %4 "main"
1392fd4e5da5Sopenharmony_ci               OpExecutionMode %4 OriginUpperLeft
1393fd4e5da5Sopenharmony_ci               OpSource ESSL 310
1394fd4e5da5Sopenharmony_ci         %20 = OpTypeBool
1395fd4e5da5Sopenharmony_ci         %21 = OpConstantTrue %20
1396fd4e5da5Sopenharmony_ci          %2 = OpTypeVoid
1397fd4e5da5Sopenharmony_ci          %3 = OpTypeFunction %2
1398fd4e5da5Sopenharmony_ci        %200 = OpTypeStruct %20
1399fd4e5da5Sopenharmony_ci        %201 = OpTypeFunction %200
1400fd4e5da5Sopenharmony_ci          %4 = OpFunction %2 None %3
1401fd4e5da5Sopenharmony_ci          %5 = OpLabel
1402fd4e5da5Sopenharmony_ci               OpBranch %54
1403fd4e5da5Sopenharmony_ci         %54 = OpLabel
1404fd4e5da5Sopenharmony_ci        %204 = OpFunctionCall %200 %202
1405fd4e5da5Sopenharmony_ci          %6 = OpCompositeExtract %20 %204 0
1406fd4e5da5Sopenharmony_ci               OpSelectionMerge %8 None
1407fd4e5da5Sopenharmony_ci               OpBranchConditional %6 %7 %8
1408fd4e5da5Sopenharmony_ci          %7 = OpLabel
1409fd4e5da5Sopenharmony_ci               OpBranch %8
1410fd4e5da5Sopenharmony_ci          %8 = OpLabel
1411fd4e5da5Sopenharmony_ci               OpReturn
1412fd4e5da5Sopenharmony_ci               OpFunctionEnd
1413fd4e5da5Sopenharmony_ci        %202 = OpFunction %200 None %201
1414fd4e5da5Sopenharmony_ci        %203 = OpLabel
1415fd4e5da5Sopenharmony_ci        %206 = OpCopyObject %20 %21
1416fd4e5da5Sopenharmony_ci        %205 = OpCompositeConstruct %200 %206
1417fd4e5da5Sopenharmony_ci               OpReturnValue %205
1418fd4e5da5Sopenharmony_ci               OpFunctionEnd
1419fd4e5da5Sopenharmony_ci  )";
1420fd4e5da5Sopenharmony_ci  ASSERT_TRUE(IsEqual(env, after_transformation, context.get()));
1421fd4e5da5Sopenharmony_ci}
1422fd4e5da5Sopenharmony_ci
1423fd4e5da5Sopenharmony_ciTEST(TransformationOutlineFunctionTest,
1424fd4e5da5Sopenharmony_ci     OutlineRegionEndingWithConditionalBranch2) {
1425fd4e5da5Sopenharmony_ci  std::string shader = R"(
1426fd4e5da5Sopenharmony_ci               OpCapability Shader
1427fd4e5da5Sopenharmony_ci          %1 = OpExtInstImport "GLSL.std.450"
1428fd4e5da5Sopenharmony_ci               OpMemoryModel Logical GLSL450
1429fd4e5da5Sopenharmony_ci               OpEntryPoint Fragment %4 "main"
1430fd4e5da5Sopenharmony_ci               OpExecutionMode %4 OriginUpperLeft
1431fd4e5da5Sopenharmony_ci               OpSource ESSL 310
1432fd4e5da5Sopenharmony_ci         %20 = OpTypeBool
1433fd4e5da5Sopenharmony_ci         %21 = OpConstantTrue %20
1434fd4e5da5Sopenharmony_ci          %2 = OpTypeVoid
1435fd4e5da5Sopenharmony_ci          %3 = OpTypeFunction %2
1436fd4e5da5Sopenharmony_ci          %4 = OpFunction %2 None %3
1437fd4e5da5Sopenharmony_ci          %5 = OpLabel
1438fd4e5da5Sopenharmony_ci          %6 = OpCopyObject %20 %21
1439fd4e5da5Sopenharmony_ci               OpBranch %54
1440fd4e5da5Sopenharmony_ci         %54 = OpLabel
1441fd4e5da5Sopenharmony_ci               OpSelectionMerge %8 None
1442fd4e5da5Sopenharmony_ci               OpBranchConditional %6 %7 %8
1443fd4e5da5Sopenharmony_ci          %7 = OpLabel
1444fd4e5da5Sopenharmony_ci               OpBranch %8
1445fd4e5da5Sopenharmony_ci          %8 = OpLabel
1446fd4e5da5Sopenharmony_ci               OpReturn
1447fd4e5da5Sopenharmony_ci               OpFunctionEnd
1448fd4e5da5Sopenharmony_ci  )";
1449fd4e5da5Sopenharmony_ci
1450fd4e5da5Sopenharmony_ci  const auto env = SPV_ENV_UNIVERSAL_1_5;
1451fd4e5da5Sopenharmony_ci  const auto consumer = nullptr;
1452fd4e5da5Sopenharmony_ci  const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption);
1453fd4e5da5Sopenharmony_ci  spvtools::ValidatorOptions validator_options;
1454fd4e5da5Sopenharmony_ci  ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
1455fd4e5da5Sopenharmony_ci                                               kConsoleMessageConsumer));
1456fd4e5da5Sopenharmony_ci  TransformationContext transformation_context(
1457fd4e5da5Sopenharmony_ci      MakeUnique<FactManager>(context.get()), validator_options);
1458fd4e5da5Sopenharmony_ci  TransformationOutlineFunction transformation(
1459fd4e5da5Sopenharmony_ci      /*entry_block*/ 54,
1460fd4e5da5Sopenharmony_ci      /*exit_block*/ 54,
1461fd4e5da5Sopenharmony_ci      /*new_function_struct_return_type_id*/ 200,
1462fd4e5da5Sopenharmony_ci      /*new_function_type_id*/ 201,
1463fd4e5da5Sopenharmony_ci      /*new_function_id*/ 202,
1464fd4e5da5Sopenharmony_ci      /*new_function_region_entry_block*/ 203,
1465fd4e5da5Sopenharmony_ci      /*new_caller_result_id*/ 204,
1466fd4e5da5Sopenharmony_ci      /*new_callee_result_id*/ 205,
1467fd4e5da5Sopenharmony_ci      /*input_id_to_fresh_id*/ {},
1468fd4e5da5Sopenharmony_ci      /*output_id_to_fresh_id*/ {});
1469fd4e5da5Sopenharmony_ci
1470fd4e5da5Sopenharmony_ci  ASSERT_TRUE(
1471fd4e5da5Sopenharmony_ci      transformation.IsApplicable(context.get(), transformation_context));
1472fd4e5da5Sopenharmony_ci  ApplyAndCheckFreshIds(transformation, context.get(), &transformation_context);
1473fd4e5da5Sopenharmony_ci  ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
1474fd4e5da5Sopenharmony_ci                                               kConsoleMessageConsumer));
1475fd4e5da5Sopenharmony_ci
1476fd4e5da5Sopenharmony_ci  std::string after_transformation = R"(
1477fd4e5da5Sopenharmony_ci               OpCapability Shader
1478fd4e5da5Sopenharmony_ci          %1 = OpExtInstImport "GLSL.std.450"
1479fd4e5da5Sopenharmony_ci               OpMemoryModel Logical GLSL450
1480fd4e5da5Sopenharmony_ci               OpEntryPoint Fragment %4 "main"
1481fd4e5da5Sopenharmony_ci               OpExecutionMode %4 OriginUpperLeft
1482fd4e5da5Sopenharmony_ci               OpSource ESSL 310
1483fd4e5da5Sopenharmony_ci         %20 = OpTypeBool
1484fd4e5da5Sopenharmony_ci         %21 = OpConstantTrue %20
1485fd4e5da5Sopenharmony_ci          %2 = OpTypeVoid
1486fd4e5da5Sopenharmony_ci          %3 = OpTypeFunction %2
1487fd4e5da5Sopenharmony_ci          %4 = OpFunction %2 None %3
1488fd4e5da5Sopenharmony_ci          %5 = OpLabel
1489fd4e5da5Sopenharmony_ci          %6 = OpCopyObject %20 %21
1490fd4e5da5Sopenharmony_ci               OpBranch %54
1491fd4e5da5Sopenharmony_ci         %54 = OpLabel
1492fd4e5da5Sopenharmony_ci        %204 = OpFunctionCall %2 %202
1493fd4e5da5Sopenharmony_ci               OpSelectionMerge %8 None
1494fd4e5da5Sopenharmony_ci               OpBranchConditional %6 %7 %8
1495fd4e5da5Sopenharmony_ci          %7 = OpLabel
1496fd4e5da5Sopenharmony_ci               OpBranch %8
1497fd4e5da5Sopenharmony_ci          %8 = OpLabel
1498fd4e5da5Sopenharmony_ci               OpReturn
1499fd4e5da5Sopenharmony_ci               OpFunctionEnd
1500fd4e5da5Sopenharmony_ci        %202 = OpFunction %2 None %3
1501fd4e5da5Sopenharmony_ci        %203 = OpLabel
1502fd4e5da5Sopenharmony_ci               OpReturn
1503fd4e5da5Sopenharmony_ci               OpFunctionEnd
1504fd4e5da5Sopenharmony_ci  )";
1505fd4e5da5Sopenharmony_ci  ASSERT_TRUE(IsEqual(env, after_transformation, context.get()));
1506fd4e5da5Sopenharmony_ci}
1507fd4e5da5Sopenharmony_ci
1508fd4e5da5Sopenharmony_ciTEST(TransformationOutlineFunctionTest, DoNotOutlineRegionThatStartsWithOpPhi) {
1509fd4e5da5Sopenharmony_ci  std::string shader = R"(
1510fd4e5da5Sopenharmony_ci               OpCapability Shader
1511fd4e5da5Sopenharmony_ci          %1 = OpExtInstImport "GLSL.std.450"
1512fd4e5da5Sopenharmony_ci               OpMemoryModel Logical GLSL450
1513fd4e5da5Sopenharmony_ci               OpEntryPoint Fragment %4 "main"
1514fd4e5da5Sopenharmony_ci               OpExecutionMode %4 OriginUpperLeft
1515fd4e5da5Sopenharmony_ci               OpSource ESSL 310
1516fd4e5da5Sopenharmony_ci               OpName %4 "main"
1517fd4e5da5Sopenharmony_ci          %2 = OpTypeVoid
1518fd4e5da5Sopenharmony_ci          %3 = OpTypeFunction %2
1519fd4e5da5Sopenharmony_ci          %6 = OpTypeBool
1520fd4e5da5Sopenharmony_ci          %7 = OpConstantTrue %6
1521fd4e5da5Sopenharmony_ci          %4 = OpFunction %2 None %3
1522fd4e5da5Sopenharmony_ci          %5 = OpLabel
1523fd4e5da5Sopenharmony_ci               OpBranch %21
1524fd4e5da5Sopenharmony_ci         %21 = OpLabel
1525fd4e5da5Sopenharmony_ci         %22 = OpPhi %6 %7 %5
1526fd4e5da5Sopenharmony_ci         %23 = OpCopyObject %6 %22
1527fd4e5da5Sopenharmony_ci               OpBranch %24
1528fd4e5da5Sopenharmony_ci         %24 = OpLabel
1529fd4e5da5Sopenharmony_ci         %25 = OpCopyObject %6 %23
1530fd4e5da5Sopenharmony_ci         %26 = OpCopyObject %6 %22
1531fd4e5da5Sopenharmony_ci               OpReturn
1532fd4e5da5Sopenharmony_ci               OpFunctionEnd
1533fd4e5da5Sopenharmony_ci  )";
1534fd4e5da5Sopenharmony_ci
1535fd4e5da5Sopenharmony_ci  const auto env = SPV_ENV_UNIVERSAL_1_5;
1536fd4e5da5Sopenharmony_ci  const auto consumer = nullptr;
1537fd4e5da5Sopenharmony_ci  const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption);
1538fd4e5da5Sopenharmony_ci  spvtools::ValidatorOptions validator_options;
1539fd4e5da5Sopenharmony_ci  ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
1540fd4e5da5Sopenharmony_ci                                               kConsoleMessageConsumer));
1541fd4e5da5Sopenharmony_ci  TransformationContext transformation_context(
1542fd4e5da5Sopenharmony_ci      MakeUnique<FactManager>(context.get()), validator_options);
1543fd4e5da5Sopenharmony_ci  TransformationOutlineFunction transformation(
1544fd4e5da5Sopenharmony_ci      /*entry_block*/ 21,
1545fd4e5da5Sopenharmony_ci      /*exit_block*/ 21,
1546fd4e5da5Sopenharmony_ci      /*new_function_struct_return_type_id*/ 200,
1547fd4e5da5Sopenharmony_ci      /*new_function_type_id*/ 201,
1548fd4e5da5Sopenharmony_ci      /*new_function_id*/ 202,
1549fd4e5da5Sopenharmony_ci      /*new_function_region_entry_block*/ 204,
1550fd4e5da5Sopenharmony_ci      /*new_caller_result_id*/ 205,
1551fd4e5da5Sopenharmony_ci      /*new_callee_result_id*/ 206,
1552fd4e5da5Sopenharmony_ci      /*input_id_to_fresh_id*/ {{22, 207}},
1553fd4e5da5Sopenharmony_ci      /*output_id_to_fresh_id*/ {{23, 208}});
1554fd4e5da5Sopenharmony_ci
1555fd4e5da5Sopenharmony_ci  ASSERT_FALSE(
1556fd4e5da5Sopenharmony_ci      transformation.IsApplicable(context.get(), transformation_context));
1557fd4e5da5Sopenharmony_ci}
1558fd4e5da5Sopenharmony_ci
1559fd4e5da5Sopenharmony_ciTEST(TransformationOutlineFunctionTest,
1560fd4e5da5Sopenharmony_ci     DoNotOutlineRegionThatStartsWithLoopHeader) {
1561fd4e5da5Sopenharmony_ci  std::string shader = R"(
1562fd4e5da5Sopenharmony_ci               OpCapability Shader
1563fd4e5da5Sopenharmony_ci          %1 = OpExtInstImport "GLSL.std.450"
1564fd4e5da5Sopenharmony_ci               OpMemoryModel Logical GLSL450
1565fd4e5da5Sopenharmony_ci               OpEntryPoint Fragment %4 "main"
1566fd4e5da5Sopenharmony_ci               OpExecutionMode %4 OriginUpperLeft
1567fd4e5da5Sopenharmony_ci               OpSource ESSL 310
1568fd4e5da5Sopenharmony_ci               OpName %4 "main"
1569fd4e5da5Sopenharmony_ci          %2 = OpTypeVoid
1570fd4e5da5Sopenharmony_ci          %3 = OpTypeFunction %2
1571fd4e5da5Sopenharmony_ci          %6 = OpTypeBool
1572fd4e5da5Sopenharmony_ci          %7 = OpConstantTrue %6
1573fd4e5da5Sopenharmony_ci          %4 = OpFunction %2 None %3
1574fd4e5da5Sopenharmony_ci          %5 = OpLabel
1575fd4e5da5Sopenharmony_ci               OpBranch %21
1576fd4e5da5Sopenharmony_ci         %21 = OpLabel
1577fd4e5da5Sopenharmony_ci               OpLoopMerge %22 %23 None
1578fd4e5da5Sopenharmony_ci               OpBranch %24
1579fd4e5da5Sopenharmony_ci         %24 = OpLabel
1580fd4e5da5Sopenharmony_ci               OpBranchConditional %7 %22 %23
1581fd4e5da5Sopenharmony_ci         %23 = OpLabel
1582fd4e5da5Sopenharmony_ci               OpBranch %21
1583fd4e5da5Sopenharmony_ci         %22 = OpLabel
1584fd4e5da5Sopenharmony_ci               OpBranch %25
1585fd4e5da5Sopenharmony_ci         %25 = OpLabel
1586fd4e5da5Sopenharmony_ci               OpReturn
1587fd4e5da5Sopenharmony_ci               OpFunctionEnd
1588fd4e5da5Sopenharmony_ci  )";
1589fd4e5da5Sopenharmony_ci
1590fd4e5da5Sopenharmony_ci  const auto env = SPV_ENV_UNIVERSAL_1_5;
1591fd4e5da5Sopenharmony_ci  const auto consumer = nullptr;
1592fd4e5da5Sopenharmony_ci  const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption);
1593fd4e5da5Sopenharmony_ci  spvtools::ValidatorOptions validator_options;
1594fd4e5da5Sopenharmony_ci  ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
1595fd4e5da5Sopenharmony_ci                                               kConsoleMessageConsumer));
1596fd4e5da5Sopenharmony_ci  TransformationContext transformation_context(
1597fd4e5da5Sopenharmony_ci      MakeUnique<FactManager>(context.get()), validator_options);
1598fd4e5da5Sopenharmony_ci  TransformationOutlineFunction transformation(
1599fd4e5da5Sopenharmony_ci      /*entry_block*/ 21,
1600fd4e5da5Sopenharmony_ci      /*exit_block*/ 24,
1601fd4e5da5Sopenharmony_ci      /*new_function_struct_return_type_id*/ 200,
1602fd4e5da5Sopenharmony_ci      /*new_function_type_id*/ 201,
1603fd4e5da5Sopenharmony_ci      /*new_function_id*/ 202,
1604fd4e5da5Sopenharmony_ci      /*new_function_region_entry_block*/ 204,
1605fd4e5da5Sopenharmony_ci      /*new_caller_result_id*/ 205,
1606fd4e5da5Sopenharmony_ci      /*new_callee_result_id*/ 206,
1607fd4e5da5Sopenharmony_ci      /*input_id_to_fresh_id*/ {},
1608fd4e5da5Sopenharmony_ci      /*output_id_to_fresh_id*/ {});
1609fd4e5da5Sopenharmony_ci
1610fd4e5da5Sopenharmony_ci  ASSERT_FALSE(
1611fd4e5da5Sopenharmony_ci      transformation.IsApplicable(context.get(), transformation_context));
1612fd4e5da5Sopenharmony_ci}
1613fd4e5da5Sopenharmony_ci
1614fd4e5da5Sopenharmony_ciTEST(TransformationOutlineFunctionTest,
1615fd4e5da5Sopenharmony_ci     DoNotOutlineRegionThatEndsWithLoopMerge) {
1616fd4e5da5Sopenharmony_ci  std::string shader = R"(
1617fd4e5da5Sopenharmony_ci               OpCapability Shader
1618fd4e5da5Sopenharmony_ci          %1 = OpExtInstImport "GLSL.std.450"
1619fd4e5da5Sopenharmony_ci               OpMemoryModel Logical GLSL450
1620fd4e5da5Sopenharmony_ci               OpEntryPoint Fragment %4 "main"
1621fd4e5da5Sopenharmony_ci               OpExecutionMode %4 OriginUpperLeft
1622fd4e5da5Sopenharmony_ci               OpSource ESSL 310
1623fd4e5da5Sopenharmony_ci               OpName %4 "main"
1624fd4e5da5Sopenharmony_ci          %2 = OpTypeVoid
1625fd4e5da5Sopenharmony_ci          %3 = OpTypeFunction %2
1626fd4e5da5Sopenharmony_ci          %6 = OpTypeBool
1627fd4e5da5Sopenharmony_ci          %7 = OpConstantTrue %6
1628fd4e5da5Sopenharmony_ci          %4 = OpFunction %2 None %3
1629fd4e5da5Sopenharmony_ci          %5 = OpLabel
1630fd4e5da5Sopenharmony_ci               OpBranch %21
1631fd4e5da5Sopenharmony_ci         %21 = OpLabel
1632fd4e5da5Sopenharmony_ci               OpLoopMerge %22 %23 None
1633fd4e5da5Sopenharmony_ci               OpBranch %24
1634fd4e5da5Sopenharmony_ci         %24 = OpLabel
1635fd4e5da5Sopenharmony_ci               OpBranchConditional %7 %22 %23
1636fd4e5da5Sopenharmony_ci         %23 = OpLabel
1637fd4e5da5Sopenharmony_ci               OpBranch %21
1638fd4e5da5Sopenharmony_ci         %22 = OpLabel
1639fd4e5da5Sopenharmony_ci               OpBranch %25
1640fd4e5da5Sopenharmony_ci         %25 = OpLabel
1641fd4e5da5Sopenharmony_ci               OpReturn
1642fd4e5da5Sopenharmony_ci               OpFunctionEnd
1643fd4e5da5Sopenharmony_ci  )";
1644fd4e5da5Sopenharmony_ci
1645fd4e5da5Sopenharmony_ci  const auto env = SPV_ENV_UNIVERSAL_1_5;
1646fd4e5da5Sopenharmony_ci  const auto consumer = nullptr;
1647fd4e5da5Sopenharmony_ci  const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption);
1648fd4e5da5Sopenharmony_ci  spvtools::ValidatorOptions validator_options;
1649fd4e5da5Sopenharmony_ci  ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
1650fd4e5da5Sopenharmony_ci                                               kConsoleMessageConsumer));
1651fd4e5da5Sopenharmony_ci  TransformationContext transformation_context(
1652fd4e5da5Sopenharmony_ci      MakeUnique<FactManager>(context.get()), validator_options);
1653fd4e5da5Sopenharmony_ci  TransformationOutlineFunction transformation(
1654fd4e5da5Sopenharmony_ci      /*entry_block*/ 5,
1655fd4e5da5Sopenharmony_ci      /*exit_block*/ 22,
1656fd4e5da5Sopenharmony_ci      /*new_function_struct_return_type_id*/ 200,
1657fd4e5da5Sopenharmony_ci      /*new_function_type_id*/ 201,
1658fd4e5da5Sopenharmony_ci      /*new_function_id*/ 202,
1659fd4e5da5Sopenharmony_ci      /*new_function_region_entry_block*/ 204,
1660fd4e5da5Sopenharmony_ci      /*new_caller_result_id*/ 205,
1661fd4e5da5Sopenharmony_ci      /*new_callee_result_id*/ 206,
1662fd4e5da5Sopenharmony_ci      /*input_id_to_fresh_id*/ {},
1663fd4e5da5Sopenharmony_ci      /*output_id_to_fresh_id*/ {});
1664fd4e5da5Sopenharmony_ci
1665fd4e5da5Sopenharmony_ci  ASSERT_FALSE(
1666fd4e5da5Sopenharmony_ci      transformation.IsApplicable(context.get(), transformation_context));
1667fd4e5da5Sopenharmony_ci}
1668fd4e5da5Sopenharmony_ci
1669fd4e5da5Sopenharmony_ciTEST(TransformationOutlineFunctionTest, DoNotOutlineRegionThatUsesAccessChain) {
1670fd4e5da5Sopenharmony_ci  // An access chain result is a pointer, but it cannot be passed as a function
1671fd4e5da5Sopenharmony_ci  // parameter, as it is not a memory object.
1672fd4e5da5Sopenharmony_ci  std::string shader = R"(
1673fd4e5da5Sopenharmony_ci               OpCapability Shader
1674fd4e5da5Sopenharmony_ci          %1 = OpExtInstImport "GLSL.std.450"
1675fd4e5da5Sopenharmony_ci               OpMemoryModel Logical GLSL450
1676fd4e5da5Sopenharmony_ci               OpEntryPoint Fragment %4 "main"
1677fd4e5da5Sopenharmony_ci               OpExecutionMode %4 OriginUpperLeft
1678fd4e5da5Sopenharmony_ci               OpSource ESSL 310
1679fd4e5da5Sopenharmony_ci               OpName %4 "main"
1680fd4e5da5Sopenharmony_ci          %2 = OpTypeVoid
1681fd4e5da5Sopenharmony_ci          %3 = OpTypeFunction %2
1682fd4e5da5Sopenharmony_ci          %6 = OpTypeFloat 32
1683fd4e5da5Sopenharmony_ci          %7 = OpTypeVector %6 4
1684fd4e5da5Sopenharmony_ci          %8 = OpTypePointer Function %7
1685fd4e5da5Sopenharmony_ci          %9 = OpTypePointer Function %6
1686fd4e5da5Sopenharmony_ci         %18 = OpTypeInt 32 0
1687fd4e5da5Sopenharmony_ci         %19 = OpConstant %18 0
1688fd4e5da5Sopenharmony_ci          %4 = OpFunction %2 None %3
1689fd4e5da5Sopenharmony_ci          %5 = OpLabel
1690fd4e5da5Sopenharmony_ci         %10 = OpVariable %8 Function
1691fd4e5da5Sopenharmony_ci               OpBranch %11
1692fd4e5da5Sopenharmony_ci         %11 = OpLabel
1693fd4e5da5Sopenharmony_ci         %12 = OpAccessChain %9 %10 %19
1694fd4e5da5Sopenharmony_ci               OpBranch %13
1695fd4e5da5Sopenharmony_ci         %13 = OpLabel
1696fd4e5da5Sopenharmony_ci         %14 = OpLoad %6 %12
1697fd4e5da5Sopenharmony_ci               OpBranch %15
1698fd4e5da5Sopenharmony_ci         %15 = OpLabel
1699fd4e5da5Sopenharmony_ci               OpReturn
1700fd4e5da5Sopenharmony_ci               OpFunctionEnd
1701fd4e5da5Sopenharmony_ci  )";
1702fd4e5da5Sopenharmony_ci
1703fd4e5da5Sopenharmony_ci  const auto env = SPV_ENV_UNIVERSAL_1_5;
1704fd4e5da5Sopenharmony_ci  const auto consumer = nullptr;
1705fd4e5da5Sopenharmony_ci  const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption);
1706fd4e5da5Sopenharmony_ci  spvtools::ValidatorOptions validator_options;
1707fd4e5da5Sopenharmony_ci  ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
1708fd4e5da5Sopenharmony_ci                                               kConsoleMessageConsumer));
1709fd4e5da5Sopenharmony_ci  TransformationContext transformation_context(
1710fd4e5da5Sopenharmony_ci      MakeUnique<FactManager>(context.get()), validator_options);
1711fd4e5da5Sopenharmony_ci  TransformationOutlineFunction transformation(
1712fd4e5da5Sopenharmony_ci      /*entry_block*/ 13,
1713fd4e5da5Sopenharmony_ci      /*exit_block*/ 15,
1714fd4e5da5Sopenharmony_ci      /*new_function_struct_return_type_id*/ 200,
1715fd4e5da5Sopenharmony_ci      /*new_function_type_id*/ 201,
1716fd4e5da5Sopenharmony_ci      /*new_function_id*/ 202,
1717fd4e5da5Sopenharmony_ci      /*new_function_region_entry_block*/ 204,
1718fd4e5da5Sopenharmony_ci      /*new_caller_result_id*/ 205,
1719fd4e5da5Sopenharmony_ci      /*new_callee_result_id*/ 206,
1720fd4e5da5Sopenharmony_ci      /*input_id_to_fresh_id*/ {{12, 207}},
1721fd4e5da5Sopenharmony_ci      /*output_id_to_fresh_id*/ {});
1722fd4e5da5Sopenharmony_ci
1723fd4e5da5Sopenharmony_ci  ASSERT_FALSE(
1724fd4e5da5Sopenharmony_ci      transformation.IsApplicable(context.get(), transformation_context));
1725fd4e5da5Sopenharmony_ci}
1726fd4e5da5Sopenharmony_ci
1727fd4e5da5Sopenharmony_ciTEST(TransformationOutlineFunctionTest,
1728fd4e5da5Sopenharmony_ci     DoNotOutlineRegionThatUsesCopiedObject) {
1729fd4e5da5Sopenharmony_ci  // Copying a variable leads to a pointer, but one that cannot be passed as a
1730fd4e5da5Sopenharmony_ci  // function parameter, as it is not a memory object.
1731fd4e5da5Sopenharmony_ci  std::string shader = R"(
1732fd4e5da5Sopenharmony_ci               OpCapability Shader
1733fd4e5da5Sopenharmony_ci          %1 = OpExtInstImport "GLSL.std.450"
1734fd4e5da5Sopenharmony_ci               OpMemoryModel Logical GLSL450
1735fd4e5da5Sopenharmony_ci               OpEntryPoint Fragment %4 "main"
1736fd4e5da5Sopenharmony_ci               OpExecutionMode %4 OriginUpperLeft
1737fd4e5da5Sopenharmony_ci               OpSource ESSL 310
1738fd4e5da5Sopenharmony_ci               OpName %4 "main"
1739fd4e5da5Sopenharmony_ci          %2 = OpTypeVoid
1740fd4e5da5Sopenharmony_ci          %3 = OpTypeFunction %2
1741fd4e5da5Sopenharmony_ci          %6 = OpTypeFloat 32
1742fd4e5da5Sopenharmony_ci          %7 = OpTypeVector %6 4
1743fd4e5da5Sopenharmony_ci          %8 = OpTypePointer Function %7
1744fd4e5da5Sopenharmony_ci          %9 = OpTypePointer Function %6
1745fd4e5da5Sopenharmony_ci         %18 = OpTypeInt 32 0
1746fd4e5da5Sopenharmony_ci         %19 = OpConstant %18 0
1747fd4e5da5Sopenharmony_ci          %4 = OpFunction %2 None %3
1748fd4e5da5Sopenharmony_ci          %5 = OpLabel
1749fd4e5da5Sopenharmony_ci         %10 = OpVariable %8 Function
1750fd4e5da5Sopenharmony_ci               OpBranch %11
1751fd4e5da5Sopenharmony_ci         %11 = OpLabel
1752fd4e5da5Sopenharmony_ci         %20 = OpCopyObject %8 %10
1753fd4e5da5Sopenharmony_ci               OpBranch %13
1754fd4e5da5Sopenharmony_ci         %13 = OpLabel
1755fd4e5da5Sopenharmony_ci         %12 = OpAccessChain %9 %20 %19
1756fd4e5da5Sopenharmony_ci         %14 = OpLoad %6 %12
1757fd4e5da5Sopenharmony_ci               OpBranch %15
1758fd4e5da5Sopenharmony_ci         %15 = OpLabel
1759fd4e5da5Sopenharmony_ci               OpReturn
1760fd4e5da5Sopenharmony_ci               OpFunctionEnd
1761fd4e5da5Sopenharmony_ci  )";
1762fd4e5da5Sopenharmony_ci
1763fd4e5da5Sopenharmony_ci  const auto env = SPV_ENV_UNIVERSAL_1_5;
1764fd4e5da5Sopenharmony_ci  const auto consumer = nullptr;
1765fd4e5da5Sopenharmony_ci  const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption);
1766fd4e5da5Sopenharmony_ci  spvtools::ValidatorOptions validator_options;
1767fd4e5da5Sopenharmony_ci  ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
1768fd4e5da5Sopenharmony_ci                                               kConsoleMessageConsumer));
1769fd4e5da5Sopenharmony_ci  TransformationContext transformation_context(
1770fd4e5da5Sopenharmony_ci      MakeUnique<FactManager>(context.get()), validator_options);
1771fd4e5da5Sopenharmony_ci  TransformationOutlineFunction transformation(
1772fd4e5da5Sopenharmony_ci      /*entry_block*/ 13,
1773fd4e5da5Sopenharmony_ci      /*exit_block*/ 15,
1774fd4e5da5Sopenharmony_ci      /*new_function_struct_return_type_id*/ 200,
1775fd4e5da5Sopenharmony_ci      /*new_function_type_id*/ 201,
1776fd4e5da5Sopenharmony_ci      /*new_function_id*/ 202,
1777fd4e5da5Sopenharmony_ci      /*new_function_region_entry_block*/ 204,
1778fd4e5da5Sopenharmony_ci      /*new_caller_result_id*/ 205,
1779fd4e5da5Sopenharmony_ci      /*new_callee_result_id*/ 206,
1780fd4e5da5Sopenharmony_ci      /*input_id_to_fresh_id*/ {{20, 207}},
1781fd4e5da5Sopenharmony_ci      /*output_id_to_fresh_id*/ {});
1782fd4e5da5Sopenharmony_ci
1783fd4e5da5Sopenharmony_ci  ASSERT_FALSE(
1784fd4e5da5Sopenharmony_ci      transformation.IsApplicable(context.get(), transformation_context));
1785fd4e5da5Sopenharmony_ci}
1786fd4e5da5Sopenharmony_ci
1787fd4e5da5Sopenharmony_ciTEST(TransformationOutlineFunctionTest,
1788fd4e5da5Sopenharmony_ci     DoOutlineRegionThatUsesPointerParameter) {
1789fd4e5da5Sopenharmony_ci  // The region being outlined reads from a function parameter of pointer type.
1790fd4e5da5Sopenharmony_ci  // This is OK: the function parameter can itself be passed on as a function
1791fd4e5da5Sopenharmony_ci  // parameter.
1792fd4e5da5Sopenharmony_ci  std::string shader = R"(
1793fd4e5da5Sopenharmony_ci               OpCapability Shader
1794fd4e5da5Sopenharmony_ci          %1 = OpExtInstImport "GLSL.std.450"
1795fd4e5da5Sopenharmony_ci               OpMemoryModel Logical GLSL450
1796fd4e5da5Sopenharmony_ci               OpEntryPoint Fragment %4 "main"
1797fd4e5da5Sopenharmony_ci               OpExecutionMode %4 OriginUpperLeft
1798fd4e5da5Sopenharmony_ci               OpSource ESSL 310
1799fd4e5da5Sopenharmony_ci          %2 = OpTypeVoid
1800fd4e5da5Sopenharmony_ci          %3 = OpTypeFunction %2
1801fd4e5da5Sopenharmony_ci          %6 = OpTypeInt 32 1
1802fd4e5da5Sopenharmony_ci          %7 = OpTypePointer Function %6
1803fd4e5da5Sopenharmony_ci          %8 = OpTypeFunction %2 %7
1804fd4e5da5Sopenharmony_ci         %13 = OpConstant %6 2
1805fd4e5da5Sopenharmony_ci          %4 = OpFunction %2 None %3
1806fd4e5da5Sopenharmony_ci          %5 = OpLabel
1807fd4e5da5Sopenharmony_ci         %15 = OpVariable %7 Function
1808fd4e5da5Sopenharmony_ci         %16 = OpVariable %7 Function
1809fd4e5da5Sopenharmony_ci         %17 = OpLoad %6 %15
1810fd4e5da5Sopenharmony_ci               OpStore %16 %17
1811fd4e5da5Sopenharmony_ci         %18 = OpFunctionCall %2 %10 %16
1812fd4e5da5Sopenharmony_ci         %19 = OpLoad %6 %16
1813fd4e5da5Sopenharmony_ci               OpStore %15 %19
1814fd4e5da5Sopenharmony_ci               OpReturn
1815fd4e5da5Sopenharmony_ci               OpFunctionEnd
1816fd4e5da5Sopenharmony_ci         %10 = OpFunction %2 None %8
1817fd4e5da5Sopenharmony_ci          %9 = OpFunctionParameter %7
1818fd4e5da5Sopenharmony_ci         %11 = OpLabel
1819fd4e5da5Sopenharmony_ci         %12 = OpLoad %6 %9
1820fd4e5da5Sopenharmony_ci         %14 = OpIAdd %6 %12 %13
1821fd4e5da5Sopenharmony_ci               OpBranch %20
1822fd4e5da5Sopenharmony_ci         %20 = OpLabel
1823fd4e5da5Sopenharmony_ci               OpStore %9 %14
1824fd4e5da5Sopenharmony_ci               OpReturn
1825fd4e5da5Sopenharmony_ci               OpFunctionEnd
1826fd4e5da5Sopenharmony_ci  )";
1827fd4e5da5Sopenharmony_ci
1828fd4e5da5Sopenharmony_ci  const auto env = SPV_ENV_UNIVERSAL_1_5;
1829fd4e5da5Sopenharmony_ci  const auto consumer = nullptr;
1830fd4e5da5Sopenharmony_ci  const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption);
1831fd4e5da5Sopenharmony_ci  spvtools::ValidatorOptions validator_options;
1832fd4e5da5Sopenharmony_ci  ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
1833fd4e5da5Sopenharmony_ci                                               kConsoleMessageConsumer));
1834fd4e5da5Sopenharmony_ci  TransformationContext transformation_context(
1835fd4e5da5Sopenharmony_ci      MakeUnique<FactManager>(context.get()), validator_options);
1836fd4e5da5Sopenharmony_ci  TransformationOutlineFunction transformation(
1837fd4e5da5Sopenharmony_ci      /*entry_block*/ 11,
1838fd4e5da5Sopenharmony_ci      /*exit_block*/ 11,
1839fd4e5da5Sopenharmony_ci      /*new_function_struct_return_type_id*/ 200,
1840fd4e5da5Sopenharmony_ci      /*new_function_type_id*/ 201,
1841fd4e5da5Sopenharmony_ci      /*new_function_id*/ 202,
1842fd4e5da5Sopenharmony_ci      /*new_function_region_entry_block*/ 204,
1843fd4e5da5Sopenharmony_ci      /*new_caller_result_id*/ 205,
1844fd4e5da5Sopenharmony_ci      /*new_callee_result_id*/ 206,
1845fd4e5da5Sopenharmony_ci      /*input_id_to_fresh_id*/ {{9, 207}},
1846fd4e5da5Sopenharmony_ci      /*output_id_to_fresh_id*/ {{14, 208}});
1847fd4e5da5Sopenharmony_ci
1848fd4e5da5Sopenharmony_ci  ASSERT_TRUE(
1849fd4e5da5Sopenharmony_ci      transformation.IsApplicable(context.get(), transformation_context));
1850fd4e5da5Sopenharmony_ci  ApplyAndCheckFreshIds(transformation, context.get(), &transformation_context);
1851fd4e5da5Sopenharmony_ci  ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
1852fd4e5da5Sopenharmony_ci                                               kConsoleMessageConsumer));
1853fd4e5da5Sopenharmony_ci
1854fd4e5da5Sopenharmony_ci  std::string after_transformation = R"(
1855fd4e5da5Sopenharmony_ci               OpCapability Shader
1856fd4e5da5Sopenharmony_ci          %1 = OpExtInstImport "GLSL.std.450"
1857fd4e5da5Sopenharmony_ci               OpMemoryModel Logical GLSL450
1858fd4e5da5Sopenharmony_ci               OpEntryPoint Fragment %4 "main"
1859fd4e5da5Sopenharmony_ci               OpExecutionMode %4 OriginUpperLeft
1860fd4e5da5Sopenharmony_ci               OpSource ESSL 310
1861fd4e5da5Sopenharmony_ci          %2 = OpTypeVoid
1862fd4e5da5Sopenharmony_ci          %3 = OpTypeFunction %2
1863fd4e5da5Sopenharmony_ci          %6 = OpTypeInt 32 1
1864fd4e5da5Sopenharmony_ci          %7 = OpTypePointer Function %6
1865fd4e5da5Sopenharmony_ci          %8 = OpTypeFunction %2 %7
1866fd4e5da5Sopenharmony_ci         %13 = OpConstant %6 2
1867fd4e5da5Sopenharmony_ci        %200 = OpTypeStruct %6
1868fd4e5da5Sopenharmony_ci        %201 = OpTypeFunction %200 %7
1869fd4e5da5Sopenharmony_ci          %4 = OpFunction %2 None %3
1870fd4e5da5Sopenharmony_ci          %5 = OpLabel
1871fd4e5da5Sopenharmony_ci         %15 = OpVariable %7 Function
1872fd4e5da5Sopenharmony_ci         %16 = OpVariable %7 Function
1873fd4e5da5Sopenharmony_ci         %17 = OpLoad %6 %15
1874fd4e5da5Sopenharmony_ci               OpStore %16 %17
1875fd4e5da5Sopenharmony_ci         %18 = OpFunctionCall %2 %10 %16
1876fd4e5da5Sopenharmony_ci         %19 = OpLoad %6 %16
1877fd4e5da5Sopenharmony_ci               OpStore %15 %19
1878fd4e5da5Sopenharmony_ci               OpReturn
1879fd4e5da5Sopenharmony_ci               OpFunctionEnd
1880fd4e5da5Sopenharmony_ci         %10 = OpFunction %2 None %8
1881fd4e5da5Sopenharmony_ci          %9 = OpFunctionParameter %7
1882fd4e5da5Sopenharmony_ci         %11 = OpLabel
1883fd4e5da5Sopenharmony_ci        %205 = OpFunctionCall %200 %202 %9
1884fd4e5da5Sopenharmony_ci         %14 = OpCompositeExtract %6 %205 0
1885fd4e5da5Sopenharmony_ci               OpBranch %20
1886fd4e5da5Sopenharmony_ci         %20 = OpLabel
1887fd4e5da5Sopenharmony_ci               OpStore %9 %14
1888fd4e5da5Sopenharmony_ci               OpReturn
1889fd4e5da5Sopenharmony_ci               OpFunctionEnd
1890fd4e5da5Sopenharmony_ci        %202 = OpFunction %200 None %201
1891fd4e5da5Sopenharmony_ci        %207 = OpFunctionParameter %7
1892fd4e5da5Sopenharmony_ci        %204 = OpLabel
1893fd4e5da5Sopenharmony_ci         %12 = OpLoad %6 %207
1894fd4e5da5Sopenharmony_ci        %208 = OpIAdd %6 %12 %13
1895fd4e5da5Sopenharmony_ci        %206 = OpCompositeConstruct %200 %208
1896fd4e5da5Sopenharmony_ci               OpReturnValue %206
1897fd4e5da5Sopenharmony_ci               OpFunctionEnd
1898fd4e5da5Sopenharmony_ci  )";
1899fd4e5da5Sopenharmony_ci  ASSERT_TRUE(IsEqual(env, after_transformation, context.get()));
1900fd4e5da5Sopenharmony_ci}
1901fd4e5da5Sopenharmony_ci
1902fd4e5da5Sopenharmony_ciTEST(TransformationOutlineFunctionTest, OutlineLivesafe) {
1903fd4e5da5Sopenharmony_ci  // In the following, %30 is a livesafe function, with irrelevant parameter
1904fd4e5da5Sopenharmony_ci  // %200 and irrelevant local variable %201.  Variable %100 is a loop limiter,
1905fd4e5da5Sopenharmony_ci  // which is not irrelevant.  The test checks that the outlined function is
1906fd4e5da5Sopenharmony_ci  // livesafe, and that the parameters corresponding to %200 and %201 have the
1907fd4e5da5Sopenharmony_ci  // irrelevant fact associated with them.
1908fd4e5da5Sopenharmony_ci  std::string shader = R"(
1909fd4e5da5Sopenharmony_ci               OpCapability Shader
1910fd4e5da5Sopenharmony_ci          %1 = OpExtInstImport "GLSL.std.450"
1911fd4e5da5Sopenharmony_ci               OpMemoryModel Logical GLSL450
1912fd4e5da5Sopenharmony_ci               OpEntryPoint Fragment %4 "main"
1913fd4e5da5Sopenharmony_ci               OpExecutionMode %4 OriginUpperLeft
1914fd4e5da5Sopenharmony_ci               OpSource ESSL 310
1915fd4e5da5Sopenharmony_ci          %2 = OpTypeVoid
1916fd4e5da5Sopenharmony_ci          %3 = OpTypeFunction %2
1917fd4e5da5Sopenharmony_ci          %6 = OpTypeInt 32 0
1918fd4e5da5Sopenharmony_ci          %7 = OpTypePointer Function %6
1919fd4e5da5Sopenharmony_ci        %199 = OpTypeFunction %2 %7
1920fd4e5da5Sopenharmony_ci          %8 = OpConstant %6 0
1921fd4e5da5Sopenharmony_ci          %9 = OpConstant %6 1
1922fd4e5da5Sopenharmony_ci         %10 = OpConstant %6 5
1923fd4e5da5Sopenharmony_ci         %11 = OpTypeBool
1924fd4e5da5Sopenharmony_ci         %12 = OpConstantTrue %11
1925fd4e5da5Sopenharmony_ci          %4 = OpFunction %2 None %3
1926fd4e5da5Sopenharmony_ci          %5 = OpLabel
1927fd4e5da5Sopenharmony_ci               OpReturn
1928fd4e5da5Sopenharmony_ci               OpFunctionEnd
1929fd4e5da5Sopenharmony_ci         %30 = OpFunction %2 None %199
1930fd4e5da5Sopenharmony_ci        %200 = OpFunctionParameter %7
1931fd4e5da5Sopenharmony_ci         %31 = OpLabel
1932fd4e5da5Sopenharmony_ci        %100 = OpVariable %7 Function %8
1933fd4e5da5Sopenharmony_ci        %201 = OpVariable %7 Function %8
1934fd4e5da5Sopenharmony_ci               OpBranch %198
1935fd4e5da5Sopenharmony_ci        %198 = OpLabel
1936fd4e5da5Sopenharmony_ci               OpBranch %20
1937fd4e5da5Sopenharmony_ci         %20 = OpLabel
1938fd4e5da5Sopenharmony_ci        %101 = OpLoad %6 %100
1939fd4e5da5Sopenharmony_ci        %102 = OpIAdd %6 %101 %9
1940fd4e5da5Sopenharmony_ci        %202 = OpLoad %6 %200
1941fd4e5da5Sopenharmony_ci               OpStore %201 %202
1942fd4e5da5Sopenharmony_ci               OpStore %100 %102
1943fd4e5da5Sopenharmony_ci        %103 = OpUGreaterThanEqual %11 %101 %10
1944fd4e5da5Sopenharmony_ci               OpLoopMerge %21 %22 None
1945fd4e5da5Sopenharmony_ci               OpBranchConditional %103 %21 %104
1946fd4e5da5Sopenharmony_ci        %104 = OpLabel
1947fd4e5da5Sopenharmony_ci               OpBranchConditional %12 %23 %21
1948fd4e5da5Sopenharmony_ci         %23 = OpLabel
1949fd4e5da5Sopenharmony_ci        %105 = OpLoad %6 %100
1950fd4e5da5Sopenharmony_ci        %106 = OpIAdd %6 %105 %9
1951fd4e5da5Sopenharmony_ci               OpStore %100 %106
1952fd4e5da5Sopenharmony_ci        %107 = OpUGreaterThanEqual %11 %105 %10
1953fd4e5da5Sopenharmony_ci               OpLoopMerge %25 %26 None
1954fd4e5da5Sopenharmony_ci               OpBranchConditional %107 %25 %108
1955fd4e5da5Sopenharmony_ci        %108 = OpLabel
1956fd4e5da5Sopenharmony_ci               OpBranch %28
1957fd4e5da5Sopenharmony_ci         %28 = OpLabel
1958fd4e5da5Sopenharmony_ci               OpBranchConditional %12 %26 %25
1959fd4e5da5Sopenharmony_ci         %26 = OpLabel
1960fd4e5da5Sopenharmony_ci               OpBranch %23
1961fd4e5da5Sopenharmony_ci         %25 = OpLabel
1962fd4e5da5Sopenharmony_ci        %109 = OpLoad %6 %100
1963fd4e5da5Sopenharmony_ci        %110 = OpIAdd %6 %109 %9
1964fd4e5da5Sopenharmony_ci               OpStore %100 %110
1965fd4e5da5Sopenharmony_ci        %111 = OpUGreaterThanEqual %11 %109 %10
1966fd4e5da5Sopenharmony_ci               OpLoopMerge %24 %27 None
1967fd4e5da5Sopenharmony_ci               OpBranchConditional %111 %24 %112
1968fd4e5da5Sopenharmony_ci        %112 = OpLabel
1969fd4e5da5Sopenharmony_ci               OpBranchConditional %12 %24 %27
1970fd4e5da5Sopenharmony_ci         %27 = OpLabel
1971fd4e5da5Sopenharmony_ci               OpBranch %25
1972fd4e5da5Sopenharmony_ci         %24 = OpLabel
1973fd4e5da5Sopenharmony_ci               OpBranch %22
1974fd4e5da5Sopenharmony_ci         %22 = OpLabel
1975fd4e5da5Sopenharmony_ci               OpBranch %20
1976fd4e5da5Sopenharmony_ci         %21 = OpLabel
1977fd4e5da5Sopenharmony_ci               OpBranch %197
1978fd4e5da5Sopenharmony_ci        %197 = OpLabel
1979fd4e5da5Sopenharmony_ci               OpReturn
1980fd4e5da5Sopenharmony_ci               OpFunctionEnd
1981fd4e5da5Sopenharmony_ci  )";
1982fd4e5da5Sopenharmony_ci
1983fd4e5da5Sopenharmony_ci  const auto env = SPV_ENV_UNIVERSAL_1_5;
1984fd4e5da5Sopenharmony_ci  const auto consumer = nullptr;
1985fd4e5da5Sopenharmony_ci  const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption);
1986fd4e5da5Sopenharmony_ci  spvtools::ValidatorOptions validator_options;
1987fd4e5da5Sopenharmony_ci  ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
1988fd4e5da5Sopenharmony_ci                                               kConsoleMessageConsumer));
1989fd4e5da5Sopenharmony_ci  TransformationContext transformation_context(
1990fd4e5da5Sopenharmony_ci      MakeUnique<FactManager>(context.get()), validator_options);
1991fd4e5da5Sopenharmony_ci  transformation_context.GetFactManager()->AddFactFunctionIsLivesafe(30);
1992fd4e5da5Sopenharmony_ci  transformation_context.GetFactManager()->AddFactValueOfPointeeIsIrrelevant(
1993fd4e5da5Sopenharmony_ci      200);
1994fd4e5da5Sopenharmony_ci  transformation_context.GetFactManager()->AddFactValueOfPointeeIsIrrelevant(
1995fd4e5da5Sopenharmony_ci      201);
1996fd4e5da5Sopenharmony_ci
1997fd4e5da5Sopenharmony_ci  TransformationOutlineFunction transformation(
1998fd4e5da5Sopenharmony_ci      /*entry_block*/ 198,
1999fd4e5da5Sopenharmony_ci      /*exit_block*/ 197,
2000fd4e5da5Sopenharmony_ci      /*new_function_struct_return_type_id*/ 400,
2001fd4e5da5Sopenharmony_ci      /*new_function_type_id*/ 401,
2002fd4e5da5Sopenharmony_ci      /*new_function_id*/ 402,
2003fd4e5da5Sopenharmony_ci      /*new_function_region_entry_block*/ 404,
2004fd4e5da5Sopenharmony_ci      /*new_caller_result_id*/ 405,
2005fd4e5da5Sopenharmony_ci      /*new_callee_result_id*/ 406,
2006fd4e5da5Sopenharmony_ci      /*input_id_to_fresh_id*/ {{100, 407}, {200, 408}, {201, 409}},
2007fd4e5da5Sopenharmony_ci      /*output_id_to_fresh_id*/ {});
2008fd4e5da5Sopenharmony_ci
2009fd4e5da5Sopenharmony_ci  ASSERT_TRUE(
2010fd4e5da5Sopenharmony_ci      transformation.IsApplicable(context.get(), transformation_context));
2011fd4e5da5Sopenharmony_ci  ApplyAndCheckFreshIds(transformation, context.get(), &transformation_context);
2012fd4e5da5Sopenharmony_ci  ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
2013fd4e5da5Sopenharmony_ci                                               kConsoleMessageConsumer));
2014fd4e5da5Sopenharmony_ci
2015fd4e5da5Sopenharmony_ci  // The original function should still be livesafe.
2016fd4e5da5Sopenharmony_ci  ASSERT_TRUE(transformation_context.GetFactManager()->FunctionIsLivesafe(30));
2017fd4e5da5Sopenharmony_ci  // The outlined function should be livesafe.
2018fd4e5da5Sopenharmony_ci  ASSERT_TRUE(transformation_context.GetFactManager()->FunctionIsLivesafe(402));
2019fd4e5da5Sopenharmony_ci  // The variable and parameter that were originally irrelevant should still be.
2020fd4e5da5Sopenharmony_ci  ASSERT_TRUE(
2021fd4e5da5Sopenharmony_ci      transformation_context.GetFactManager()->PointeeValueIsIrrelevant(200));
2022fd4e5da5Sopenharmony_ci  ASSERT_TRUE(
2023fd4e5da5Sopenharmony_ci      transformation_context.GetFactManager()->PointeeValueIsIrrelevant(201));
2024fd4e5da5Sopenharmony_ci  // The loop limiter should still be non-irrelevant.
2025fd4e5da5Sopenharmony_ci  ASSERT_FALSE(
2026fd4e5da5Sopenharmony_ci      transformation_context.GetFactManager()->PointeeValueIsIrrelevant(100));
2027fd4e5da5Sopenharmony_ci  // The parameters for the original irrelevant variables should be irrelevant.
2028fd4e5da5Sopenharmony_ci  ASSERT_TRUE(
2029fd4e5da5Sopenharmony_ci      transformation_context.GetFactManager()->PointeeValueIsIrrelevant(408));
2030fd4e5da5Sopenharmony_ci  ASSERT_TRUE(
2031fd4e5da5Sopenharmony_ci      transformation_context.GetFactManager()->PointeeValueIsIrrelevant(409));
2032fd4e5da5Sopenharmony_ci  // The parameter for the loop limiter should not be irrelevant.
2033fd4e5da5Sopenharmony_ci  ASSERT_FALSE(
2034fd4e5da5Sopenharmony_ci      transformation_context.GetFactManager()->PointeeValueIsIrrelevant(407));
2035fd4e5da5Sopenharmony_ci
2036fd4e5da5Sopenharmony_ci  std::string after_transformation = R"(
2037fd4e5da5Sopenharmony_ci               OpCapability Shader
2038fd4e5da5Sopenharmony_ci          %1 = OpExtInstImport "GLSL.std.450"
2039fd4e5da5Sopenharmony_ci               OpMemoryModel Logical GLSL450
2040fd4e5da5Sopenharmony_ci               OpEntryPoint Fragment %4 "main"
2041fd4e5da5Sopenharmony_ci               OpExecutionMode %4 OriginUpperLeft
2042fd4e5da5Sopenharmony_ci               OpSource ESSL 310
2043fd4e5da5Sopenharmony_ci          %2 = OpTypeVoid
2044fd4e5da5Sopenharmony_ci          %3 = OpTypeFunction %2
2045fd4e5da5Sopenharmony_ci          %6 = OpTypeInt 32 0
2046fd4e5da5Sopenharmony_ci          %7 = OpTypePointer Function %6
2047fd4e5da5Sopenharmony_ci        %199 = OpTypeFunction %2 %7
2048fd4e5da5Sopenharmony_ci          %8 = OpConstant %6 0
2049fd4e5da5Sopenharmony_ci          %9 = OpConstant %6 1
2050fd4e5da5Sopenharmony_ci         %10 = OpConstant %6 5
2051fd4e5da5Sopenharmony_ci         %11 = OpTypeBool
2052fd4e5da5Sopenharmony_ci         %12 = OpConstantTrue %11
2053fd4e5da5Sopenharmony_ci        %401 = OpTypeFunction %2 %7 %7 %7
2054fd4e5da5Sopenharmony_ci          %4 = OpFunction %2 None %3
2055fd4e5da5Sopenharmony_ci          %5 = OpLabel
2056fd4e5da5Sopenharmony_ci               OpReturn
2057fd4e5da5Sopenharmony_ci               OpFunctionEnd
2058fd4e5da5Sopenharmony_ci         %30 = OpFunction %2 None %199
2059fd4e5da5Sopenharmony_ci        %200 = OpFunctionParameter %7
2060fd4e5da5Sopenharmony_ci         %31 = OpLabel
2061fd4e5da5Sopenharmony_ci        %100 = OpVariable %7 Function %8
2062fd4e5da5Sopenharmony_ci        %201 = OpVariable %7 Function %8
2063fd4e5da5Sopenharmony_ci               OpBranch %198
2064fd4e5da5Sopenharmony_ci        %198 = OpLabel
2065fd4e5da5Sopenharmony_ci        %405 = OpFunctionCall %2 %402 %200 %100 %201
2066fd4e5da5Sopenharmony_ci               OpReturn
2067fd4e5da5Sopenharmony_ci               OpFunctionEnd
2068fd4e5da5Sopenharmony_ci        %402 = OpFunction %2 None %401
2069fd4e5da5Sopenharmony_ci        %408 = OpFunctionParameter %7
2070fd4e5da5Sopenharmony_ci        %407 = OpFunctionParameter %7
2071fd4e5da5Sopenharmony_ci        %409 = OpFunctionParameter %7
2072fd4e5da5Sopenharmony_ci        %404 = OpLabel
2073fd4e5da5Sopenharmony_ci               OpBranch %20
2074fd4e5da5Sopenharmony_ci         %20 = OpLabel
2075fd4e5da5Sopenharmony_ci        %101 = OpLoad %6 %407
2076fd4e5da5Sopenharmony_ci        %102 = OpIAdd %6 %101 %9
2077fd4e5da5Sopenharmony_ci        %202 = OpLoad %6 %408
2078fd4e5da5Sopenharmony_ci               OpStore %409 %202
2079fd4e5da5Sopenharmony_ci               OpStore %407 %102
2080fd4e5da5Sopenharmony_ci        %103 = OpUGreaterThanEqual %11 %101 %10
2081fd4e5da5Sopenharmony_ci               OpLoopMerge %21 %22 None
2082fd4e5da5Sopenharmony_ci               OpBranchConditional %103 %21 %104
2083fd4e5da5Sopenharmony_ci        %104 = OpLabel
2084fd4e5da5Sopenharmony_ci               OpBranchConditional %12 %23 %21
2085fd4e5da5Sopenharmony_ci         %23 = OpLabel
2086fd4e5da5Sopenharmony_ci        %105 = OpLoad %6 %407
2087fd4e5da5Sopenharmony_ci        %106 = OpIAdd %6 %105 %9
2088fd4e5da5Sopenharmony_ci               OpStore %407 %106
2089fd4e5da5Sopenharmony_ci        %107 = OpUGreaterThanEqual %11 %105 %10
2090fd4e5da5Sopenharmony_ci               OpLoopMerge %25 %26 None
2091fd4e5da5Sopenharmony_ci               OpBranchConditional %107 %25 %108
2092fd4e5da5Sopenharmony_ci        %108 = OpLabel
2093fd4e5da5Sopenharmony_ci               OpBranch %28
2094fd4e5da5Sopenharmony_ci         %28 = OpLabel
2095fd4e5da5Sopenharmony_ci               OpBranchConditional %12 %26 %25
2096fd4e5da5Sopenharmony_ci         %26 = OpLabel
2097fd4e5da5Sopenharmony_ci               OpBranch %23
2098fd4e5da5Sopenharmony_ci         %25 = OpLabel
2099fd4e5da5Sopenharmony_ci        %109 = OpLoad %6 %407
2100fd4e5da5Sopenharmony_ci        %110 = OpIAdd %6 %109 %9
2101fd4e5da5Sopenharmony_ci               OpStore %407 %110
2102fd4e5da5Sopenharmony_ci        %111 = OpUGreaterThanEqual %11 %109 %10
2103fd4e5da5Sopenharmony_ci               OpLoopMerge %24 %27 None
2104fd4e5da5Sopenharmony_ci               OpBranchConditional %111 %24 %112
2105fd4e5da5Sopenharmony_ci        %112 = OpLabel
2106fd4e5da5Sopenharmony_ci               OpBranchConditional %12 %24 %27
2107fd4e5da5Sopenharmony_ci         %27 = OpLabel
2108fd4e5da5Sopenharmony_ci               OpBranch %25
2109fd4e5da5Sopenharmony_ci         %24 = OpLabel
2110fd4e5da5Sopenharmony_ci               OpBranch %22
2111fd4e5da5Sopenharmony_ci         %22 = OpLabel
2112fd4e5da5Sopenharmony_ci               OpBranch %20
2113fd4e5da5Sopenharmony_ci         %21 = OpLabel
2114fd4e5da5Sopenharmony_ci               OpBranch %197
2115fd4e5da5Sopenharmony_ci        %197 = OpLabel
2116fd4e5da5Sopenharmony_ci               OpReturn
2117fd4e5da5Sopenharmony_ci               OpFunctionEnd
2118fd4e5da5Sopenharmony_ci  )";
2119fd4e5da5Sopenharmony_ci  ASSERT_TRUE(IsEqual(env, after_transformation, context.get()));
2120fd4e5da5Sopenharmony_ci}
2121fd4e5da5Sopenharmony_ci
2122fd4e5da5Sopenharmony_ciTEST(TransformationOutlineFunctionTest, OutlineWithDeadBlocks1) {
2123fd4e5da5Sopenharmony_ci  // This checks that if all blocks in the region being outlined were dead, all
2124fd4e5da5Sopenharmony_ci  // blocks in the outlined function will be dead.
2125fd4e5da5Sopenharmony_ci  std::string shader = R"(
2126fd4e5da5Sopenharmony_ci               OpCapability Shader
2127fd4e5da5Sopenharmony_ci          %1 = OpExtInstImport "GLSL.std.450"
2128fd4e5da5Sopenharmony_ci               OpMemoryModel Logical GLSL450
2129fd4e5da5Sopenharmony_ci               OpEntryPoint Fragment %4 "main"
2130fd4e5da5Sopenharmony_ci               OpExecutionMode %4 OriginUpperLeft
2131fd4e5da5Sopenharmony_ci               OpSource ESSL 310
2132fd4e5da5Sopenharmony_ci               OpName %4 "main"
2133fd4e5da5Sopenharmony_ci               OpName %10 "foo(i1;"
2134fd4e5da5Sopenharmony_ci               OpName %9 "x"
2135fd4e5da5Sopenharmony_ci               OpName %12 "y"
2136fd4e5da5Sopenharmony_ci               OpName %21 "i"
2137fd4e5da5Sopenharmony_ci               OpName %46 "param"
2138fd4e5da5Sopenharmony_ci          %2 = OpTypeVoid
2139fd4e5da5Sopenharmony_ci          %3 = OpTypeFunction %2
2140fd4e5da5Sopenharmony_ci          %6 = OpTypeInt 32 1
2141fd4e5da5Sopenharmony_ci          %7 = OpTypePointer Function %6
2142fd4e5da5Sopenharmony_ci          %8 = OpTypeFunction %2 %7
2143fd4e5da5Sopenharmony_ci         %13 = OpConstant %6 2
2144fd4e5da5Sopenharmony_ci         %14 = OpTypeBool
2145fd4e5da5Sopenharmony_ci         %15 = OpConstantFalse %14
2146fd4e5da5Sopenharmony_ci         %22 = OpConstant %6 0
2147fd4e5da5Sopenharmony_ci         %29 = OpConstant %6 10
2148fd4e5da5Sopenharmony_ci         %41 = OpConstant %6 1
2149fd4e5da5Sopenharmony_ci          %4 = OpFunction %2 None %3
2150fd4e5da5Sopenharmony_ci          %5 = OpLabel
2151fd4e5da5Sopenharmony_ci         %46 = OpVariable %7 Function
2152fd4e5da5Sopenharmony_ci               OpStore %46 %13
2153fd4e5da5Sopenharmony_ci         %47 = OpFunctionCall %2 %10 %46
2154fd4e5da5Sopenharmony_ci               OpReturn
2155fd4e5da5Sopenharmony_ci               OpFunctionEnd
2156fd4e5da5Sopenharmony_ci         %10 = OpFunction %2 None %8
2157fd4e5da5Sopenharmony_ci          %9 = OpFunctionParameter %7
2158fd4e5da5Sopenharmony_ci         %11 = OpLabel
2159fd4e5da5Sopenharmony_ci         %12 = OpVariable %7 Function
2160fd4e5da5Sopenharmony_ci         %21 = OpVariable %7 Function
2161fd4e5da5Sopenharmony_ci               OpStore %12 %13
2162fd4e5da5Sopenharmony_ci               OpSelectionMerge %17 None
2163fd4e5da5Sopenharmony_ci               OpBranchConditional %15 %16 %17
2164fd4e5da5Sopenharmony_ci         %16 = OpLabel
2165fd4e5da5Sopenharmony_ci         %18 = OpLoad %6 %9
2166fd4e5da5Sopenharmony_ci               OpStore %12 %18
2167fd4e5da5Sopenharmony_ci         %19 = OpLoad %6 %9
2168fd4e5da5Sopenharmony_ci         %20 = OpIAdd %6 %19 %13
2169fd4e5da5Sopenharmony_ci               OpStore %9 %20
2170fd4e5da5Sopenharmony_ci               OpStore %21 %22
2171fd4e5da5Sopenharmony_ci               OpBranch %23
2172fd4e5da5Sopenharmony_ci         %23 = OpLabel
2173fd4e5da5Sopenharmony_ci               OpLoopMerge %25 %26 None
2174fd4e5da5Sopenharmony_ci               OpBranch %27
2175fd4e5da5Sopenharmony_ci         %27 = OpLabel
2176fd4e5da5Sopenharmony_ci         %28 = OpLoad %6 %21
2177fd4e5da5Sopenharmony_ci         %30 = OpSLessThan %14 %28 %29
2178fd4e5da5Sopenharmony_ci               OpBranchConditional %30 %24 %25
2179fd4e5da5Sopenharmony_ci         %24 = OpLabel
2180fd4e5da5Sopenharmony_ci         %31 = OpLoad %6 %9
2181fd4e5da5Sopenharmony_ci         %32 = OpLoad %6 %21
2182fd4e5da5Sopenharmony_ci         %33 = OpSGreaterThan %14 %31 %32
2183fd4e5da5Sopenharmony_ci               OpSelectionMerge %35 None
2184fd4e5da5Sopenharmony_ci               OpBranchConditional %33 %34 %35
2185fd4e5da5Sopenharmony_ci         %34 = OpLabel
2186fd4e5da5Sopenharmony_ci               OpBranch %26
2187fd4e5da5Sopenharmony_ci         %35 = OpLabel
2188fd4e5da5Sopenharmony_ci         %37 = OpLoad %6 %9
2189fd4e5da5Sopenharmony_ci         %38 = OpLoad %6 %12
2190fd4e5da5Sopenharmony_ci         %39 = OpIAdd %6 %38 %37
2191fd4e5da5Sopenharmony_ci               OpStore %12 %39
2192fd4e5da5Sopenharmony_ci               OpBranch %26
2193fd4e5da5Sopenharmony_ci         %26 = OpLabel
2194fd4e5da5Sopenharmony_ci         %40 = OpLoad %6 %21
2195fd4e5da5Sopenharmony_ci         %42 = OpIAdd %6 %40 %41
2196fd4e5da5Sopenharmony_ci               OpStore %21 %42
2197fd4e5da5Sopenharmony_ci               OpBranch %23
2198fd4e5da5Sopenharmony_ci         %25 = OpLabel
2199fd4e5da5Sopenharmony_ci               OpBranch %50
2200fd4e5da5Sopenharmony_ci         %50 = OpLabel
2201fd4e5da5Sopenharmony_ci               OpBranch %17
2202fd4e5da5Sopenharmony_ci         %17 = OpLabel
2203fd4e5da5Sopenharmony_ci         %43 = OpLoad %6 %9
2204fd4e5da5Sopenharmony_ci         %44 = OpLoad %6 %12
2205fd4e5da5Sopenharmony_ci         %45 = OpIAdd %6 %44 %43
2206fd4e5da5Sopenharmony_ci               OpStore %12 %45
2207fd4e5da5Sopenharmony_ci               OpReturn
2208fd4e5da5Sopenharmony_ci               OpFunctionEnd
2209fd4e5da5Sopenharmony_ci  )";
2210fd4e5da5Sopenharmony_ci
2211fd4e5da5Sopenharmony_ci  const auto env = SPV_ENV_UNIVERSAL_1_5;
2212fd4e5da5Sopenharmony_ci  const auto consumer = nullptr;
2213fd4e5da5Sopenharmony_ci  const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption);
2214fd4e5da5Sopenharmony_ci  spvtools::ValidatorOptions validator_options;
2215fd4e5da5Sopenharmony_ci  ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
2216fd4e5da5Sopenharmony_ci                                               kConsoleMessageConsumer));
2217fd4e5da5Sopenharmony_ci  TransformationContext transformation_context(
2218fd4e5da5Sopenharmony_ci      MakeUnique<FactManager>(context.get()), validator_options);
2219fd4e5da5Sopenharmony_ci  for (uint32_t block_id : {16u, 23u, 24u, 26u, 27u, 34u, 35u, 50u}) {
2220fd4e5da5Sopenharmony_ci    transformation_context.GetFactManager()->AddFactBlockIsDead(block_id);
2221fd4e5da5Sopenharmony_ci  }
2222fd4e5da5Sopenharmony_ci
2223fd4e5da5Sopenharmony_ci  TransformationOutlineFunction transformation(
2224fd4e5da5Sopenharmony_ci      /*entry_block*/ 16,
2225fd4e5da5Sopenharmony_ci      /*exit_block*/ 50,
2226fd4e5da5Sopenharmony_ci      /*new_function_struct_return_type_id*/ 200,
2227fd4e5da5Sopenharmony_ci      /*new_function_type_id*/ 201,
2228fd4e5da5Sopenharmony_ci      /*new_function_id*/ 202,
2229fd4e5da5Sopenharmony_ci      /*new_function_region_entry_block*/ 203,
2230fd4e5da5Sopenharmony_ci      /*new_caller_result_id*/ 204,
2231fd4e5da5Sopenharmony_ci      /*new_callee_result_id*/ 205,
2232fd4e5da5Sopenharmony_ci      /*input_id_to_fresh_id*/ {{9, 206}, {12, 207}, {21, 208}},
2233fd4e5da5Sopenharmony_ci      /*output_id_to_fresh_id*/ {});
2234fd4e5da5Sopenharmony_ci
2235fd4e5da5Sopenharmony_ci  ASSERT_TRUE(
2236fd4e5da5Sopenharmony_ci      transformation.IsApplicable(context.get(), transformation_context));
2237fd4e5da5Sopenharmony_ci  ApplyAndCheckFreshIds(transformation, context.get(), &transformation_context);
2238fd4e5da5Sopenharmony_ci  ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
2239fd4e5da5Sopenharmony_ci                                               kConsoleMessageConsumer));
2240fd4e5da5Sopenharmony_ci  // All the original blocks, plus the new function entry block, should be dead.
2241fd4e5da5Sopenharmony_ci  for (uint32_t block_id : {16u, 23u, 24u, 26u, 27u, 34u, 35u, 50u, 203u}) {
2242fd4e5da5Sopenharmony_ci    ASSERT_TRUE(transformation_context.GetFactManager()->BlockIsDead(block_id));
2243fd4e5da5Sopenharmony_ci  }
2244fd4e5da5Sopenharmony_ci}
2245fd4e5da5Sopenharmony_ci
2246fd4e5da5Sopenharmony_ciTEST(TransformationOutlineFunctionTest, OutlineWithDeadBlocks2) {
2247fd4e5da5Sopenharmony_ci  // This checks that if some, but not all, blocks in the outlined region are
2248fd4e5da5Sopenharmony_ci  // dead, those (but not others) will be dead in the outlined function.
2249fd4e5da5Sopenharmony_ci  std::string shader = R"(
2250fd4e5da5Sopenharmony_ci               OpCapability Shader
2251fd4e5da5Sopenharmony_ci          %1 = OpExtInstImport "GLSL.std.450"
2252fd4e5da5Sopenharmony_ci               OpMemoryModel Logical GLSL450
2253fd4e5da5Sopenharmony_ci               OpEntryPoint Fragment %4 "main" %8
2254fd4e5da5Sopenharmony_ci               OpExecutionMode %4 OriginUpperLeft
2255fd4e5da5Sopenharmony_ci               OpSource ESSL 310
2256fd4e5da5Sopenharmony_ci          %2 = OpTypeVoid
2257fd4e5da5Sopenharmony_ci          %3 = OpTypeFunction %2
2258fd4e5da5Sopenharmony_ci          %6 = OpTypeBool
2259fd4e5da5Sopenharmony_ci          %7 = OpTypePointer Private %6
2260fd4e5da5Sopenharmony_ci          %8 = OpVariable %7 Private
2261fd4e5da5Sopenharmony_ci          %9 = OpConstantFalse %6
2262fd4e5da5Sopenharmony_ci         %10 = OpTypePointer Function %6
2263fd4e5da5Sopenharmony_ci         %12 = OpConstantTrue %6
2264fd4e5da5Sopenharmony_ci          %4 = OpFunction %2 None %3
2265fd4e5da5Sopenharmony_ci          %5 = OpLabel
2266fd4e5da5Sopenharmony_ci         %11 = OpVariable %10 Function
2267fd4e5da5Sopenharmony_ci               OpBranch %30
2268fd4e5da5Sopenharmony_ci         %30 = OpLabel
2269fd4e5da5Sopenharmony_ci               OpStore %8 %9
2270fd4e5da5Sopenharmony_ci               OpBranch %31
2271fd4e5da5Sopenharmony_ci         %31 = OpLabel
2272fd4e5da5Sopenharmony_ci               OpStore %11 %12
2273fd4e5da5Sopenharmony_ci               OpSelectionMerge %36 None
2274fd4e5da5Sopenharmony_ci               OpBranchConditional %9 %32 %33
2275fd4e5da5Sopenharmony_ci         %32 = OpLabel
2276fd4e5da5Sopenharmony_ci               OpBranch %34
2277fd4e5da5Sopenharmony_ci         %33 = OpLabel
2278fd4e5da5Sopenharmony_ci               OpBranch %36
2279fd4e5da5Sopenharmony_ci         %34 = OpLabel
2280fd4e5da5Sopenharmony_ci               OpBranch %35
2281fd4e5da5Sopenharmony_ci         %35 = OpLabel
2282fd4e5da5Sopenharmony_ci               OpBranch %36
2283fd4e5da5Sopenharmony_ci         %36 = OpLabel
2284fd4e5da5Sopenharmony_ci               OpBranch %37
2285fd4e5da5Sopenharmony_ci         %37 = OpLabel
2286fd4e5da5Sopenharmony_ci         %13 = OpLoad %6 %8
2287fd4e5da5Sopenharmony_ci               OpStore %11 %13
2288fd4e5da5Sopenharmony_ci         %14 = OpLoad %6 %11
2289fd4e5da5Sopenharmony_ci               OpStore %8 %14
2290fd4e5da5Sopenharmony_ci               OpReturn
2291fd4e5da5Sopenharmony_ci               OpFunctionEnd
2292fd4e5da5Sopenharmony_ci  )";
2293fd4e5da5Sopenharmony_ci
2294fd4e5da5Sopenharmony_ci  const auto env = SPV_ENV_UNIVERSAL_1_5;
2295fd4e5da5Sopenharmony_ci  const auto consumer = nullptr;
2296fd4e5da5Sopenharmony_ci  const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption);
2297fd4e5da5Sopenharmony_ci  spvtools::ValidatorOptions validator_options;
2298fd4e5da5Sopenharmony_ci  ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
2299fd4e5da5Sopenharmony_ci                                               kConsoleMessageConsumer));
2300fd4e5da5Sopenharmony_ci  TransformationContext transformation_context(
2301fd4e5da5Sopenharmony_ci      MakeUnique<FactManager>(context.get()), validator_options);
2302fd4e5da5Sopenharmony_ci  for (uint32_t block_id : {32u, 34u, 35u}) {
2303fd4e5da5Sopenharmony_ci    transformation_context.GetFactManager()->AddFactBlockIsDead(block_id);
2304fd4e5da5Sopenharmony_ci  }
2305fd4e5da5Sopenharmony_ci
2306fd4e5da5Sopenharmony_ci  TransformationOutlineFunction transformation(
2307fd4e5da5Sopenharmony_ci      /*entry_block*/ 30,
2308fd4e5da5Sopenharmony_ci      /*exit_block*/ 37,
2309fd4e5da5Sopenharmony_ci      /*new_function_struct_return_type_id*/ 200,
2310fd4e5da5Sopenharmony_ci      /*new_function_type_id*/ 201,
2311fd4e5da5Sopenharmony_ci      /*new_function_id*/ 202,
2312fd4e5da5Sopenharmony_ci      /*new_function_region_entry_block*/ 203,
2313fd4e5da5Sopenharmony_ci      /*new_caller_result_id*/ 204,
2314fd4e5da5Sopenharmony_ci      /*new_callee_result_id*/ 205,
2315fd4e5da5Sopenharmony_ci      /*input_id_to_fresh_id*/ {{11, 206}},
2316fd4e5da5Sopenharmony_ci      /*output_id_to_fresh_id*/ {});
2317fd4e5da5Sopenharmony_ci
2318fd4e5da5Sopenharmony_ci  ASSERT_TRUE(
2319fd4e5da5Sopenharmony_ci      transformation.IsApplicable(context.get(), transformation_context));
2320fd4e5da5Sopenharmony_ci  ApplyAndCheckFreshIds(transformation, context.get(), &transformation_context);
2321fd4e5da5Sopenharmony_ci  ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
2322fd4e5da5Sopenharmony_ci                                               kConsoleMessageConsumer));
2323fd4e5da5Sopenharmony_ci  // The blocks that were originally dead, but not others, should be dead.
2324fd4e5da5Sopenharmony_ci  for (uint32_t block_id : {32u, 34u, 35u}) {
2325fd4e5da5Sopenharmony_ci    ASSERT_TRUE(transformation_context.GetFactManager()->BlockIsDead(block_id));
2326fd4e5da5Sopenharmony_ci  }
2327fd4e5da5Sopenharmony_ci  for (uint32_t block_id : {5u, 30u, 31u, 33u, 36u, 37u, 203u}) {
2328fd4e5da5Sopenharmony_ci    ASSERT_FALSE(
2329fd4e5da5Sopenharmony_ci        transformation_context.GetFactManager()->BlockIsDead(block_id));
2330fd4e5da5Sopenharmony_ci  }
2331fd4e5da5Sopenharmony_ci}
2332fd4e5da5Sopenharmony_ci
2333fd4e5da5Sopenharmony_ciTEST(TransformationOutlineFunctionTest,
2334fd4e5da5Sopenharmony_ci     OutlineWithIrrelevantVariablesAndParameters) {
2335fd4e5da5Sopenharmony_ci  // This checks that if the outlined region uses a mixture of irrelevant and
2336fd4e5da5Sopenharmony_ci  // non-irrelevant variables and parameters, these properties are preserved
2337fd4e5da5Sopenharmony_ci  // during outlining.
2338fd4e5da5Sopenharmony_ci  std::string shader = R"(
2339fd4e5da5Sopenharmony_ci               OpCapability Shader
2340fd4e5da5Sopenharmony_ci          %1 = OpExtInstImport "GLSL.std.450"
2341fd4e5da5Sopenharmony_ci               OpMemoryModel Logical GLSL450
2342fd4e5da5Sopenharmony_ci               OpEntryPoint Fragment %4 "main"
2343fd4e5da5Sopenharmony_ci               OpExecutionMode %4 OriginUpperLeft
2344fd4e5da5Sopenharmony_ci               OpSource ESSL 310
2345fd4e5da5Sopenharmony_ci          %2 = OpTypeVoid
2346fd4e5da5Sopenharmony_ci          %3 = OpTypeFunction %2
2347fd4e5da5Sopenharmony_ci          %6 = OpTypeInt 32 1
2348fd4e5da5Sopenharmony_ci          %7 = OpTypePointer Function %6
2349fd4e5da5Sopenharmony_ci          %8 = OpTypeFunction %2 %7 %7
2350fd4e5da5Sopenharmony_ci         %13 = OpConstant %6 2
2351fd4e5da5Sopenharmony_ci         %15 = OpConstant %6 3
2352fd4e5da5Sopenharmony_ci          %4 = OpFunction %2 None %3
2353fd4e5da5Sopenharmony_ci          %5 = OpLabel
2354fd4e5da5Sopenharmony_ci               OpReturn
2355fd4e5da5Sopenharmony_ci               OpFunctionEnd
2356fd4e5da5Sopenharmony_ci         %11 = OpFunction %2 None %8
2357fd4e5da5Sopenharmony_ci          %9 = OpFunctionParameter %7
2358fd4e5da5Sopenharmony_ci         %10 = OpFunctionParameter %7
2359fd4e5da5Sopenharmony_ci         %12 = OpLabel
2360fd4e5da5Sopenharmony_ci         %14 = OpVariable %7 Function
2361fd4e5da5Sopenharmony_ci         %20 = OpVariable %7 Function
2362fd4e5da5Sopenharmony_ci               OpBranch %50
2363fd4e5da5Sopenharmony_ci         %50 = OpLabel
2364fd4e5da5Sopenharmony_ci               OpStore %9 %13
2365fd4e5da5Sopenharmony_ci               OpStore %14 %15
2366fd4e5da5Sopenharmony_ci         %16 = OpLoad %6 %14
2367fd4e5da5Sopenharmony_ci               OpStore %10 %16
2368fd4e5da5Sopenharmony_ci         %17 = OpLoad %6 %9
2369fd4e5da5Sopenharmony_ci         %18 = OpLoad %6 %10
2370fd4e5da5Sopenharmony_ci         %19 = OpIAdd %6 %17 %18
2371fd4e5da5Sopenharmony_ci               OpStore %14 %19
2372fd4e5da5Sopenharmony_ci         %21 = OpLoad %6 %9
2373fd4e5da5Sopenharmony_ci               OpStore %20 %21
2374fd4e5da5Sopenharmony_ci               OpReturn
2375fd4e5da5Sopenharmony_ci               OpFunctionEnd
2376fd4e5da5Sopenharmony_ci  )";
2377fd4e5da5Sopenharmony_ci
2378fd4e5da5Sopenharmony_ci  const auto env = SPV_ENV_UNIVERSAL_1_5;
2379fd4e5da5Sopenharmony_ci  const auto consumer = nullptr;
2380fd4e5da5Sopenharmony_ci  const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption);
2381fd4e5da5Sopenharmony_ci  spvtools::ValidatorOptions validator_options;
2382fd4e5da5Sopenharmony_ci  ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
2383fd4e5da5Sopenharmony_ci                                               kConsoleMessageConsumer));
2384fd4e5da5Sopenharmony_ci  TransformationContext transformation_context(
2385fd4e5da5Sopenharmony_ci      MakeUnique<FactManager>(context.get()), validator_options);
2386fd4e5da5Sopenharmony_ci  transformation_context.GetFactManager()->AddFactValueOfPointeeIsIrrelevant(9);
2387fd4e5da5Sopenharmony_ci  transformation_context.GetFactManager()->AddFactValueOfPointeeIsIrrelevant(
2388fd4e5da5Sopenharmony_ci      14);
2389fd4e5da5Sopenharmony_ci
2390fd4e5da5Sopenharmony_ci  TransformationOutlineFunction transformation(
2391fd4e5da5Sopenharmony_ci      /*entry_block*/ 50,
2392fd4e5da5Sopenharmony_ci      /*exit_block*/ 50,
2393fd4e5da5Sopenharmony_ci      /*new_function_struct_return_type_id*/ 200,
2394fd4e5da5Sopenharmony_ci      /*new_function_type_id*/ 201,
2395fd4e5da5Sopenharmony_ci      /*new_function_id*/ 202,
2396fd4e5da5Sopenharmony_ci      /*new_function_region_entry_block*/ 203,
2397fd4e5da5Sopenharmony_ci      /*new_caller_result_id*/ 204,
2398fd4e5da5Sopenharmony_ci      /*new_callee_result_id*/ 205,
2399fd4e5da5Sopenharmony_ci      /*input_id_to_fresh_id*/ {{9, 206}, {10, 207}, {14, 208}, {20, 209}},
2400fd4e5da5Sopenharmony_ci      /*output_id_to_fresh_id*/ {});
2401fd4e5da5Sopenharmony_ci
2402fd4e5da5Sopenharmony_ci  ASSERT_TRUE(
2403fd4e5da5Sopenharmony_ci      transformation.IsApplicable(context.get(), transformation_context));
2404fd4e5da5Sopenharmony_ci  ApplyAndCheckFreshIds(transformation, context.get(), &transformation_context);
2405fd4e5da5Sopenharmony_ci  ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
2406fd4e5da5Sopenharmony_ci                                               kConsoleMessageConsumer));
2407fd4e5da5Sopenharmony_ci  // The variables that were originally irrelevant, plus input parameters
2408fd4e5da5Sopenharmony_ci  // corresponding to them, should be irrelevant.  The rest should not be.
2409fd4e5da5Sopenharmony_ci  for (uint32_t variable_id : {9u, 14u, 206u, 208u}) {
2410fd4e5da5Sopenharmony_ci    ASSERT_TRUE(
2411fd4e5da5Sopenharmony_ci        transformation_context.GetFactManager()->PointeeValueIsIrrelevant(
2412fd4e5da5Sopenharmony_ci            variable_id));
2413fd4e5da5Sopenharmony_ci  }
2414fd4e5da5Sopenharmony_ci  for (uint32_t variable_id : {10u, 20u, 207u, 209u}) {
2415fd4e5da5Sopenharmony_ci    ASSERT_FALSE(
2416fd4e5da5Sopenharmony_ci        transformation_context.GetFactManager()->BlockIsDead(variable_id));
2417fd4e5da5Sopenharmony_ci  }
2418fd4e5da5Sopenharmony_ci}
2419fd4e5da5Sopenharmony_ci
2420fd4e5da5Sopenharmony_ciTEST(TransformationOutlineFunctionTest,
2421fd4e5da5Sopenharmony_ci     DoNotOutlineCodeThatProducesUsedPointer) {
2422fd4e5da5Sopenharmony_ci  // This checks that we cannot outline a region of code if it produces a
2423fd4e5da5Sopenharmony_ci  // pointer result id that gets used outside the region.  This avoids creating
2424fd4e5da5Sopenharmony_ci  // a struct with a pointer member.
2425fd4e5da5Sopenharmony_ci  std::string shader = R"(
2426fd4e5da5Sopenharmony_ci               OpCapability Shader
2427fd4e5da5Sopenharmony_ci          %1 = OpExtInstImport "GLSL.std.450"
2428fd4e5da5Sopenharmony_ci               OpMemoryModel Logical GLSL450
2429fd4e5da5Sopenharmony_ci               OpEntryPoint Fragment %6 "main"
2430fd4e5da5Sopenharmony_ci               OpExecutionMode %6 OriginUpperLeft
2431fd4e5da5Sopenharmony_ci               OpSource ESSL 310
2432fd4e5da5Sopenharmony_ci          %2 = OpTypeVoid
2433fd4e5da5Sopenharmony_ci          %3 = OpTypeFunction %2
2434fd4e5da5Sopenharmony_ci         %21 = OpTypeBool
2435fd4e5da5Sopenharmony_ci        %100 = OpTypeInt 32 0
2436fd4e5da5Sopenharmony_ci         %99 = OpConstant %100 0
2437fd4e5da5Sopenharmony_ci        %101 = OpTypeVector %100 2
2438fd4e5da5Sopenharmony_ci        %102 = OpTypePointer Function %100
2439fd4e5da5Sopenharmony_ci        %103 = OpTypePointer Function %101
2440fd4e5da5Sopenharmony_ci          %6 = OpFunction %2 None %3
2441fd4e5da5Sopenharmony_ci          %7 = OpLabel
2442fd4e5da5Sopenharmony_ci        %104 = OpVariable %103 Function
2443fd4e5da5Sopenharmony_ci               OpBranch %80
2444fd4e5da5Sopenharmony_ci         %80 = OpLabel
2445fd4e5da5Sopenharmony_ci        %105 = OpAccessChain %102 %104 %99
2446fd4e5da5Sopenharmony_ci               OpBranch %106
2447fd4e5da5Sopenharmony_ci        %106 = OpLabel
2448fd4e5da5Sopenharmony_ci               OpStore %105 %99
2449fd4e5da5Sopenharmony_ci               OpReturn
2450fd4e5da5Sopenharmony_ci               OpFunctionEnd
2451fd4e5da5Sopenharmony_ci  )";
2452fd4e5da5Sopenharmony_ci
2453fd4e5da5Sopenharmony_ci  const auto env = SPV_ENV_UNIVERSAL_1_5;
2454fd4e5da5Sopenharmony_ci  const auto consumer = nullptr;
2455fd4e5da5Sopenharmony_ci  const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption);
2456fd4e5da5Sopenharmony_ci  spvtools::ValidatorOptions validator_options;
2457fd4e5da5Sopenharmony_ci  ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
2458fd4e5da5Sopenharmony_ci                                               kConsoleMessageConsumer));
2459fd4e5da5Sopenharmony_ci  TransformationContext transformation_context(
2460fd4e5da5Sopenharmony_ci      MakeUnique<FactManager>(context.get()), validator_options);
2461fd4e5da5Sopenharmony_ci  TransformationOutlineFunction transformation(
2462fd4e5da5Sopenharmony_ci      /*entry_block*/ 80,
2463fd4e5da5Sopenharmony_ci      /*exit_block*/ 80,
2464fd4e5da5Sopenharmony_ci      /*new_function_struct_return_type_id*/ 300,
2465fd4e5da5Sopenharmony_ci      /*new_function_type_id*/ 301,
2466fd4e5da5Sopenharmony_ci      /*new_function_id*/ 302,
2467fd4e5da5Sopenharmony_ci      /*new_function_region_entry_block*/ 304,
2468fd4e5da5Sopenharmony_ci      /*new_caller_result_id*/ 305,
2469fd4e5da5Sopenharmony_ci      /*new_callee_result_id*/ 306,
2470fd4e5da5Sopenharmony_ci      /*input_id_to_fresh_id*/ {{104, 307}},
2471fd4e5da5Sopenharmony_ci      /*output_id_to_fresh_id*/ {{105, 308}});
2472fd4e5da5Sopenharmony_ci
2473fd4e5da5Sopenharmony_ci  ASSERT_FALSE(
2474fd4e5da5Sopenharmony_ci      transformation.IsApplicable(context.get(), transformation_context));
2475fd4e5da5Sopenharmony_ci}
2476fd4e5da5Sopenharmony_ci
2477fd4e5da5Sopenharmony_ciTEST(TransformationOutlineFunctionTest, ExitBlockHeadsLoop) {
2478fd4e5da5Sopenharmony_ci  // This checks that it is not possible outline a region that ends in a loop
2479fd4e5da5Sopenharmony_ci  // head.
2480fd4e5da5Sopenharmony_ci  std::string shader = R"(
2481fd4e5da5Sopenharmony_ci               OpCapability Shader
2482fd4e5da5Sopenharmony_ci          %1 = OpExtInstImport "GLSL.std.450"
2483fd4e5da5Sopenharmony_ci               OpMemoryModel Logical GLSL450
2484fd4e5da5Sopenharmony_ci               OpEntryPoint Fragment %4 "main"
2485fd4e5da5Sopenharmony_ci               OpExecutionMode %4 OriginUpperLeft
2486fd4e5da5Sopenharmony_ci               OpSource ESSL 310
2487fd4e5da5Sopenharmony_ci          %2 = OpTypeVoid
2488fd4e5da5Sopenharmony_ci          %3 = OpTypeFunction %2
2489fd4e5da5Sopenharmony_ci         %15 = OpTypeInt 32 1
2490fd4e5da5Sopenharmony_ci         %35 = OpTypeBool
2491fd4e5da5Sopenharmony_ci         %39 = OpConstant %15 1
2492fd4e5da5Sopenharmony_ci         %40 = OpConstantTrue %35
2493fd4e5da5Sopenharmony_ci          %4 = OpFunction %2 None %3
2494fd4e5da5Sopenharmony_ci          %5 = OpLabel
2495fd4e5da5Sopenharmony_ci               OpBranch %22
2496fd4e5da5Sopenharmony_ci         %22 = OpLabel
2497fd4e5da5Sopenharmony_ci               OpBranch %23
2498fd4e5da5Sopenharmony_ci         %23 = OpLabel
2499fd4e5da5Sopenharmony_ci         %24 = OpPhi %15 %39 %22 %39 %25
2500fd4e5da5Sopenharmony_ci               OpLoopMerge %26 %25 None
2501fd4e5da5Sopenharmony_ci               OpBranchConditional %40 %25 %26
2502fd4e5da5Sopenharmony_ci         %25 = OpLabel
2503fd4e5da5Sopenharmony_ci               OpBranch %23
2504fd4e5da5Sopenharmony_ci         %26 = OpLabel
2505fd4e5da5Sopenharmony_ci               OpReturn
2506fd4e5da5Sopenharmony_ci               OpFunctionEnd
2507fd4e5da5Sopenharmony_ci  )";
2508fd4e5da5Sopenharmony_ci
2509fd4e5da5Sopenharmony_ci  const auto env = SPV_ENV_UNIVERSAL_1_5;
2510fd4e5da5Sopenharmony_ci  const auto consumer = nullptr;
2511fd4e5da5Sopenharmony_ci  const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption);
2512fd4e5da5Sopenharmony_ci  spvtools::ValidatorOptions validator_options;
2513fd4e5da5Sopenharmony_ci  ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
2514fd4e5da5Sopenharmony_ci                                               kConsoleMessageConsumer));
2515fd4e5da5Sopenharmony_ci  TransformationContext transformation_context(
2516fd4e5da5Sopenharmony_ci      MakeUnique<FactManager>(context.get()), validator_options);
2517fd4e5da5Sopenharmony_ci  TransformationOutlineFunction transformation(
2518fd4e5da5Sopenharmony_ci      /*entry_block*/ 22,
2519fd4e5da5Sopenharmony_ci      /*exit_block*/ 23,
2520fd4e5da5Sopenharmony_ci      /*new_function_struct_return_type_id*/ 200,
2521fd4e5da5Sopenharmony_ci      /*new_function_type_id*/ 201,
2522fd4e5da5Sopenharmony_ci      /*new_function_id*/ 202,
2523fd4e5da5Sopenharmony_ci      /*new_function_region_entry_block*/ 203,
2524fd4e5da5Sopenharmony_ci      /*new_caller_result_id*/ 204,
2525fd4e5da5Sopenharmony_ci      /*new_callee_result_id*/ 205,
2526fd4e5da5Sopenharmony_ci      /*input_id_to_fresh_id*/ {},
2527fd4e5da5Sopenharmony_ci      /*output_id_to_fresh_id*/ {});
2528fd4e5da5Sopenharmony_ci
2529fd4e5da5Sopenharmony_ci  ASSERT_FALSE(
2530fd4e5da5Sopenharmony_ci      transformation.IsApplicable(context.get(), transformation_context));
2531fd4e5da5Sopenharmony_ci  ApplyAndCheckFreshIds(transformation, context.get(), &transformation_context);
2532fd4e5da5Sopenharmony_ci}
2533fd4e5da5Sopenharmony_ci
2534fd4e5da5Sopenharmony_ciTEST(TransformationOutlineFunctionTest, Miscellaneous1) {
2535fd4e5da5Sopenharmony_ci  // This tests outlining of some non-trivial code, and also tests the way
2536fd4e5da5Sopenharmony_ci  // overflow ids are used by the transformation.
2537fd4e5da5Sopenharmony_ci
2538fd4e5da5Sopenharmony_ci  std::string reference_shader = R"(
2539fd4e5da5Sopenharmony_ci               OpCapability Shader
2540fd4e5da5Sopenharmony_ci          %1 = OpExtInstImport "GLSL.std.450"
2541fd4e5da5Sopenharmony_ci               OpMemoryModel Logical GLSL450
2542fd4e5da5Sopenharmony_ci               OpEntryPoint Fragment %4 "main" %85
2543fd4e5da5Sopenharmony_ci               OpExecutionMode %4 OriginUpperLeft
2544fd4e5da5Sopenharmony_ci               OpSource ESSL 310
2545fd4e5da5Sopenharmony_ci               OpName %4 "main"
2546fd4e5da5Sopenharmony_ci               OpName %28 "buf"
2547fd4e5da5Sopenharmony_ci               OpMemberName %28 0 "u1"
2548fd4e5da5Sopenharmony_ci               OpMemberName %28 1 "u2"
2549fd4e5da5Sopenharmony_ci               OpName %30 ""
2550fd4e5da5Sopenharmony_ci               OpName %85 "color"
2551fd4e5da5Sopenharmony_ci               OpMemberDecorate %28 0 Offset 0
2552fd4e5da5Sopenharmony_ci               OpMemberDecorate %28 1 Offset 4
2553fd4e5da5Sopenharmony_ci               OpDecorate %28 Block
2554fd4e5da5Sopenharmony_ci               OpDecorate %30 DescriptorSet 0
2555fd4e5da5Sopenharmony_ci               OpDecorate %30 Binding 0
2556fd4e5da5Sopenharmony_ci               OpDecorate %85 Location 0
2557fd4e5da5Sopenharmony_ci          %2 = OpTypeVoid
2558fd4e5da5Sopenharmony_ci          %3 = OpTypeFunction %2
2559fd4e5da5Sopenharmony_ci          %6 = OpTypeFloat 32
2560fd4e5da5Sopenharmony_ci          %7 = OpTypeVector %6 4
2561fd4e5da5Sopenharmony_ci         %10 = OpConstant %6 1
2562fd4e5da5Sopenharmony_ci         %11 = OpConstant %6 2
2563fd4e5da5Sopenharmony_ci         %12 = OpConstant %6 3
2564fd4e5da5Sopenharmony_ci         %13 = OpConstant %6 4
2565fd4e5da5Sopenharmony_ci         %14 = OpConstantComposite %7 %10 %11 %12 %13
2566fd4e5da5Sopenharmony_ci         %15 = OpTypeInt 32 1
2567fd4e5da5Sopenharmony_ci         %18 = OpConstant %15 0
2568fd4e5da5Sopenharmony_ci         %28 = OpTypeStruct %6 %6
2569fd4e5da5Sopenharmony_ci         %29 = OpTypePointer Uniform %28
2570fd4e5da5Sopenharmony_ci         %30 = OpVariable %29 Uniform
2571fd4e5da5Sopenharmony_ci         %31 = OpTypePointer Uniform %6
2572fd4e5da5Sopenharmony_ci         %35 = OpTypeBool
2573fd4e5da5Sopenharmony_ci         %39 = OpConstant %15 1
2574fd4e5da5Sopenharmony_ci         %84 = OpTypePointer Output %7
2575fd4e5da5Sopenharmony_ci         %85 = OpVariable %84 Output
2576fd4e5da5Sopenharmony_ci        %114 = OpConstant %15 8
2577fd4e5da5Sopenharmony_ci          %4 = OpFunction %2 None %3
2578fd4e5da5Sopenharmony_ci          %5 = OpLabel
2579fd4e5da5Sopenharmony_ci               OpBranch %22
2580fd4e5da5Sopenharmony_ci         %22 = OpLabel
2581fd4e5da5Sopenharmony_ci        %103 = OpPhi %15 %18 %5 %106 %43
2582fd4e5da5Sopenharmony_ci        %102 = OpPhi %7 %14 %5 %107 %43
2583fd4e5da5Sopenharmony_ci        %101 = OpPhi %15 %18 %5 %40 %43
2584fd4e5da5Sopenharmony_ci         %32 = OpAccessChain %31 %30 %18
2585fd4e5da5Sopenharmony_ci         %33 = OpLoad %6 %32
2586fd4e5da5Sopenharmony_ci         %34 = OpConvertFToS %15 %33
2587fd4e5da5Sopenharmony_ci         %36 = OpSLessThan %35 %101 %34
2588fd4e5da5Sopenharmony_ci               OpLoopMerge %24 %43 None
2589fd4e5da5Sopenharmony_ci               OpBranchConditional %36 %23 %24
2590fd4e5da5Sopenharmony_ci         %23 = OpLabel
2591fd4e5da5Sopenharmony_ci         %40 = OpIAdd %15 %101 %39
2592fd4e5da5Sopenharmony_ci               OpBranch %150
2593fd4e5da5Sopenharmony_ci        %150 = OpLabel
2594fd4e5da5Sopenharmony_ci               OpBranch %41
2595fd4e5da5Sopenharmony_ci         %41 = OpLabel
2596fd4e5da5Sopenharmony_ci        %107 = OpPhi %7 %102 %150 %111 %65
2597fd4e5da5Sopenharmony_ci        %106 = OpPhi %15 %103 %150 %110 %65
2598fd4e5da5Sopenharmony_ci        %104 = OpPhi %15 %40 %150 %81 %65
2599fd4e5da5Sopenharmony_ci         %47 = OpAccessChain %31 %30 %39
2600fd4e5da5Sopenharmony_ci         %48 = OpLoad %6 %47
2601fd4e5da5Sopenharmony_ci         %49 = OpConvertFToS %15 %48
2602fd4e5da5Sopenharmony_ci         %50 = OpSLessThan %35 %104 %49
2603fd4e5da5Sopenharmony_ci               OpLoopMerge %1000 %65 None
2604fd4e5da5Sopenharmony_ci               OpBranchConditional %50 %42 %1000
2605fd4e5da5Sopenharmony_ci         %42 = OpLabel
2606fd4e5da5Sopenharmony_ci         %60 = OpIAdd %15 %106 %114
2607fd4e5da5Sopenharmony_ci         %63 = OpSGreaterThan %35 %104 %60
2608fd4e5da5Sopenharmony_ci               OpBranchConditional %63 %64 %65
2609fd4e5da5Sopenharmony_ci         %64 = OpLabel
2610fd4e5da5Sopenharmony_ci         %71 = OpCompositeExtract %6 %107 0
2611fd4e5da5Sopenharmony_ci         %72 = OpFAdd %6 %71 %11
2612fd4e5da5Sopenharmony_ci         %97 = OpCompositeInsert %7 %72 %107 0
2613fd4e5da5Sopenharmony_ci         %76 = OpCompositeExtract %6 %107 3
2614fd4e5da5Sopenharmony_ci         %77 = OpConvertFToS %15 %76
2615fd4e5da5Sopenharmony_ci         %79 = OpIAdd %15 %60 %77
2616fd4e5da5Sopenharmony_ci               OpBranch %65
2617fd4e5da5Sopenharmony_ci         %65 = OpLabel
2618fd4e5da5Sopenharmony_ci        %111 = OpPhi %7 %107 %42 %97 %64
2619fd4e5da5Sopenharmony_ci        %110 = OpPhi %15 %60 %42 %79 %64
2620fd4e5da5Sopenharmony_ci         %81 = OpIAdd %15 %104 %39
2621fd4e5da5Sopenharmony_ci               OpBranch %41
2622fd4e5da5Sopenharmony_ci       %1000 = OpLabel
2623fd4e5da5Sopenharmony_ci               OpBranch %1001
2624fd4e5da5Sopenharmony_ci       %1001 = OpLabel
2625fd4e5da5Sopenharmony_ci               OpBranch %43
2626fd4e5da5Sopenharmony_ci         %43 = OpLabel
2627fd4e5da5Sopenharmony_ci               OpBranch %22
2628fd4e5da5Sopenharmony_ci         %24 = OpLabel
2629fd4e5da5Sopenharmony_ci         %87 = OpCompositeExtract %6 %102 0
2630fd4e5da5Sopenharmony_ci         %91 = OpConvertSToF %6 %103
2631fd4e5da5Sopenharmony_ci         %92 = OpCompositeConstruct %7 %87 %11 %91 %10
2632fd4e5da5Sopenharmony_ci               OpStore %85 %92
2633fd4e5da5Sopenharmony_ci               OpReturn
2634fd4e5da5Sopenharmony_ci               OpFunctionEnd
2635fd4e5da5Sopenharmony_ci  )";
2636fd4e5da5Sopenharmony_ci
2637fd4e5da5Sopenharmony_ci  const auto env = SPV_ENV_UNIVERSAL_1_3;
2638fd4e5da5Sopenharmony_ci  const auto consumer = nullptr;
2639fd4e5da5Sopenharmony_ci  spvtools::ValidatorOptions validator_options;
2640fd4e5da5Sopenharmony_ci
2641fd4e5da5Sopenharmony_ci  TransformationOutlineFunction transformation(
2642fd4e5da5Sopenharmony_ci      /*entry_block*/ 150,
2643fd4e5da5Sopenharmony_ci      /*exit_block*/ 1001,
2644fd4e5da5Sopenharmony_ci      /*new_function_struct_return_type_id*/ 200,
2645fd4e5da5Sopenharmony_ci      /*new_function_type_id*/ 201,
2646fd4e5da5Sopenharmony_ci      /*new_function_id*/ 202,
2647fd4e5da5Sopenharmony_ci      /*new_function_region_entry_block*/ 203,
2648fd4e5da5Sopenharmony_ci      /*new_caller_result_id*/ 204,
2649fd4e5da5Sopenharmony_ci      /*new_callee_result_id*/ 205,
2650fd4e5da5Sopenharmony_ci      /*input_id_to_fresh_id*/ {{102, 300}, {103, 301}, {40, 302}},
2651fd4e5da5Sopenharmony_ci      /*output_id_to_fresh_id*/ {{106, 400}, {107, 401}});
2652fd4e5da5Sopenharmony_ci
2653fd4e5da5Sopenharmony_ci  TransformationOutlineFunction transformation_with_missing_input_id(
2654fd4e5da5Sopenharmony_ci      /*entry_block*/ 150,
2655fd4e5da5Sopenharmony_ci      /*exit_block*/ 1001,
2656fd4e5da5Sopenharmony_ci      /*new_function_struct_return_type_id*/ 200,
2657fd4e5da5Sopenharmony_ci      /*new_function_type_id*/ 201,
2658fd4e5da5Sopenharmony_ci      /*new_function_id*/ 202,
2659fd4e5da5Sopenharmony_ci      /*new_function_region_entry_block*/ 203,
2660fd4e5da5Sopenharmony_ci      /*new_caller_result_id*/ 204,
2661fd4e5da5Sopenharmony_ci      /*new_callee_result_id*/ 205,
2662fd4e5da5Sopenharmony_ci      /*input_id_to_fresh_id*/ {{102, 300}, {40, 302}},
2663fd4e5da5Sopenharmony_ci      /*output_id_to_fresh_id*/ {{106, 400}, {107, 401}});
2664fd4e5da5Sopenharmony_ci
2665fd4e5da5Sopenharmony_ci  TransformationOutlineFunction transformation_with_missing_output_id(
2666fd4e5da5Sopenharmony_ci      /*entry_block*/ 150,
2667fd4e5da5Sopenharmony_ci      /*exit_block*/ 1001,
2668fd4e5da5Sopenharmony_ci      /*new_function_struct_return_type_id*/ 200,
2669fd4e5da5Sopenharmony_ci      /*new_function_type_id*/ 201,
2670fd4e5da5Sopenharmony_ci      /*new_function_id*/ 202,
2671fd4e5da5Sopenharmony_ci      /*new_function_region_entry_block*/ 203,
2672fd4e5da5Sopenharmony_ci      /*new_caller_result_id*/ 204,
2673fd4e5da5Sopenharmony_ci      /*new_callee_result_id*/ 205,
2674fd4e5da5Sopenharmony_ci      /*input_id_to_fresh_id*/ {{102, 300}, {103, 301}, {40, 302}},
2675fd4e5da5Sopenharmony_ci      /*output_id_to_fresh_id*/ {{106, 400}});
2676fd4e5da5Sopenharmony_ci
2677fd4e5da5Sopenharmony_ci  TransformationOutlineFunction
2678fd4e5da5Sopenharmony_ci      transformation_with_missing_input_and_output_ids(
2679fd4e5da5Sopenharmony_ci          /*entry_block*/ 150,
2680fd4e5da5Sopenharmony_ci          /*exit_block*/ 1001,
2681fd4e5da5Sopenharmony_ci          /*new_function_struct_return_type_id*/ 200,
2682fd4e5da5Sopenharmony_ci          /*new_function_type_id*/ 201,
2683fd4e5da5Sopenharmony_ci          /*new_function_id*/ 202,
2684fd4e5da5Sopenharmony_ci          /*new_function_region_entry_block*/ 203,
2685fd4e5da5Sopenharmony_ci          /*new_caller_result_id*/ 204,
2686fd4e5da5Sopenharmony_ci          /*new_callee_result_id*/ 205,
2687fd4e5da5Sopenharmony_ci          /*input_id_to_fresh_id*/ {{102, 300}, {40, 302}},
2688fd4e5da5Sopenharmony_ci          /*output_id_to_fresh_id*/ {{106, 400}});
2689fd4e5da5Sopenharmony_ci
2690fd4e5da5Sopenharmony_ci  {
2691fd4e5da5Sopenharmony_ci    const auto context =
2692fd4e5da5Sopenharmony_ci        BuildModule(env, consumer, reference_shader, kFuzzAssembleOption);
2693fd4e5da5Sopenharmony_ci    ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(
2694fd4e5da5Sopenharmony_ci        context.get(), validator_options, kConsoleMessageConsumer));
2695fd4e5da5Sopenharmony_ci
2696fd4e5da5Sopenharmony_ci    TransformationContext transformation_context(
2697fd4e5da5Sopenharmony_ci        MakeUnique<FactManager>(context.get()), validator_options);
2698fd4e5da5Sopenharmony_ci
2699fd4e5da5Sopenharmony_ci#ifndef NDEBUG
2700fd4e5da5Sopenharmony_ci    // We expect the following applicability checks to lead to assertion
2701fd4e5da5Sopenharmony_ci    // failures since the transformations are missing input or output ids, and
2702fd4e5da5Sopenharmony_ci    // the transformation context does not have a source of overflow ids.
2703fd4e5da5Sopenharmony_ci    ASSERT_DEATH(transformation_with_missing_input_id.IsApplicable(
2704fd4e5da5Sopenharmony_ci                     context.get(), transformation_context),
2705fd4e5da5Sopenharmony_ci                 "Bad attempt to query whether overflow ids are available.");
2706fd4e5da5Sopenharmony_ci    ASSERT_DEATH(transformation_with_missing_output_id.IsApplicable(
2707fd4e5da5Sopenharmony_ci                     context.get(), transformation_context),
2708fd4e5da5Sopenharmony_ci                 "Bad attempt to query whether overflow ids are available.");
2709fd4e5da5Sopenharmony_ci    ASSERT_DEATH(transformation_with_missing_input_and_output_ids.IsApplicable(
2710fd4e5da5Sopenharmony_ci                     context.get(), transformation_context),
2711fd4e5da5Sopenharmony_ci                 "Bad attempt to query whether overflow ids are available.");
2712fd4e5da5Sopenharmony_ci#endif
2713fd4e5da5Sopenharmony_ci
2714fd4e5da5Sopenharmony_ci    ASSERT_TRUE(
2715fd4e5da5Sopenharmony_ci        transformation.IsApplicable(context.get(), transformation_context));
2716fd4e5da5Sopenharmony_ci    ApplyAndCheckFreshIds(transformation, context.get(),
2717fd4e5da5Sopenharmony_ci                          &transformation_context);
2718fd4e5da5Sopenharmony_ci    ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(
2719fd4e5da5Sopenharmony_ci        context.get(), validator_options, kConsoleMessageConsumer));
2720fd4e5da5Sopenharmony_ci
2721fd4e5da5Sopenharmony_ci    std::string variant_shader = R"(
2722fd4e5da5Sopenharmony_ci                 OpCapability Shader
2723fd4e5da5Sopenharmony_ci            %1 = OpExtInstImport "GLSL.std.450"
2724fd4e5da5Sopenharmony_ci                 OpMemoryModel Logical GLSL450
2725fd4e5da5Sopenharmony_ci                 OpEntryPoint Fragment %4 "main" %85
2726fd4e5da5Sopenharmony_ci                 OpExecutionMode %4 OriginUpperLeft
2727fd4e5da5Sopenharmony_ci                 OpSource ESSL 310
2728fd4e5da5Sopenharmony_ci                 OpName %4 "main"
2729fd4e5da5Sopenharmony_ci                 OpName %28 "buf"
2730fd4e5da5Sopenharmony_ci                 OpMemberName %28 0 "u1"
2731fd4e5da5Sopenharmony_ci                 OpMemberName %28 1 "u2"
2732fd4e5da5Sopenharmony_ci                 OpName %30 ""
2733fd4e5da5Sopenharmony_ci                 OpName %85 "color"
2734fd4e5da5Sopenharmony_ci                 OpMemberDecorate %28 0 Offset 0
2735fd4e5da5Sopenharmony_ci                 OpMemberDecorate %28 1 Offset 4
2736fd4e5da5Sopenharmony_ci                 OpDecorate %28 Block
2737fd4e5da5Sopenharmony_ci                 OpDecorate %30 DescriptorSet 0
2738fd4e5da5Sopenharmony_ci                 OpDecorate %30 Binding 0
2739fd4e5da5Sopenharmony_ci                 OpDecorate %85 Location 0
2740fd4e5da5Sopenharmony_ci            %2 = OpTypeVoid
2741fd4e5da5Sopenharmony_ci            %3 = OpTypeFunction %2
2742fd4e5da5Sopenharmony_ci            %6 = OpTypeFloat 32
2743fd4e5da5Sopenharmony_ci            %7 = OpTypeVector %6 4
2744fd4e5da5Sopenharmony_ci           %10 = OpConstant %6 1
2745fd4e5da5Sopenharmony_ci           %11 = OpConstant %6 2
2746fd4e5da5Sopenharmony_ci           %12 = OpConstant %6 3
2747fd4e5da5Sopenharmony_ci           %13 = OpConstant %6 4
2748fd4e5da5Sopenharmony_ci           %14 = OpConstantComposite %7 %10 %11 %12 %13
2749fd4e5da5Sopenharmony_ci           %15 = OpTypeInt 32 1
2750fd4e5da5Sopenharmony_ci           %18 = OpConstant %15 0
2751fd4e5da5Sopenharmony_ci           %28 = OpTypeStruct %6 %6
2752fd4e5da5Sopenharmony_ci           %29 = OpTypePointer Uniform %28
2753fd4e5da5Sopenharmony_ci           %30 = OpVariable %29 Uniform
2754fd4e5da5Sopenharmony_ci           %31 = OpTypePointer Uniform %6
2755fd4e5da5Sopenharmony_ci           %35 = OpTypeBool
2756fd4e5da5Sopenharmony_ci           %39 = OpConstant %15 1
2757fd4e5da5Sopenharmony_ci           %84 = OpTypePointer Output %7
2758fd4e5da5Sopenharmony_ci           %85 = OpVariable %84 Output
2759fd4e5da5Sopenharmony_ci          %114 = OpConstant %15 8
2760fd4e5da5Sopenharmony_ci          %200 = OpTypeStruct %7 %15
2761fd4e5da5Sopenharmony_ci          %201 = OpTypeFunction %200 %15 %7 %15
2762fd4e5da5Sopenharmony_ci            %4 = OpFunction %2 None %3
2763fd4e5da5Sopenharmony_ci            %5 = OpLabel
2764fd4e5da5Sopenharmony_ci                 OpBranch %22
2765fd4e5da5Sopenharmony_ci           %22 = OpLabel
2766fd4e5da5Sopenharmony_ci          %103 = OpPhi %15 %18 %5 %106 %43
2767fd4e5da5Sopenharmony_ci          %102 = OpPhi %7 %14 %5 %107 %43
2768fd4e5da5Sopenharmony_ci          %101 = OpPhi %15 %18 %5 %40 %43
2769fd4e5da5Sopenharmony_ci           %32 = OpAccessChain %31 %30 %18
2770fd4e5da5Sopenharmony_ci           %33 = OpLoad %6 %32
2771fd4e5da5Sopenharmony_ci           %34 = OpConvertFToS %15 %33
2772fd4e5da5Sopenharmony_ci           %36 = OpSLessThan %35 %101 %34
2773fd4e5da5Sopenharmony_ci                 OpLoopMerge %24 %43 None
2774fd4e5da5Sopenharmony_ci                 OpBranchConditional %36 %23 %24
2775fd4e5da5Sopenharmony_ci           %23 = OpLabel
2776fd4e5da5Sopenharmony_ci           %40 = OpIAdd %15 %101 %39
2777fd4e5da5Sopenharmony_ci                 OpBranch %150
2778fd4e5da5Sopenharmony_ci          %150 = OpLabel
2779fd4e5da5Sopenharmony_ci          %204 = OpFunctionCall %200 %202 %103 %102 %40
2780fd4e5da5Sopenharmony_ci          %107 = OpCompositeExtract %7 %204 0
2781fd4e5da5Sopenharmony_ci          %106 = OpCompositeExtract %15 %204 1
2782fd4e5da5Sopenharmony_ci                 OpBranch %43
2783fd4e5da5Sopenharmony_ci           %43 = OpLabel
2784fd4e5da5Sopenharmony_ci                 OpBranch %22
2785fd4e5da5Sopenharmony_ci           %24 = OpLabel
2786fd4e5da5Sopenharmony_ci           %87 = OpCompositeExtract %6 %102 0
2787fd4e5da5Sopenharmony_ci           %91 = OpConvertSToF %6 %103
2788fd4e5da5Sopenharmony_ci           %92 = OpCompositeConstruct %7 %87 %11 %91 %10
2789fd4e5da5Sopenharmony_ci                 OpStore %85 %92
2790fd4e5da5Sopenharmony_ci                 OpReturn
2791fd4e5da5Sopenharmony_ci                 OpFunctionEnd
2792fd4e5da5Sopenharmony_ci          %202 = OpFunction %200 None %201
2793fd4e5da5Sopenharmony_ci          %301 = OpFunctionParameter %15
2794fd4e5da5Sopenharmony_ci          %300 = OpFunctionParameter %7
2795fd4e5da5Sopenharmony_ci          %302 = OpFunctionParameter %15
2796fd4e5da5Sopenharmony_ci          %203 = OpLabel
2797fd4e5da5Sopenharmony_ci                 OpBranch %41
2798fd4e5da5Sopenharmony_ci           %41 = OpLabel
2799fd4e5da5Sopenharmony_ci          %401 = OpPhi %7 %300 %203 %111 %65
2800fd4e5da5Sopenharmony_ci          %400 = OpPhi %15 %301 %203 %110 %65
2801fd4e5da5Sopenharmony_ci          %104 = OpPhi %15 %302 %203 %81 %65
2802fd4e5da5Sopenharmony_ci           %47 = OpAccessChain %31 %30 %39
2803fd4e5da5Sopenharmony_ci           %48 = OpLoad %6 %47
2804fd4e5da5Sopenharmony_ci           %49 = OpConvertFToS %15 %48
2805fd4e5da5Sopenharmony_ci           %50 = OpSLessThan %35 %104 %49
2806fd4e5da5Sopenharmony_ci                 OpLoopMerge %1000 %65 None
2807fd4e5da5Sopenharmony_ci                 OpBranchConditional %50 %42 %1000
2808fd4e5da5Sopenharmony_ci           %42 = OpLabel
2809fd4e5da5Sopenharmony_ci           %60 = OpIAdd %15 %400 %114
2810fd4e5da5Sopenharmony_ci           %63 = OpSGreaterThan %35 %104 %60
2811fd4e5da5Sopenharmony_ci                 OpBranchConditional %63 %64 %65
2812fd4e5da5Sopenharmony_ci           %64 = OpLabel
2813fd4e5da5Sopenharmony_ci           %71 = OpCompositeExtract %6 %401 0
2814fd4e5da5Sopenharmony_ci           %72 = OpFAdd %6 %71 %11
2815fd4e5da5Sopenharmony_ci           %97 = OpCompositeInsert %7 %72 %401 0
2816fd4e5da5Sopenharmony_ci           %76 = OpCompositeExtract %6 %401 3
2817fd4e5da5Sopenharmony_ci           %77 = OpConvertFToS %15 %76
2818fd4e5da5Sopenharmony_ci           %79 = OpIAdd %15 %60 %77
2819fd4e5da5Sopenharmony_ci                 OpBranch %65
2820fd4e5da5Sopenharmony_ci           %65 = OpLabel
2821fd4e5da5Sopenharmony_ci          %111 = OpPhi %7 %401 %42 %97 %64
2822fd4e5da5Sopenharmony_ci          %110 = OpPhi %15 %60 %42 %79 %64
2823fd4e5da5Sopenharmony_ci           %81 = OpIAdd %15 %104 %39
2824fd4e5da5Sopenharmony_ci                 OpBranch %41
2825fd4e5da5Sopenharmony_ci         %1000 = OpLabel
2826fd4e5da5Sopenharmony_ci                 OpBranch %1001
2827fd4e5da5Sopenharmony_ci         %1001 = OpLabel
2828fd4e5da5Sopenharmony_ci          %205 = OpCompositeConstruct %200 %401 %400
2829fd4e5da5Sopenharmony_ci                 OpReturnValue %205
2830fd4e5da5Sopenharmony_ci                 OpFunctionEnd
2831fd4e5da5Sopenharmony_ci    )";
2832fd4e5da5Sopenharmony_ci    ASSERT_TRUE(IsEqual(env, variant_shader, context.get()));
2833fd4e5da5Sopenharmony_ci  }
2834fd4e5da5Sopenharmony_ci
2835fd4e5da5Sopenharmony_ci  {
2836fd4e5da5Sopenharmony_ci    const auto context =
2837fd4e5da5Sopenharmony_ci        BuildModule(env, consumer, reference_shader, kFuzzAssembleOption);
2838fd4e5da5Sopenharmony_ci    ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(
2839fd4e5da5Sopenharmony_ci        context.get(), validator_options, kConsoleMessageConsumer));
2840fd4e5da5Sopenharmony_ci    auto overflow_ids_unique_ptr = MakeUnique<CounterOverflowIdSource>(2000);
2841fd4e5da5Sopenharmony_ci    auto overflow_ids_ptr = overflow_ids_unique_ptr.get();
2842fd4e5da5Sopenharmony_ci    TransformationContext new_transformation_context(
2843fd4e5da5Sopenharmony_ci        MakeUnique<FactManager>(context.get()), validator_options,
2844fd4e5da5Sopenharmony_ci        std::move(overflow_ids_unique_ptr));
2845fd4e5da5Sopenharmony_ci    ASSERT_TRUE(transformation_with_missing_input_id.IsApplicable(
2846fd4e5da5Sopenharmony_ci        context.get(), new_transformation_context));
2847fd4e5da5Sopenharmony_ci    ASSERT_TRUE(transformation_with_missing_output_id.IsApplicable(
2848fd4e5da5Sopenharmony_ci        context.get(), new_transformation_context));
2849fd4e5da5Sopenharmony_ci    ASSERT_TRUE(transformation_with_missing_input_and_output_ids.IsApplicable(
2850fd4e5da5Sopenharmony_ci        context.get(), new_transformation_context));
2851fd4e5da5Sopenharmony_ci    ApplyAndCheckFreshIds(transformation_with_missing_input_and_output_ids,
2852fd4e5da5Sopenharmony_ci                          context.get(), &new_transformation_context,
2853fd4e5da5Sopenharmony_ci                          overflow_ids_ptr->GetIssuedOverflowIds());
2854fd4e5da5Sopenharmony_ci    ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(
2855fd4e5da5Sopenharmony_ci        context.get(), validator_options, kConsoleMessageConsumer));
2856fd4e5da5Sopenharmony_ci
2857fd4e5da5Sopenharmony_ci    std::string variant_shader = R"(
2858fd4e5da5Sopenharmony_ci                 OpCapability Shader
2859fd4e5da5Sopenharmony_ci            %1 = OpExtInstImport "GLSL.std.450"
2860fd4e5da5Sopenharmony_ci                 OpMemoryModel Logical GLSL450
2861fd4e5da5Sopenharmony_ci                 OpEntryPoint Fragment %4 "main" %85
2862fd4e5da5Sopenharmony_ci                 OpExecutionMode %4 OriginUpperLeft
2863fd4e5da5Sopenharmony_ci                 OpSource ESSL 310
2864fd4e5da5Sopenharmony_ci                 OpName %4 "main"
2865fd4e5da5Sopenharmony_ci                 OpName %28 "buf"
2866fd4e5da5Sopenharmony_ci                 OpMemberName %28 0 "u1"
2867fd4e5da5Sopenharmony_ci                 OpMemberName %28 1 "u2"
2868fd4e5da5Sopenharmony_ci                 OpName %30 ""
2869fd4e5da5Sopenharmony_ci                 OpName %85 "color"
2870fd4e5da5Sopenharmony_ci                 OpMemberDecorate %28 0 Offset 0
2871fd4e5da5Sopenharmony_ci                 OpMemberDecorate %28 1 Offset 4
2872fd4e5da5Sopenharmony_ci                 OpDecorate %28 Block
2873fd4e5da5Sopenharmony_ci                 OpDecorate %30 DescriptorSet 0
2874fd4e5da5Sopenharmony_ci                 OpDecorate %30 Binding 0
2875fd4e5da5Sopenharmony_ci                 OpDecorate %85 Location 0
2876fd4e5da5Sopenharmony_ci            %2 = OpTypeVoid
2877fd4e5da5Sopenharmony_ci            %3 = OpTypeFunction %2
2878fd4e5da5Sopenharmony_ci            %6 = OpTypeFloat 32
2879fd4e5da5Sopenharmony_ci            %7 = OpTypeVector %6 4
2880fd4e5da5Sopenharmony_ci           %10 = OpConstant %6 1
2881fd4e5da5Sopenharmony_ci           %11 = OpConstant %6 2
2882fd4e5da5Sopenharmony_ci           %12 = OpConstant %6 3
2883fd4e5da5Sopenharmony_ci           %13 = OpConstant %6 4
2884fd4e5da5Sopenharmony_ci           %14 = OpConstantComposite %7 %10 %11 %12 %13
2885fd4e5da5Sopenharmony_ci           %15 = OpTypeInt 32 1
2886fd4e5da5Sopenharmony_ci           %18 = OpConstant %15 0
2887fd4e5da5Sopenharmony_ci           %28 = OpTypeStruct %6 %6
2888fd4e5da5Sopenharmony_ci           %29 = OpTypePointer Uniform %28
2889fd4e5da5Sopenharmony_ci           %30 = OpVariable %29 Uniform
2890fd4e5da5Sopenharmony_ci           %31 = OpTypePointer Uniform %6
2891fd4e5da5Sopenharmony_ci           %35 = OpTypeBool
2892fd4e5da5Sopenharmony_ci           %39 = OpConstant %15 1
2893fd4e5da5Sopenharmony_ci           %84 = OpTypePointer Output %7
2894fd4e5da5Sopenharmony_ci           %85 = OpVariable %84 Output
2895fd4e5da5Sopenharmony_ci          %114 = OpConstant %15 8
2896fd4e5da5Sopenharmony_ci          %200 = OpTypeStruct %7 %15
2897fd4e5da5Sopenharmony_ci          %201 = OpTypeFunction %200 %15 %7 %15
2898fd4e5da5Sopenharmony_ci            %4 = OpFunction %2 None %3
2899fd4e5da5Sopenharmony_ci            %5 = OpLabel
2900fd4e5da5Sopenharmony_ci                 OpBranch %22
2901fd4e5da5Sopenharmony_ci           %22 = OpLabel
2902fd4e5da5Sopenharmony_ci          %103 = OpPhi %15 %18 %5 %106 %43
2903fd4e5da5Sopenharmony_ci          %102 = OpPhi %7 %14 %5 %107 %43
2904fd4e5da5Sopenharmony_ci          %101 = OpPhi %15 %18 %5 %40 %43
2905fd4e5da5Sopenharmony_ci           %32 = OpAccessChain %31 %30 %18
2906fd4e5da5Sopenharmony_ci           %33 = OpLoad %6 %32
2907fd4e5da5Sopenharmony_ci           %34 = OpConvertFToS %15 %33
2908fd4e5da5Sopenharmony_ci           %36 = OpSLessThan %35 %101 %34
2909fd4e5da5Sopenharmony_ci                 OpLoopMerge %24 %43 None
2910fd4e5da5Sopenharmony_ci                 OpBranchConditional %36 %23 %24
2911fd4e5da5Sopenharmony_ci           %23 = OpLabel
2912fd4e5da5Sopenharmony_ci           %40 = OpIAdd %15 %101 %39
2913fd4e5da5Sopenharmony_ci                 OpBranch %150
2914fd4e5da5Sopenharmony_ci          %150 = OpLabel
2915fd4e5da5Sopenharmony_ci          %204 = OpFunctionCall %200 %202 %103 %102 %40
2916fd4e5da5Sopenharmony_ci          %107 = OpCompositeExtract %7 %204 0
2917fd4e5da5Sopenharmony_ci          %106 = OpCompositeExtract %15 %204 1
2918fd4e5da5Sopenharmony_ci                 OpBranch %43
2919fd4e5da5Sopenharmony_ci           %43 = OpLabel
2920fd4e5da5Sopenharmony_ci                 OpBranch %22
2921fd4e5da5Sopenharmony_ci           %24 = OpLabel
2922fd4e5da5Sopenharmony_ci           %87 = OpCompositeExtract %6 %102 0
2923fd4e5da5Sopenharmony_ci           %91 = OpConvertSToF %6 %103
2924fd4e5da5Sopenharmony_ci           %92 = OpCompositeConstruct %7 %87 %11 %91 %10
2925fd4e5da5Sopenharmony_ci                 OpStore %85 %92
2926fd4e5da5Sopenharmony_ci                 OpReturn
2927fd4e5da5Sopenharmony_ci                 OpFunctionEnd
2928fd4e5da5Sopenharmony_ci          %202 = OpFunction %200 None %201
2929fd4e5da5Sopenharmony_ci         %2000 = OpFunctionParameter %15
2930fd4e5da5Sopenharmony_ci          %300 = OpFunctionParameter %7
2931fd4e5da5Sopenharmony_ci          %302 = OpFunctionParameter %15
2932fd4e5da5Sopenharmony_ci          %203 = OpLabel
2933fd4e5da5Sopenharmony_ci                 OpBranch %41
2934fd4e5da5Sopenharmony_ci           %41 = OpLabel
2935fd4e5da5Sopenharmony_ci         %2001 = OpPhi %7 %300 %203 %111 %65
2936fd4e5da5Sopenharmony_ci          %400 = OpPhi %15 %2000 %203 %110 %65
2937fd4e5da5Sopenharmony_ci          %104 = OpPhi %15 %302 %203 %81 %65
2938fd4e5da5Sopenharmony_ci           %47 = OpAccessChain %31 %30 %39
2939fd4e5da5Sopenharmony_ci           %48 = OpLoad %6 %47
2940fd4e5da5Sopenharmony_ci           %49 = OpConvertFToS %15 %48
2941fd4e5da5Sopenharmony_ci           %50 = OpSLessThan %35 %104 %49
2942fd4e5da5Sopenharmony_ci                 OpLoopMerge %1000 %65 None
2943fd4e5da5Sopenharmony_ci                 OpBranchConditional %50 %42 %1000
2944fd4e5da5Sopenharmony_ci           %42 = OpLabel
2945fd4e5da5Sopenharmony_ci           %60 = OpIAdd %15 %400 %114
2946fd4e5da5Sopenharmony_ci           %63 = OpSGreaterThan %35 %104 %60
2947fd4e5da5Sopenharmony_ci                 OpBranchConditional %63 %64 %65
2948fd4e5da5Sopenharmony_ci           %64 = OpLabel
2949fd4e5da5Sopenharmony_ci           %71 = OpCompositeExtract %6 %2001 0
2950fd4e5da5Sopenharmony_ci           %72 = OpFAdd %6 %71 %11
2951fd4e5da5Sopenharmony_ci           %97 = OpCompositeInsert %7 %72 %2001 0
2952fd4e5da5Sopenharmony_ci           %76 = OpCompositeExtract %6 %2001 3
2953fd4e5da5Sopenharmony_ci           %77 = OpConvertFToS %15 %76
2954fd4e5da5Sopenharmony_ci           %79 = OpIAdd %15 %60 %77
2955fd4e5da5Sopenharmony_ci                 OpBranch %65
2956fd4e5da5Sopenharmony_ci           %65 = OpLabel
2957fd4e5da5Sopenharmony_ci          %111 = OpPhi %7 %2001 %42 %97 %64
2958fd4e5da5Sopenharmony_ci          %110 = OpPhi %15 %60 %42 %79 %64
2959fd4e5da5Sopenharmony_ci           %81 = OpIAdd %15 %104 %39
2960fd4e5da5Sopenharmony_ci                 OpBranch %41
2961fd4e5da5Sopenharmony_ci         %1000 = OpLabel
2962fd4e5da5Sopenharmony_ci                 OpBranch %1001
2963fd4e5da5Sopenharmony_ci         %1001 = OpLabel
2964fd4e5da5Sopenharmony_ci          %205 = OpCompositeConstruct %200 %2001 %400
2965fd4e5da5Sopenharmony_ci                 OpReturnValue %205
2966fd4e5da5Sopenharmony_ci                 OpFunctionEnd
2967fd4e5da5Sopenharmony_ci    )";
2968fd4e5da5Sopenharmony_ci    ASSERT_TRUE(IsEqual(env, variant_shader, context.get()));
2969fd4e5da5Sopenharmony_ci  }
2970fd4e5da5Sopenharmony_ci}
2971fd4e5da5Sopenharmony_ci
2972fd4e5da5Sopenharmony_ciTEST(TransformationOutlineFunctionTest, Miscellaneous2) {
2973fd4e5da5Sopenharmony_ci  std::string shader = R"(
2974fd4e5da5Sopenharmony_ci               OpCapability Shader
2975fd4e5da5Sopenharmony_ci          %1 = OpExtInstImport "GLSL.std.450"
2976fd4e5da5Sopenharmony_ci               OpMemoryModel Logical GLSL450
2977fd4e5da5Sopenharmony_ci               OpEntryPoint Fragment %4 "main"
2978fd4e5da5Sopenharmony_ci               OpExecutionMode %4 OriginUpperLeft
2979fd4e5da5Sopenharmony_ci               OpSource ESSL 310
2980fd4e5da5Sopenharmony_ci          %2 = OpTypeVoid
2981fd4e5da5Sopenharmony_ci          %3 = OpTypeFunction %2
2982fd4e5da5Sopenharmony_ci         %21 = OpTypeBool
2983fd4e5da5Sopenharmony_ci        %167 = OpConstantTrue %21
2984fd4e5da5Sopenharmony_ci        %168 = OpConstantFalse %21
2985fd4e5da5Sopenharmony_ci          %4 = OpFunction %2 None %3
2986fd4e5da5Sopenharmony_ci          %5 = OpLabel
2987fd4e5da5Sopenharmony_ci               OpBranch %34
2988fd4e5da5Sopenharmony_ci         %34 = OpLabel
2989fd4e5da5Sopenharmony_ci               OpLoopMerge %36 %37 None
2990fd4e5da5Sopenharmony_ci               OpBranchConditional %168 %37 %38
2991fd4e5da5Sopenharmony_ci         %38 = OpLabel
2992fd4e5da5Sopenharmony_ci               OpBranchConditional %168 %37 %36
2993fd4e5da5Sopenharmony_ci         %37 = OpLabel
2994fd4e5da5Sopenharmony_ci               OpBranch %34
2995fd4e5da5Sopenharmony_ci         %36 = OpLabel
2996fd4e5da5Sopenharmony_ci               OpReturn
2997fd4e5da5Sopenharmony_ci               OpFunctionEnd
2998fd4e5da5Sopenharmony_ci  )";
2999fd4e5da5Sopenharmony_ci
3000fd4e5da5Sopenharmony_ci  const auto env = SPV_ENV_UNIVERSAL_1_5;
3001fd4e5da5Sopenharmony_ci  const auto consumer = nullptr;
3002fd4e5da5Sopenharmony_ci  const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption);
3003fd4e5da5Sopenharmony_ci  spvtools::ValidatorOptions validator_options;
3004fd4e5da5Sopenharmony_ci  ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
3005fd4e5da5Sopenharmony_ci                                               kConsoleMessageConsumer));
3006fd4e5da5Sopenharmony_ci  TransformationContext transformation_context(
3007fd4e5da5Sopenharmony_ci      MakeUnique<FactManager>(context.get()), validator_options);
3008fd4e5da5Sopenharmony_ci  TransformationOutlineFunction transformation(
3009fd4e5da5Sopenharmony_ci      /*entry_block*/ 38,
3010fd4e5da5Sopenharmony_ci      /*exit_block*/ 36,
3011fd4e5da5Sopenharmony_ci      /*new_function_struct_return_type_id*/ 200,
3012fd4e5da5Sopenharmony_ci      /*new_function_type_id*/ 201,
3013fd4e5da5Sopenharmony_ci      /*new_function_id*/ 202,
3014fd4e5da5Sopenharmony_ci      /*new_function_region_entry_block*/ 203,
3015fd4e5da5Sopenharmony_ci      /*new_caller_result_id*/ 204,
3016fd4e5da5Sopenharmony_ci      /*new_callee_result_id*/ 205,
3017fd4e5da5Sopenharmony_ci      /*input_id_to_fresh_id*/ {},
3018fd4e5da5Sopenharmony_ci      /*output_id_to_fresh_id*/ {});
3019fd4e5da5Sopenharmony_ci
3020fd4e5da5Sopenharmony_ci  ASSERT_FALSE(
3021fd4e5da5Sopenharmony_ci      transformation.IsApplicable(context.get(), transformation_context));
3022fd4e5da5Sopenharmony_ci}
3023fd4e5da5Sopenharmony_ci
3024fd4e5da5Sopenharmony_ciTEST(TransformationOutlineFunctionTest, Miscellaneous3) {
3025fd4e5da5Sopenharmony_ci  std::string shader = R"(
3026fd4e5da5Sopenharmony_ci               OpCapability Shader
3027fd4e5da5Sopenharmony_ci          %1 = OpExtInstImport "GLSL.std.450"
3028fd4e5da5Sopenharmony_ci               OpMemoryModel Logical GLSL450
3029fd4e5da5Sopenharmony_ci               OpEntryPoint Fragment %6 "main"
3030fd4e5da5Sopenharmony_ci               OpExecutionMode %6 OriginUpperLeft
3031fd4e5da5Sopenharmony_ci               OpSource ESSL 310
3032fd4e5da5Sopenharmony_ci          %2 = OpTypeVoid
3033fd4e5da5Sopenharmony_ci          %3 = OpTypeFunction %2
3034fd4e5da5Sopenharmony_ci         %21 = OpTypeBool
3035fd4e5da5Sopenharmony_ci        %167 = OpConstantTrue %21
3036fd4e5da5Sopenharmony_ci          %6 = OpFunction %2 None %3
3037fd4e5da5Sopenharmony_ci          %7 = OpLabel
3038fd4e5da5Sopenharmony_ci               OpBranch %80
3039fd4e5da5Sopenharmony_ci         %80 = OpLabel
3040fd4e5da5Sopenharmony_ci               OpBranch %14
3041fd4e5da5Sopenharmony_ci         %14 = OpLabel
3042fd4e5da5Sopenharmony_ci               OpLoopMerge %16 %17 None
3043fd4e5da5Sopenharmony_ci               OpBranch %18
3044fd4e5da5Sopenharmony_ci         %18 = OpLabel
3045fd4e5da5Sopenharmony_ci               OpBranchConditional %167 %15 %16
3046fd4e5da5Sopenharmony_ci         %15 = OpLabel
3047fd4e5da5Sopenharmony_ci               OpBranch %17
3048fd4e5da5Sopenharmony_ci         %16 = OpLabel
3049fd4e5da5Sopenharmony_ci               OpBranch %81
3050fd4e5da5Sopenharmony_ci         %81 = OpLabel
3051fd4e5da5Sopenharmony_ci               OpReturn
3052fd4e5da5Sopenharmony_ci         %17 = OpLabel
3053fd4e5da5Sopenharmony_ci               OpBranch %14
3054fd4e5da5Sopenharmony_ci               OpFunctionEnd
3055fd4e5da5Sopenharmony_ci  )";
3056fd4e5da5Sopenharmony_ci
3057fd4e5da5Sopenharmony_ci  const auto env = SPV_ENV_UNIVERSAL_1_5;
3058fd4e5da5Sopenharmony_ci  const auto consumer = nullptr;
3059fd4e5da5Sopenharmony_ci  const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption);
3060fd4e5da5Sopenharmony_ci  spvtools::ValidatorOptions validator_options;
3061fd4e5da5Sopenharmony_ci  ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
3062fd4e5da5Sopenharmony_ci                                               kConsoleMessageConsumer));
3063fd4e5da5Sopenharmony_ci  TransformationContext transformation_context(
3064fd4e5da5Sopenharmony_ci      MakeUnique<FactManager>(context.get()), validator_options);
3065fd4e5da5Sopenharmony_ci  TransformationOutlineFunction transformation(
3066fd4e5da5Sopenharmony_ci      /*entry_block*/ 80,
3067fd4e5da5Sopenharmony_ci      /*exit_block*/ 81,
3068fd4e5da5Sopenharmony_ci      /*new_function_struct_return_type_id*/ 300,
3069fd4e5da5Sopenharmony_ci      /*new_function_type_id*/ 301,
3070fd4e5da5Sopenharmony_ci      /*new_function_id*/ 302,
3071fd4e5da5Sopenharmony_ci      /*new_function_region_entry_block*/ 304,
3072fd4e5da5Sopenharmony_ci      /*new_caller_result_id*/ 305,
3073fd4e5da5Sopenharmony_ci      /*new_callee_result_id*/ 306,
3074fd4e5da5Sopenharmony_ci      /*input_id_to_fresh_id*/ {},
3075fd4e5da5Sopenharmony_ci      /*output_id_to_fresh_id*/ {});
3076fd4e5da5Sopenharmony_ci
3077fd4e5da5Sopenharmony_ci  ASSERT_TRUE(
3078fd4e5da5Sopenharmony_ci      transformation.IsApplicable(context.get(), transformation_context));
3079fd4e5da5Sopenharmony_ci  ApplyAndCheckFreshIds(transformation, context.get(), &transformation_context);
3080fd4e5da5Sopenharmony_ci  ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
3081fd4e5da5Sopenharmony_ci                                               kConsoleMessageConsumer));
3082fd4e5da5Sopenharmony_ci
3083fd4e5da5Sopenharmony_ci  std::string after_transformation = R"(
3084fd4e5da5Sopenharmony_ci               OpCapability Shader
3085fd4e5da5Sopenharmony_ci          %1 = OpExtInstImport "GLSL.std.450"
3086fd4e5da5Sopenharmony_ci               OpMemoryModel Logical GLSL450
3087fd4e5da5Sopenharmony_ci               OpEntryPoint Fragment %6 "main"
3088fd4e5da5Sopenharmony_ci               OpExecutionMode %6 OriginUpperLeft
3089fd4e5da5Sopenharmony_ci               OpSource ESSL 310
3090fd4e5da5Sopenharmony_ci          %2 = OpTypeVoid
3091fd4e5da5Sopenharmony_ci          %3 = OpTypeFunction %2
3092fd4e5da5Sopenharmony_ci         %21 = OpTypeBool
3093fd4e5da5Sopenharmony_ci        %167 = OpConstantTrue %21
3094fd4e5da5Sopenharmony_ci          %6 = OpFunction %2 None %3
3095fd4e5da5Sopenharmony_ci          %7 = OpLabel
3096fd4e5da5Sopenharmony_ci               OpBranch %80
3097fd4e5da5Sopenharmony_ci         %80 = OpLabel
3098fd4e5da5Sopenharmony_ci        %305 = OpFunctionCall %2 %302
3099fd4e5da5Sopenharmony_ci               OpReturn
3100fd4e5da5Sopenharmony_ci               OpFunctionEnd
3101fd4e5da5Sopenharmony_ci        %302 = OpFunction %2 None %3
3102fd4e5da5Sopenharmony_ci        %304 = OpLabel
3103fd4e5da5Sopenharmony_ci               OpBranch %14
3104fd4e5da5Sopenharmony_ci         %14 = OpLabel
3105fd4e5da5Sopenharmony_ci               OpLoopMerge %16 %17 None
3106fd4e5da5Sopenharmony_ci               OpBranch %18
3107fd4e5da5Sopenharmony_ci         %18 = OpLabel
3108fd4e5da5Sopenharmony_ci               OpBranchConditional %167 %15 %16
3109fd4e5da5Sopenharmony_ci         %15 = OpLabel
3110fd4e5da5Sopenharmony_ci               OpBranch %17
3111fd4e5da5Sopenharmony_ci         %16 = OpLabel
3112fd4e5da5Sopenharmony_ci               OpBranch %81
3113fd4e5da5Sopenharmony_ci         %81 = OpLabel
3114fd4e5da5Sopenharmony_ci               OpReturn
3115fd4e5da5Sopenharmony_ci         %17 = OpLabel
3116fd4e5da5Sopenharmony_ci               OpBranch %14
3117fd4e5da5Sopenharmony_ci               OpFunctionEnd
3118fd4e5da5Sopenharmony_ci  )";
3119fd4e5da5Sopenharmony_ci  ASSERT_TRUE(IsEqual(env, after_transformation, context.get()));
3120fd4e5da5Sopenharmony_ci}
3121fd4e5da5Sopenharmony_ci
3122fd4e5da5Sopenharmony_ciTEST(TransformationOutlineFunctionTest, Miscellaneous4) {
3123fd4e5da5Sopenharmony_ci  std::string shader = R"(
3124fd4e5da5Sopenharmony_ci               OpCapability Shader
3125fd4e5da5Sopenharmony_ci          %1 = OpExtInstImport "GLSL.std.450"
3126fd4e5da5Sopenharmony_ci               OpMemoryModel Logical GLSL450
3127fd4e5da5Sopenharmony_ci               OpEntryPoint Fragment %6 "main"
3128fd4e5da5Sopenharmony_ci               OpExecutionMode %6 OriginUpperLeft
3129fd4e5da5Sopenharmony_ci               OpSource ESSL 310
3130fd4e5da5Sopenharmony_ci          %2 = OpTypeVoid
3131fd4e5da5Sopenharmony_ci          %3 = OpTypeFunction %2
3132fd4e5da5Sopenharmony_ci         %21 = OpTypeBool
3133fd4e5da5Sopenharmony_ci        %100 = OpTypeInt 32 0
3134fd4e5da5Sopenharmony_ci        %101 = OpTypePointer Function %100
3135fd4e5da5Sopenharmony_ci        %102 = OpTypePointer Function %100
3136fd4e5da5Sopenharmony_ci        %103 = OpTypeFunction %2 %101
3137fd4e5da5Sopenharmony_ci          %6 = OpFunction %2 None %3
3138fd4e5da5Sopenharmony_ci          %7 = OpLabel
3139fd4e5da5Sopenharmony_ci        %104 = OpVariable %102 Function
3140fd4e5da5Sopenharmony_ci               OpBranch %80
3141fd4e5da5Sopenharmony_ci         %80 = OpLabel
3142fd4e5da5Sopenharmony_ci        %105 = OpLoad %100 %104
3143fd4e5da5Sopenharmony_ci               OpBranch %106
3144fd4e5da5Sopenharmony_ci        %106 = OpLabel
3145fd4e5da5Sopenharmony_ci               OpReturn
3146fd4e5da5Sopenharmony_ci               OpFunctionEnd
3147fd4e5da5Sopenharmony_ci  )";
3148fd4e5da5Sopenharmony_ci
3149fd4e5da5Sopenharmony_ci  const auto env = SPV_ENV_UNIVERSAL_1_5;
3150fd4e5da5Sopenharmony_ci  const auto consumer = nullptr;
3151fd4e5da5Sopenharmony_ci  const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption);
3152fd4e5da5Sopenharmony_ci  spvtools::ValidatorOptions validator_options;
3153fd4e5da5Sopenharmony_ci  ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
3154fd4e5da5Sopenharmony_ci                                               kConsoleMessageConsumer));
3155fd4e5da5Sopenharmony_ci  TransformationContext transformation_context(
3156fd4e5da5Sopenharmony_ci      MakeUnique<FactManager>(context.get()), validator_options);
3157fd4e5da5Sopenharmony_ci  TransformationOutlineFunction transformation(
3158fd4e5da5Sopenharmony_ci      /*entry_block*/ 80,
3159fd4e5da5Sopenharmony_ci      /*exit_block*/ 106,
3160fd4e5da5Sopenharmony_ci      /*new_function_struct_return_type_id*/ 300,
3161fd4e5da5Sopenharmony_ci      /*new_function_type_id*/ 301,
3162fd4e5da5Sopenharmony_ci      /*new_function_id*/ 302,
3163fd4e5da5Sopenharmony_ci      /*new_function_region_entry_block*/ 304,
3164fd4e5da5Sopenharmony_ci      /*new_caller_result_id*/ 305,
3165fd4e5da5Sopenharmony_ci      /*new_callee_result_id*/ 306,
3166fd4e5da5Sopenharmony_ci      /*input_id_to_fresh_id*/ {{104, 307}},
3167fd4e5da5Sopenharmony_ci      /*output_id_to_fresh_id*/ {});
3168fd4e5da5Sopenharmony_ci
3169fd4e5da5Sopenharmony_ci  ASSERT_TRUE(
3170fd4e5da5Sopenharmony_ci      transformation.IsApplicable(context.get(), transformation_context));
3171fd4e5da5Sopenharmony_ci  ApplyAndCheckFreshIds(transformation, context.get(), &transformation_context);
3172fd4e5da5Sopenharmony_ci  ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
3173fd4e5da5Sopenharmony_ci                                               kConsoleMessageConsumer));
3174fd4e5da5Sopenharmony_ci
3175fd4e5da5Sopenharmony_ci  std::string after_transformation = R"(
3176fd4e5da5Sopenharmony_ci               OpCapability Shader
3177fd4e5da5Sopenharmony_ci          %1 = OpExtInstImport "GLSL.std.450"
3178fd4e5da5Sopenharmony_ci               OpMemoryModel Logical GLSL450
3179fd4e5da5Sopenharmony_ci               OpEntryPoint Fragment %6 "main"
3180fd4e5da5Sopenharmony_ci               OpExecutionMode %6 OriginUpperLeft
3181fd4e5da5Sopenharmony_ci               OpSource ESSL 310
3182fd4e5da5Sopenharmony_ci          %2 = OpTypeVoid
3183fd4e5da5Sopenharmony_ci          %3 = OpTypeFunction %2
3184fd4e5da5Sopenharmony_ci         %21 = OpTypeBool
3185fd4e5da5Sopenharmony_ci        %100 = OpTypeInt 32 0
3186fd4e5da5Sopenharmony_ci        %101 = OpTypePointer Function %100
3187fd4e5da5Sopenharmony_ci        %102 = OpTypePointer Function %100
3188fd4e5da5Sopenharmony_ci        %103 = OpTypeFunction %2 %101
3189fd4e5da5Sopenharmony_ci        %301 = OpTypeFunction %2 %102
3190fd4e5da5Sopenharmony_ci          %6 = OpFunction %2 None %3
3191fd4e5da5Sopenharmony_ci          %7 = OpLabel
3192fd4e5da5Sopenharmony_ci        %104 = OpVariable %102 Function
3193fd4e5da5Sopenharmony_ci               OpBranch %80
3194fd4e5da5Sopenharmony_ci         %80 = OpLabel
3195fd4e5da5Sopenharmony_ci        %305 = OpFunctionCall %2 %302 %104
3196fd4e5da5Sopenharmony_ci               OpReturn
3197fd4e5da5Sopenharmony_ci               OpFunctionEnd
3198fd4e5da5Sopenharmony_ci        %302 = OpFunction %2 None %301
3199fd4e5da5Sopenharmony_ci        %307 = OpFunctionParameter %102
3200fd4e5da5Sopenharmony_ci        %304 = OpLabel
3201fd4e5da5Sopenharmony_ci        %105 = OpLoad %100 %307
3202fd4e5da5Sopenharmony_ci               OpBranch %106
3203fd4e5da5Sopenharmony_ci        %106 = OpLabel
3204fd4e5da5Sopenharmony_ci               OpReturn
3205fd4e5da5Sopenharmony_ci               OpFunctionEnd
3206fd4e5da5Sopenharmony_ci  )";
3207fd4e5da5Sopenharmony_ci  ASSERT_TRUE(IsEqual(env, after_transformation, context.get()));
3208fd4e5da5Sopenharmony_ci}
3209fd4e5da5Sopenharmony_ci
3210fd4e5da5Sopenharmony_ciTEST(TransformationOutlineFunctionTest, NoOutlineWithUnreachableBlocks) {
3211fd4e5da5Sopenharmony_ci  // This checks that outlining will not be performed if a node in the region
3212fd4e5da5Sopenharmony_ci  // has an unreachable predecessor.
3213fd4e5da5Sopenharmony_ci
3214fd4e5da5Sopenharmony_ci  std::string shader = R"(
3215fd4e5da5Sopenharmony_ci               OpCapability Shader
3216fd4e5da5Sopenharmony_ci          %1 = OpExtInstImport "GLSL.std.450"
3217fd4e5da5Sopenharmony_ci               OpMemoryModel Logical GLSL450
3218fd4e5da5Sopenharmony_ci               OpEntryPoint Fragment %4 "main"
3219fd4e5da5Sopenharmony_ci               OpExecutionMode %4 OriginUpperLeft
3220fd4e5da5Sopenharmony_ci               OpSource ESSL 310
3221fd4e5da5Sopenharmony_ci               OpName %4 "main"
3222fd4e5da5Sopenharmony_ci          %2 = OpTypeVoid
3223fd4e5da5Sopenharmony_ci          %3 = OpTypeFunction %2
3224fd4e5da5Sopenharmony_ci          %4 = OpFunction %2 None %3
3225fd4e5da5Sopenharmony_ci          %7 = OpLabel
3226fd4e5da5Sopenharmony_ci               OpBranch %5
3227fd4e5da5Sopenharmony_ci          %5 = OpLabel
3228fd4e5da5Sopenharmony_ci               OpReturn
3229fd4e5da5Sopenharmony_ci          %6 = OpLabel
3230fd4e5da5Sopenharmony_ci               OpBranch %5
3231fd4e5da5Sopenharmony_ci               OpFunctionEnd
3232fd4e5da5Sopenharmony_ci  )";
3233fd4e5da5Sopenharmony_ci
3234fd4e5da5Sopenharmony_ci  const auto env = SPV_ENV_UNIVERSAL_1_4;
3235fd4e5da5Sopenharmony_ci  const auto consumer = nullptr;
3236fd4e5da5Sopenharmony_ci  const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption);
3237fd4e5da5Sopenharmony_ci  spvtools::ValidatorOptions validator_options;
3238fd4e5da5Sopenharmony_ci  ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
3239fd4e5da5Sopenharmony_ci                                               kConsoleMessageConsumer));
3240fd4e5da5Sopenharmony_ci  TransformationContext transformation_context(
3241fd4e5da5Sopenharmony_ci      MakeUnique<FactManager>(context.get()), validator_options);
3242fd4e5da5Sopenharmony_ci  TransformationOutlineFunction transformation(5, 5, /* not relevant */ 200,
3243fd4e5da5Sopenharmony_ci                                               100, 101, 102, 103,
3244fd4e5da5Sopenharmony_ci                                               /* not relevant */ 201, {}, {});
3245fd4e5da5Sopenharmony_ci  ASSERT_FALSE(
3246fd4e5da5Sopenharmony_ci      transformation.IsApplicable(context.get(), transformation_context));
3247fd4e5da5Sopenharmony_ci}
3248fd4e5da5Sopenharmony_ci
3249fd4e5da5Sopenharmony_ci}  // namespace
3250fd4e5da5Sopenharmony_ci}  // namespace fuzz
3251fd4e5da5Sopenharmony_ci}  // namespace spvtools
3252