1fd4e5da5Sopenharmony_ci// Copyright (c) 2020 André Perez Maselco
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_inline_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 "source/fuzz/instruction_descriptor.h"
21fd4e5da5Sopenharmony_ci#include "test/fuzz/fuzz_test_util.h"
22fd4e5da5Sopenharmony_ci
23fd4e5da5Sopenharmony_cinamespace spvtools {
24fd4e5da5Sopenharmony_cinamespace fuzz {
25fd4e5da5Sopenharmony_cinamespace {
26fd4e5da5Sopenharmony_ci
27fd4e5da5Sopenharmony_ciTEST(TransformationInlineFunctionTest, IsApplicable) {
28fd4e5da5Sopenharmony_ci  std::string shader = R"(
29fd4e5da5Sopenharmony_ci               OpCapability Shader
30fd4e5da5Sopenharmony_ci          %1 = OpExtInstImport "GLSL.std.450"
31fd4e5da5Sopenharmony_ci               OpMemoryModel Logical GLSL450
32fd4e5da5Sopenharmony_ci               OpEntryPoint Fragment %52 "main"
33fd4e5da5Sopenharmony_ci               OpExecutionMode %52 OriginUpperLeft
34fd4e5da5Sopenharmony_ci               OpName %56 "function_with_void_return"
35fd4e5da5Sopenharmony_ci
36fd4e5da5Sopenharmony_ci; Types
37fd4e5da5Sopenharmony_ci          %2 = OpTypeBool
38fd4e5da5Sopenharmony_ci          %3 = OpTypeFloat 32
39fd4e5da5Sopenharmony_ci          %4 = OpTypeVector %3 4
40fd4e5da5Sopenharmony_ci          %5 = OpTypePointer Function %4
41fd4e5da5Sopenharmony_ci          %6 = OpTypeVoid
42fd4e5da5Sopenharmony_ci          %7 = OpTypeFunction %6
43fd4e5da5Sopenharmony_ci          %8 = OpTypeFunction %3 %5 %5
44fd4e5da5Sopenharmony_ci
45fd4e5da5Sopenharmony_ci; Constant scalars
46fd4e5da5Sopenharmony_ci          %9 = OpConstant %3 1
47fd4e5da5Sopenharmony_ci         %10 = OpConstant %3 2
48fd4e5da5Sopenharmony_ci         %11 = OpConstant %3 3
49fd4e5da5Sopenharmony_ci         %12 = OpConstant %3 4
50fd4e5da5Sopenharmony_ci         %13 = OpConstant %3 5
51fd4e5da5Sopenharmony_ci         %14 = OpConstant %3 6
52fd4e5da5Sopenharmony_ci         %15 = OpConstant %3 7
53fd4e5da5Sopenharmony_ci         %16 = OpConstant %3 8
54fd4e5da5Sopenharmony_ci         %17 = OpConstantTrue %2
55fd4e5da5Sopenharmony_ci
56fd4e5da5Sopenharmony_ci; Constant vectors
57fd4e5da5Sopenharmony_ci         %18 = OpConstantComposite %4 %9 %10 %11 %12
58fd4e5da5Sopenharmony_ci         %19 = OpConstantComposite %4 %13 %14 %15 %16
59fd4e5da5Sopenharmony_ci
60fd4e5da5Sopenharmony_ci; function with void return
61fd4e5da5Sopenharmony_ci         %20 = OpFunction %6 None %7
62fd4e5da5Sopenharmony_ci         %21 = OpLabel
63fd4e5da5Sopenharmony_ci               OpReturn
64fd4e5da5Sopenharmony_ci               OpFunctionEnd
65fd4e5da5Sopenharmony_ci
66fd4e5da5Sopenharmony_ci; function with early return
67fd4e5da5Sopenharmony_ci         %22 = OpFunction %6 None %7
68fd4e5da5Sopenharmony_ci         %23 = OpLabel
69fd4e5da5Sopenharmony_ci               OpSelectionMerge %26 None
70fd4e5da5Sopenharmony_ci               OpBranchConditional %17 %24 %25
71fd4e5da5Sopenharmony_ci         %24 = OpLabel
72fd4e5da5Sopenharmony_ci               OpReturn
73fd4e5da5Sopenharmony_ci         %25 = OpLabel
74fd4e5da5Sopenharmony_ci               OpBranch %26
75fd4e5da5Sopenharmony_ci         %26 = OpLabel
76fd4e5da5Sopenharmony_ci               OpReturn
77fd4e5da5Sopenharmony_ci               OpFunctionEnd
78fd4e5da5Sopenharmony_ci
79fd4e5da5Sopenharmony_ci; function containing an OpKill instruction
80fd4e5da5Sopenharmony_ci         %27 = OpFunction %6 None %7
81fd4e5da5Sopenharmony_ci         %28 = OpLabel
82fd4e5da5Sopenharmony_ci               OpKill
83fd4e5da5Sopenharmony_ci               OpFunctionEnd
84fd4e5da5Sopenharmony_ci
85fd4e5da5Sopenharmony_ci; function containing an OpUnreachable instruction
86fd4e5da5Sopenharmony_ci         %29 = OpFunction %6 None %7
87fd4e5da5Sopenharmony_ci         %30 = OpLabel
88fd4e5da5Sopenharmony_ci               OpUnreachable
89fd4e5da5Sopenharmony_ci               OpFunctionEnd
90fd4e5da5Sopenharmony_ci
91fd4e5da5Sopenharmony_ci; dot product function
92fd4e5da5Sopenharmony_ci         %31 = OpFunction %3 None %8
93fd4e5da5Sopenharmony_ci         %32 = OpFunctionParameter %5
94fd4e5da5Sopenharmony_ci         %33 = OpFunctionParameter %5
95fd4e5da5Sopenharmony_ci         %34 = OpLabel
96fd4e5da5Sopenharmony_ci         %35 = OpLoad %4 %32
97fd4e5da5Sopenharmony_ci         %36 = OpLoad %4 %33
98fd4e5da5Sopenharmony_ci         %37 = OpCompositeExtract %3 %35 0
99fd4e5da5Sopenharmony_ci         %38 = OpCompositeExtract %3 %36 0
100fd4e5da5Sopenharmony_ci         %39 = OpFMul %3 %37 %38
101fd4e5da5Sopenharmony_ci         %40 = OpCompositeExtract %3 %35 1
102fd4e5da5Sopenharmony_ci         %41 = OpCompositeExtract %3 %36 1
103fd4e5da5Sopenharmony_ci         %42 = OpFMul %3 %40 %41
104fd4e5da5Sopenharmony_ci         %43 = OpCompositeExtract %3 %35 2
105fd4e5da5Sopenharmony_ci         %44 = OpCompositeExtract %3 %36 2
106fd4e5da5Sopenharmony_ci         %45 = OpFMul %3 %43 %44
107fd4e5da5Sopenharmony_ci         %46 = OpCompositeExtract %3 %35 3
108fd4e5da5Sopenharmony_ci         %47 = OpCompositeExtract %3 %36 3
109fd4e5da5Sopenharmony_ci         %48 = OpFMul %3 %46 %47
110fd4e5da5Sopenharmony_ci         %49 = OpFAdd %3 %39 %42
111fd4e5da5Sopenharmony_ci         %50 = OpFAdd %3 %45 %49
112fd4e5da5Sopenharmony_ci         %51 = OpFAdd %3 %48 %50
113fd4e5da5Sopenharmony_ci               OpReturnValue %51
114fd4e5da5Sopenharmony_ci               OpFunctionEnd
115fd4e5da5Sopenharmony_ci
116fd4e5da5Sopenharmony_ci; main function
117fd4e5da5Sopenharmony_ci         %52 = OpFunction %6 None %7
118fd4e5da5Sopenharmony_ci         %53 = OpLabel
119fd4e5da5Sopenharmony_ci         %54 = OpVariable %5 Function
120fd4e5da5Sopenharmony_ci         %55 = OpVariable %5 Function
121fd4e5da5Sopenharmony_ci         %56 = OpFunctionCall %6 %20 ; function with void return
122fd4e5da5Sopenharmony_ci               OpBranch %57
123fd4e5da5Sopenharmony_ci         %57 = OpLabel
124fd4e5da5Sopenharmony_ci         %59 = OpFunctionCall %6 %22 ; function with early return
125fd4e5da5Sopenharmony_ci               OpBranch %60
126fd4e5da5Sopenharmony_ci         %60 = OpLabel
127fd4e5da5Sopenharmony_ci         %61 = OpFunctionCall %6 %27 ; function containing OpKill
128fd4e5da5Sopenharmony_ci               OpBranch %62
129fd4e5da5Sopenharmony_ci         %62 = OpLabel
130fd4e5da5Sopenharmony_ci         %63 = OpFunctionCall %6 %29 ; function containing OpUnreachable
131fd4e5da5Sopenharmony_ci               OpBranch %64
132fd4e5da5Sopenharmony_ci         %64 = OpLabel
133fd4e5da5Sopenharmony_ci               OpStore %54 %18
134fd4e5da5Sopenharmony_ci               OpStore %55 %19
135fd4e5da5Sopenharmony_ci         %65 = OpFunctionCall %3 %31 %54 %55 ; dot product function
136fd4e5da5Sopenharmony_ci               OpBranch %66
137fd4e5da5Sopenharmony_ci         %66 = OpLabel
138fd4e5da5Sopenharmony_ci               OpReturn
139fd4e5da5Sopenharmony_ci               OpFunctionEnd
140fd4e5da5Sopenharmony_ci  )";
141fd4e5da5Sopenharmony_ci
142fd4e5da5Sopenharmony_ci  const auto env = SPV_ENV_UNIVERSAL_1_5;
143fd4e5da5Sopenharmony_ci  const auto consumer = nullptr;
144fd4e5da5Sopenharmony_ci  const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption);
145fd4e5da5Sopenharmony_ci  spvtools::ValidatorOptions validator_options;
146fd4e5da5Sopenharmony_ci  ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
147fd4e5da5Sopenharmony_ci                                               kConsoleMessageConsumer));
148fd4e5da5Sopenharmony_ci  TransformationContext transformation_context(
149fd4e5da5Sopenharmony_ci      MakeUnique<FactManager>(context.get()), validator_options);
150fd4e5da5Sopenharmony_ci  // Tests undefined OpFunctionCall instruction.
151fd4e5da5Sopenharmony_ci  auto transformation = TransformationInlineFunction(67, {});
152fd4e5da5Sopenharmony_ci  ASSERT_FALSE(
153fd4e5da5Sopenharmony_ci      transformation.IsApplicable(context.get(), transformation_context));
154fd4e5da5Sopenharmony_ci
155fd4e5da5Sopenharmony_ci  // Tests false OpFunctionCall instruction.
156fd4e5da5Sopenharmony_ci  transformation = TransformationInlineFunction(42, {});
157fd4e5da5Sopenharmony_ci  ASSERT_FALSE(
158fd4e5da5Sopenharmony_ci      transformation.IsApplicable(context.get(), transformation_context));
159fd4e5da5Sopenharmony_ci
160fd4e5da5Sopenharmony_ci  // Tests use of called function with void return.
161fd4e5da5Sopenharmony_ci  transformation = TransformationInlineFunction(56, {});
162fd4e5da5Sopenharmony_ci  ASSERT_FALSE(
163fd4e5da5Sopenharmony_ci      transformation.IsApplicable(context.get(), transformation_context));
164fd4e5da5Sopenharmony_ci
165fd4e5da5Sopenharmony_ci  // Tests called function having an early return.
166fd4e5da5Sopenharmony_ci  transformation =
167fd4e5da5Sopenharmony_ci      TransformationInlineFunction(59, {{24, 67}, {25, 68}, {26, 69}});
168fd4e5da5Sopenharmony_ci  ASSERT_FALSE(
169fd4e5da5Sopenharmony_ci      transformation.IsApplicable(context.get(), transformation_context));
170fd4e5da5Sopenharmony_ci
171fd4e5da5Sopenharmony_ci  // Tests called function containing an OpKill instruction.
172fd4e5da5Sopenharmony_ci  transformation = TransformationInlineFunction(61, {});
173fd4e5da5Sopenharmony_ci  ASSERT_FALSE(
174fd4e5da5Sopenharmony_ci      transformation.IsApplicable(context.get(), transformation_context));
175fd4e5da5Sopenharmony_ci
176fd4e5da5Sopenharmony_ci  // Tests called function containing an OpUnreachable instruction.
177fd4e5da5Sopenharmony_ci  transformation = TransformationInlineFunction(63, {});
178fd4e5da5Sopenharmony_ci  ASSERT_FALSE(
179fd4e5da5Sopenharmony_ci      transformation.IsApplicable(context.get(), transformation_context));
180fd4e5da5Sopenharmony_ci
181fd4e5da5Sopenharmony_ci  // Tests applicable transformation.
182fd4e5da5Sopenharmony_ci  transformation = TransformationInlineFunction(65, {{35, 67},
183fd4e5da5Sopenharmony_ci                                                     {36, 68},
184fd4e5da5Sopenharmony_ci                                                     {37, 69},
185fd4e5da5Sopenharmony_ci                                                     {38, 70},
186fd4e5da5Sopenharmony_ci                                                     {39, 71},
187fd4e5da5Sopenharmony_ci                                                     {40, 72},
188fd4e5da5Sopenharmony_ci                                                     {41, 73},
189fd4e5da5Sopenharmony_ci                                                     {42, 74},
190fd4e5da5Sopenharmony_ci                                                     {43, 75},
191fd4e5da5Sopenharmony_ci                                                     {44, 76},
192fd4e5da5Sopenharmony_ci                                                     {45, 77},
193fd4e5da5Sopenharmony_ci                                                     {46, 78},
194fd4e5da5Sopenharmony_ci                                                     {47, 79},
195fd4e5da5Sopenharmony_ci                                                     {48, 80},
196fd4e5da5Sopenharmony_ci                                                     {49, 81},
197fd4e5da5Sopenharmony_ci                                                     {50, 82},
198fd4e5da5Sopenharmony_ci                                                     {51, 83}});
199fd4e5da5Sopenharmony_ci  ASSERT_TRUE(
200fd4e5da5Sopenharmony_ci      transformation.IsApplicable(context.get(), transformation_context));
201fd4e5da5Sopenharmony_ci}
202fd4e5da5Sopenharmony_ci
203fd4e5da5Sopenharmony_ciTEST(TransformationInlineFunctionTest, Apply) {
204fd4e5da5Sopenharmony_ci  std::string reference_shader = R"(
205fd4e5da5Sopenharmony_ci               OpCapability Shader
206fd4e5da5Sopenharmony_ci          %1 = OpExtInstImport "GLSL.std.450"
207fd4e5da5Sopenharmony_ci               OpMemoryModel Logical GLSL450
208fd4e5da5Sopenharmony_ci               OpEntryPoint Vertex %39 "main"
209fd4e5da5Sopenharmony_ci
210fd4e5da5Sopenharmony_ci; Types
211fd4e5da5Sopenharmony_ci          %2 = OpTypeFloat 32
212fd4e5da5Sopenharmony_ci          %3 = OpTypeVector %2 4
213fd4e5da5Sopenharmony_ci          %4 = OpTypePointer Function %3
214fd4e5da5Sopenharmony_ci          %5 = OpTypeVoid
215fd4e5da5Sopenharmony_ci          %6 = OpTypeFunction %5
216fd4e5da5Sopenharmony_ci          %7 = OpTypeFunction %2 %4 %4
217fd4e5da5Sopenharmony_ci
218fd4e5da5Sopenharmony_ci; Constant scalars
219fd4e5da5Sopenharmony_ci          %8 = OpConstant %2 1
220fd4e5da5Sopenharmony_ci          %9 = OpConstant %2 2
221fd4e5da5Sopenharmony_ci         %10 = OpConstant %2 3
222fd4e5da5Sopenharmony_ci         %11 = OpConstant %2 4
223fd4e5da5Sopenharmony_ci         %12 = OpConstant %2 5
224fd4e5da5Sopenharmony_ci         %13 = OpConstant %2 6
225fd4e5da5Sopenharmony_ci         %14 = OpConstant %2 7
226fd4e5da5Sopenharmony_ci         %15 = OpConstant %2 8
227fd4e5da5Sopenharmony_ci
228fd4e5da5Sopenharmony_ci; Constant vectors
229fd4e5da5Sopenharmony_ci         %16 = OpConstantComposite %3 %8 %9 %10 %11
230fd4e5da5Sopenharmony_ci         %17 = OpConstantComposite %3 %12 %13 %14 %15
231fd4e5da5Sopenharmony_ci
232fd4e5da5Sopenharmony_ci; dot product function
233fd4e5da5Sopenharmony_ci         %18 = OpFunction %2 None %7
234fd4e5da5Sopenharmony_ci         %19 = OpFunctionParameter %4
235fd4e5da5Sopenharmony_ci         %20 = OpFunctionParameter %4
236fd4e5da5Sopenharmony_ci         %21 = OpLabel
237fd4e5da5Sopenharmony_ci         %22 = OpLoad %3 %19
238fd4e5da5Sopenharmony_ci         %23 = OpLoad %3 %20
239fd4e5da5Sopenharmony_ci         %24 = OpCompositeExtract %2 %22 0
240fd4e5da5Sopenharmony_ci         %25 = OpCompositeExtract %2 %23 0
241fd4e5da5Sopenharmony_ci         %26 = OpFMul %2 %24 %25
242fd4e5da5Sopenharmony_ci         %27 = OpCompositeExtract %2 %22 1
243fd4e5da5Sopenharmony_ci         %28 = OpCompositeExtract %2 %23 1
244fd4e5da5Sopenharmony_ci         %29 = OpFMul %2 %27 %28
245fd4e5da5Sopenharmony_ci         %30 = OpCompositeExtract %2 %22 2
246fd4e5da5Sopenharmony_ci         %31 = OpCompositeExtract %2 %23 2
247fd4e5da5Sopenharmony_ci         %32 = OpFMul %2 %30 %31
248fd4e5da5Sopenharmony_ci         %33 = OpCompositeExtract %2 %22 3
249fd4e5da5Sopenharmony_ci         %34 = OpCompositeExtract %2 %23 3
250fd4e5da5Sopenharmony_ci         %35 = OpFMul %2 %33 %34
251fd4e5da5Sopenharmony_ci         %36 = OpFAdd %2 %26 %29
252fd4e5da5Sopenharmony_ci         %37 = OpFAdd %2 %32 %36
253fd4e5da5Sopenharmony_ci         %38 = OpFAdd %2 %35 %37
254fd4e5da5Sopenharmony_ci               OpReturnValue %38
255fd4e5da5Sopenharmony_ci               OpFunctionEnd
256fd4e5da5Sopenharmony_ci
257fd4e5da5Sopenharmony_ci; main function
258fd4e5da5Sopenharmony_ci         %39 = OpFunction %5 None %6
259fd4e5da5Sopenharmony_ci         %40 = OpLabel
260fd4e5da5Sopenharmony_ci         %41 = OpVariable %4 Function
261fd4e5da5Sopenharmony_ci         %42 = OpVariable %4 Function
262fd4e5da5Sopenharmony_ci               OpStore %41 %16
263fd4e5da5Sopenharmony_ci               OpStore %42 %17
264fd4e5da5Sopenharmony_ci         %43 = OpFunctionCall %2 %18 %41 %42 ; dot product function call
265fd4e5da5Sopenharmony_ci               OpBranch %44
266fd4e5da5Sopenharmony_ci         %44 = OpLabel
267fd4e5da5Sopenharmony_ci               OpReturn
268fd4e5da5Sopenharmony_ci               OpFunctionEnd
269fd4e5da5Sopenharmony_ci  )";
270fd4e5da5Sopenharmony_ci
271fd4e5da5Sopenharmony_ci  const auto env = SPV_ENV_UNIVERSAL_1_5;
272fd4e5da5Sopenharmony_ci  const auto consumer = nullptr;
273fd4e5da5Sopenharmony_ci  const auto context =
274fd4e5da5Sopenharmony_ci      BuildModule(env, consumer, reference_shader, kFuzzAssembleOption);
275fd4e5da5Sopenharmony_ci  spvtools::ValidatorOptions validator_options;
276fd4e5da5Sopenharmony_ci  ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
277fd4e5da5Sopenharmony_ci                                               kConsoleMessageConsumer));
278fd4e5da5Sopenharmony_ci  TransformationContext transformation_context(
279fd4e5da5Sopenharmony_ci      MakeUnique<FactManager>(context.get()), validator_options);
280fd4e5da5Sopenharmony_ci  auto transformation = TransformationInlineFunction(43, {{22, 45},
281fd4e5da5Sopenharmony_ci                                                          {23, 46},
282fd4e5da5Sopenharmony_ci                                                          {24, 47},
283fd4e5da5Sopenharmony_ci                                                          {25, 48},
284fd4e5da5Sopenharmony_ci                                                          {26, 49},
285fd4e5da5Sopenharmony_ci                                                          {27, 50},
286fd4e5da5Sopenharmony_ci                                                          {28, 51},
287fd4e5da5Sopenharmony_ci                                                          {29, 52},
288fd4e5da5Sopenharmony_ci                                                          {30, 53},
289fd4e5da5Sopenharmony_ci                                                          {31, 54},
290fd4e5da5Sopenharmony_ci                                                          {32, 55},
291fd4e5da5Sopenharmony_ci                                                          {33, 56},
292fd4e5da5Sopenharmony_ci                                                          {34, 57},
293fd4e5da5Sopenharmony_ci                                                          {35, 58},
294fd4e5da5Sopenharmony_ci                                                          {36, 59},
295fd4e5da5Sopenharmony_ci                                                          {37, 60},
296fd4e5da5Sopenharmony_ci                                                          {38, 61}});
297fd4e5da5Sopenharmony_ci  ApplyAndCheckFreshIds(transformation, context.get(), &transformation_context);
298fd4e5da5Sopenharmony_ci
299fd4e5da5Sopenharmony_ci  std::string variant_shader = R"(
300fd4e5da5Sopenharmony_ci               OpCapability Shader
301fd4e5da5Sopenharmony_ci          %1 = OpExtInstImport "GLSL.std.450"
302fd4e5da5Sopenharmony_ci               OpMemoryModel Logical GLSL450
303fd4e5da5Sopenharmony_ci               OpEntryPoint Vertex %39 "main"
304fd4e5da5Sopenharmony_ci
305fd4e5da5Sopenharmony_ci; Types
306fd4e5da5Sopenharmony_ci          %2 = OpTypeFloat 32
307fd4e5da5Sopenharmony_ci          %3 = OpTypeVector %2 4
308fd4e5da5Sopenharmony_ci          %4 = OpTypePointer Function %3
309fd4e5da5Sopenharmony_ci          %5 = OpTypeVoid
310fd4e5da5Sopenharmony_ci          %6 = OpTypeFunction %5
311fd4e5da5Sopenharmony_ci          %7 = OpTypeFunction %2 %4 %4
312fd4e5da5Sopenharmony_ci
313fd4e5da5Sopenharmony_ci; Constant scalars
314fd4e5da5Sopenharmony_ci          %8 = OpConstant %2 1
315fd4e5da5Sopenharmony_ci          %9 = OpConstant %2 2
316fd4e5da5Sopenharmony_ci         %10 = OpConstant %2 3
317fd4e5da5Sopenharmony_ci         %11 = OpConstant %2 4
318fd4e5da5Sopenharmony_ci         %12 = OpConstant %2 5
319fd4e5da5Sopenharmony_ci         %13 = OpConstant %2 6
320fd4e5da5Sopenharmony_ci         %14 = OpConstant %2 7
321fd4e5da5Sopenharmony_ci         %15 = OpConstant %2 8
322fd4e5da5Sopenharmony_ci
323fd4e5da5Sopenharmony_ci; Constant vectors
324fd4e5da5Sopenharmony_ci         %16 = OpConstantComposite %3 %8 %9 %10 %11
325fd4e5da5Sopenharmony_ci         %17 = OpConstantComposite %3 %12 %13 %14 %15
326fd4e5da5Sopenharmony_ci
327fd4e5da5Sopenharmony_ci; dot product function
328fd4e5da5Sopenharmony_ci         %18 = OpFunction %2 None %7
329fd4e5da5Sopenharmony_ci         %19 = OpFunctionParameter %4
330fd4e5da5Sopenharmony_ci         %20 = OpFunctionParameter %4
331fd4e5da5Sopenharmony_ci         %21 = OpLabel
332fd4e5da5Sopenharmony_ci         %22 = OpLoad %3 %19
333fd4e5da5Sopenharmony_ci         %23 = OpLoad %3 %20
334fd4e5da5Sopenharmony_ci         %24 = OpCompositeExtract %2 %22 0
335fd4e5da5Sopenharmony_ci         %25 = OpCompositeExtract %2 %23 0
336fd4e5da5Sopenharmony_ci         %26 = OpFMul %2 %24 %25
337fd4e5da5Sopenharmony_ci         %27 = OpCompositeExtract %2 %22 1
338fd4e5da5Sopenharmony_ci         %28 = OpCompositeExtract %2 %23 1
339fd4e5da5Sopenharmony_ci         %29 = OpFMul %2 %27 %28
340fd4e5da5Sopenharmony_ci         %30 = OpCompositeExtract %2 %22 2
341fd4e5da5Sopenharmony_ci         %31 = OpCompositeExtract %2 %23 2
342fd4e5da5Sopenharmony_ci         %32 = OpFMul %2 %30 %31
343fd4e5da5Sopenharmony_ci         %33 = OpCompositeExtract %2 %22 3
344fd4e5da5Sopenharmony_ci         %34 = OpCompositeExtract %2 %23 3
345fd4e5da5Sopenharmony_ci         %35 = OpFMul %2 %33 %34
346fd4e5da5Sopenharmony_ci         %36 = OpFAdd %2 %26 %29
347fd4e5da5Sopenharmony_ci         %37 = OpFAdd %2 %32 %36
348fd4e5da5Sopenharmony_ci         %38 = OpFAdd %2 %35 %37
349fd4e5da5Sopenharmony_ci               OpReturnValue %38
350fd4e5da5Sopenharmony_ci               OpFunctionEnd
351fd4e5da5Sopenharmony_ci
352fd4e5da5Sopenharmony_ci; main function
353fd4e5da5Sopenharmony_ci         %39 = OpFunction %5 None %6
354fd4e5da5Sopenharmony_ci         %40 = OpLabel
355fd4e5da5Sopenharmony_ci         %41 = OpVariable %4 Function
356fd4e5da5Sopenharmony_ci         %42 = OpVariable %4 Function
357fd4e5da5Sopenharmony_ci               OpStore %41 %16
358fd4e5da5Sopenharmony_ci               OpStore %42 %17
359fd4e5da5Sopenharmony_ci         %45 = OpLoad %3 %41
360fd4e5da5Sopenharmony_ci         %46 = OpLoad %3 %42
361fd4e5da5Sopenharmony_ci         %47 = OpCompositeExtract %2 %45 0
362fd4e5da5Sopenharmony_ci         %48 = OpCompositeExtract %2 %46 0
363fd4e5da5Sopenharmony_ci         %49 = OpFMul %2 %47 %48
364fd4e5da5Sopenharmony_ci         %50 = OpCompositeExtract %2 %45 1
365fd4e5da5Sopenharmony_ci         %51 = OpCompositeExtract %2 %46 1
366fd4e5da5Sopenharmony_ci         %52 = OpFMul %2 %50 %51
367fd4e5da5Sopenharmony_ci         %53 = OpCompositeExtract %2 %45 2
368fd4e5da5Sopenharmony_ci         %54 = OpCompositeExtract %2 %46 2
369fd4e5da5Sopenharmony_ci         %55 = OpFMul %2 %53 %54
370fd4e5da5Sopenharmony_ci         %56 = OpCompositeExtract %2 %45 3
371fd4e5da5Sopenharmony_ci         %57 = OpCompositeExtract %2 %46 3
372fd4e5da5Sopenharmony_ci         %58 = OpFMul %2 %56 %57
373fd4e5da5Sopenharmony_ci         %59 = OpFAdd %2 %49 %52
374fd4e5da5Sopenharmony_ci         %60 = OpFAdd %2 %55 %59
375fd4e5da5Sopenharmony_ci         %61 = OpFAdd %2 %58 %60
376fd4e5da5Sopenharmony_ci         %43 = OpCopyObject %2 %61
377fd4e5da5Sopenharmony_ci               OpBranch %44
378fd4e5da5Sopenharmony_ci         %44 = OpLabel
379fd4e5da5Sopenharmony_ci               OpReturn
380fd4e5da5Sopenharmony_ci               OpFunctionEnd
381fd4e5da5Sopenharmony_ci  )";
382fd4e5da5Sopenharmony_ci
383fd4e5da5Sopenharmony_ci  ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
384fd4e5da5Sopenharmony_ci                                               kConsoleMessageConsumer));
385fd4e5da5Sopenharmony_ci  ASSERT_TRUE(IsEqual(env, variant_shader, context.get()));
386fd4e5da5Sopenharmony_ci}
387fd4e5da5Sopenharmony_ci
388fd4e5da5Sopenharmony_ciTEST(TransformationInlineFunctionTest, ApplyToMultipleFunctions) {
389fd4e5da5Sopenharmony_ci  std::string reference_shader = R"(
390fd4e5da5Sopenharmony_ci               OpCapability Shader
391fd4e5da5Sopenharmony_ci          %1 = OpExtInstImport "GLSL.std.450"
392fd4e5da5Sopenharmony_ci               OpMemoryModel Logical GLSL450
393fd4e5da5Sopenharmony_ci               OpEntryPoint Vertex %15 "main"
394fd4e5da5Sopenharmony_ci
395fd4e5da5Sopenharmony_ci; Types
396fd4e5da5Sopenharmony_ci          %2 = OpTypeInt 32 1
397fd4e5da5Sopenharmony_ci          %3 = OpTypeBool
398fd4e5da5Sopenharmony_ci          %4 = OpTypePointer Private %2
399fd4e5da5Sopenharmony_ci          %5 = OpTypePointer Function %2
400fd4e5da5Sopenharmony_ci          %6 = OpTypeVoid
401fd4e5da5Sopenharmony_ci          %7 = OpTypeFunction %6
402fd4e5da5Sopenharmony_ci          %8 = OpTypeFunction %2 %5
403fd4e5da5Sopenharmony_ci          %9 = OpTypeFunction %2 %2
404fd4e5da5Sopenharmony_ci
405fd4e5da5Sopenharmony_ci; Constants
406fd4e5da5Sopenharmony_ci         %10 = OpConstant %2 0
407fd4e5da5Sopenharmony_ci         %11 = OpConstant %2 1
408fd4e5da5Sopenharmony_ci         %12 = OpConstant %2 2
409fd4e5da5Sopenharmony_ci         %13 = OpConstant %2 3
410fd4e5da5Sopenharmony_ci
411fd4e5da5Sopenharmony_ci; Global variable
412fd4e5da5Sopenharmony_ci         %14 = OpVariable %4 Private
413fd4e5da5Sopenharmony_ci
414fd4e5da5Sopenharmony_ci; main function
415fd4e5da5Sopenharmony_ci         %15 = OpFunction %6 None %7
416fd4e5da5Sopenharmony_ci         %16 = OpLabel
417fd4e5da5Sopenharmony_ci         %17 = OpVariable %5 Function
418fd4e5da5Sopenharmony_ci         %18 = OpVariable %5 Function
419fd4e5da5Sopenharmony_ci         %19 = OpVariable %5 Function
420fd4e5da5Sopenharmony_ci               OpStore %17 %13
421fd4e5da5Sopenharmony_ci         %20 = OpLoad %2 %17
422fd4e5da5Sopenharmony_ci               OpStore %18 %20
423fd4e5da5Sopenharmony_ci         %21 = OpFunctionCall %2 %36 %18
424fd4e5da5Sopenharmony_ci               OpBranch %22
425fd4e5da5Sopenharmony_ci         %22 = OpLabel
426fd4e5da5Sopenharmony_ci         %23 = OpFunctionCall %2 %36 %18
427fd4e5da5Sopenharmony_ci               OpStore %17 %21
428fd4e5da5Sopenharmony_ci         %24 = OpLoad %2 %17
429fd4e5da5Sopenharmony_ci         %25 = OpFunctionCall %2 %54 %24
430fd4e5da5Sopenharmony_ci               OpBranch %26
431fd4e5da5Sopenharmony_ci         %26 = OpLabel
432fd4e5da5Sopenharmony_ci         %27 = OpFunctionCall %2 %54 %24
433fd4e5da5Sopenharmony_ci         %28 = OpLoad %2 %17
434fd4e5da5Sopenharmony_ci         %29 = OpIAdd %2 %28 %25
435fd4e5da5Sopenharmony_ci               OpStore %17 %29
436fd4e5da5Sopenharmony_ci         %30 = OpFunctionCall %6 %67
437fd4e5da5Sopenharmony_ci               OpBranch %31
438fd4e5da5Sopenharmony_ci         %31 = OpLabel
439fd4e5da5Sopenharmony_ci         %32 = OpFunctionCall %6 %67
440fd4e5da5Sopenharmony_ci         %33 = OpLoad %2 %14
441fd4e5da5Sopenharmony_ci         %34 = OpLoad %2 %17
442fd4e5da5Sopenharmony_ci         %35 = OpIAdd %2 %34 %33
443fd4e5da5Sopenharmony_ci               OpStore %17 %35
444fd4e5da5Sopenharmony_ci               OpReturn
445fd4e5da5Sopenharmony_ci               OpFunctionEnd
446fd4e5da5Sopenharmony_ci
447fd4e5da5Sopenharmony_ci; Function %36
448fd4e5da5Sopenharmony_ci         %36 = OpFunction %2 None %8
449fd4e5da5Sopenharmony_ci         %37 = OpFunctionParameter %5
450fd4e5da5Sopenharmony_ci         %38 = OpLabel
451fd4e5da5Sopenharmony_ci         %39 = OpVariable %5 Function
452fd4e5da5Sopenharmony_ci         %40 = OpVariable %5 Function
453fd4e5da5Sopenharmony_ci               OpStore %39 %10
454fd4e5da5Sopenharmony_ci               OpBranch %41
455fd4e5da5Sopenharmony_ci         %41 = OpLabel
456fd4e5da5Sopenharmony_ci               OpLoopMerge %52 %49 None
457fd4e5da5Sopenharmony_ci               OpBranch %42
458fd4e5da5Sopenharmony_ci         %42 = OpLabel
459fd4e5da5Sopenharmony_ci         %43 = OpLoad %2 %39
460fd4e5da5Sopenharmony_ci         %44 = OpLoad %2 %37
461fd4e5da5Sopenharmony_ci         %45 = OpSLessThan %3 %43 %44
462fd4e5da5Sopenharmony_ci               OpBranchConditional %45 %46 %52
463fd4e5da5Sopenharmony_ci         %46 = OpLabel
464fd4e5da5Sopenharmony_ci         %47 = OpLoad %2 %40
465fd4e5da5Sopenharmony_ci         %48 = OpIAdd %2 %47 %11
466fd4e5da5Sopenharmony_ci               OpStore %40 %48
467fd4e5da5Sopenharmony_ci               OpBranch %49
468fd4e5da5Sopenharmony_ci         %49 = OpLabel
469fd4e5da5Sopenharmony_ci         %50 = OpLoad %2 %39
470fd4e5da5Sopenharmony_ci         %51 = OpIAdd %2 %50 %12
471fd4e5da5Sopenharmony_ci               OpStore %39 %51
472fd4e5da5Sopenharmony_ci               OpBranch %41
473fd4e5da5Sopenharmony_ci         %52 = OpLabel
474fd4e5da5Sopenharmony_ci         %53 = OpLoad %2 %40
475fd4e5da5Sopenharmony_ci               OpReturnValue %53
476fd4e5da5Sopenharmony_ci               OpFunctionEnd
477fd4e5da5Sopenharmony_ci
478fd4e5da5Sopenharmony_ci; Function %54
479fd4e5da5Sopenharmony_ci         %54 = OpFunction %2 None %9
480fd4e5da5Sopenharmony_ci         %55 = OpFunctionParameter %2
481fd4e5da5Sopenharmony_ci         %56 = OpLabel
482fd4e5da5Sopenharmony_ci         %57 = OpVariable %5 Function
483fd4e5da5Sopenharmony_ci               OpStore %57 %10
484fd4e5da5Sopenharmony_ci         %58 = OpSGreaterThan %3 %55 %10
485fd4e5da5Sopenharmony_ci               OpSelectionMerge %62 None
486fd4e5da5Sopenharmony_ci               OpBranchConditional %58 %64 %59
487fd4e5da5Sopenharmony_ci         %59 = OpLabel
488fd4e5da5Sopenharmony_ci         %60 = OpLoad %2 %57
489fd4e5da5Sopenharmony_ci         %61 = OpISub %2 %60 %12
490fd4e5da5Sopenharmony_ci               OpStore %57 %61
491fd4e5da5Sopenharmony_ci               OpBranch %62
492fd4e5da5Sopenharmony_ci         %62 = OpLabel
493fd4e5da5Sopenharmony_ci         %63 = OpLoad %2 %57
494fd4e5da5Sopenharmony_ci               OpReturnValue %63
495fd4e5da5Sopenharmony_ci         %64 = OpLabel
496fd4e5da5Sopenharmony_ci         %65 = OpLoad %2 %57
497fd4e5da5Sopenharmony_ci         %66 = OpIAdd %2 %65 %11
498fd4e5da5Sopenharmony_ci               OpStore %57 %66
499fd4e5da5Sopenharmony_ci               OpBranch %62
500fd4e5da5Sopenharmony_ci               OpFunctionEnd
501fd4e5da5Sopenharmony_ci
502fd4e5da5Sopenharmony_ci; Function %67
503fd4e5da5Sopenharmony_ci         %67 = OpFunction %6 None %7
504fd4e5da5Sopenharmony_ci         %68 = OpLabel
505fd4e5da5Sopenharmony_ci               OpStore %14 %12
506fd4e5da5Sopenharmony_ci               OpReturn
507fd4e5da5Sopenharmony_ci               OpFunctionEnd
508fd4e5da5Sopenharmony_ci  )";
509fd4e5da5Sopenharmony_ci
510fd4e5da5Sopenharmony_ci  const auto env = SPV_ENV_UNIVERSAL_1_3;
511fd4e5da5Sopenharmony_ci  const auto consumer = nullptr;
512fd4e5da5Sopenharmony_ci  const auto context =
513fd4e5da5Sopenharmony_ci      BuildModule(env, consumer, reference_shader, kFuzzAssembleOption);
514fd4e5da5Sopenharmony_ci  spvtools::ValidatorOptions validator_options;
515fd4e5da5Sopenharmony_ci  ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
516fd4e5da5Sopenharmony_ci                                               kConsoleMessageConsumer));
517fd4e5da5Sopenharmony_ci  TransformationContext transformation_context(
518fd4e5da5Sopenharmony_ci      MakeUnique<FactManager>(context.get()), validator_options);
519fd4e5da5Sopenharmony_ci  auto transformation = TransformationInlineFunction(30, {});
520fd4e5da5Sopenharmony_ci  ASSERT_TRUE(
521fd4e5da5Sopenharmony_ci      transformation.IsApplicable(context.get(), transformation_context));
522fd4e5da5Sopenharmony_ci  ApplyAndCheckFreshIds(transformation, context.get(), &transformation_context);
523fd4e5da5Sopenharmony_ci
524fd4e5da5Sopenharmony_ci  // Tests a parameter included in the id map.
525fd4e5da5Sopenharmony_ci  transformation = TransformationInlineFunction(25, {{55, 69},
526fd4e5da5Sopenharmony_ci                                                     {56, 70},
527fd4e5da5Sopenharmony_ci                                                     {57, 71},
528fd4e5da5Sopenharmony_ci                                                     {58, 72},
529fd4e5da5Sopenharmony_ci                                                     {59, 73},
530fd4e5da5Sopenharmony_ci                                                     {60, 74},
531fd4e5da5Sopenharmony_ci                                                     {61, 75},
532fd4e5da5Sopenharmony_ci                                                     {62, 76},
533fd4e5da5Sopenharmony_ci                                                     {63, 77},
534fd4e5da5Sopenharmony_ci                                                     {64, 78},
535fd4e5da5Sopenharmony_ci                                                     {65, 79},
536fd4e5da5Sopenharmony_ci                                                     {66, 80}});
537fd4e5da5Sopenharmony_ci  ASSERT_FALSE(
538fd4e5da5Sopenharmony_ci      transformation.IsApplicable(context.get(), transformation_context));
539fd4e5da5Sopenharmony_ci
540fd4e5da5Sopenharmony_ci#ifndef NDEBUG
541fd4e5da5Sopenharmony_ci  // Tests the id of the returned value not included in the id map.
542fd4e5da5Sopenharmony_ci  transformation = TransformationInlineFunction(25, {{56, 69},
543fd4e5da5Sopenharmony_ci                                                     {57, 70},
544fd4e5da5Sopenharmony_ci                                                     {58, 71},
545fd4e5da5Sopenharmony_ci                                                     {59, 72},
546fd4e5da5Sopenharmony_ci                                                     {60, 73},
547fd4e5da5Sopenharmony_ci                                                     {61, 74},
548fd4e5da5Sopenharmony_ci                                                     {62, 75},
549fd4e5da5Sopenharmony_ci                                                     {64, 76},
550fd4e5da5Sopenharmony_ci                                                     {65, 77},
551fd4e5da5Sopenharmony_ci                                                     {66, 78}});
552fd4e5da5Sopenharmony_ci  ASSERT_DEATH(
553fd4e5da5Sopenharmony_ci      transformation.IsApplicable(context.get(), transformation_context),
554fd4e5da5Sopenharmony_ci      "Bad attempt to query whether overflow ids are available.");
555fd4e5da5Sopenharmony_ci#endif
556fd4e5da5Sopenharmony_ci
557fd4e5da5Sopenharmony_ci  transformation = TransformationInlineFunction(25, {{57, 69},
558fd4e5da5Sopenharmony_ci                                                     {58, 70},
559fd4e5da5Sopenharmony_ci                                                     {59, 71},
560fd4e5da5Sopenharmony_ci                                                     {60, 72},
561fd4e5da5Sopenharmony_ci                                                     {61, 73},
562fd4e5da5Sopenharmony_ci                                                     {62, 74},
563fd4e5da5Sopenharmony_ci                                                     {63, 75},
564fd4e5da5Sopenharmony_ci                                                     {64, 76},
565fd4e5da5Sopenharmony_ci                                                     {65, 77},
566fd4e5da5Sopenharmony_ci                                                     {66, 78}});
567fd4e5da5Sopenharmony_ci  ASSERT_TRUE(
568fd4e5da5Sopenharmony_ci      transformation.IsApplicable(context.get(), transformation_context));
569fd4e5da5Sopenharmony_ci  ApplyAndCheckFreshIds(transformation, context.get(), &transformation_context);
570fd4e5da5Sopenharmony_ci
571fd4e5da5Sopenharmony_ci  transformation = TransformationInlineFunction(21, {{39, 79},
572fd4e5da5Sopenharmony_ci                                                     {40, 80},
573fd4e5da5Sopenharmony_ci                                                     {41, 81},
574fd4e5da5Sopenharmony_ci                                                     {42, 82},
575fd4e5da5Sopenharmony_ci                                                     {43, 83},
576fd4e5da5Sopenharmony_ci                                                     {44, 84},
577fd4e5da5Sopenharmony_ci                                                     {45, 85},
578fd4e5da5Sopenharmony_ci                                                     {46, 86},
579fd4e5da5Sopenharmony_ci                                                     {47, 87},
580fd4e5da5Sopenharmony_ci                                                     {48, 88},
581fd4e5da5Sopenharmony_ci                                                     {49, 89},
582fd4e5da5Sopenharmony_ci                                                     {50, 90},
583fd4e5da5Sopenharmony_ci                                                     {51, 91},
584fd4e5da5Sopenharmony_ci                                                     {52, 92},
585fd4e5da5Sopenharmony_ci                                                     {53, 93}});
586fd4e5da5Sopenharmony_ci  ASSERT_TRUE(
587fd4e5da5Sopenharmony_ci      transformation.IsApplicable(context.get(), transformation_context));
588fd4e5da5Sopenharmony_ci  ApplyAndCheckFreshIds(transformation, context.get(), &transformation_context);
589fd4e5da5Sopenharmony_ci
590fd4e5da5Sopenharmony_ci  std::string variant_shader = R"(
591fd4e5da5Sopenharmony_ci               OpCapability Shader
592fd4e5da5Sopenharmony_ci          %1 = OpExtInstImport "GLSL.std.450"
593fd4e5da5Sopenharmony_ci               OpMemoryModel Logical GLSL450
594fd4e5da5Sopenharmony_ci               OpEntryPoint Vertex %15 "main"
595fd4e5da5Sopenharmony_ci
596fd4e5da5Sopenharmony_ci; Types
597fd4e5da5Sopenharmony_ci          %2 = OpTypeInt 32 1
598fd4e5da5Sopenharmony_ci          %3 = OpTypeBool
599fd4e5da5Sopenharmony_ci          %4 = OpTypePointer Private %2
600fd4e5da5Sopenharmony_ci          %5 = OpTypePointer Function %2
601fd4e5da5Sopenharmony_ci          %6 = OpTypeVoid
602fd4e5da5Sopenharmony_ci          %7 = OpTypeFunction %6
603fd4e5da5Sopenharmony_ci          %8 = OpTypeFunction %2 %5
604fd4e5da5Sopenharmony_ci          %9 = OpTypeFunction %2 %2
605fd4e5da5Sopenharmony_ci
606fd4e5da5Sopenharmony_ci; Constants
607fd4e5da5Sopenharmony_ci         %10 = OpConstant %2 0
608fd4e5da5Sopenharmony_ci         %11 = OpConstant %2 1
609fd4e5da5Sopenharmony_ci         %12 = OpConstant %2 2
610fd4e5da5Sopenharmony_ci         %13 = OpConstant %2 3
611fd4e5da5Sopenharmony_ci
612fd4e5da5Sopenharmony_ci; Global variable
613fd4e5da5Sopenharmony_ci         %14 = OpVariable %4 Private
614fd4e5da5Sopenharmony_ci
615fd4e5da5Sopenharmony_ci; main function
616fd4e5da5Sopenharmony_ci         %15 = OpFunction %6 None %7
617fd4e5da5Sopenharmony_ci         %16 = OpLabel
618fd4e5da5Sopenharmony_ci         %80 = OpVariable %5 Function
619fd4e5da5Sopenharmony_ci         %79 = OpVariable %5 Function
620fd4e5da5Sopenharmony_ci         %69 = OpVariable %5 Function
621fd4e5da5Sopenharmony_ci         %17 = OpVariable %5 Function
622fd4e5da5Sopenharmony_ci         %18 = OpVariable %5 Function
623fd4e5da5Sopenharmony_ci         %19 = OpVariable %5 Function
624fd4e5da5Sopenharmony_ci               OpStore %17 %13
625fd4e5da5Sopenharmony_ci         %20 = OpLoad %2 %17
626fd4e5da5Sopenharmony_ci               OpStore %18 %20
627fd4e5da5Sopenharmony_ci               OpStore %79 %10
628fd4e5da5Sopenharmony_ci               OpBranch %81
629fd4e5da5Sopenharmony_ci         %81 = OpLabel
630fd4e5da5Sopenharmony_ci               OpLoopMerge %92 %89 None
631fd4e5da5Sopenharmony_ci               OpBranch %82
632fd4e5da5Sopenharmony_ci         %82 = OpLabel
633fd4e5da5Sopenharmony_ci         %83 = OpLoad %2 %79
634fd4e5da5Sopenharmony_ci         %84 = OpLoad %2 %18
635fd4e5da5Sopenharmony_ci         %85 = OpSLessThan %3 %83 %84
636fd4e5da5Sopenharmony_ci               OpBranchConditional %85 %86 %92
637fd4e5da5Sopenharmony_ci         %86 = OpLabel
638fd4e5da5Sopenharmony_ci         %87 = OpLoad %2 %80
639fd4e5da5Sopenharmony_ci         %88 = OpIAdd %2 %87 %11
640fd4e5da5Sopenharmony_ci               OpStore %80 %88
641fd4e5da5Sopenharmony_ci               OpBranch %89
642fd4e5da5Sopenharmony_ci         %89 = OpLabel
643fd4e5da5Sopenharmony_ci         %90 = OpLoad %2 %79
644fd4e5da5Sopenharmony_ci         %91 = OpIAdd %2 %90 %12
645fd4e5da5Sopenharmony_ci               OpStore %79 %91
646fd4e5da5Sopenharmony_ci               OpBranch %81
647fd4e5da5Sopenharmony_ci         %92 = OpLabel
648fd4e5da5Sopenharmony_ci         %93 = OpLoad %2 %80
649fd4e5da5Sopenharmony_ci         %21 = OpCopyObject %2 %93
650fd4e5da5Sopenharmony_ci               OpBranch %22
651fd4e5da5Sopenharmony_ci         %22 = OpLabel
652fd4e5da5Sopenharmony_ci         %23 = OpFunctionCall %2 %36 %18
653fd4e5da5Sopenharmony_ci               OpStore %17 %21
654fd4e5da5Sopenharmony_ci         %24 = OpLoad %2 %17
655fd4e5da5Sopenharmony_ci               OpStore %69 %10
656fd4e5da5Sopenharmony_ci         %70 = OpSGreaterThan %3 %24 %10
657fd4e5da5Sopenharmony_ci               OpSelectionMerge %74 None
658fd4e5da5Sopenharmony_ci               OpBranchConditional %70 %76 %71
659fd4e5da5Sopenharmony_ci         %71 = OpLabel
660fd4e5da5Sopenharmony_ci         %72 = OpLoad %2 %69
661fd4e5da5Sopenharmony_ci         %73 = OpISub %2 %72 %12
662fd4e5da5Sopenharmony_ci               OpStore %69 %73
663fd4e5da5Sopenharmony_ci               OpBranch %74
664fd4e5da5Sopenharmony_ci         %74 = OpLabel
665fd4e5da5Sopenharmony_ci         %75 = OpLoad %2 %69
666fd4e5da5Sopenharmony_ci         %25 = OpCopyObject %2 %75
667fd4e5da5Sopenharmony_ci               OpBranch %26
668fd4e5da5Sopenharmony_ci         %76 = OpLabel
669fd4e5da5Sopenharmony_ci         %77 = OpLoad %2 %69
670fd4e5da5Sopenharmony_ci         %78 = OpIAdd %2 %77 %11
671fd4e5da5Sopenharmony_ci               OpStore %69 %78
672fd4e5da5Sopenharmony_ci               OpBranch %74
673fd4e5da5Sopenharmony_ci         %26 = OpLabel
674fd4e5da5Sopenharmony_ci         %27 = OpFunctionCall %2 %54 %24
675fd4e5da5Sopenharmony_ci         %28 = OpLoad %2 %17
676fd4e5da5Sopenharmony_ci         %29 = OpIAdd %2 %28 %25
677fd4e5da5Sopenharmony_ci               OpStore %17 %29
678fd4e5da5Sopenharmony_ci               OpStore %14 %12
679fd4e5da5Sopenharmony_ci               OpBranch %31
680fd4e5da5Sopenharmony_ci         %31 = OpLabel
681fd4e5da5Sopenharmony_ci         %32 = OpFunctionCall %6 %67
682fd4e5da5Sopenharmony_ci         %33 = OpLoad %2 %14
683fd4e5da5Sopenharmony_ci         %34 = OpLoad %2 %17
684fd4e5da5Sopenharmony_ci         %35 = OpIAdd %2 %34 %33
685fd4e5da5Sopenharmony_ci               OpStore %17 %35
686fd4e5da5Sopenharmony_ci               OpReturn
687fd4e5da5Sopenharmony_ci               OpFunctionEnd
688fd4e5da5Sopenharmony_ci
689fd4e5da5Sopenharmony_ci; Function %36
690fd4e5da5Sopenharmony_ci         %36 = OpFunction %2 None %8
691fd4e5da5Sopenharmony_ci         %37 = OpFunctionParameter %5
692fd4e5da5Sopenharmony_ci         %38 = OpLabel
693fd4e5da5Sopenharmony_ci         %39 = OpVariable %5 Function
694fd4e5da5Sopenharmony_ci         %40 = OpVariable %5 Function
695fd4e5da5Sopenharmony_ci               OpStore %39 %10
696fd4e5da5Sopenharmony_ci               OpBranch %41
697fd4e5da5Sopenharmony_ci         %41 = OpLabel
698fd4e5da5Sopenharmony_ci               OpLoopMerge %52 %49 None
699fd4e5da5Sopenharmony_ci               OpBranch %42
700fd4e5da5Sopenharmony_ci         %42 = OpLabel
701fd4e5da5Sopenharmony_ci         %43 = OpLoad %2 %39
702fd4e5da5Sopenharmony_ci         %44 = OpLoad %2 %37
703fd4e5da5Sopenharmony_ci         %45 = OpSLessThan %3 %43 %44
704fd4e5da5Sopenharmony_ci               OpBranchConditional %45 %46 %52
705fd4e5da5Sopenharmony_ci         %46 = OpLabel
706fd4e5da5Sopenharmony_ci         %47 = OpLoad %2 %40
707fd4e5da5Sopenharmony_ci         %48 = OpIAdd %2 %47 %11
708fd4e5da5Sopenharmony_ci               OpStore %40 %48
709fd4e5da5Sopenharmony_ci               OpBranch %49
710fd4e5da5Sopenharmony_ci         %49 = OpLabel
711fd4e5da5Sopenharmony_ci         %50 = OpLoad %2 %39
712fd4e5da5Sopenharmony_ci         %51 = OpIAdd %2 %50 %12
713fd4e5da5Sopenharmony_ci               OpStore %39 %51
714fd4e5da5Sopenharmony_ci               OpBranch %41
715fd4e5da5Sopenharmony_ci         %52 = OpLabel
716fd4e5da5Sopenharmony_ci         %53 = OpLoad %2 %40
717fd4e5da5Sopenharmony_ci               OpReturnValue %53
718fd4e5da5Sopenharmony_ci               OpFunctionEnd
719fd4e5da5Sopenharmony_ci
720fd4e5da5Sopenharmony_ci; Function %54
721fd4e5da5Sopenharmony_ci         %54 = OpFunction %2 None %9
722fd4e5da5Sopenharmony_ci         %55 = OpFunctionParameter %2
723fd4e5da5Sopenharmony_ci         %56 = OpLabel
724fd4e5da5Sopenharmony_ci         %57 = OpVariable %5 Function
725fd4e5da5Sopenharmony_ci               OpStore %57 %10
726fd4e5da5Sopenharmony_ci         %58 = OpSGreaterThan %3 %55 %10
727fd4e5da5Sopenharmony_ci               OpSelectionMerge %62 None
728fd4e5da5Sopenharmony_ci               OpBranchConditional %58 %64 %59
729fd4e5da5Sopenharmony_ci         %59 = OpLabel
730fd4e5da5Sopenharmony_ci         %60 = OpLoad %2 %57
731fd4e5da5Sopenharmony_ci         %61 = OpISub %2 %60 %12
732fd4e5da5Sopenharmony_ci               OpStore %57 %61
733fd4e5da5Sopenharmony_ci               OpBranch %62
734fd4e5da5Sopenharmony_ci         %62 = OpLabel
735fd4e5da5Sopenharmony_ci         %63 = OpLoad %2 %57
736fd4e5da5Sopenharmony_ci               OpReturnValue %63
737fd4e5da5Sopenharmony_ci         %64 = OpLabel
738fd4e5da5Sopenharmony_ci         %65 = OpLoad %2 %57
739fd4e5da5Sopenharmony_ci         %66 = OpIAdd %2 %65 %11
740fd4e5da5Sopenharmony_ci               OpStore %57 %66
741fd4e5da5Sopenharmony_ci               OpBranch %62
742fd4e5da5Sopenharmony_ci               OpFunctionEnd
743fd4e5da5Sopenharmony_ci
744fd4e5da5Sopenharmony_ci; Function %67
745fd4e5da5Sopenharmony_ci         %67 = OpFunction %6 None %7
746fd4e5da5Sopenharmony_ci         %68 = OpLabel
747fd4e5da5Sopenharmony_ci               OpStore %14 %12
748fd4e5da5Sopenharmony_ci               OpReturn
749fd4e5da5Sopenharmony_ci               OpFunctionEnd
750fd4e5da5Sopenharmony_ci  )";
751fd4e5da5Sopenharmony_ci
752fd4e5da5Sopenharmony_ci  ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
753fd4e5da5Sopenharmony_ci                                               kConsoleMessageConsumer));
754fd4e5da5Sopenharmony_ci  ASSERT_TRUE(IsEqual(env, variant_shader, context.get()));
755fd4e5da5Sopenharmony_ci}
756fd4e5da5Sopenharmony_ci
757fd4e5da5Sopenharmony_ciTEST(TransformationInlineFunctionTest, HandlesOpPhisInTheSecondBlock) {
758fd4e5da5Sopenharmony_ci  std::string shader = R"(
759fd4e5da5Sopenharmony_ci               OpCapability Shader
760fd4e5da5Sopenharmony_ci          %1 = OpExtInstImport "GLSL.std.450"
761fd4e5da5Sopenharmony_ci               OpMemoryModel Logical GLSL450
762fd4e5da5Sopenharmony_ci               OpEntryPoint Fragment %4 "main"
763fd4e5da5Sopenharmony_ci               OpExecutionMode %4 OriginUpperLeft
764fd4e5da5Sopenharmony_ci          %2 = OpTypeVoid
765fd4e5da5Sopenharmony_ci          %3 = OpTypeFunction %2
766fd4e5da5Sopenharmony_ci         %10 = OpTypeInt 32 0
767fd4e5da5Sopenharmony_ci         %11 = OpUndef %10
768fd4e5da5Sopenharmony_ci          %4 = OpFunction %2 None %3
769fd4e5da5Sopenharmony_ci          %5 = OpLabel
770fd4e5da5Sopenharmony_ci          %6 = OpFunctionCall %2 %7
771fd4e5da5Sopenharmony_ci               OpBranch %14
772fd4e5da5Sopenharmony_ci         %14 = OpLabel
773fd4e5da5Sopenharmony_ci               OpReturn
774fd4e5da5Sopenharmony_ci               OpFunctionEnd
775fd4e5da5Sopenharmony_ci          %7 = OpFunction %2 None %3
776fd4e5da5Sopenharmony_ci          %8 = OpLabel
777fd4e5da5Sopenharmony_ci               OpBranch %13
778fd4e5da5Sopenharmony_ci         %13 = OpLabel
779fd4e5da5Sopenharmony_ci         %12 = OpPhi %10 %11 %8
780fd4e5da5Sopenharmony_ci               OpReturn
781fd4e5da5Sopenharmony_ci               OpFunctionEnd
782fd4e5da5Sopenharmony_ci  )";
783fd4e5da5Sopenharmony_ci
784fd4e5da5Sopenharmony_ci  const auto env = SPV_ENV_UNIVERSAL_1_3;
785fd4e5da5Sopenharmony_ci  const auto consumer = nullptr;
786fd4e5da5Sopenharmony_ci  const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption);
787fd4e5da5Sopenharmony_ci  spvtools::ValidatorOptions validator_options;
788fd4e5da5Sopenharmony_ci  ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
789fd4e5da5Sopenharmony_ci                                               kConsoleMessageConsumer));
790fd4e5da5Sopenharmony_ci  TransformationContext transformation_context(
791fd4e5da5Sopenharmony_ci      MakeUnique<FactManager>(context.get()), validator_options);
792fd4e5da5Sopenharmony_ci  TransformationInlineFunction transformation(6,
793fd4e5da5Sopenharmony_ci                                              {{{8, 20}, {13, 21}, {12, 22}}});
794fd4e5da5Sopenharmony_ci  ASSERT_TRUE(
795fd4e5da5Sopenharmony_ci      transformation.IsApplicable(context.get(), transformation_context));
796fd4e5da5Sopenharmony_ci  ApplyAndCheckFreshIds(transformation, context.get(), &transformation_context);
797fd4e5da5Sopenharmony_ci  ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
798fd4e5da5Sopenharmony_ci                                               kConsoleMessageConsumer));
799fd4e5da5Sopenharmony_ci
800fd4e5da5Sopenharmony_ci  std::string after_transformation = R"(
801fd4e5da5Sopenharmony_ci               OpCapability Shader
802fd4e5da5Sopenharmony_ci          %1 = OpExtInstImport "GLSL.std.450"
803fd4e5da5Sopenharmony_ci               OpMemoryModel Logical GLSL450
804fd4e5da5Sopenharmony_ci               OpEntryPoint Fragment %4 "main"
805fd4e5da5Sopenharmony_ci               OpExecutionMode %4 OriginUpperLeft
806fd4e5da5Sopenharmony_ci          %2 = OpTypeVoid
807fd4e5da5Sopenharmony_ci          %3 = OpTypeFunction %2
808fd4e5da5Sopenharmony_ci         %10 = OpTypeInt 32 0
809fd4e5da5Sopenharmony_ci         %11 = OpUndef %10
810fd4e5da5Sopenharmony_ci          %4 = OpFunction %2 None %3
811fd4e5da5Sopenharmony_ci          %5 = OpLabel
812fd4e5da5Sopenharmony_ci               OpBranch %21
813fd4e5da5Sopenharmony_ci         %21 = OpLabel
814fd4e5da5Sopenharmony_ci         %22 = OpPhi %10 %11 %5
815fd4e5da5Sopenharmony_ci               OpBranch %14
816fd4e5da5Sopenharmony_ci         %14 = OpLabel
817fd4e5da5Sopenharmony_ci               OpReturn
818fd4e5da5Sopenharmony_ci               OpFunctionEnd
819fd4e5da5Sopenharmony_ci          %7 = OpFunction %2 None %3
820fd4e5da5Sopenharmony_ci          %8 = OpLabel
821fd4e5da5Sopenharmony_ci               OpBranch %13
822fd4e5da5Sopenharmony_ci         %13 = OpLabel
823fd4e5da5Sopenharmony_ci         %12 = OpPhi %10 %11 %8
824fd4e5da5Sopenharmony_ci               OpReturn
825fd4e5da5Sopenharmony_ci               OpFunctionEnd
826fd4e5da5Sopenharmony_ci  )";
827fd4e5da5Sopenharmony_ci
828fd4e5da5Sopenharmony_ci  ASSERT_TRUE(IsEqual(env, after_transformation, context.get()));
829fd4e5da5Sopenharmony_ci}
830fd4e5da5Sopenharmony_ci
831fd4e5da5Sopenharmony_ciTEST(TransformationInlineFunctionTest, OverflowIds) {
832fd4e5da5Sopenharmony_ci  std::string reference_shader = R"(
833fd4e5da5Sopenharmony_ci               OpCapability Shader
834fd4e5da5Sopenharmony_ci          %1 = OpExtInstImport "GLSL.std.450"
835fd4e5da5Sopenharmony_ci               OpMemoryModel Logical GLSL450
836fd4e5da5Sopenharmony_ci               OpEntryPoint Vertex %39 "main"
837fd4e5da5Sopenharmony_ci
838fd4e5da5Sopenharmony_ci; Types
839fd4e5da5Sopenharmony_ci          %2 = OpTypeFloat 32
840fd4e5da5Sopenharmony_ci          %3 = OpTypeVector %2 4
841fd4e5da5Sopenharmony_ci          %4 = OpTypePointer Function %3
842fd4e5da5Sopenharmony_ci          %5 = OpTypeVoid
843fd4e5da5Sopenharmony_ci          %6 = OpTypeFunction %5
844fd4e5da5Sopenharmony_ci          %7 = OpTypeFunction %2 %4 %4
845fd4e5da5Sopenharmony_ci
846fd4e5da5Sopenharmony_ci; Constant scalars
847fd4e5da5Sopenharmony_ci          %8 = OpConstant %2 1
848fd4e5da5Sopenharmony_ci          %9 = OpConstant %2 2
849fd4e5da5Sopenharmony_ci         %10 = OpConstant %2 3
850fd4e5da5Sopenharmony_ci         %11 = OpConstant %2 4
851fd4e5da5Sopenharmony_ci         %12 = OpConstant %2 5
852fd4e5da5Sopenharmony_ci         %13 = OpConstant %2 6
853fd4e5da5Sopenharmony_ci         %14 = OpConstant %2 7
854fd4e5da5Sopenharmony_ci         %15 = OpConstant %2 8
855fd4e5da5Sopenharmony_ci
856fd4e5da5Sopenharmony_ci; Constant vectors
857fd4e5da5Sopenharmony_ci         %16 = OpConstantComposite %3 %8 %9 %10 %11
858fd4e5da5Sopenharmony_ci         %17 = OpConstantComposite %3 %12 %13 %14 %15
859fd4e5da5Sopenharmony_ci
860fd4e5da5Sopenharmony_ci; dot product function
861fd4e5da5Sopenharmony_ci         %18 = OpFunction %2 None %7
862fd4e5da5Sopenharmony_ci         %19 = OpFunctionParameter %4
863fd4e5da5Sopenharmony_ci         %20 = OpFunctionParameter %4
864fd4e5da5Sopenharmony_ci         %21 = OpLabel
865fd4e5da5Sopenharmony_ci         %22 = OpLoad %3 %19
866fd4e5da5Sopenharmony_ci         %23 = OpLoad %3 %20
867fd4e5da5Sopenharmony_ci         %24 = OpCompositeExtract %2 %22 0
868fd4e5da5Sopenharmony_ci         %25 = OpCompositeExtract %2 %23 0
869fd4e5da5Sopenharmony_ci         %26 = OpFMul %2 %24 %25
870fd4e5da5Sopenharmony_ci         %27 = OpCompositeExtract %2 %22 1
871fd4e5da5Sopenharmony_ci         %28 = OpCompositeExtract %2 %23 1
872fd4e5da5Sopenharmony_ci         %29 = OpFMul %2 %27 %28
873fd4e5da5Sopenharmony_ci               OpBranch %100
874fd4e5da5Sopenharmony_ci        %100 = OpLabel
875fd4e5da5Sopenharmony_ci         %30 = OpCompositeExtract %2 %22 2
876fd4e5da5Sopenharmony_ci         %31 = OpCompositeExtract %2 %23 2
877fd4e5da5Sopenharmony_ci         %32 = OpFMul %2 %30 %31
878fd4e5da5Sopenharmony_ci         %33 = OpCompositeExtract %2 %22 3
879fd4e5da5Sopenharmony_ci         %34 = OpCompositeExtract %2 %23 3
880fd4e5da5Sopenharmony_ci         %35 = OpFMul %2 %33 %34
881fd4e5da5Sopenharmony_ci         %36 = OpFAdd %2 %26 %29
882fd4e5da5Sopenharmony_ci         %37 = OpFAdd %2 %32 %36
883fd4e5da5Sopenharmony_ci         %38 = OpFAdd %2 %35 %37
884fd4e5da5Sopenharmony_ci               OpReturnValue %38
885fd4e5da5Sopenharmony_ci               OpFunctionEnd
886fd4e5da5Sopenharmony_ci
887fd4e5da5Sopenharmony_ci; main function
888fd4e5da5Sopenharmony_ci         %39 = OpFunction %5 None %6
889fd4e5da5Sopenharmony_ci         %40 = OpLabel
890fd4e5da5Sopenharmony_ci         %41 = OpVariable %4 Function
891fd4e5da5Sopenharmony_ci         %42 = OpVariable %4 Function
892fd4e5da5Sopenharmony_ci               OpStore %41 %16
893fd4e5da5Sopenharmony_ci               OpStore %42 %17
894fd4e5da5Sopenharmony_ci         %43 = OpFunctionCall %2 %18 %41 %42 ; dot product function call
895fd4e5da5Sopenharmony_ci               OpBranch %44
896fd4e5da5Sopenharmony_ci         %44 = OpLabel
897fd4e5da5Sopenharmony_ci               OpReturn
898fd4e5da5Sopenharmony_ci               OpFunctionEnd
899fd4e5da5Sopenharmony_ci  )";
900fd4e5da5Sopenharmony_ci
901fd4e5da5Sopenharmony_ci  const auto env = SPV_ENV_UNIVERSAL_1_5;
902fd4e5da5Sopenharmony_ci  const auto consumer = nullptr;
903fd4e5da5Sopenharmony_ci  const auto context =
904fd4e5da5Sopenharmony_ci      BuildModule(env, consumer, reference_shader, kFuzzAssembleOption);
905fd4e5da5Sopenharmony_ci  spvtools::ValidatorOptions validator_options;
906fd4e5da5Sopenharmony_ci  ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
907fd4e5da5Sopenharmony_ci                                               kConsoleMessageConsumer));
908fd4e5da5Sopenharmony_ci  auto overflow_ids_unique_ptr = MakeUnique<CounterOverflowIdSource>(1000);
909fd4e5da5Sopenharmony_ci  auto overflow_ids_ptr = overflow_ids_unique_ptr.get();
910fd4e5da5Sopenharmony_ci  TransformationContext transformation_context(
911fd4e5da5Sopenharmony_ci      MakeUnique<FactManager>(context.get()), validator_options,
912fd4e5da5Sopenharmony_ci      std::move(overflow_ids_unique_ptr));
913fd4e5da5Sopenharmony_ci  auto transformation = TransformationInlineFunction(43, {{22, 45},
914fd4e5da5Sopenharmony_ci                                                          {23, 46},
915fd4e5da5Sopenharmony_ci                                                          {24, 47},
916fd4e5da5Sopenharmony_ci                                                          {25, 48},
917fd4e5da5Sopenharmony_ci                                                          {26, 49},
918fd4e5da5Sopenharmony_ci                                                          {27, 50},
919fd4e5da5Sopenharmony_ci                                                          {28, 51},
920fd4e5da5Sopenharmony_ci                                                          {29, 52}});
921fd4e5da5Sopenharmony_ci
922fd4e5da5Sopenharmony_ci  // The following ids are left un-mapped; overflow ids will be required for
923fd4e5da5Sopenharmony_ci  // them: 30, 31, 32, 33, 34, 35, 36, 37, 38, 100
924fd4e5da5Sopenharmony_ci
925fd4e5da5Sopenharmony_ci  ASSERT_TRUE(
926fd4e5da5Sopenharmony_ci      transformation.IsApplicable(context.get(), transformation_context));
927fd4e5da5Sopenharmony_ci
928fd4e5da5Sopenharmony_ci  ApplyAndCheckFreshIds(transformation, context.get(), &transformation_context,
929fd4e5da5Sopenharmony_ci                        overflow_ids_ptr->GetIssuedOverflowIds());
930fd4e5da5Sopenharmony_ci
931fd4e5da5Sopenharmony_ci  std::string variant_shader = R"(
932fd4e5da5Sopenharmony_ci               OpCapability Shader
933fd4e5da5Sopenharmony_ci          %1 = OpExtInstImport "GLSL.std.450"
934fd4e5da5Sopenharmony_ci               OpMemoryModel Logical GLSL450
935fd4e5da5Sopenharmony_ci               OpEntryPoint Vertex %39 "main"
936fd4e5da5Sopenharmony_ci
937fd4e5da5Sopenharmony_ci; Types
938fd4e5da5Sopenharmony_ci          %2 = OpTypeFloat 32
939fd4e5da5Sopenharmony_ci          %3 = OpTypeVector %2 4
940fd4e5da5Sopenharmony_ci          %4 = OpTypePointer Function %3
941fd4e5da5Sopenharmony_ci          %5 = OpTypeVoid
942fd4e5da5Sopenharmony_ci          %6 = OpTypeFunction %5
943fd4e5da5Sopenharmony_ci          %7 = OpTypeFunction %2 %4 %4
944fd4e5da5Sopenharmony_ci
945fd4e5da5Sopenharmony_ci; Constant scalars
946fd4e5da5Sopenharmony_ci          %8 = OpConstant %2 1
947fd4e5da5Sopenharmony_ci          %9 = OpConstant %2 2
948fd4e5da5Sopenharmony_ci         %10 = OpConstant %2 3
949fd4e5da5Sopenharmony_ci         %11 = OpConstant %2 4
950fd4e5da5Sopenharmony_ci         %12 = OpConstant %2 5
951fd4e5da5Sopenharmony_ci         %13 = OpConstant %2 6
952fd4e5da5Sopenharmony_ci         %14 = OpConstant %2 7
953fd4e5da5Sopenharmony_ci         %15 = OpConstant %2 8
954fd4e5da5Sopenharmony_ci
955fd4e5da5Sopenharmony_ci; Constant vectors
956fd4e5da5Sopenharmony_ci         %16 = OpConstantComposite %3 %8 %9 %10 %11
957fd4e5da5Sopenharmony_ci         %17 = OpConstantComposite %3 %12 %13 %14 %15
958fd4e5da5Sopenharmony_ci
959fd4e5da5Sopenharmony_ci; dot product function
960fd4e5da5Sopenharmony_ci         %18 = OpFunction %2 None %7
961fd4e5da5Sopenharmony_ci         %19 = OpFunctionParameter %4
962fd4e5da5Sopenharmony_ci         %20 = OpFunctionParameter %4
963fd4e5da5Sopenharmony_ci         %21 = OpLabel
964fd4e5da5Sopenharmony_ci         %22 = OpLoad %3 %19
965fd4e5da5Sopenharmony_ci         %23 = OpLoad %3 %20
966fd4e5da5Sopenharmony_ci         %24 = OpCompositeExtract %2 %22 0
967fd4e5da5Sopenharmony_ci         %25 = OpCompositeExtract %2 %23 0
968fd4e5da5Sopenharmony_ci         %26 = OpFMul %2 %24 %25
969fd4e5da5Sopenharmony_ci         %27 = OpCompositeExtract %2 %22 1
970fd4e5da5Sopenharmony_ci         %28 = OpCompositeExtract %2 %23 1
971fd4e5da5Sopenharmony_ci         %29 = OpFMul %2 %27 %28
972fd4e5da5Sopenharmony_ci               OpBranch %100
973fd4e5da5Sopenharmony_ci        %100 = OpLabel
974fd4e5da5Sopenharmony_ci         %30 = OpCompositeExtract %2 %22 2
975fd4e5da5Sopenharmony_ci         %31 = OpCompositeExtract %2 %23 2
976fd4e5da5Sopenharmony_ci         %32 = OpFMul %2 %30 %31
977fd4e5da5Sopenharmony_ci         %33 = OpCompositeExtract %2 %22 3
978fd4e5da5Sopenharmony_ci         %34 = OpCompositeExtract %2 %23 3
979fd4e5da5Sopenharmony_ci         %35 = OpFMul %2 %33 %34
980fd4e5da5Sopenharmony_ci         %36 = OpFAdd %2 %26 %29
981fd4e5da5Sopenharmony_ci         %37 = OpFAdd %2 %32 %36
982fd4e5da5Sopenharmony_ci         %38 = OpFAdd %2 %35 %37
983fd4e5da5Sopenharmony_ci               OpReturnValue %38
984fd4e5da5Sopenharmony_ci               OpFunctionEnd
985fd4e5da5Sopenharmony_ci
986fd4e5da5Sopenharmony_ci; main function
987fd4e5da5Sopenharmony_ci         %39 = OpFunction %5 None %6
988fd4e5da5Sopenharmony_ci         %40 = OpLabel
989fd4e5da5Sopenharmony_ci         %41 = OpVariable %4 Function
990fd4e5da5Sopenharmony_ci         %42 = OpVariable %4 Function
991fd4e5da5Sopenharmony_ci               OpStore %41 %16
992fd4e5da5Sopenharmony_ci               OpStore %42 %17
993fd4e5da5Sopenharmony_ci         %45 = OpLoad %3 %41
994fd4e5da5Sopenharmony_ci         %46 = OpLoad %3 %42
995fd4e5da5Sopenharmony_ci         %47 = OpCompositeExtract %2 %45 0
996fd4e5da5Sopenharmony_ci         %48 = OpCompositeExtract %2 %46 0
997fd4e5da5Sopenharmony_ci         %49 = OpFMul %2 %47 %48
998fd4e5da5Sopenharmony_ci         %50 = OpCompositeExtract %2 %45 1
999fd4e5da5Sopenharmony_ci         %51 = OpCompositeExtract %2 %46 1
1000fd4e5da5Sopenharmony_ci         %52 = OpFMul %2 %50 %51
1001fd4e5da5Sopenharmony_ci               OpBranch %1000
1002fd4e5da5Sopenharmony_ci       %1000 = OpLabel
1003fd4e5da5Sopenharmony_ci       %1001 = OpCompositeExtract %2 %45 2
1004fd4e5da5Sopenharmony_ci       %1002 = OpCompositeExtract %2 %46 2
1005fd4e5da5Sopenharmony_ci       %1003 = OpFMul %2 %1001 %1002
1006fd4e5da5Sopenharmony_ci       %1004 = OpCompositeExtract %2 %45 3
1007fd4e5da5Sopenharmony_ci       %1005 = OpCompositeExtract %2 %46 3
1008fd4e5da5Sopenharmony_ci       %1006 = OpFMul %2 %1004 %1005
1009fd4e5da5Sopenharmony_ci       %1007 = OpFAdd %2 %49 %52
1010fd4e5da5Sopenharmony_ci       %1008 = OpFAdd %2 %1003 %1007
1011fd4e5da5Sopenharmony_ci       %1009 = OpFAdd %2 %1006 %1008
1012fd4e5da5Sopenharmony_ci         %43 = OpCopyObject %2 %1009
1013fd4e5da5Sopenharmony_ci               OpBranch %44
1014fd4e5da5Sopenharmony_ci         %44 = OpLabel
1015fd4e5da5Sopenharmony_ci               OpReturn
1016fd4e5da5Sopenharmony_ci               OpFunctionEnd
1017fd4e5da5Sopenharmony_ci  )";
1018fd4e5da5Sopenharmony_ci
1019fd4e5da5Sopenharmony_ci  ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
1020fd4e5da5Sopenharmony_ci                                               kConsoleMessageConsumer));
1021fd4e5da5Sopenharmony_ci  ASSERT_TRUE(IsEqual(env, variant_shader, context.get()));
1022fd4e5da5Sopenharmony_ci}
1023fd4e5da5Sopenharmony_ci
1024fd4e5da5Sopenharmony_ciTEST(TransformationInlineFunctionTest, OpPhiInBlockFollowingCall) {
1025fd4e5da5Sopenharmony_ci  // This test checks that if the block after the inlined function call has an
1026fd4e5da5Sopenharmony_ci  // OpPhi instruction and the called function contains multiple blocks then the
1027fd4e5da5Sopenharmony_ci  // OpPhi instruction gets updated to refer to the return block of the inlined
1028fd4e5da5Sopenharmony_ci  // function, since the block containing the call will no longer be a
1029fd4e5da5Sopenharmony_ci  // predecessor.
1030fd4e5da5Sopenharmony_ci
1031fd4e5da5Sopenharmony_ci  std::string reference_shader = R"(
1032fd4e5da5Sopenharmony_ci               OpCapability Shader
1033fd4e5da5Sopenharmony_ci          %1 = OpExtInstImport "GLSL.std.450"
1034fd4e5da5Sopenharmony_ci               OpMemoryModel Logical GLSL450
1035fd4e5da5Sopenharmony_ci               OpEntryPoint Fragment %4 "main"
1036fd4e5da5Sopenharmony_ci               OpExecutionMode %4 OriginUpperLeft
1037fd4e5da5Sopenharmony_ci               OpSource ESSL 320
1038fd4e5da5Sopenharmony_ci          %2 = OpTypeVoid
1039fd4e5da5Sopenharmony_ci          %3 = OpTypeFunction %2
1040fd4e5da5Sopenharmony_ci         %13 = OpTypeBool
1041fd4e5da5Sopenharmony_ci         %14 = OpConstantTrue %13
1042fd4e5da5Sopenharmony_ci          %4 = OpFunction %2 None %3
1043fd4e5da5Sopenharmony_ci          %5 = OpLabel
1044fd4e5da5Sopenharmony_ci               OpBranch %10
1045fd4e5da5Sopenharmony_ci         %10 = OpLabel
1046fd4e5da5Sopenharmony_ci          %8 = OpFunctionCall %2 %6
1047fd4e5da5Sopenharmony_ci               OpBranch %11
1048fd4e5da5Sopenharmony_ci         %11 = OpLabel
1049fd4e5da5Sopenharmony_ci         %12 = OpPhi %13 %14 %10
1050fd4e5da5Sopenharmony_ci               OpReturn
1051fd4e5da5Sopenharmony_ci               OpFunctionEnd
1052fd4e5da5Sopenharmony_ci          %6 = OpFunction %2 None %3
1053fd4e5da5Sopenharmony_ci          %7 = OpLabel
1054fd4e5da5Sopenharmony_ci               OpBranch %20
1055fd4e5da5Sopenharmony_ci         %20 = OpLabel
1056fd4e5da5Sopenharmony_ci               OpReturn
1057fd4e5da5Sopenharmony_ci               OpFunctionEnd
1058fd4e5da5Sopenharmony_ci  )";
1059fd4e5da5Sopenharmony_ci
1060fd4e5da5Sopenharmony_ci  const auto env = SPV_ENV_UNIVERSAL_1_5;
1061fd4e5da5Sopenharmony_ci  const auto consumer = nullptr;
1062fd4e5da5Sopenharmony_ci  const auto context =
1063fd4e5da5Sopenharmony_ci      BuildModule(env, consumer, reference_shader, kFuzzAssembleOption);
1064fd4e5da5Sopenharmony_ci  spvtools::ValidatorOptions validator_options;
1065fd4e5da5Sopenharmony_ci  ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
1066fd4e5da5Sopenharmony_ci                                               kConsoleMessageConsumer));
1067fd4e5da5Sopenharmony_ci  TransformationContext transformation_context(
1068fd4e5da5Sopenharmony_ci      MakeUnique<FactManager>(context.get()), validator_options);
1069fd4e5da5Sopenharmony_ci  auto transformation = TransformationInlineFunction(8, {{7, 100}, {20, 101}});
1070fd4e5da5Sopenharmony_ci
1071fd4e5da5Sopenharmony_ci  ASSERT_TRUE(
1072fd4e5da5Sopenharmony_ci      transformation.IsApplicable(context.get(), transformation_context));
1073fd4e5da5Sopenharmony_ci
1074fd4e5da5Sopenharmony_ci  ApplyAndCheckFreshIds(transformation, context.get(), &transformation_context);
1075fd4e5da5Sopenharmony_ci
1076fd4e5da5Sopenharmony_ci  ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
1077fd4e5da5Sopenharmony_ci                                               kConsoleMessageConsumer));
1078fd4e5da5Sopenharmony_ci
1079fd4e5da5Sopenharmony_ci  std::string variant_shader = R"(
1080fd4e5da5Sopenharmony_ci               OpCapability Shader
1081fd4e5da5Sopenharmony_ci          %1 = OpExtInstImport "GLSL.std.450"
1082fd4e5da5Sopenharmony_ci               OpMemoryModel Logical GLSL450
1083fd4e5da5Sopenharmony_ci               OpEntryPoint Fragment %4 "main"
1084fd4e5da5Sopenharmony_ci               OpExecutionMode %4 OriginUpperLeft
1085fd4e5da5Sopenharmony_ci               OpSource ESSL 320
1086fd4e5da5Sopenharmony_ci          %2 = OpTypeVoid
1087fd4e5da5Sopenharmony_ci          %3 = OpTypeFunction %2
1088fd4e5da5Sopenharmony_ci         %13 = OpTypeBool
1089fd4e5da5Sopenharmony_ci         %14 = OpConstantTrue %13
1090fd4e5da5Sopenharmony_ci          %4 = OpFunction %2 None %3
1091fd4e5da5Sopenharmony_ci          %5 = OpLabel
1092fd4e5da5Sopenharmony_ci               OpBranch %10
1093fd4e5da5Sopenharmony_ci         %10 = OpLabel
1094fd4e5da5Sopenharmony_ci               OpBranch %101
1095fd4e5da5Sopenharmony_ci        %101 = OpLabel
1096fd4e5da5Sopenharmony_ci               OpBranch %11
1097fd4e5da5Sopenharmony_ci         %11 = OpLabel
1098fd4e5da5Sopenharmony_ci         %12 = OpPhi %13 %14 %101
1099fd4e5da5Sopenharmony_ci               OpReturn
1100fd4e5da5Sopenharmony_ci               OpFunctionEnd
1101fd4e5da5Sopenharmony_ci          %6 = OpFunction %2 None %3
1102fd4e5da5Sopenharmony_ci          %7 = OpLabel
1103fd4e5da5Sopenharmony_ci               OpBranch %20
1104fd4e5da5Sopenharmony_ci         %20 = OpLabel
1105fd4e5da5Sopenharmony_ci               OpReturn
1106fd4e5da5Sopenharmony_ci               OpFunctionEnd
1107fd4e5da5Sopenharmony_ci  )";
1108fd4e5da5Sopenharmony_ci
1109fd4e5da5Sopenharmony_ci  ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
1110fd4e5da5Sopenharmony_ci                                               kConsoleMessageConsumer));
1111fd4e5da5Sopenharmony_ci  ASSERT_TRUE(IsEqual(env, variant_shader, context.get()));
1112fd4e5da5Sopenharmony_ci}
1113fd4e5da5Sopenharmony_ci
1114fd4e5da5Sopenharmony_ci}  // namespace
1115fd4e5da5Sopenharmony_ci}  // namespace fuzz
1116fd4e5da5Sopenharmony_ci}  // namespace spvtools
1117