1fd4e5da5Sopenharmony_ci// Copyright (c) 2020 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_equation_instruction.h"
16fd4e5da5Sopenharmony_ci
17fd4e5da5Sopenharmony_ci#include "gtest/gtest.h"
18fd4e5da5Sopenharmony_ci#include "source/fuzz/fuzzer_util.h"
19fd4e5da5Sopenharmony_ci#include "source/fuzz/instruction_descriptor.h"
20fd4e5da5Sopenharmony_ci#include "test/fuzz/fuzz_test_util.h"
21fd4e5da5Sopenharmony_ci
22fd4e5da5Sopenharmony_cinamespace spvtools {
23fd4e5da5Sopenharmony_cinamespace fuzz {
24fd4e5da5Sopenharmony_cinamespace {
25fd4e5da5Sopenharmony_ci
26fd4e5da5Sopenharmony_ciTEST(TransformationEquationInstructionTest, SignedNegate) {
27fd4e5da5Sopenharmony_ci  std::string shader = R"(
28fd4e5da5Sopenharmony_ci               OpCapability Shader
29fd4e5da5Sopenharmony_ci          %1 = OpExtInstImport "GLSL.std.450"
30fd4e5da5Sopenharmony_ci               OpMemoryModel Logical GLSL450
31fd4e5da5Sopenharmony_ci               OpEntryPoint Fragment %12 "main"
32fd4e5da5Sopenharmony_ci               OpExecutionMode %12 OriginUpperLeft
33fd4e5da5Sopenharmony_ci               OpSource ESSL 310
34fd4e5da5Sopenharmony_ci          %2 = OpTypeVoid
35fd4e5da5Sopenharmony_ci          %3 = OpTypeFunction %2
36fd4e5da5Sopenharmony_ci          %6 = OpTypeInt 32 1
37fd4e5da5Sopenharmony_ci          %7 = OpConstant %6 24
38fd4e5da5Sopenharmony_ci         %40 = OpTypeBool
39fd4e5da5Sopenharmony_ci         %41 = OpConstantTrue %40
40fd4e5da5Sopenharmony_ci         %20 = OpUndef %6
41fd4e5da5Sopenharmony_ci         %12 = OpFunction %2 None %3
42fd4e5da5Sopenharmony_ci         %13 = OpLabel
43fd4e5da5Sopenharmony_ci         %30 = OpCopyObject %6 %7
44fd4e5da5Sopenharmony_ci               OpReturn
45fd4e5da5Sopenharmony_ci               OpFunctionEnd
46fd4e5da5Sopenharmony_ci  )";
47fd4e5da5Sopenharmony_ci
48fd4e5da5Sopenharmony_ci  const auto env = SPV_ENV_UNIVERSAL_1_3;
49fd4e5da5Sopenharmony_ci  const auto consumer = nullptr;
50fd4e5da5Sopenharmony_ci  const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption);
51fd4e5da5Sopenharmony_ci  spvtools::ValidatorOptions validator_options;
52fd4e5da5Sopenharmony_ci  ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
53fd4e5da5Sopenharmony_ci                                               kConsoleMessageConsumer));
54fd4e5da5Sopenharmony_ci  TransformationContext transformation_context(
55fd4e5da5Sopenharmony_ci      MakeUnique<FactManager>(context.get()), validator_options);
56fd4e5da5Sopenharmony_ci  protobufs::InstructionDescriptor return_instruction =
57fd4e5da5Sopenharmony_ci      MakeInstructionDescriptor(13, spv::Op::OpReturn, 0);
58fd4e5da5Sopenharmony_ci
59fd4e5da5Sopenharmony_ci  // Bad: id already in use.
60fd4e5da5Sopenharmony_ci  ASSERT_FALSE(TransformationEquationInstruction(7, spv::Op::OpSNegate, {7},
61fd4e5da5Sopenharmony_ci                                                 return_instruction)
62fd4e5da5Sopenharmony_ci                   .IsApplicable(context.get(), transformation_context));
63fd4e5da5Sopenharmony_ci
64fd4e5da5Sopenharmony_ci  // Bad: identified instruction does not exist.
65fd4e5da5Sopenharmony_ci  ASSERT_FALSE(TransformationEquationInstruction(
66fd4e5da5Sopenharmony_ci                   14, spv::Op::OpSNegate, {7},
67fd4e5da5Sopenharmony_ci                   MakeInstructionDescriptor(13, spv::Op::OpLoad, 0))
68fd4e5da5Sopenharmony_ci                   .IsApplicable(context.get(), transformation_context));
69fd4e5da5Sopenharmony_ci
70fd4e5da5Sopenharmony_ci  // Bad: id 100 does not exist
71fd4e5da5Sopenharmony_ci  ASSERT_FALSE(TransformationEquationInstruction(14, spv::Op::OpSNegate, {100},
72fd4e5da5Sopenharmony_ci                                                 return_instruction)
73fd4e5da5Sopenharmony_ci                   .IsApplicable(context.get(), transformation_context));
74fd4e5da5Sopenharmony_ci
75fd4e5da5Sopenharmony_ci  // Bad: id 20 is an OpUndef
76fd4e5da5Sopenharmony_ci  ASSERT_FALSE(TransformationEquationInstruction(14, spv::Op::OpSNegate, {20},
77fd4e5da5Sopenharmony_ci                                                 return_instruction)
78fd4e5da5Sopenharmony_ci                   .IsApplicable(context.get(), transformation_context));
79fd4e5da5Sopenharmony_ci
80fd4e5da5Sopenharmony_ci  // Bad: id 30 is not available right before its definition
81fd4e5da5Sopenharmony_ci  ASSERT_FALSE(TransformationEquationInstruction(
82fd4e5da5Sopenharmony_ci                   14, spv::Op::OpSNegate, {30},
83fd4e5da5Sopenharmony_ci                   MakeInstructionDescriptor(30, spv::Op::OpCopyObject, 0))
84fd4e5da5Sopenharmony_ci                   .IsApplicable(context.get(), transformation_context));
85fd4e5da5Sopenharmony_ci
86fd4e5da5Sopenharmony_ci  // Bad: too many arguments to OpSNegate.
87fd4e5da5Sopenharmony_ci  ASSERT_FALSE(TransformationEquationInstruction(14, spv::Op::OpSNegate, {7, 7},
88fd4e5da5Sopenharmony_ci                                                 return_instruction)
89fd4e5da5Sopenharmony_ci                   .IsApplicable(context.get(), transformation_context));
90fd4e5da5Sopenharmony_ci
91fd4e5da5Sopenharmony_ci  // Bad: 40 is a type id.
92fd4e5da5Sopenharmony_ci  ASSERT_FALSE(TransformationEquationInstruction(14, spv::Op::OpSNegate, {40},
93fd4e5da5Sopenharmony_ci                                                 return_instruction)
94fd4e5da5Sopenharmony_ci                   .IsApplicable(context.get(), transformation_context));
95fd4e5da5Sopenharmony_ci
96fd4e5da5Sopenharmony_ci  // Bad: wrong type of argument to OpSNegate.
97fd4e5da5Sopenharmony_ci  ASSERT_FALSE(TransformationEquationInstruction(14, spv::Op::OpSNegate, {41},
98fd4e5da5Sopenharmony_ci                                                 return_instruction)
99fd4e5da5Sopenharmony_ci                   .IsApplicable(context.get(), transformation_context));
100fd4e5da5Sopenharmony_ci
101fd4e5da5Sopenharmony_ci  auto transformation1 = TransformationEquationInstruction(
102fd4e5da5Sopenharmony_ci      14, spv::Op::OpSNegate, {7}, return_instruction);
103fd4e5da5Sopenharmony_ci  ASSERT_TRUE(
104fd4e5da5Sopenharmony_ci      transformation1.IsApplicable(context.get(), transformation_context));
105fd4e5da5Sopenharmony_ci  ASSERT_EQ(nullptr, context->get_def_use_mgr()->GetDef(14));
106fd4e5da5Sopenharmony_ci  ASSERT_EQ(nullptr, context->get_instr_block(14));
107fd4e5da5Sopenharmony_ci  ApplyAndCheckFreshIds(transformation1, context.get(),
108fd4e5da5Sopenharmony_ci                        &transformation_context);
109fd4e5da5Sopenharmony_ci  ASSERT_EQ(spv::Op::OpSNegate,
110fd4e5da5Sopenharmony_ci            context->get_def_use_mgr()->GetDef(14)->opcode());
111fd4e5da5Sopenharmony_ci  ASSERT_EQ(13, context->get_instr_block(14)->id());
112fd4e5da5Sopenharmony_ci  ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
113fd4e5da5Sopenharmony_ci                                               kConsoleMessageConsumer));
114fd4e5da5Sopenharmony_ci
115fd4e5da5Sopenharmony_ci  auto transformation2 = TransformationEquationInstruction(
116fd4e5da5Sopenharmony_ci      15, spv::Op::OpSNegate, {14}, return_instruction);
117fd4e5da5Sopenharmony_ci  ASSERT_TRUE(
118fd4e5da5Sopenharmony_ci      transformation2.IsApplicable(context.get(), transformation_context));
119fd4e5da5Sopenharmony_ci  ApplyAndCheckFreshIds(transformation2, context.get(),
120fd4e5da5Sopenharmony_ci                        &transformation_context);
121fd4e5da5Sopenharmony_ci  ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
122fd4e5da5Sopenharmony_ci                                               kConsoleMessageConsumer));
123fd4e5da5Sopenharmony_ci
124fd4e5da5Sopenharmony_ci  ASSERT_TRUE(transformation_context.GetFactManager()->IsSynonymous(
125fd4e5da5Sopenharmony_ci      MakeDataDescriptor(15, {}), MakeDataDescriptor(7, {})));
126fd4e5da5Sopenharmony_ci
127fd4e5da5Sopenharmony_ci  std::string after_transformation = R"(
128fd4e5da5Sopenharmony_ci               OpCapability Shader
129fd4e5da5Sopenharmony_ci          %1 = OpExtInstImport "GLSL.std.450"
130fd4e5da5Sopenharmony_ci               OpMemoryModel Logical GLSL450
131fd4e5da5Sopenharmony_ci               OpEntryPoint Fragment %12 "main"
132fd4e5da5Sopenharmony_ci               OpExecutionMode %12 OriginUpperLeft
133fd4e5da5Sopenharmony_ci               OpSource ESSL 310
134fd4e5da5Sopenharmony_ci          %2 = OpTypeVoid
135fd4e5da5Sopenharmony_ci          %3 = OpTypeFunction %2
136fd4e5da5Sopenharmony_ci          %6 = OpTypeInt 32 1
137fd4e5da5Sopenharmony_ci          %7 = OpConstant %6 24
138fd4e5da5Sopenharmony_ci         %40 = OpTypeBool
139fd4e5da5Sopenharmony_ci         %41 = OpConstantTrue %40
140fd4e5da5Sopenharmony_ci         %20 = OpUndef %6
141fd4e5da5Sopenharmony_ci         %12 = OpFunction %2 None %3
142fd4e5da5Sopenharmony_ci         %13 = OpLabel
143fd4e5da5Sopenharmony_ci         %30 = OpCopyObject %6 %7
144fd4e5da5Sopenharmony_ci         %14 = OpSNegate %6 %7
145fd4e5da5Sopenharmony_ci         %15 = OpSNegate %6 %14
146fd4e5da5Sopenharmony_ci               OpReturn
147fd4e5da5Sopenharmony_ci               OpFunctionEnd
148fd4e5da5Sopenharmony_ci  )";
149fd4e5da5Sopenharmony_ci
150fd4e5da5Sopenharmony_ci  ASSERT_TRUE(IsEqual(env, after_transformation, context.get()));
151fd4e5da5Sopenharmony_ci}
152fd4e5da5Sopenharmony_ci
153fd4e5da5Sopenharmony_ciTEST(TransformationEquationInstructionTest, LogicalNot) {
154fd4e5da5Sopenharmony_ci  std::string shader = R"(
155fd4e5da5Sopenharmony_ci               OpCapability Shader
156fd4e5da5Sopenharmony_ci          %1 = OpExtInstImport "GLSL.std.450"
157fd4e5da5Sopenharmony_ci               OpMemoryModel Logical GLSL450
158fd4e5da5Sopenharmony_ci               OpEntryPoint Fragment %12 "main"
159fd4e5da5Sopenharmony_ci               OpExecutionMode %12 OriginUpperLeft
160fd4e5da5Sopenharmony_ci               OpSource ESSL 310
161fd4e5da5Sopenharmony_ci          %2 = OpTypeVoid
162fd4e5da5Sopenharmony_ci          %3 = OpTypeFunction %2
163fd4e5da5Sopenharmony_ci          %6 = OpTypeBool
164fd4e5da5Sopenharmony_ci          %7 = OpConstantTrue %6
165fd4e5da5Sopenharmony_ci         %20 = OpTypeInt 32 0
166fd4e5da5Sopenharmony_ci         %21 = OpConstant %20 5
167fd4e5da5Sopenharmony_ci         %12 = OpFunction %2 None %3
168fd4e5da5Sopenharmony_ci         %13 = OpLabel
169fd4e5da5Sopenharmony_ci               OpReturn
170fd4e5da5Sopenharmony_ci               OpFunctionEnd
171fd4e5da5Sopenharmony_ci  )";
172fd4e5da5Sopenharmony_ci
173fd4e5da5Sopenharmony_ci  const auto env = SPV_ENV_UNIVERSAL_1_3;
174fd4e5da5Sopenharmony_ci  const auto consumer = nullptr;
175fd4e5da5Sopenharmony_ci  const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption);
176fd4e5da5Sopenharmony_ci  spvtools::ValidatorOptions validator_options;
177fd4e5da5Sopenharmony_ci  ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
178fd4e5da5Sopenharmony_ci                                               kConsoleMessageConsumer));
179fd4e5da5Sopenharmony_ci  TransformationContext transformation_context(
180fd4e5da5Sopenharmony_ci      MakeUnique<FactManager>(context.get()), validator_options);
181fd4e5da5Sopenharmony_ci  protobufs::InstructionDescriptor return_instruction =
182fd4e5da5Sopenharmony_ci      MakeInstructionDescriptor(13, spv::Op::OpReturn, 0);
183fd4e5da5Sopenharmony_ci
184fd4e5da5Sopenharmony_ci  // Bad: too few arguments to OpLogicalNot.
185fd4e5da5Sopenharmony_ci  ASSERT_FALSE(TransformationEquationInstruction(14, spv::Op::OpLogicalNot, {},
186fd4e5da5Sopenharmony_ci                                                 return_instruction)
187fd4e5da5Sopenharmony_ci                   .IsApplicable(context.get(), transformation_context));
188fd4e5da5Sopenharmony_ci
189fd4e5da5Sopenharmony_ci  // Bad: 6 is a type id.
190fd4e5da5Sopenharmony_ci  ASSERT_FALSE(TransformationEquationInstruction(14, spv::Op::OpLogicalNot, {6},
191fd4e5da5Sopenharmony_ci                                                 return_instruction)
192fd4e5da5Sopenharmony_ci                   .IsApplicable(context.get(), transformation_context));
193fd4e5da5Sopenharmony_ci
194fd4e5da5Sopenharmony_ci  // Bad: wrong type of argument to OpLogicalNot.
195fd4e5da5Sopenharmony_ci  ASSERT_FALSE(TransformationEquationInstruction(14, spv::Op::OpLogicalNot,
196fd4e5da5Sopenharmony_ci                                                 {21}, return_instruction)
197fd4e5da5Sopenharmony_ci                   .IsApplicable(context.get(), transformation_context));
198fd4e5da5Sopenharmony_ci
199fd4e5da5Sopenharmony_ci  auto transformation1 = TransformationEquationInstruction(
200fd4e5da5Sopenharmony_ci      14, spv::Op::OpLogicalNot, {7}, return_instruction);
201fd4e5da5Sopenharmony_ci  ASSERT_TRUE(
202fd4e5da5Sopenharmony_ci      transformation1.IsApplicable(context.get(), transformation_context));
203fd4e5da5Sopenharmony_ci  ApplyAndCheckFreshIds(transformation1, context.get(),
204fd4e5da5Sopenharmony_ci                        &transformation_context);
205fd4e5da5Sopenharmony_ci  ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
206fd4e5da5Sopenharmony_ci                                               kConsoleMessageConsumer));
207fd4e5da5Sopenharmony_ci
208fd4e5da5Sopenharmony_ci  auto transformation2 = TransformationEquationInstruction(
209fd4e5da5Sopenharmony_ci      15, spv::Op::OpLogicalNot, {14}, return_instruction);
210fd4e5da5Sopenharmony_ci  ASSERT_TRUE(
211fd4e5da5Sopenharmony_ci      transformation2.IsApplicable(context.get(), transformation_context));
212fd4e5da5Sopenharmony_ci  ApplyAndCheckFreshIds(transformation2, context.get(),
213fd4e5da5Sopenharmony_ci                        &transformation_context);
214fd4e5da5Sopenharmony_ci  ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
215fd4e5da5Sopenharmony_ci                                               kConsoleMessageConsumer));
216fd4e5da5Sopenharmony_ci
217fd4e5da5Sopenharmony_ci  ASSERT_TRUE(transformation_context.GetFactManager()->IsSynonymous(
218fd4e5da5Sopenharmony_ci      MakeDataDescriptor(15, {}), MakeDataDescriptor(7, {})));
219fd4e5da5Sopenharmony_ci
220fd4e5da5Sopenharmony_ci  std::string after_transformation = R"(
221fd4e5da5Sopenharmony_ci               OpCapability Shader
222fd4e5da5Sopenharmony_ci          %1 = OpExtInstImport "GLSL.std.450"
223fd4e5da5Sopenharmony_ci               OpMemoryModel Logical GLSL450
224fd4e5da5Sopenharmony_ci               OpEntryPoint Fragment %12 "main"
225fd4e5da5Sopenharmony_ci               OpExecutionMode %12 OriginUpperLeft
226fd4e5da5Sopenharmony_ci               OpSource ESSL 310
227fd4e5da5Sopenharmony_ci          %2 = OpTypeVoid
228fd4e5da5Sopenharmony_ci          %3 = OpTypeFunction %2
229fd4e5da5Sopenharmony_ci          %6 = OpTypeBool
230fd4e5da5Sopenharmony_ci          %7 = OpConstantTrue %6
231fd4e5da5Sopenharmony_ci         %20 = OpTypeInt 32 0
232fd4e5da5Sopenharmony_ci         %21 = OpConstant %20 5
233fd4e5da5Sopenharmony_ci         %12 = OpFunction %2 None %3
234fd4e5da5Sopenharmony_ci         %13 = OpLabel
235fd4e5da5Sopenharmony_ci         %14 = OpLogicalNot %6 %7
236fd4e5da5Sopenharmony_ci         %15 = OpLogicalNot %6 %14
237fd4e5da5Sopenharmony_ci               OpReturn
238fd4e5da5Sopenharmony_ci               OpFunctionEnd
239fd4e5da5Sopenharmony_ci  )";
240fd4e5da5Sopenharmony_ci
241fd4e5da5Sopenharmony_ci  ASSERT_TRUE(IsEqual(env, after_transformation, context.get()));
242fd4e5da5Sopenharmony_ci}
243fd4e5da5Sopenharmony_ci
244fd4e5da5Sopenharmony_ciTEST(TransformationEquationInstructionTest, AddSubNegate1) {
245fd4e5da5Sopenharmony_ci  std::string shader = R"(
246fd4e5da5Sopenharmony_ci               OpCapability Shader
247fd4e5da5Sopenharmony_ci          %1 = OpExtInstImport "GLSL.std.450"
248fd4e5da5Sopenharmony_ci               OpMemoryModel Logical GLSL450
249fd4e5da5Sopenharmony_ci               OpEntryPoint Fragment %12 "main"
250fd4e5da5Sopenharmony_ci               OpExecutionMode %12 OriginUpperLeft
251fd4e5da5Sopenharmony_ci               OpSource ESSL 310
252fd4e5da5Sopenharmony_ci          %2 = OpTypeVoid
253fd4e5da5Sopenharmony_ci          %3 = OpTypeFunction %2
254fd4e5da5Sopenharmony_ci          %6 = OpTypeInt 32 1
255fd4e5da5Sopenharmony_ci         %30 = OpTypeVector %6 3
256fd4e5da5Sopenharmony_ci         %15 = OpConstant %6 24
257fd4e5da5Sopenharmony_ci         %16 = OpConstant %6 37
258fd4e5da5Sopenharmony_ci         %31 = OpConstantComposite %30 %15 %16 %15
259fd4e5da5Sopenharmony_ci         %33 = OpTypeBool
260fd4e5da5Sopenharmony_ci         %32 = OpConstantTrue %33
261fd4e5da5Sopenharmony_ci         %12 = OpFunction %2 None %3
262fd4e5da5Sopenharmony_ci         %13 = OpLabel
263fd4e5da5Sopenharmony_ci               OpReturn
264fd4e5da5Sopenharmony_ci               OpFunctionEnd
265fd4e5da5Sopenharmony_ci  )";
266fd4e5da5Sopenharmony_ci
267fd4e5da5Sopenharmony_ci  const auto env = SPV_ENV_UNIVERSAL_1_3;
268fd4e5da5Sopenharmony_ci  const auto consumer = nullptr;
269fd4e5da5Sopenharmony_ci  const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption);
270fd4e5da5Sopenharmony_ci  spvtools::ValidatorOptions validator_options;
271fd4e5da5Sopenharmony_ci  ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
272fd4e5da5Sopenharmony_ci                                               kConsoleMessageConsumer));
273fd4e5da5Sopenharmony_ci  TransformationContext transformation_context(
274fd4e5da5Sopenharmony_ci      MakeUnique<FactManager>(context.get()), validator_options);
275fd4e5da5Sopenharmony_ci  protobufs::InstructionDescriptor return_instruction =
276fd4e5da5Sopenharmony_ci      MakeInstructionDescriptor(13, spv::Op::OpReturn, 0);
277fd4e5da5Sopenharmony_ci
278fd4e5da5Sopenharmony_ci  // Bad: too many arguments to OpIAdd.
279fd4e5da5Sopenharmony_ci  ASSERT_FALSE(TransformationEquationInstruction(
280fd4e5da5Sopenharmony_ci                   14, spv::Op::OpIAdd, {15, 16, 16}, return_instruction)
281fd4e5da5Sopenharmony_ci                   .IsApplicable(context.get(), transformation_context));
282fd4e5da5Sopenharmony_ci  // Bad: boolean argument to OpIAdd.
283fd4e5da5Sopenharmony_ci  ASSERT_FALSE(TransformationEquationInstruction(14, spv::Op::OpIAdd, {15, 32},
284fd4e5da5Sopenharmony_ci                                                 return_instruction)
285fd4e5da5Sopenharmony_ci                   .IsApplicable(context.get(), transformation_context));
286fd4e5da5Sopenharmony_ci  // Bad: type as argument to OpIAdd.
287fd4e5da5Sopenharmony_ci  ASSERT_FALSE(TransformationEquationInstruction(14, spv::Op::OpIAdd, {33, 16},
288fd4e5da5Sopenharmony_ci                                                 return_instruction)
289fd4e5da5Sopenharmony_ci                   .IsApplicable(context.get(), transformation_context));
290fd4e5da5Sopenharmony_ci  // Bad: arguments of mismatched widths
291fd4e5da5Sopenharmony_ci  ASSERT_FALSE(TransformationEquationInstruction(14, spv::Op::OpIAdd, {15, 31},
292fd4e5da5Sopenharmony_ci                                                 return_instruction)
293fd4e5da5Sopenharmony_ci                   .IsApplicable(context.get(), transformation_context));
294fd4e5da5Sopenharmony_ci  // Bad: arguments of mismatched widths
295fd4e5da5Sopenharmony_ci  ASSERT_FALSE(TransformationEquationInstruction(14, spv::Op::OpIAdd, {31, 15},
296fd4e5da5Sopenharmony_ci                                                 return_instruction)
297fd4e5da5Sopenharmony_ci                   .IsApplicable(context.get(), transformation_context));
298fd4e5da5Sopenharmony_ci
299fd4e5da5Sopenharmony_ci  auto transformation1 = TransformationEquationInstruction(
300fd4e5da5Sopenharmony_ci      14, spv::Op::OpIAdd, {15, 16}, return_instruction);
301fd4e5da5Sopenharmony_ci  ASSERT_TRUE(
302fd4e5da5Sopenharmony_ci      transformation1.IsApplicable(context.get(), transformation_context));
303fd4e5da5Sopenharmony_ci  ApplyAndCheckFreshIds(transformation1, context.get(),
304fd4e5da5Sopenharmony_ci                        &transformation_context);
305fd4e5da5Sopenharmony_ci  ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
306fd4e5da5Sopenharmony_ci                                               kConsoleMessageConsumer));
307fd4e5da5Sopenharmony_ci
308fd4e5da5Sopenharmony_ci  auto transformation2 = TransformationEquationInstruction(
309fd4e5da5Sopenharmony_ci      19, spv::Op::OpISub, {14, 16}, return_instruction);
310fd4e5da5Sopenharmony_ci  ASSERT_TRUE(
311fd4e5da5Sopenharmony_ci      transformation2.IsApplicable(context.get(), transformation_context));
312fd4e5da5Sopenharmony_ci  ApplyAndCheckFreshIds(transformation2, context.get(),
313fd4e5da5Sopenharmony_ci                        &transformation_context);
314fd4e5da5Sopenharmony_ci  ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
315fd4e5da5Sopenharmony_ci                                               kConsoleMessageConsumer));
316fd4e5da5Sopenharmony_ci  ASSERT_TRUE(transformation_context.GetFactManager()->IsSynonymous(
317fd4e5da5Sopenharmony_ci      MakeDataDescriptor(15, {}), MakeDataDescriptor(19, {})));
318fd4e5da5Sopenharmony_ci
319fd4e5da5Sopenharmony_ci  auto transformation3 = TransformationEquationInstruction(
320fd4e5da5Sopenharmony_ci      20, spv::Op::OpISub, {14, 15}, return_instruction);
321fd4e5da5Sopenharmony_ci  ASSERT_TRUE(
322fd4e5da5Sopenharmony_ci      transformation3.IsApplicable(context.get(), transformation_context));
323fd4e5da5Sopenharmony_ci  ApplyAndCheckFreshIds(transformation3, context.get(),
324fd4e5da5Sopenharmony_ci                        &transformation_context);
325fd4e5da5Sopenharmony_ci  ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
326fd4e5da5Sopenharmony_ci                                               kConsoleMessageConsumer));
327fd4e5da5Sopenharmony_ci  ASSERT_TRUE(transformation_context.GetFactManager()->IsSynonymous(
328fd4e5da5Sopenharmony_ci      MakeDataDescriptor(20, {}), MakeDataDescriptor(16, {})));
329fd4e5da5Sopenharmony_ci
330fd4e5da5Sopenharmony_ci  auto transformation4 = TransformationEquationInstruction(
331fd4e5da5Sopenharmony_ci      22, spv::Op::OpISub, {16, 14}, return_instruction);
332fd4e5da5Sopenharmony_ci  ASSERT_TRUE(
333fd4e5da5Sopenharmony_ci      transformation4.IsApplicable(context.get(), transformation_context));
334fd4e5da5Sopenharmony_ci  ApplyAndCheckFreshIds(transformation4, context.get(),
335fd4e5da5Sopenharmony_ci                        &transformation_context);
336fd4e5da5Sopenharmony_ci  ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
337fd4e5da5Sopenharmony_ci                                               kConsoleMessageConsumer));
338fd4e5da5Sopenharmony_ci
339fd4e5da5Sopenharmony_ci  auto transformation5 = TransformationEquationInstruction(
340fd4e5da5Sopenharmony_ci      24, spv::Op::OpSNegate, {22}, return_instruction);
341fd4e5da5Sopenharmony_ci  ASSERT_TRUE(
342fd4e5da5Sopenharmony_ci      transformation5.IsApplicable(context.get(), transformation_context));
343fd4e5da5Sopenharmony_ci  ApplyAndCheckFreshIds(transformation5, context.get(),
344fd4e5da5Sopenharmony_ci                        &transformation_context);
345fd4e5da5Sopenharmony_ci  ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
346fd4e5da5Sopenharmony_ci                                               kConsoleMessageConsumer));
347fd4e5da5Sopenharmony_ci  ASSERT_TRUE(transformation_context.GetFactManager()->IsSynonymous(
348fd4e5da5Sopenharmony_ci      MakeDataDescriptor(24, {}), MakeDataDescriptor(15, {})));
349fd4e5da5Sopenharmony_ci
350fd4e5da5Sopenharmony_ci  std::string after_transformation = R"(
351fd4e5da5Sopenharmony_ci               OpCapability Shader
352fd4e5da5Sopenharmony_ci          %1 = OpExtInstImport "GLSL.std.450"
353fd4e5da5Sopenharmony_ci               OpMemoryModel Logical GLSL450
354fd4e5da5Sopenharmony_ci               OpEntryPoint Fragment %12 "main"
355fd4e5da5Sopenharmony_ci               OpExecutionMode %12 OriginUpperLeft
356fd4e5da5Sopenharmony_ci               OpSource ESSL 310
357fd4e5da5Sopenharmony_ci          %2 = OpTypeVoid
358fd4e5da5Sopenharmony_ci          %3 = OpTypeFunction %2
359fd4e5da5Sopenharmony_ci          %6 = OpTypeInt 32 1
360fd4e5da5Sopenharmony_ci         %30 = OpTypeVector %6 3
361fd4e5da5Sopenharmony_ci         %15 = OpConstant %6 24
362fd4e5da5Sopenharmony_ci         %16 = OpConstant %6 37
363fd4e5da5Sopenharmony_ci         %31 = OpConstantComposite %30 %15 %16 %15
364fd4e5da5Sopenharmony_ci         %33 = OpTypeBool
365fd4e5da5Sopenharmony_ci         %32 = OpConstantTrue %33
366fd4e5da5Sopenharmony_ci         %12 = OpFunction %2 None %3
367fd4e5da5Sopenharmony_ci         %13 = OpLabel
368fd4e5da5Sopenharmony_ci         %14 = OpIAdd %6 %15 %16
369fd4e5da5Sopenharmony_ci         %19 = OpISub %6 %14 %16 ; ==> synonymous(%19, %15)
370fd4e5da5Sopenharmony_ci         %20 = OpISub %6 %14 %15 ; ==> synonymous(%20, %16)
371fd4e5da5Sopenharmony_ci         %22 = OpISub %6 %16 %14
372fd4e5da5Sopenharmony_ci         %24 = OpSNegate %6 %22 ; ==> synonymous(%24, %15)
373fd4e5da5Sopenharmony_ci               OpReturn
374fd4e5da5Sopenharmony_ci               OpFunctionEnd
375fd4e5da5Sopenharmony_ci  )";
376fd4e5da5Sopenharmony_ci
377fd4e5da5Sopenharmony_ci  ASSERT_TRUE(IsEqual(env, after_transformation, context.get()));
378fd4e5da5Sopenharmony_ci}
379fd4e5da5Sopenharmony_ci
380fd4e5da5Sopenharmony_ciTEST(TransformationEquationInstructionTest, AddSubNegate2) {
381fd4e5da5Sopenharmony_ci  std::string shader = R"(
382fd4e5da5Sopenharmony_ci               OpCapability Shader
383fd4e5da5Sopenharmony_ci          %1 = OpExtInstImport "GLSL.std.450"
384fd4e5da5Sopenharmony_ci               OpMemoryModel Logical GLSL450
385fd4e5da5Sopenharmony_ci               OpEntryPoint Fragment %12 "main"
386fd4e5da5Sopenharmony_ci               OpExecutionMode %12 OriginUpperLeft
387fd4e5da5Sopenharmony_ci               OpSource ESSL 310
388fd4e5da5Sopenharmony_ci          %2 = OpTypeVoid
389fd4e5da5Sopenharmony_ci          %3 = OpTypeFunction %2
390fd4e5da5Sopenharmony_ci          %6 = OpTypeInt 32 1
391fd4e5da5Sopenharmony_ci         %15 = OpConstant %6 24
392fd4e5da5Sopenharmony_ci         %16 = OpConstant %6 37
393fd4e5da5Sopenharmony_ci         %12 = OpFunction %2 None %3
394fd4e5da5Sopenharmony_ci         %13 = OpLabel
395fd4e5da5Sopenharmony_ci               OpReturn
396fd4e5da5Sopenharmony_ci               OpFunctionEnd
397fd4e5da5Sopenharmony_ci  )";
398fd4e5da5Sopenharmony_ci
399fd4e5da5Sopenharmony_ci  const auto env = SPV_ENV_UNIVERSAL_1_3;
400fd4e5da5Sopenharmony_ci  const auto consumer = nullptr;
401fd4e5da5Sopenharmony_ci  const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption);
402fd4e5da5Sopenharmony_ci  spvtools::ValidatorOptions validator_options;
403fd4e5da5Sopenharmony_ci  ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
404fd4e5da5Sopenharmony_ci                                               kConsoleMessageConsumer));
405fd4e5da5Sopenharmony_ci  TransformationContext transformation_context(
406fd4e5da5Sopenharmony_ci      MakeUnique<FactManager>(context.get()), validator_options);
407fd4e5da5Sopenharmony_ci  protobufs::InstructionDescriptor return_instruction =
408fd4e5da5Sopenharmony_ci      MakeInstructionDescriptor(13, spv::Op::OpReturn, 0);
409fd4e5da5Sopenharmony_ci
410fd4e5da5Sopenharmony_ci  auto transformation1 = TransformationEquationInstruction(
411fd4e5da5Sopenharmony_ci      14, spv::Op::OpISub, {15, 16}, return_instruction);
412fd4e5da5Sopenharmony_ci  ASSERT_TRUE(
413fd4e5da5Sopenharmony_ci      transformation1.IsApplicable(context.get(), transformation_context));
414fd4e5da5Sopenharmony_ci  ApplyAndCheckFreshIds(transformation1, context.get(),
415fd4e5da5Sopenharmony_ci                        &transformation_context);
416fd4e5da5Sopenharmony_ci  ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
417fd4e5da5Sopenharmony_ci                                               kConsoleMessageConsumer));
418fd4e5da5Sopenharmony_ci
419fd4e5da5Sopenharmony_ci  auto transformation2 = TransformationEquationInstruction(
420fd4e5da5Sopenharmony_ci      17, spv::Op::OpIAdd, {14, 16}, return_instruction);
421fd4e5da5Sopenharmony_ci  ASSERT_TRUE(
422fd4e5da5Sopenharmony_ci      transformation2.IsApplicable(context.get(), transformation_context));
423fd4e5da5Sopenharmony_ci  ApplyAndCheckFreshIds(transformation2, context.get(),
424fd4e5da5Sopenharmony_ci                        &transformation_context);
425fd4e5da5Sopenharmony_ci  ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
426fd4e5da5Sopenharmony_ci                                               kConsoleMessageConsumer));
427fd4e5da5Sopenharmony_ci  ASSERT_TRUE(transformation_context.GetFactManager()->IsSynonymous(
428fd4e5da5Sopenharmony_ci      MakeDataDescriptor(17, {}), MakeDataDescriptor(15, {})));
429fd4e5da5Sopenharmony_ci
430fd4e5da5Sopenharmony_ci  auto transformation3 = TransformationEquationInstruction(
431fd4e5da5Sopenharmony_ci      18, spv::Op::OpIAdd, {16, 14}, return_instruction);
432fd4e5da5Sopenharmony_ci  ASSERT_TRUE(
433fd4e5da5Sopenharmony_ci      transformation3.IsApplicable(context.get(), transformation_context));
434fd4e5da5Sopenharmony_ci  ApplyAndCheckFreshIds(transformation3, context.get(),
435fd4e5da5Sopenharmony_ci                        &transformation_context);
436fd4e5da5Sopenharmony_ci  ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
437fd4e5da5Sopenharmony_ci                                               kConsoleMessageConsumer));
438fd4e5da5Sopenharmony_ci  ASSERT_TRUE(transformation_context.GetFactManager()->IsSynonymous(
439fd4e5da5Sopenharmony_ci      MakeDataDescriptor(17, {}), MakeDataDescriptor(18, {})));
440fd4e5da5Sopenharmony_ci  ASSERT_TRUE(transformation_context.GetFactManager()->IsSynonymous(
441fd4e5da5Sopenharmony_ci      MakeDataDescriptor(18, {}), MakeDataDescriptor(15, {})));
442fd4e5da5Sopenharmony_ci
443fd4e5da5Sopenharmony_ci  auto transformation4 = TransformationEquationInstruction(
444fd4e5da5Sopenharmony_ci      19, spv::Op::OpISub, {14, 15}, return_instruction);
445fd4e5da5Sopenharmony_ci  ASSERT_TRUE(
446fd4e5da5Sopenharmony_ci      transformation4.IsApplicable(context.get(), transformation_context));
447fd4e5da5Sopenharmony_ci  ApplyAndCheckFreshIds(transformation4, context.get(),
448fd4e5da5Sopenharmony_ci                        &transformation_context);
449fd4e5da5Sopenharmony_ci  ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
450fd4e5da5Sopenharmony_ci                                               kConsoleMessageConsumer));
451fd4e5da5Sopenharmony_ci
452fd4e5da5Sopenharmony_ci  auto transformation5 = TransformationEquationInstruction(
453fd4e5da5Sopenharmony_ci      20, spv::Op::OpSNegate, {19}, return_instruction);
454fd4e5da5Sopenharmony_ci  ASSERT_TRUE(
455fd4e5da5Sopenharmony_ci      transformation5.IsApplicable(context.get(), transformation_context));
456fd4e5da5Sopenharmony_ci  ApplyAndCheckFreshIds(transformation5, context.get(),
457fd4e5da5Sopenharmony_ci                        &transformation_context);
458fd4e5da5Sopenharmony_ci  ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
459fd4e5da5Sopenharmony_ci                                               kConsoleMessageConsumer));
460fd4e5da5Sopenharmony_ci  ASSERT_TRUE(transformation_context.GetFactManager()->IsSynonymous(
461fd4e5da5Sopenharmony_ci      MakeDataDescriptor(20, {}), MakeDataDescriptor(16, {})));
462fd4e5da5Sopenharmony_ci
463fd4e5da5Sopenharmony_ci  auto transformation6 = TransformationEquationInstruction(
464fd4e5da5Sopenharmony_ci      21, spv::Op::OpISub, {14, 19}, return_instruction);
465fd4e5da5Sopenharmony_ci  ASSERT_TRUE(
466fd4e5da5Sopenharmony_ci      transformation6.IsApplicable(context.get(), transformation_context));
467fd4e5da5Sopenharmony_ci  ApplyAndCheckFreshIds(transformation6, context.get(),
468fd4e5da5Sopenharmony_ci                        &transformation_context);
469fd4e5da5Sopenharmony_ci  ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
470fd4e5da5Sopenharmony_ci                                               kConsoleMessageConsumer));
471fd4e5da5Sopenharmony_ci  ASSERT_TRUE(transformation_context.GetFactManager()->IsSynonymous(
472fd4e5da5Sopenharmony_ci      MakeDataDescriptor(21, {}), MakeDataDescriptor(15, {})));
473fd4e5da5Sopenharmony_ci
474fd4e5da5Sopenharmony_ci  auto transformation7 = TransformationEquationInstruction(
475fd4e5da5Sopenharmony_ci      22, spv::Op::OpISub, {14, 18}, return_instruction);
476fd4e5da5Sopenharmony_ci  ASSERT_TRUE(
477fd4e5da5Sopenharmony_ci      transformation7.IsApplicable(context.get(), transformation_context));
478fd4e5da5Sopenharmony_ci  ApplyAndCheckFreshIds(transformation7, context.get(),
479fd4e5da5Sopenharmony_ci                        &transformation_context);
480fd4e5da5Sopenharmony_ci  ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
481fd4e5da5Sopenharmony_ci                                               kConsoleMessageConsumer));
482fd4e5da5Sopenharmony_ci
483fd4e5da5Sopenharmony_ci  auto transformation8 = TransformationEquationInstruction(
484fd4e5da5Sopenharmony_ci      23, spv::Op::OpSNegate, {22}, return_instruction);
485fd4e5da5Sopenharmony_ci  ASSERT_TRUE(
486fd4e5da5Sopenharmony_ci      transformation8.IsApplicable(context.get(), transformation_context));
487fd4e5da5Sopenharmony_ci  ApplyAndCheckFreshIds(transformation8, context.get(),
488fd4e5da5Sopenharmony_ci                        &transformation_context);
489fd4e5da5Sopenharmony_ci  ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
490fd4e5da5Sopenharmony_ci                                               kConsoleMessageConsumer));
491fd4e5da5Sopenharmony_ci  ASSERT_TRUE(transformation_context.GetFactManager()->IsSynonymous(
492fd4e5da5Sopenharmony_ci      MakeDataDescriptor(23, {}), MakeDataDescriptor(16, {})));
493fd4e5da5Sopenharmony_ci
494fd4e5da5Sopenharmony_ci  std::string after_transformation = R"(
495fd4e5da5Sopenharmony_ci               OpCapability Shader
496fd4e5da5Sopenharmony_ci          %1 = OpExtInstImport "GLSL.std.450"
497fd4e5da5Sopenharmony_ci               OpMemoryModel Logical GLSL450
498fd4e5da5Sopenharmony_ci               OpEntryPoint Fragment %12 "main"
499fd4e5da5Sopenharmony_ci               OpExecutionMode %12 OriginUpperLeft
500fd4e5da5Sopenharmony_ci               OpSource ESSL 310
501fd4e5da5Sopenharmony_ci          %2 = OpTypeVoid
502fd4e5da5Sopenharmony_ci          %3 = OpTypeFunction %2
503fd4e5da5Sopenharmony_ci          %6 = OpTypeInt 32 1
504fd4e5da5Sopenharmony_ci         %15 = OpConstant %6 24
505fd4e5da5Sopenharmony_ci         %16 = OpConstant %6 37
506fd4e5da5Sopenharmony_ci         %12 = OpFunction %2 None %3
507fd4e5da5Sopenharmony_ci         %13 = OpLabel
508fd4e5da5Sopenharmony_ci         %14 = OpISub %6 %15 %16
509fd4e5da5Sopenharmony_ci         %17 = OpIAdd %6 %14 %16 ; ==> synonymous(%17, %15)
510fd4e5da5Sopenharmony_ci         %18 = OpIAdd %6 %16 %14 ; ==> synonymous(%17, %18, %15)
511fd4e5da5Sopenharmony_ci         %19 = OpISub %6 %14 %15
512fd4e5da5Sopenharmony_ci         %20 = OpSNegate %6 %19 ; ==> synonymous(%20, %16)
513fd4e5da5Sopenharmony_ci         %21 = OpISub %6 %14 %19 ; ==> synonymous(%21, %15)
514fd4e5da5Sopenharmony_ci         %22 = OpISub %6 %14 %18
515fd4e5da5Sopenharmony_ci         %23 = OpSNegate %6 %22 ; ==> synonymous(%23, %16)
516fd4e5da5Sopenharmony_ci               OpReturn
517fd4e5da5Sopenharmony_ci               OpFunctionEnd
518fd4e5da5Sopenharmony_ci  )";
519fd4e5da5Sopenharmony_ci
520fd4e5da5Sopenharmony_ci  ASSERT_TRUE(IsEqual(env, after_transformation, context.get()));
521fd4e5da5Sopenharmony_ci}
522fd4e5da5Sopenharmony_ci
523fd4e5da5Sopenharmony_ciTEST(TransformationEquationInstructionTest, Bitcast) {
524fd4e5da5Sopenharmony_ci  std::string shader = R"(
525fd4e5da5Sopenharmony_ci               OpCapability Shader
526fd4e5da5Sopenharmony_ci          %1 = OpExtInstImport "GLSL.std.450"
527fd4e5da5Sopenharmony_ci               OpMemoryModel Logical GLSL450
528fd4e5da5Sopenharmony_ci               OpEntryPoint Fragment %12 "main"
529fd4e5da5Sopenharmony_ci               OpExecutionMode %12 OriginUpperLeft
530fd4e5da5Sopenharmony_ci               OpSource ESSL 310
531fd4e5da5Sopenharmony_ci          %2 = OpTypeVoid
532fd4e5da5Sopenharmony_ci          %3 = OpTypeFunction %2
533fd4e5da5Sopenharmony_ci          %6 = OpTypeInt 32 1
534fd4e5da5Sopenharmony_ci          %7 = OpTypeInt 32 0
535fd4e5da5Sopenharmony_ci          %8 = OpTypeFloat 32
536fd4e5da5Sopenharmony_ci          %9 = OpTypeVector %6 2
537fd4e5da5Sopenharmony_ci         %10 = OpTypeVector %7 2
538fd4e5da5Sopenharmony_ci         %11 = OpTypeVector %8 2
539fd4e5da5Sopenharmony_ci         %21 = OpTypeBool
540fd4e5da5Sopenharmony_ci         %22 = OpTypeVector %21 2
541fd4e5da5Sopenharmony_ci         %15 = OpConstant %6 24
542fd4e5da5Sopenharmony_ci         %16 = OpConstant %7 24
543fd4e5da5Sopenharmony_ci         %17 = OpConstant %8 24
544fd4e5da5Sopenharmony_ci         %18 = OpConstantComposite %9 %15 %15
545fd4e5da5Sopenharmony_ci         %19 = OpConstantComposite %10 %16 %16
546fd4e5da5Sopenharmony_ci         %20 = OpConstantComposite %11 %17 %17
547fd4e5da5Sopenharmony_ci         %23 = OpConstantTrue %21
548fd4e5da5Sopenharmony_ci         %24 = OpConstantComposite %22 %23 %23
549fd4e5da5Sopenharmony_ci         %12 = OpFunction %2 None %3
550fd4e5da5Sopenharmony_ci         %13 = OpLabel
551fd4e5da5Sopenharmony_ci               OpReturn
552fd4e5da5Sopenharmony_ci               OpFunctionEnd
553fd4e5da5Sopenharmony_ci  )";
554fd4e5da5Sopenharmony_ci
555fd4e5da5Sopenharmony_ci  const auto env = SPV_ENV_UNIVERSAL_1_3;
556fd4e5da5Sopenharmony_ci  const auto consumer = nullptr;
557fd4e5da5Sopenharmony_ci  const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption);
558fd4e5da5Sopenharmony_ci  spvtools::ValidatorOptions validator_options;
559fd4e5da5Sopenharmony_ci  ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
560fd4e5da5Sopenharmony_ci                                               kConsoleMessageConsumer));
561fd4e5da5Sopenharmony_ci  TransformationContext transformation_context(
562fd4e5da5Sopenharmony_ci      MakeUnique<FactManager>(context.get()), validator_options);
563fd4e5da5Sopenharmony_ci  auto insert_before = MakeInstructionDescriptor(13, spv::Op::OpReturn, 0);
564fd4e5da5Sopenharmony_ci
565fd4e5da5Sopenharmony_ci  // Too many operands.
566fd4e5da5Sopenharmony_ci  ASSERT_FALSE(TransformationEquationInstruction(50, spv::Op::OpBitcast,
567fd4e5da5Sopenharmony_ci                                                 {15, 16}, insert_before)
568fd4e5da5Sopenharmony_ci                   .IsApplicable(context.get(), transformation_context));
569fd4e5da5Sopenharmony_ci
570fd4e5da5Sopenharmony_ci  // Too few operands.
571fd4e5da5Sopenharmony_ci  ASSERT_FALSE(TransformationEquationInstruction(50, spv::Op::OpBitcast, {},
572fd4e5da5Sopenharmony_ci                                                 insert_before)
573fd4e5da5Sopenharmony_ci                   .IsApplicable(context.get(), transformation_context));
574fd4e5da5Sopenharmony_ci
575fd4e5da5Sopenharmony_ci  // Operand's id is invalid.
576fd4e5da5Sopenharmony_ci  ASSERT_FALSE(TransformationEquationInstruction(50, spv::Op::OpBitcast, {50},
577fd4e5da5Sopenharmony_ci                                                 insert_before)
578fd4e5da5Sopenharmony_ci                   .IsApplicable(context.get(), transformation_context));
579fd4e5da5Sopenharmony_ci
580fd4e5da5Sopenharmony_ci  // Operand's type is invalid
581fd4e5da5Sopenharmony_ci  ASSERT_FALSE(TransformationEquationInstruction(50, spv::Op::OpBitcast, {13},
582fd4e5da5Sopenharmony_ci                                                 insert_before)
583fd4e5da5Sopenharmony_ci                   .IsApplicable(context.get(), transformation_context));
584fd4e5da5Sopenharmony_ci
585fd4e5da5Sopenharmony_ci  // Operand must be a scalar or a vector of numerical type.
586fd4e5da5Sopenharmony_ci#ifndef NDEBUG
587fd4e5da5Sopenharmony_ci  ASSERT_DEATH(TransformationEquationInstruction(50, spv::Op::OpBitcast, {23},
588fd4e5da5Sopenharmony_ci                                                 insert_before)
589fd4e5da5Sopenharmony_ci                   .IsApplicable(context.get(), transformation_context),
590fd4e5da5Sopenharmony_ci               "Operand is not a scalar or a vector of numerical type");
591fd4e5da5Sopenharmony_ci  ASSERT_DEATH(TransformationEquationInstruction(50, spv::Op::OpBitcast, {24},
592fd4e5da5Sopenharmony_ci                                                 insert_before)
593fd4e5da5Sopenharmony_ci                   .IsApplicable(context.get(), transformation_context),
594fd4e5da5Sopenharmony_ci               "Only vectors of numerical components are supported");
595fd4e5da5Sopenharmony_ci#else
596fd4e5da5Sopenharmony_ci  ASSERT_FALSE(TransformationEquationInstruction(50, spv::Op::OpBitcast, {23},
597fd4e5da5Sopenharmony_ci                                                 insert_before)
598fd4e5da5Sopenharmony_ci                   .IsApplicable(context.get(), transformation_context));
599fd4e5da5Sopenharmony_ci  ASSERT_FALSE(TransformationEquationInstruction(50, spv::Op::OpBitcast, {24},
600fd4e5da5Sopenharmony_ci                                                 insert_before)
601fd4e5da5Sopenharmony_ci                   .IsApplicable(context.get(), transformation_context));
602fd4e5da5Sopenharmony_ci#endif
603fd4e5da5Sopenharmony_ci
604fd4e5da5Sopenharmony_ci  for (uint32_t operand_id = 15, fresh_id = 50; operand_id <= 20;
605fd4e5da5Sopenharmony_ci       ++operand_id, ++fresh_id) {
606fd4e5da5Sopenharmony_ci    TransformationEquationInstruction transformation(
607fd4e5da5Sopenharmony_ci        fresh_id, spv::Op::OpBitcast, {operand_id}, insert_before);
608fd4e5da5Sopenharmony_ci    ASSERT_TRUE(
609fd4e5da5Sopenharmony_ci        transformation.IsApplicable(context.get(), transformation_context));
610fd4e5da5Sopenharmony_ci    ApplyAndCheckFreshIds(transformation, context.get(),
611fd4e5da5Sopenharmony_ci                          &transformation_context);
612fd4e5da5Sopenharmony_ci  }
613fd4e5da5Sopenharmony_ci
614fd4e5da5Sopenharmony_ci  std::string expected_shader = R"(
615fd4e5da5Sopenharmony_ci               OpCapability Shader
616fd4e5da5Sopenharmony_ci          %1 = OpExtInstImport "GLSL.std.450"
617fd4e5da5Sopenharmony_ci               OpMemoryModel Logical GLSL450
618fd4e5da5Sopenharmony_ci               OpEntryPoint Fragment %12 "main"
619fd4e5da5Sopenharmony_ci               OpExecutionMode %12 OriginUpperLeft
620fd4e5da5Sopenharmony_ci               OpSource ESSL 310
621fd4e5da5Sopenharmony_ci          %2 = OpTypeVoid
622fd4e5da5Sopenharmony_ci          %3 = OpTypeFunction %2
623fd4e5da5Sopenharmony_ci          %6 = OpTypeInt 32 1
624fd4e5da5Sopenharmony_ci          %7 = OpTypeInt 32 0
625fd4e5da5Sopenharmony_ci          %8 = OpTypeFloat 32
626fd4e5da5Sopenharmony_ci          %9 = OpTypeVector %6 2
627fd4e5da5Sopenharmony_ci         %10 = OpTypeVector %7 2
628fd4e5da5Sopenharmony_ci         %11 = OpTypeVector %8 2
629fd4e5da5Sopenharmony_ci         %21 = OpTypeBool
630fd4e5da5Sopenharmony_ci         %22 = OpTypeVector %21 2
631fd4e5da5Sopenharmony_ci         %15 = OpConstant %6 24
632fd4e5da5Sopenharmony_ci         %16 = OpConstant %7 24
633fd4e5da5Sopenharmony_ci         %17 = OpConstant %8 24
634fd4e5da5Sopenharmony_ci         %18 = OpConstantComposite %9 %15 %15
635fd4e5da5Sopenharmony_ci         %19 = OpConstantComposite %10 %16 %16
636fd4e5da5Sopenharmony_ci         %20 = OpConstantComposite %11 %17 %17
637fd4e5da5Sopenharmony_ci         %23 = OpConstantTrue %21
638fd4e5da5Sopenharmony_ci         %24 = OpConstantComposite %22 %23 %23
639fd4e5da5Sopenharmony_ci         %12 = OpFunction %2 None %3
640fd4e5da5Sopenharmony_ci         %13 = OpLabel
641fd4e5da5Sopenharmony_ci         %50 = OpBitcast %8 %15
642fd4e5da5Sopenharmony_ci         %51 = OpBitcast %8 %16
643fd4e5da5Sopenharmony_ci         %52 = OpBitcast %6 %17
644fd4e5da5Sopenharmony_ci         %53 = OpBitcast %11 %18
645fd4e5da5Sopenharmony_ci         %54 = OpBitcast %11 %19
646fd4e5da5Sopenharmony_ci         %55 = OpBitcast %9 %20
647fd4e5da5Sopenharmony_ci               OpReturn
648fd4e5da5Sopenharmony_ci               OpFunctionEnd
649fd4e5da5Sopenharmony_ci  )";
650fd4e5da5Sopenharmony_ci
651fd4e5da5Sopenharmony_ci  ASSERT_TRUE(IsEqual(env, expected_shader, context.get()));
652fd4e5da5Sopenharmony_ci}
653fd4e5da5Sopenharmony_ci
654fd4e5da5Sopenharmony_ciTEST(TransformationEquationInstructionTest,
655fd4e5da5Sopenharmony_ci     BitcastResultTypeFloatDoesNotExist) {
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 %12 "main"
661fd4e5da5Sopenharmony_ci               OpExecutionMode %12 OriginUpperLeft
662fd4e5da5Sopenharmony_ci               OpSource ESSL 310
663fd4e5da5Sopenharmony_ci          %2 = OpTypeVoid
664fd4e5da5Sopenharmony_ci          %3 = OpTypeFunction %2
665fd4e5da5Sopenharmony_ci          %6 = OpTypeInt 32 1
666fd4e5da5Sopenharmony_ci          %7 = OpTypeInt 32 0
667fd4e5da5Sopenharmony_ci          %9 = OpTypeVector %6 2
668fd4e5da5Sopenharmony_ci         %10 = OpTypeVector %7 2
669fd4e5da5Sopenharmony_ci         %15 = OpConstant %6 24
670fd4e5da5Sopenharmony_ci         %16 = OpConstant %7 24
671fd4e5da5Sopenharmony_ci         %18 = OpConstantComposite %9 %15 %15
672fd4e5da5Sopenharmony_ci         %19 = OpConstantComposite %10 %16 %16
673fd4e5da5Sopenharmony_ci         %12 = OpFunction %2 None %3
674fd4e5da5Sopenharmony_ci         %13 = OpLabel
675fd4e5da5Sopenharmony_ci               OpReturn
676fd4e5da5Sopenharmony_ci               OpFunctionEnd
677fd4e5da5Sopenharmony_ci  )";
678fd4e5da5Sopenharmony_ci
679fd4e5da5Sopenharmony_ci  const auto env = SPV_ENV_UNIVERSAL_1_3;
680fd4e5da5Sopenharmony_ci  const auto consumer = nullptr;
681fd4e5da5Sopenharmony_ci  const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption);
682fd4e5da5Sopenharmony_ci  spvtools::ValidatorOptions validator_options;
683fd4e5da5Sopenharmony_ci  ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
684fd4e5da5Sopenharmony_ci                                               kConsoleMessageConsumer));
685fd4e5da5Sopenharmony_ci  TransformationContext transformation_context(
686fd4e5da5Sopenharmony_ci      MakeUnique<FactManager>(context.get()), validator_options);
687fd4e5da5Sopenharmony_ci  auto insert_before = MakeInstructionDescriptor(13, spv::Op::OpReturn, 0);
688fd4e5da5Sopenharmony_ci
689fd4e5da5Sopenharmony_ci  // Scalar floating-point type does not exist.
690fd4e5da5Sopenharmony_ci  ASSERT_FALSE(TransformationEquationInstruction(50, spv::Op::OpBitcast, {15},
691fd4e5da5Sopenharmony_ci                                                 insert_before)
692fd4e5da5Sopenharmony_ci                   .IsApplicable(context.get(), transformation_context));
693fd4e5da5Sopenharmony_ci  ASSERT_FALSE(TransformationEquationInstruction(50, spv::Op::OpBitcast, {16},
694fd4e5da5Sopenharmony_ci                                                 insert_before)
695fd4e5da5Sopenharmony_ci                   .IsApplicable(context.get(), transformation_context));
696fd4e5da5Sopenharmony_ci
697fd4e5da5Sopenharmony_ci  // Vector of floating-point components does not exist.
698fd4e5da5Sopenharmony_ci  ASSERT_FALSE(TransformationEquationInstruction(50, spv::Op::OpBitcast, {18},
699fd4e5da5Sopenharmony_ci                                                 insert_before)
700fd4e5da5Sopenharmony_ci                   .IsApplicable(context.get(), transformation_context));
701fd4e5da5Sopenharmony_ci  ASSERT_FALSE(TransformationEquationInstruction(50, spv::Op::OpBitcast, {19},
702fd4e5da5Sopenharmony_ci                                                 insert_before)
703fd4e5da5Sopenharmony_ci                   .IsApplicable(context.get(), transformation_context));
704fd4e5da5Sopenharmony_ci}
705fd4e5da5Sopenharmony_ci
706fd4e5da5Sopenharmony_ciTEST(TransformationEquationInstructionTest, BitcastResultTypeIntDoesNotExist1) {
707fd4e5da5Sopenharmony_ci  std::string shader = R"(
708fd4e5da5Sopenharmony_ci               OpCapability Shader
709fd4e5da5Sopenharmony_ci          %1 = OpExtInstImport "GLSL.std.450"
710fd4e5da5Sopenharmony_ci               OpMemoryModel Logical GLSL450
711fd4e5da5Sopenharmony_ci               OpEntryPoint Fragment %12 "main"
712fd4e5da5Sopenharmony_ci               OpExecutionMode %12 OriginUpperLeft
713fd4e5da5Sopenharmony_ci               OpSource ESSL 310
714fd4e5da5Sopenharmony_ci          %2 = OpTypeVoid
715fd4e5da5Sopenharmony_ci          %3 = OpTypeFunction %2
716fd4e5da5Sopenharmony_ci          %8 = OpTypeFloat 32
717fd4e5da5Sopenharmony_ci         %11 = OpTypeVector %8 2
718fd4e5da5Sopenharmony_ci         %17 = OpConstant %8 24
719fd4e5da5Sopenharmony_ci         %20 = OpConstantComposite %11 %17 %17
720fd4e5da5Sopenharmony_ci         %12 = OpFunction %2 None %3
721fd4e5da5Sopenharmony_ci         %13 = OpLabel
722fd4e5da5Sopenharmony_ci               OpReturn
723fd4e5da5Sopenharmony_ci               OpFunctionEnd
724fd4e5da5Sopenharmony_ci  )";
725fd4e5da5Sopenharmony_ci
726fd4e5da5Sopenharmony_ci  const auto env = SPV_ENV_UNIVERSAL_1_3;
727fd4e5da5Sopenharmony_ci  const auto consumer = nullptr;
728fd4e5da5Sopenharmony_ci  const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption);
729fd4e5da5Sopenharmony_ci  spvtools::ValidatorOptions validator_options;
730fd4e5da5Sopenharmony_ci  ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
731fd4e5da5Sopenharmony_ci                                               kConsoleMessageConsumer));
732fd4e5da5Sopenharmony_ci  TransformationContext transformation_context(
733fd4e5da5Sopenharmony_ci      MakeUnique<FactManager>(context.get()), validator_options);
734fd4e5da5Sopenharmony_ci  auto insert_before = MakeInstructionDescriptor(13, spv::Op::OpReturn, 0);
735fd4e5da5Sopenharmony_ci
736fd4e5da5Sopenharmony_ci  // Scalar integral type does not exist.
737fd4e5da5Sopenharmony_ci  ASSERT_FALSE(TransformationEquationInstruction(50, spv::Op::OpBitcast, {17},
738fd4e5da5Sopenharmony_ci                                                 insert_before)
739fd4e5da5Sopenharmony_ci                   .IsApplicable(context.get(), transformation_context));
740fd4e5da5Sopenharmony_ci
741fd4e5da5Sopenharmony_ci  // Vector of integral components does not exist.
742fd4e5da5Sopenharmony_ci  ASSERT_FALSE(TransformationEquationInstruction(50, spv::Op::OpBitcast, {20},
743fd4e5da5Sopenharmony_ci                                                 insert_before)
744fd4e5da5Sopenharmony_ci                   .IsApplicable(context.get(), transformation_context));
745fd4e5da5Sopenharmony_ci}
746fd4e5da5Sopenharmony_ci
747fd4e5da5Sopenharmony_ciTEST(TransformationEquationInstructionTest, BitcastResultTypeIntDoesNotExist2) {
748fd4e5da5Sopenharmony_ci  std::string shader = R"(
749fd4e5da5Sopenharmony_ci               OpCapability Shader
750fd4e5da5Sopenharmony_ci          %1 = OpExtInstImport "GLSL.std.450"
751fd4e5da5Sopenharmony_ci               OpMemoryModel Logical GLSL450
752fd4e5da5Sopenharmony_ci               OpEntryPoint Fragment %12 "main"
753fd4e5da5Sopenharmony_ci               OpExecutionMode %12 OriginUpperLeft
754fd4e5da5Sopenharmony_ci               OpSource ESSL 310
755fd4e5da5Sopenharmony_ci          %2 = OpTypeVoid
756fd4e5da5Sopenharmony_ci          %3 = OpTypeFunction %2
757fd4e5da5Sopenharmony_ci          %4 = OpTypeInt 32 0
758fd4e5da5Sopenharmony_ci          %8 = OpTypeFloat 32
759fd4e5da5Sopenharmony_ci          %9 = OpTypeVector %4 2
760fd4e5da5Sopenharmony_ci         %11 = OpTypeVector %8 2
761fd4e5da5Sopenharmony_ci         %17 = OpConstant %8 24
762fd4e5da5Sopenharmony_ci         %20 = OpConstantComposite %11 %17 %17
763fd4e5da5Sopenharmony_ci         %12 = OpFunction %2 None %3
764fd4e5da5Sopenharmony_ci         %13 = OpLabel
765fd4e5da5Sopenharmony_ci               OpReturn
766fd4e5da5Sopenharmony_ci               OpFunctionEnd
767fd4e5da5Sopenharmony_ci  )";
768fd4e5da5Sopenharmony_ci
769fd4e5da5Sopenharmony_ci  const auto env = SPV_ENV_UNIVERSAL_1_3;
770fd4e5da5Sopenharmony_ci  const auto consumer = nullptr;
771fd4e5da5Sopenharmony_ci  const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption);
772fd4e5da5Sopenharmony_ci  spvtools::ValidatorOptions validator_options;
773fd4e5da5Sopenharmony_ci  ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
774fd4e5da5Sopenharmony_ci                                               kConsoleMessageConsumer));
775fd4e5da5Sopenharmony_ci  TransformationContext transformation_context(
776fd4e5da5Sopenharmony_ci      MakeUnique<FactManager>(context.get()), validator_options);
777fd4e5da5Sopenharmony_ci  auto insert_before = MakeInstructionDescriptor(13, spv::Op::OpReturn, 0);
778fd4e5da5Sopenharmony_ci
779fd4e5da5Sopenharmony_ci  {
780fd4e5da5Sopenharmony_ci    TransformationEquationInstruction transformation(50, spv::Op::OpBitcast,
781fd4e5da5Sopenharmony_ci                                                     {17}, insert_before);
782fd4e5da5Sopenharmony_ci    ASSERT_TRUE(
783fd4e5da5Sopenharmony_ci        transformation.IsApplicable(context.get(), transformation_context));
784fd4e5da5Sopenharmony_ci    ApplyAndCheckFreshIds(transformation, context.get(),
785fd4e5da5Sopenharmony_ci                          &transformation_context);
786fd4e5da5Sopenharmony_ci  }
787fd4e5da5Sopenharmony_ci  {
788fd4e5da5Sopenharmony_ci    TransformationEquationInstruction transformation(51, spv::Op::OpBitcast,
789fd4e5da5Sopenharmony_ci                                                     {20}, insert_before);
790fd4e5da5Sopenharmony_ci    ASSERT_TRUE(
791fd4e5da5Sopenharmony_ci        transformation.IsApplicable(context.get(), transformation_context));
792fd4e5da5Sopenharmony_ci    ApplyAndCheckFreshIds(transformation, context.get(),
793fd4e5da5Sopenharmony_ci                          &transformation_context);
794fd4e5da5Sopenharmony_ci  }
795fd4e5da5Sopenharmony_ci
796fd4e5da5Sopenharmony_ci  std::string expected_shader = R"(
797fd4e5da5Sopenharmony_ci               OpCapability Shader
798fd4e5da5Sopenharmony_ci          %1 = OpExtInstImport "GLSL.std.450"
799fd4e5da5Sopenharmony_ci               OpMemoryModel Logical GLSL450
800fd4e5da5Sopenharmony_ci               OpEntryPoint Fragment %12 "main"
801fd4e5da5Sopenharmony_ci               OpExecutionMode %12 OriginUpperLeft
802fd4e5da5Sopenharmony_ci               OpSource ESSL 310
803fd4e5da5Sopenharmony_ci          %2 = OpTypeVoid
804fd4e5da5Sopenharmony_ci          %3 = OpTypeFunction %2
805fd4e5da5Sopenharmony_ci          %4 = OpTypeInt 32 0
806fd4e5da5Sopenharmony_ci          %8 = OpTypeFloat 32
807fd4e5da5Sopenharmony_ci          %9 = OpTypeVector %4 2
808fd4e5da5Sopenharmony_ci         %11 = OpTypeVector %8 2
809fd4e5da5Sopenharmony_ci         %17 = OpConstant %8 24
810fd4e5da5Sopenharmony_ci         %20 = OpConstantComposite %11 %17 %17
811fd4e5da5Sopenharmony_ci         %12 = OpFunction %2 None %3
812fd4e5da5Sopenharmony_ci         %13 = OpLabel
813fd4e5da5Sopenharmony_ci         %50 = OpBitcast %4 %17
814fd4e5da5Sopenharmony_ci         %51 = OpBitcast %9 %20
815fd4e5da5Sopenharmony_ci               OpReturn
816fd4e5da5Sopenharmony_ci               OpFunctionEnd
817fd4e5da5Sopenharmony_ci  )";
818fd4e5da5Sopenharmony_ci
819fd4e5da5Sopenharmony_ci  ASSERT_TRUE(IsEqual(env, expected_shader, context.get()));
820fd4e5da5Sopenharmony_ci}
821fd4e5da5Sopenharmony_ci
822fd4e5da5Sopenharmony_ciTEST(TransformationEquationInstructionTest, BitcastResultTypeIntDoesNotExist3) {
823fd4e5da5Sopenharmony_ci  std::string shader = R"(
824fd4e5da5Sopenharmony_ci               OpCapability Shader
825fd4e5da5Sopenharmony_ci          %1 = OpExtInstImport "GLSL.std.450"
826fd4e5da5Sopenharmony_ci               OpMemoryModel Logical GLSL450
827fd4e5da5Sopenharmony_ci               OpEntryPoint Fragment %12 "main"
828fd4e5da5Sopenharmony_ci               OpExecutionMode %12 OriginUpperLeft
829fd4e5da5Sopenharmony_ci               OpSource ESSL 310
830fd4e5da5Sopenharmony_ci          %2 = OpTypeVoid
831fd4e5da5Sopenharmony_ci          %3 = OpTypeFunction %2
832fd4e5da5Sopenharmony_ci          %4 = OpTypeInt 32 1
833fd4e5da5Sopenharmony_ci          %8 = OpTypeFloat 32
834fd4e5da5Sopenharmony_ci          %9 = OpTypeVector %4 2
835fd4e5da5Sopenharmony_ci         %11 = OpTypeVector %8 2
836fd4e5da5Sopenharmony_ci         %17 = OpConstant %8 24
837fd4e5da5Sopenharmony_ci         %20 = OpConstantComposite %11 %17 %17
838fd4e5da5Sopenharmony_ci         %12 = OpFunction %2 None %3
839fd4e5da5Sopenharmony_ci         %13 = OpLabel
840fd4e5da5Sopenharmony_ci               OpReturn
841fd4e5da5Sopenharmony_ci               OpFunctionEnd
842fd4e5da5Sopenharmony_ci  )";
843fd4e5da5Sopenharmony_ci
844fd4e5da5Sopenharmony_ci  const auto env = SPV_ENV_UNIVERSAL_1_3;
845fd4e5da5Sopenharmony_ci  const auto consumer = nullptr;
846fd4e5da5Sopenharmony_ci  const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption);
847fd4e5da5Sopenharmony_ci  spvtools::ValidatorOptions validator_options;
848fd4e5da5Sopenharmony_ci  ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
849fd4e5da5Sopenharmony_ci                                               kConsoleMessageConsumer));
850fd4e5da5Sopenharmony_ci  TransformationContext transformation_context(
851fd4e5da5Sopenharmony_ci      MakeUnique<FactManager>(context.get()), validator_options);
852fd4e5da5Sopenharmony_ci  auto insert_before = MakeInstructionDescriptor(13, spv::Op::OpReturn, 0);
853fd4e5da5Sopenharmony_ci
854fd4e5da5Sopenharmony_ci  {
855fd4e5da5Sopenharmony_ci    TransformationEquationInstruction transformation(50, spv::Op::OpBitcast,
856fd4e5da5Sopenharmony_ci                                                     {17}, insert_before);
857fd4e5da5Sopenharmony_ci    ASSERT_TRUE(
858fd4e5da5Sopenharmony_ci        transformation.IsApplicable(context.get(), transformation_context));
859fd4e5da5Sopenharmony_ci    ApplyAndCheckFreshIds(transformation, context.get(),
860fd4e5da5Sopenharmony_ci                          &transformation_context);
861fd4e5da5Sopenharmony_ci  }
862fd4e5da5Sopenharmony_ci  {
863fd4e5da5Sopenharmony_ci    TransformationEquationInstruction transformation(51, spv::Op::OpBitcast,
864fd4e5da5Sopenharmony_ci                                                     {20}, insert_before);
865fd4e5da5Sopenharmony_ci    ASSERT_TRUE(
866fd4e5da5Sopenharmony_ci        transformation.IsApplicable(context.get(), transformation_context));
867fd4e5da5Sopenharmony_ci    ApplyAndCheckFreshIds(transformation, context.get(),
868fd4e5da5Sopenharmony_ci                          &transformation_context);
869fd4e5da5Sopenharmony_ci  }
870fd4e5da5Sopenharmony_ci
871fd4e5da5Sopenharmony_ci  std::string expected_shader = R"(
872fd4e5da5Sopenharmony_ci               OpCapability Shader
873fd4e5da5Sopenharmony_ci          %1 = OpExtInstImport "GLSL.std.450"
874fd4e5da5Sopenharmony_ci               OpMemoryModel Logical GLSL450
875fd4e5da5Sopenharmony_ci               OpEntryPoint Fragment %12 "main"
876fd4e5da5Sopenharmony_ci               OpExecutionMode %12 OriginUpperLeft
877fd4e5da5Sopenharmony_ci               OpSource ESSL 310
878fd4e5da5Sopenharmony_ci          %2 = OpTypeVoid
879fd4e5da5Sopenharmony_ci          %3 = OpTypeFunction %2
880fd4e5da5Sopenharmony_ci          %4 = OpTypeInt 32 1
881fd4e5da5Sopenharmony_ci          %8 = OpTypeFloat 32
882fd4e5da5Sopenharmony_ci          %9 = OpTypeVector %4 2
883fd4e5da5Sopenharmony_ci         %11 = OpTypeVector %8 2
884fd4e5da5Sopenharmony_ci         %17 = OpConstant %8 24
885fd4e5da5Sopenharmony_ci         %20 = OpConstantComposite %11 %17 %17
886fd4e5da5Sopenharmony_ci         %12 = OpFunction %2 None %3
887fd4e5da5Sopenharmony_ci         %13 = OpLabel
888fd4e5da5Sopenharmony_ci         %50 = OpBitcast %4 %17
889fd4e5da5Sopenharmony_ci         %51 = OpBitcast %9 %20
890fd4e5da5Sopenharmony_ci               OpReturn
891fd4e5da5Sopenharmony_ci               OpFunctionEnd
892fd4e5da5Sopenharmony_ci  )";
893fd4e5da5Sopenharmony_ci
894fd4e5da5Sopenharmony_ci  ASSERT_TRUE(IsEqual(env, expected_shader, context.get()));
895fd4e5da5Sopenharmony_ci}
896fd4e5da5Sopenharmony_ci
897fd4e5da5Sopenharmony_ciTEST(TransformationEquationInstructionTest, BitcastResultTypeIntDoesNotExist4) {
898fd4e5da5Sopenharmony_ci  std::string shader = R"(
899fd4e5da5Sopenharmony_ci               OpCapability Shader
900fd4e5da5Sopenharmony_ci          %1 = OpExtInstImport "GLSL.std.450"
901fd4e5da5Sopenharmony_ci               OpMemoryModel Logical GLSL450
902fd4e5da5Sopenharmony_ci               OpEntryPoint Fragment %12 "main"
903fd4e5da5Sopenharmony_ci               OpExecutionMode %12 OriginUpperLeft
904fd4e5da5Sopenharmony_ci               OpSource ESSL 310
905fd4e5da5Sopenharmony_ci          %2 = OpTypeVoid
906fd4e5da5Sopenharmony_ci          %3 = OpTypeFunction %2
907fd4e5da5Sopenharmony_ci          %4 = OpTypeInt 32 1
908fd4e5da5Sopenharmony_ci          %8 = OpTypeFloat 32
909fd4e5da5Sopenharmony_ci         %11 = OpTypeVector %8 2
910fd4e5da5Sopenharmony_ci         %17 = OpConstant %8 24
911fd4e5da5Sopenharmony_ci         %20 = OpConstantComposite %11 %17 %17
912fd4e5da5Sopenharmony_ci         %12 = OpFunction %2 None %3
913fd4e5da5Sopenharmony_ci         %13 = OpLabel
914fd4e5da5Sopenharmony_ci               OpReturn
915fd4e5da5Sopenharmony_ci               OpFunctionEnd
916fd4e5da5Sopenharmony_ci  )";
917fd4e5da5Sopenharmony_ci
918fd4e5da5Sopenharmony_ci  const auto env = SPV_ENV_UNIVERSAL_1_3;
919fd4e5da5Sopenharmony_ci  const auto consumer = nullptr;
920fd4e5da5Sopenharmony_ci  const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption);
921fd4e5da5Sopenharmony_ci  spvtools::ValidatorOptions validator_options;
922fd4e5da5Sopenharmony_ci  ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
923fd4e5da5Sopenharmony_ci                                               kConsoleMessageConsumer));
924fd4e5da5Sopenharmony_ci  TransformationContext transformation_context(
925fd4e5da5Sopenharmony_ci      MakeUnique<FactManager>(context.get()), validator_options);
926fd4e5da5Sopenharmony_ci  auto insert_before = MakeInstructionDescriptor(13, spv::Op::OpReturn, 0);
927fd4e5da5Sopenharmony_ci
928fd4e5da5Sopenharmony_ci  {
929fd4e5da5Sopenharmony_ci    TransformationEquationInstruction transformation(50, spv::Op::OpBitcast,
930fd4e5da5Sopenharmony_ci                                                     {17}, insert_before);
931fd4e5da5Sopenharmony_ci    ASSERT_TRUE(
932fd4e5da5Sopenharmony_ci        transformation.IsApplicable(context.get(), transformation_context));
933fd4e5da5Sopenharmony_ci    ApplyAndCheckFreshIds(transformation, context.get(),
934fd4e5da5Sopenharmony_ci                          &transformation_context);
935fd4e5da5Sopenharmony_ci  }
936fd4e5da5Sopenharmony_ci
937fd4e5da5Sopenharmony_ci  ASSERT_FALSE(TransformationEquationInstruction(51, spv::Op::OpBitcast, {20},
938fd4e5da5Sopenharmony_ci                                                 insert_before)
939fd4e5da5Sopenharmony_ci                   .IsApplicable(context.get(), transformation_context));
940fd4e5da5Sopenharmony_ci
941fd4e5da5Sopenharmony_ci  ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
942fd4e5da5Sopenharmony_ci                                               kConsoleMessageConsumer));
943fd4e5da5Sopenharmony_ci
944fd4e5da5Sopenharmony_ci  std::string expected_shader = R"(
945fd4e5da5Sopenharmony_ci               OpCapability Shader
946fd4e5da5Sopenharmony_ci          %1 = OpExtInstImport "GLSL.std.450"
947fd4e5da5Sopenharmony_ci               OpMemoryModel Logical GLSL450
948fd4e5da5Sopenharmony_ci               OpEntryPoint Fragment %12 "main"
949fd4e5da5Sopenharmony_ci               OpExecutionMode %12 OriginUpperLeft
950fd4e5da5Sopenharmony_ci               OpSource ESSL 310
951fd4e5da5Sopenharmony_ci          %2 = OpTypeVoid
952fd4e5da5Sopenharmony_ci          %3 = OpTypeFunction %2
953fd4e5da5Sopenharmony_ci          %4 = OpTypeInt 32 1
954fd4e5da5Sopenharmony_ci          %8 = OpTypeFloat 32
955fd4e5da5Sopenharmony_ci         %11 = OpTypeVector %8 2
956fd4e5da5Sopenharmony_ci         %17 = OpConstant %8 24
957fd4e5da5Sopenharmony_ci         %20 = OpConstantComposite %11 %17 %17
958fd4e5da5Sopenharmony_ci         %12 = OpFunction %2 None %3
959fd4e5da5Sopenharmony_ci         %13 = OpLabel
960fd4e5da5Sopenharmony_ci         %50 = OpBitcast %4 %17
961fd4e5da5Sopenharmony_ci               OpReturn
962fd4e5da5Sopenharmony_ci               OpFunctionEnd
963fd4e5da5Sopenharmony_ci  )";
964fd4e5da5Sopenharmony_ci
965fd4e5da5Sopenharmony_ci  ASSERT_TRUE(IsEqual(env, expected_shader, context.get()));
966fd4e5da5Sopenharmony_ci}
967fd4e5da5Sopenharmony_ci
968fd4e5da5Sopenharmony_ciTEST(TransformationEquationInstructionTest, BitcastResultTypeIntDoesNotExist5) {
969fd4e5da5Sopenharmony_ci  std::string shader = R"(
970fd4e5da5Sopenharmony_ci               OpCapability Shader
971fd4e5da5Sopenharmony_ci          %1 = OpExtInstImport "GLSL.std.450"
972fd4e5da5Sopenharmony_ci               OpMemoryModel Logical GLSL450
973fd4e5da5Sopenharmony_ci               OpEntryPoint Fragment %12 "main"
974fd4e5da5Sopenharmony_ci               OpExecutionMode %12 OriginUpperLeft
975fd4e5da5Sopenharmony_ci               OpSource ESSL 310
976fd4e5da5Sopenharmony_ci          %2 = OpTypeVoid
977fd4e5da5Sopenharmony_ci          %3 = OpTypeFunction %2
978fd4e5da5Sopenharmony_ci          %4 = OpTypeInt 32 0
979fd4e5da5Sopenharmony_ci          %8 = OpTypeFloat 32
980fd4e5da5Sopenharmony_ci         %11 = OpTypeVector %8 2
981fd4e5da5Sopenharmony_ci         %17 = OpConstant %8 24
982fd4e5da5Sopenharmony_ci         %20 = OpConstantComposite %11 %17 %17
983fd4e5da5Sopenharmony_ci         %12 = OpFunction %2 None %3
984fd4e5da5Sopenharmony_ci         %13 = OpLabel
985fd4e5da5Sopenharmony_ci               OpReturn
986fd4e5da5Sopenharmony_ci               OpFunctionEnd
987fd4e5da5Sopenharmony_ci  )";
988fd4e5da5Sopenharmony_ci
989fd4e5da5Sopenharmony_ci  const auto env = SPV_ENV_UNIVERSAL_1_3;
990fd4e5da5Sopenharmony_ci  const auto consumer = nullptr;
991fd4e5da5Sopenharmony_ci  const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption);
992fd4e5da5Sopenharmony_ci  spvtools::ValidatorOptions validator_options;
993fd4e5da5Sopenharmony_ci  ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
994fd4e5da5Sopenharmony_ci                                               kConsoleMessageConsumer));
995fd4e5da5Sopenharmony_ci  TransformationContext transformation_context(
996fd4e5da5Sopenharmony_ci      MakeUnique<FactManager>(context.get()), validator_options);
997fd4e5da5Sopenharmony_ci  auto insert_before = MakeInstructionDescriptor(13, spv::Op::OpReturn, 0);
998fd4e5da5Sopenharmony_ci
999fd4e5da5Sopenharmony_ci  {
1000fd4e5da5Sopenharmony_ci    TransformationEquationInstruction transformation(50, spv::Op::OpBitcast,
1001fd4e5da5Sopenharmony_ci                                                     {17}, insert_before);
1002fd4e5da5Sopenharmony_ci    ASSERT_TRUE(
1003fd4e5da5Sopenharmony_ci        transformation.IsApplicable(context.get(), transformation_context));
1004fd4e5da5Sopenharmony_ci    ApplyAndCheckFreshIds(transformation, context.get(),
1005fd4e5da5Sopenharmony_ci                          &transformation_context);
1006fd4e5da5Sopenharmony_ci  }
1007fd4e5da5Sopenharmony_ci
1008fd4e5da5Sopenharmony_ci  ASSERT_FALSE(TransformationEquationInstruction(51, spv::Op::OpBitcast, {20},
1009fd4e5da5Sopenharmony_ci                                                 insert_before)
1010fd4e5da5Sopenharmony_ci                   .IsApplicable(context.get(), transformation_context));
1011fd4e5da5Sopenharmony_ci
1012fd4e5da5Sopenharmony_ci  ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
1013fd4e5da5Sopenharmony_ci                                               kConsoleMessageConsumer));
1014fd4e5da5Sopenharmony_ci
1015fd4e5da5Sopenharmony_ci  std::string expected_shader = R"(
1016fd4e5da5Sopenharmony_ci               OpCapability Shader
1017fd4e5da5Sopenharmony_ci          %1 = OpExtInstImport "GLSL.std.450"
1018fd4e5da5Sopenharmony_ci               OpMemoryModel Logical GLSL450
1019fd4e5da5Sopenharmony_ci               OpEntryPoint Fragment %12 "main"
1020fd4e5da5Sopenharmony_ci               OpExecutionMode %12 OriginUpperLeft
1021fd4e5da5Sopenharmony_ci               OpSource ESSL 310
1022fd4e5da5Sopenharmony_ci          %2 = OpTypeVoid
1023fd4e5da5Sopenharmony_ci          %3 = OpTypeFunction %2
1024fd4e5da5Sopenharmony_ci          %4 = OpTypeInt 32 0
1025fd4e5da5Sopenharmony_ci          %8 = OpTypeFloat 32
1026fd4e5da5Sopenharmony_ci         %11 = OpTypeVector %8 2
1027fd4e5da5Sopenharmony_ci         %17 = OpConstant %8 24
1028fd4e5da5Sopenharmony_ci         %20 = OpConstantComposite %11 %17 %17
1029fd4e5da5Sopenharmony_ci         %12 = OpFunction %2 None %3
1030fd4e5da5Sopenharmony_ci         %13 = OpLabel
1031fd4e5da5Sopenharmony_ci         %50 = OpBitcast %4 %17
1032fd4e5da5Sopenharmony_ci               OpReturn
1033fd4e5da5Sopenharmony_ci               OpFunctionEnd
1034fd4e5da5Sopenharmony_ci  )";
1035fd4e5da5Sopenharmony_ci
1036fd4e5da5Sopenharmony_ci  ASSERT_TRUE(IsEqual(env, expected_shader, context.get()));
1037fd4e5da5Sopenharmony_ci}
1038fd4e5da5Sopenharmony_ci
1039fd4e5da5Sopenharmony_ciTEST(TransformationEquationInstructionTest, BitcastResultTypeIntDoesNotExist6) {
1040fd4e5da5Sopenharmony_ci  std::string shader = R"(
1041fd4e5da5Sopenharmony_ci               OpCapability Shader
1042fd4e5da5Sopenharmony_ci          %1 = OpExtInstImport "GLSL.std.450"
1043fd4e5da5Sopenharmony_ci               OpMemoryModel Logical GLSL450
1044fd4e5da5Sopenharmony_ci               OpEntryPoint Fragment %12 "main"
1045fd4e5da5Sopenharmony_ci               OpExecutionMode %12 OriginUpperLeft
1046fd4e5da5Sopenharmony_ci               OpSource ESSL 310
1047fd4e5da5Sopenharmony_ci          %2 = OpTypeVoid
1048fd4e5da5Sopenharmony_ci          %3 = OpTypeFunction %2
1049fd4e5da5Sopenharmony_ci          %4 = OpTypeInt 32 1
1050fd4e5da5Sopenharmony_ci          %5 = OpTypeInt 32 0
1051fd4e5da5Sopenharmony_ci          %8 = OpTypeFloat 32
1052fd4e5da5Sopenharmony_ci          %9 = OpTypeVector %5 2
1053fd4e5da5Sopenharmony_ci         %11 = OpTypeVector %8 2
1054fd4e5da5Sopenharmony_ci         %17 = OpConstant %8 24
1055fd4e5da5Sopenharmony_ci         %20 = OpConstantComposite %11 %17 %17
1056fd4e5da5Sopenharmony_ci         %12 = OpFunction %2 None %3
1057fd4e5da5Sopenharmony_ci         %13 = OpLabel
1058fd4e5da5Sopenharmony_ci               OpReturn
1059fd4e5da5Sopenharmony_ci               OpFunctionEnd
1060fd4e5da5Sopenharmony_ci  )";
1061fd4e5da5Sopenharmony_ci
1062fd4e5da5Sopenharmony_ci  const auto env = SPV_ENV_UNIVERSAL_1_3;
1063fd4e5da5Sopenharmony_ci  const auto consumer = nullptr;
1064fd4e5da5Sopenharmony_ci  const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption);
1065fd4e5da5Sopenharmony_ci  spvtools::ValidatorOptions validator_options;
1066fd4e5da5Sopenharmony_ci  ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
1067fd4e5da5Sopenharmony_ci                                               kConsoleMessageConsumer));
1068fd4e5da5Sopenharmony_ci  TransformationContext transformation_context(
1069fd4e5da5Sopenharmony_ci      MakeUnique<FactManager>(context.get()), validator_options);
1070fd4e5da5Sopenharmony_ci  auto insert_before = MakeInstructionDescriptor(13, spv::Op::OpReturn, 0);
1071fd4e5da5Sopenharmony_ci
1072fd4e5da5Sopenharmony_ci  {
1073fd4e5da5Sopenharmony_ci    TransformationEquationInstruction transformation(50, spv::Op::OpBitcast,
1074fd4e5da5Sopenharmony_ci                                                     {17}, insert_before);
1075fd4e5da5Sopenharmony_ci    ASSERT_TRUE(
1076fd4e5da5Sopenharmony_ci        transformation.IsApplicable(context.get(), transformation_context));
1077fd4e5da5Sopenharmony_ci    ApplyAndCheckFreshIds(transformation, context.get(),
1078fd4e5da5Sopenharmony_ci                          &transformation_context);
1079fd4e5da5Sopenharmony_ci  }
1080fd4e5da5Sopenharmony_ci  {
1081fd4e5da5Sopenharmony_ci    TransformationEquationInstruction transformation(51, spv::Op::OpBitcast,
1082fd4e5da5Sopenharmony_ci                                                     {20}, insert_before);
1083fd4e5da5Sopenharmony_ci    ASSERT_TRUE(
1084fd4e5da5Sopenharmony_ci        transformation.IsApplicable(context.get(), transformation_context));
1085fd4e5da5Sopenharmony_ci    ApplyAndCheckFreshIds(transformation, context.get(),
1086fd4e5da5Sopenharmony_ci                          &transformation_context);
1087fd4e5da5Sopenharmony_ci  }
1088fd4e5da5Sopenharmony_ci
1089fd4e5da5Sopenharmony_ci  ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
1090fd4e5da5Sopenharmony_ci                                               kConsoleMessageConsumer));
1091fd4e5da5Sopenharmony_ci
1092fd4e5da5Sopenharmony_ci  std::string expected_shader = R"(
1093fd4e5da5Sopenharmony_ci               OpCapability Shader
1094fd4e5da5Sopenharmony_ci          %1 = OpExtInstImport "GLSL.std.450"
1095fd4e5da5Sopenharmony_ci               OpMemoryModel Logical GLSL450
1096fd4e5da5Sopenharmony_ci               OpEntryPoint Fragment %12 "main"
1097fd4e5da5Sopenharmony_ci               OpExecutionMode %12 OriginUpperLeft
1098fd4e5da5Sopenharmony_ci               OpSource ESSL 310
1099fd4e5da5Sopenharmony_ci          %2 = OpTypeVoid
1100fd4e5da5Sopenharmony_ci          %3 = OpTypeFunction %2
1101fd4e5da5Sopenharmony_ci          %4 = OpTypeInt 32 1
1102fd4e5da5Sopenharmony_ci          %5 = OpTypeInt 32 0
1103fd4e5da5Sopenharmony_ci          %8 = OpTypeFloat 32
1104fd4e5da5Sopenharmony_ci          %9 = OpTypeVector %5 2
1105fd4e5da5Sopenharmony_ci         %11 = OpTypeVector %8 2
1106fd4e5da5Sopenharmony_ci         %17 = OpConstant %8 24
1107fd4e5da5Sopenharmony_ci         %20 = OpConstantComposite %11 %17 %17
1108fd4e5da5Sopenharmony_ci         %12 = OpFunction %2 None %3
1109fd4e5da5Sopenharmony_ci         %13 = OpLabel
1110fd4e5da5Sopenharmony_ci         %50 = OpBitcast %4 %17
1111fd4e5da5Sopenharmony_ci         %51 = OpBitcast %9 %20
1112fd4e5da5Sopenharmony_ci               OpReturn
1113fd4e5da5Sopenharmony_ci               OpFunctionEnd
1114fd4e5da5Sopenharmony_ci  )";
1115fd4e5da5Sopenharmony_ci
1116fd4e5da5Sopenharmony_ci  ASSERT_TRUE(IsEqual(env, expected_shader, context.get()));
1117fd4e5da5Sopenharmony_ci}
1118fd4e5da5Sopenharmony_ci
1119fd4e5da5Sopenharmony_ciTEST(TransformationEquationInstructionTest, BitcastResultTypeIntDoesNotExist7) {
1120fd4e5da5Sopenharmony_ci  std::string shader = R"(
1121fd4e5da5Sopenharmony_ci               OpCapability Shader
1122fd4e5da5Sopenharmony_ci          %1 = OpExtInstImport "GLSL.std.450"
1123fd4e5da5Sopenharmony_ci               OpMemoryModel Logical GLSL450
1124fd4e5da5Sopenharmony_ci               OpEntryPoint Fragment %12 "main"
1125fd4e5da5Sopenharmony_ci               OpExecutionMode %12 OriginUpperLeft
1126fd4e5da5Sopenharmony_ci               OpSource ESSL 310
1127fd4e5da5Sopenharmony_ci          %2 = OpTypeVoid
1128fd4e5da5Sopenharmony_ci          %3 = OpTypeFunction %2
1129fd4e5da5Sopenharmony_ci          %4 = OpTypeInt 32 1
1130fd4e5da5Sopenharmony_ci          %5 = OpTypeInt 32 0
1131fd4e5da5Sopenharmony_ci          %8 = OpTypeFloat 32
1132fd4e5da5Sopenharmony_ci          %9 = OpTypeVector %4 2
1133fd4e5da5Sopenharmony_ci         %11 = OpTypeVector %8 2
1134fd4e5da5Sopenharmony_ci         %17 = OpConstant %8 24
1135fd4e5da5Sopenharmony_ci         %20 = OpConstantComposite %11 %17 %17
1136fd4e5da5Sopenharmony_ci         %12 = OpFunction %2 None %3
1137fd4e5da5Sopenharmony_ci         %13 = OpLabel
1138fd4e5da5Sopenharmony_ci               OpReturn
1139fd4e5da5Sopenharmony_ci               OpFunctionEnd
1140fd4e5da5Sopenharmony_ci  )";
1141fd4e5da5Sopenharmony_ci
1142fd4e5da5Sopenharmony_ci  const auto env = SPV_ENV_UNIVERSAL_1_3;
1143fd4e5da5Sopenharmony_ci  const auto consumer = nullptr;
1144fd4e5da5Sopenharmony_ci  const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption);
1145fd4e5da5Sopenharmony_ci  spvtools::ValidatorOptions validator_options;
1146fd4e5da5Sopenharmony_ci  ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
1147fd4e5da5Sopenharmony_ci                                               kConsoleMessageConsumer));
1148fd4e5da5Sopenharmony_ci  TransformationContext transformation_context(
1149fd4e5da5Sopenharmony_ci      MakeUnique<FactManager>(context.get()), validator_options);
1150fd4e5da5Sopenharmony_ci  auto insert_before = MakeInstructionDescriptor(13, spv::Op::OpReturn, 0);
1151fd4e5da5Sopenharmony_ci
1152fd4e5da5Sopenharmony_ci  {
1153fd4e5da5Sopenharmony_ci    TransformationEquationInstruction transformation(50, spv::Op::OpBitcast,
1154fd4e5da5Sopenharmony_ci                                                     {17}, insert_before);
1155fd4e5da5Sopenharmony_ci    ASSERT_TRUE(
1156fd4e5da5Sopenharmony_ci        transformation.IsApplicable(context.get(), transformation_context));
1157fd4e5da5Sopenharmony_ci    ApplyAndCheckFreshIds(transformation, context.get(),
1158fd4e5da5Sopenharmony_ci                          &transformation_context);
1159fd4e5da5Sopenharmony_ci  }
1160fd4e5da5Sopenharmony_ci  {
1161fd4e5da5Sopenharmony_ci    TransformationEquationInstruction transformation(51, spv::Op::OpBitcast,
1162fd4e5da5Sopenharmony_ci                                                     {20}, insert_before);
1163fd4e5da5Sopenharmony_ci    ASSERT_TRUE(
1164fd4e5da5Sopenharmony_ci        transformation.IsApplicable(context.get(), transformation_context));
1165fd4e5da5Sopenharmony_ci    ApplyAndCheckFreshIds(transformation, context.get(),
1166fd4e5da5Sopenharmony_ci                          &transformation_context);
1167fd4e5da5Sopenharmony_ci  }
1168fd4e5da5Sopenharmony_ci
1169fd4e5da5Sopenharmony_ci  ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
1170fd4e5da5Sopenharmony_ci                                               kConsoleMessageConsumer));
1171fd4e5da5Sopenharmony_ci
1172fd4e5da5Sopenharmony_ci  std::string expected_shader = R"(
1173fd4e5da5Sopenharmony_ci               OpCapability Shader
1174fd4e5da5Sopenharmony_ci          %1 = OpExtInstImport "GLSL.std.450"
1175fd4e5da5Sopenharmony_ci               OpMemoryModel Logical GLSL450
1176fd4e5da5Sopenharmony_ci               OpEntryPoint Fragment %12 "main"
1177fd4e5da5Sopenharmony_ci               OpExecutionMode %12 OriginUpperLeft
1178fd4e5da5Sopenharmony_ci               OpSource ESSL 310
1179fd4e5da5Sopenharmony_ci          %2 = OpTypeVoid
1180fd4e5da5Sopenharmony_ci          %3 = OpTypeFunction %2
1181fd4e5da5Sopenharmony_ci          %4 = OpTypeInt 32 1
1182fd4e5da5Sopenharmony_ci          %5 = OpTypeInt 32 0
1183fd4e5da5Sopenharmony_ci          %8 = OpTypeFloat 32
1184fd4e5da5Sopenharmony_ci          %9 = OpTypeVector %4 2
1185fd4e5da5Sopenharmony_ci         %11 = OpTypeVector %8 2
1186fd4e5da5Sopenharmony_ci         %17 = OpConstant %8 24
1187fd4e5da5Sopenharmony_ci         %20 = OpConstantComposite %11 %17 %17
1188fd4e5da5Sopenharmony_ci         %12 = OpFunction %2 None %3
1189fd4e5da5Sopenharmony_ci         %13 = OpLabel
1190fd4e5da5Sopenharmony_ci         %50 = OpBitcast %4 %17
1191fd4e5da5Sopenharmony_ci         %51 = OpBitcast %9 %20
1192fd4e5da5Sopenharmony_ci               OpReturn
1193fd4e5da5Sopenharmony_ci               OpFunctionEnd
1194fd4e5da5Sopenharmony_ci  )";
1195fd4e5da5Sopenharmony_ci
1196fd4e5da5Sopenharmony_ci  ASSERT_TRUE(IsEqual(env, expected_shader, context.get()));
1197fd4e5da5Sopenharmony_ci}
1198fd4e5da5Sopenharmony_ci
1199fd4e5da5Sopenharmony_ciTEST(TransformationEquationInstructionTest, Miscellaneous1) {
1200fd4e5da5Sopenharmony_ci  std::string shader = R"(
1201fd4e5da5Sopenharmony_ci               OpCapability Shader
1202fd4e5da5Sopenharmony_ci          %1 = OpExtInstImport "GLSL.std.450"
1203fd4e5da5Sopenharmony_ci               OpMemoryModel Logical GLSL450
1204fd4e5da5Sopenharmony_ci               OpEntryPoint Fragment %12 "main"
1205fd4e5da5Sopenharmony_ci               OpExecutionMode %12 OriginUpperLeft
1206fd4e5da5Sopenharmony_ci               OpSource ESSL 310
1207fd4e5da5Sopenharmony_ci          %2 = OpTypeVoid
1208fd4e5da5Sopenharmony_ci          %3 = OpTypeFunction %2
1209fd4e5da5Sopenharmony_ci          %6 = OpTypeInt 32 1
1210fd4e5da5Sopenharmony_ci        %113 = OpConstant %6 24
1211fd4e5da5Sopenharmony_ci         %12 = OpFunction %2 None %3
1212fd4e5da5Sopenharmony_ci         %13 = OpLabel
1213fd4e5da5Sopenharmony_ci               OpReturn
1214fd4e5da5Sopenharmony_ci               OpFunctionEnd
1215fd4e5da5Sopenharmony_ci  )";
1216fd4e5da5Sopenharmony_ci
1217fd4e5da5Sopenharmony_ci  const auto env = SPV_ENV_UNIVERSAL_1_3;
1218fd4e5da5Sopenharmony_ci  const auto consumer = nullptr;
1219fd4e5da5Sopenharmony_ci  const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption);
1220fd4e5da5Sopenharmony_ci  spvtools::ValidatorOptions validator_options;
1221fd4e5da5Sopenharmony_ci  ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
1222fd4e5da5Sopenharmony_ci                                               kConsoleMessageConsumer));
1223fd4e5da5Sopenharmony_ci  TransformationContext transformation_context(
1224fd4e5da5Sopenharmony_ci      MakeUnique<FactManager>(context.get()), validator_options);
1225fd4e5da5Sopenharmony_ci  protobufs::InstructionDescriptor return_instruction =
1226fd4e5da5Sopenharmony_ci      MakeInstructionDescriptor(13, spv::Op::OpReturn, 0);
1227fd4e5da5Sopenharmony_ci
1228fd4e5da5Sopenharmony_ci  auto transformation1 = TransformationEquationInstruction(
1229fd4e5da5Sopenharmony_ci      522, spv::Op::OpISub, {113, 113}, return_instruction);
1230fd4e5da5Sopenharmony_ci  ASSERT_TRUE(
1231fd4e5da5Sopenharmony_ci      transformation1.IsApplicable(context.get(), transformation_context));
1232fd4e5da5Sopenharmony_ci  ApplyAndCheckFreshIds(transformation1, context.get(),
1233fd4e5da5Sopenharmony_ci                        &transformation_context);
1234fd4e5da5Sopenharmony_ci  ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
1235fd4e5da5Sopenharmony_ci                                               kConsoleMessageConsumer));
1236fd4e5da5Sopenharmony_ci
1237fd4e5da5Sopenharmony_ci  auto transformation2 = TransformationEquationInstruction(
1238fd4e5da5Sopenharmony_ci      570, spv::Op::OpIAdd, {522, 113}, return_instruction);
1239fd4e5da5Sopenharmony_ci  ASSERT_TRUE(
1240fd4e5da5Sopenharmony_ci      transformation2.IsApplicable(context.get(), transformation_context));
1241fd4e5da5Sopenharmony_ci  ApplyAndCheckFreshIds(transformation2, context.get(),
1242fd4e5da5Sopenharmony_ci                        &transformation_context);
1243fd4e5da5Sopenharmony_ci  ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
1244fd4e5da5Sopenharmony_ci                                               kConsoleMessageConsumer));
1245fd4e5da5Sopenharmony_ci
1246fd4e5da5Sopenharmony_ci  std::string after_transformation = R"(
1247fd4e5da5Sopenharmony_ci               OpCapability Shader
1248fd4e5da5Sopenharmony_ci          %1 = OpExtInstImport "GLSL.std.450"
1249fd4e5da5Sopenharmony_ci               OpMemoryModel Logical GLSL450
1250fd4e5da5Sopenharmony_ci               OpEntryPoint Fragment %12 "main"
1251fd4e5da5Sopenharmony_ci               OpExecutionMode %12 OriginUpperLeft
1252fd4e5da5Sopenharmony_ci               OpSource ESSL 310
1253fd4e5da5Sopenharmony_ci          %2 = OpTypeVoid
1254fd4e5da5Sopenharmony_ci          %3 = OpTypeFunction %2
1255fd4e5da5Sopenharmony_ci          %6 = OpTypeInt 32 1
1256fd4e5da5Sopenharmony_ci        %113 = OpConstant %6 24
1257fd4e5da5Sopenharmony_ci         %12 = OpFunction %2 None %3
1258fd4e5da5Sopenharmony_ci         %13 = OpLabel
1259fd4e5da5Sopenharmony_ci        %522 = OpISub %6 %113 %113
1260fd4e5da5Sopenharmony_ci        %570 = OpIAdd %6 %522 %113
1261fd4e5da5Sopenharmony_ci               OpReturn
1262fd4e5da5Sopenharmony_ci               OpFunctionEnd
1263fd4e5da5Sopenharmony_ci  )";
1264fd4e5da5Sopenharmony_ci
1265fd4e5da5Sopenharmony_ci  ASSERT_TRUE(transformation_context.GetFactManager()->IsSynonymous(
1266fd4e5da5Sopenharmony_ci      MakeDataDescriptor(570, {}), MakeDataDescriptor(113, {})));
1267fd4e5da5Sopenharmony_ci
1268fd4e5da5Sopenharmony_ci  ASSERT_TRUE(IsEqual(env, after_transformation, context.get()));
1269fd4e5da5Sopenharmony_ci}
1270fd4e5da5Sopenharmony_ci
1271fd4e5da5Sopenharmony_ciTEST(TransformationEquationInstructionTest, Miscellaneous2) {
1272fd4e5da5Sopenharmony_ci  std::string shader = R"(
1273fd4e5da5Sopenharmony_ci               OpCapability Shader
1274fd4e5da5Sopenharmony_ci          %1 = OpExtInstImport "GLSL.std.450"
1275fd4e5da5Sopenharmony_ci               OpMemoryModel Logical GLSL450
1276fd4e5da5Sopenharmony_ci               OpEntryPoint Fragment %12 "main"
1277fd4e5da5Sopenharmony_ci               OpExecutionMode %12 OriginUpperLeft
1278fd4e5da5Sopenharmony_ci               OpSource ESSL 310
1279fd4e5da5Sopenharmony_ci          %2 = OpTypeVoid
1280fd4e5da5Sopenharmony_ci          %3 = OpTypeFunction %2
1281fd4e5da5Sopenharmony_ci          %6 = OpTypeInt 32 1
1282fd4e5da5Sopenharmony_ci        %113 = OpConstant %6 24
1283fd4e5da5Sopenharmony_ci         %12 = OpFunction %2 None %3
1284fd4e5da5Sopenharmony_ci         %13 = OpLabel
1285fd4e5da5Sopenharmony_ci               OpReturn
1286fd4e5da5Sopenharmony_ci               OpFunctionEnd
1287fd4e5da5Sopenharmony_ci  )";
1288fd4e5da5Sopenharmony_ci
1289fd4e5da5Sopenharmony_ci  const auto env = SPV_ENV_UNIVERSAL_1_3;
1290fd4e5da5Sopenharmony_ci  const auto consumer = nullptr;
1291fd4e5da5Sopenharmony_ci  const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption);
1292fd4e5da5Sopenharmony_ci  spvtools::ValidatorOptions validator_options;
1293fd4e5da5Sopenharmony_ci  ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
1294fd4e5da5Sopenharmony_ci                                               kConsoleMessageConsumer));
1295fd4e5da5Sopenharmony_ci  TransformationContext transformation_context(
1296fd4e5da5Sopenharmony_ci      MakeUnique<FactManager>(context.get()), validator_options);
1297fd4e5da5Sopenharmony_ci  protobufs::InstructionDescriptor return_instruction =
1298fd4e5da5Sopenharmony_ci      MakeInstructionDescriptor(13, spv::Op::OpReturn, 0);
1299fd4e5da5Sopenharmony_ci
1300fd4e5da5Sopenharmony_ci  auto transformation1 = TransformationEquationInstruction(
1301fd4e5da5Sopenharmony_ci      522, spv::Op::OpISub, {113, 113}, return_instruction);
1302fd4e5da5Sopenharmony_ci  ASSERT_TRUE(
1303fd4e5da5Sopenharmony_ci      transformation1.IsApplicable(context.get(), transformation_context));
1304fd4e5da5Sopenharmony_ci  ApplyAndCheckFreshIds(transformation1, context.get(),
1305fd4e5da5Sopenharmony_ci                        &transformation_context);
1306fd4e5da5Sopenharmony_ci  ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
1307fd4e5da5Sopenharmony_ci                                               kConsoleMessageConsumer));
1308fd4e5da5Sopenharmony_ci
1309fd4e5da5Sopenharmony_ci  auto transformation2 = TransformationEquationInstruction(
1310fd4e5da5Sopenharmony_ci      570, spv::Op::OpIAdd, {522, 113}, return_instruction);
1311fd4e5da5Sopenharmony_ci  ASSERT_TRUE(
1312fd4e5da5Sopenharmony_ci      transformation2.IsApplicable(context.get(), transformation_context));
1313fd4e5da5Sopenharmony_ci  ApplyAndCheckFreshIds(transformation2, context.get(),
1314fd4e5da5Sopenharmony_ci                        &transformation_context);
1315fd4e5da5Sopenharmony_ci  ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
1316fd4e5da5Sopenharmony_ci                                               kConsoleMessageConsumer));
1317fd4e5da5Sopenharmony_ci
1318fd4e5da5Sopenharmony_ci  std::string after_transformation = R"(
1319fd4e5da5Sopenharmony_ci               OpCapability Shader
1320fd4e5da5Sopenharmony_ci          %1 = OpExtInstImport "GLSL.std.450"
1321fd4e5da5Sopenharmony_ci               OpMemoryModel Logical GLSL450
1322fd4e5da5Sopenharmony_ci               OpEntryPoint Fragment %12 "main"
1323fd4e5da5Sopenharmony_ci               OpExecutionMode %12 OriginUpperLeft
1324fd4e5da5Sopenharmony_ci               OpSource ESSL 310
1325fd4e5da5Sopenharmony_ci          %2 = OpTypeVoid
1326fd4e5da5Sopenharmony_ci          %3 = OpTypeFunction %2
1327fd4e5da5Sopenharmony_ci          %6 = OpTypeInt 32 1
1328fd4e5da5Sopenharmony_ci        %113 = OpConstant %6 24
1329fd4e5da5Sopenharmony_ci         %12 = OpFunction %2 None %3
1330fd4e5da5Sopenharmony_ci         %13 = OpLabel
1331fd4e5da5Sopenharmony_ci        %522 = OpISub %6 %113 %113
1332fd4e5da5Sopenharmony_ci        %570 = OpIAdd %6 %522 %113
1333fd4e5da5Sopenharmony_ci               OpReturn
1334fd4e5da5Sopenharmony_ci               OpFunctionEnd
1335fd4e5da5Sopenharmony_ci  )";
1336fd4e5da5Sopenharmony_ci
1337fd4e5da5Sopenharmony_ci  ASSERT_TRUE(transformation_context.GetFactManager()->IsSynonymous(
1338fd4e5da5Sopenharmony_ci      MakeDataDescriptor(570, {}), MakeDataDescriptor(113, {})));
1339fd4e5da5Sopenharmony_ci
1340fd4e5da5Sopenharmony_ci  ASSERT_TRUE(IsEqual(env, after_transformation, context.get()));
1341fd4e5da5Sopenharmony_ci}
1342fd4e5da5Sopenharmony_ci
1343fd4e5da5Sopenharmony_ciTEST(TransformationEquationInstructionTest, ConversionInstructions) {
1344fd4e5da5Sopenharmony_ci  std::string shader = R"(
1345fd4e5da5Sopenharmony_ci               OpCapability Shader
1346fd4e5da5Sopenharmony_ci          %1 = OpExtInstImport "GLSL.std.450"
1347fd4e5da5Sopenharmony_ci               OpMemoryModel Logical GLSL450
1348fd4e5da5Sopenharmony_ci               OpEntryPoint Fragment %12 "main"
1349fd4e5da5Sopenharmony_ci               OpExecutionMode %12 OriginUpperLeft
1350fd4e5da5Sopenharmony_ci               OpSource ESSL 310
1351fd4e5da5Sopenharmony_ci          %2 = OpTypeVoid
1352fd4e5da5Sopenharmony_ci          %3 = OpTypeFunction %2
1353fd4e5da5Sopenharmony_ci          %6 = OpTypeInt 32 1
1354fd4e5da5Sopenharmony_ci          %4 = OpTypeInt 32 0
1355fd4e5da5Sopenharmony_ci          %5 = OpTypeFloat 32
1356fd4e5da5Sopenharmony_ci          %7 = OpTypeVector %6 3
1357fd4e5da5Sopenharmony_ci          %8 = OpTypeVector %4 3
1358fd4e5da5Sopenharmony_ci          %9 = OpTypeVector %5 3
1359fd4e5da5Sopenharmony_ci         %10 = OpConstant %6 12
1360fd4e5da5Sopenharmony_ci         %20 = OpConstant %6 12
1361fd4e5da5Sopenharmony_ci         %11 = OpConstant %4 12
1362fd4e5da5Sopenharmony_ci         %21 = OpConstant %4 12
1363fd4e5da5Sopenharmony_ci         %14 = OpConstant %5 12
1364fd4e5da5Sopenharmony_ci         %15 = OpConstantComposite %7 %10 %10 %10
1365fd4e5da5Sopenharmony_ci         %18 = OpConstantComposite %7 %10 %10 %10
1366fd4e5da5Sopenharmony_ci         %16 = OpConstantComposite %8 %11 %11 %11
1367fd4e5da5Sopenharmony_ci         %19 = OpConstantComposite %8 %11 %11 %11
1368fd4e5da5Sopenharmony_ci         %17 = OpConstantComposite %9 %14 %14 %14
1369fd4e5da5Sopenharmony_ci         %12 = OpFunction %2 None %3
1370fd4e5da5Sopenharmony_ci         %13 = OpLabel
1371fd4e5da5Sopenharmony_ci               OpReturn
1372fd4e5da5Sopenharmony_ci               OpFunctionEnd
1373fd4e5da5Sopenharmony_ci  )";
1374fd4e5da5Sopenharmony_ci
1375fd4e5da5Sopenharmony_ci  const auto env = SPV_ENV_UNIVERSAL_1_3;
1376fd4e5da5Sopenharmony_ci  const auto consumer = nullptr;
1377fd4e5da5Sopenharmony_ci  const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption);
1378fd4e5da5Sopenharmony_ci  spvtools::ValidatorOptions validator_options;
1379fd4e5da5Sopenharmony_ci  ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
1380fd4e5da5Sopenharmony_ci                                               kConsoleMessageConsumer));
1381fd4e5da5Sopenharmony_ci  TransformationContext transformation_context(
1382fd4e5da5Sopenharmony_ci      MakeUnique<FactManager>(context.get()), validator_options);
1383fd4e5da5Sopenharmony_ci  protobufs::InstructionDescriptor return_instruction =
1384fd4e5da5Sopenharmony_ci      MakeInstructionDescriptor(13, spv::Op::OpReturn, 0);
1385fd4e5da5Sopenharmony_ci
1386fd4e5da5Sopenharmony_ci  // Too few instruction operands.
1387fd4e5da5Sopenharmony_ci  ASSERT_FALSE(TransformationEquationInstruction(50, spv::Op::OpConvertSToF, {},
1388fd4e5da5Sopenharmony_ci                                                 return_instruction)
1389fd4e5da5Sopenharmony_ci                   .IsApplicable(context.get(), transformation_context));
1390fd4e5da5Sopenharmony_ci
1391fd4e5da5Sopenharmony_ci  // Too many instruction operands.
1392fd4e5da5Sopenharmony_ci  ASSERT_FALSE(TransformationEquationInstruction(50, spv::Op::OpConvertSToF,
1393fd4e5da5Sopenharmony_ci                                                 {15, 16}, return_instruction)
1394fd4e5da5Sopenharmony_ci                   .IsApplicable(context.get(), transformation_context));
1395fd4e5da5Sopenharmony_ci
1396fd4e5da5Sopenharmony_ci  // Operand has no type id.
1397fd4e5da5Sopenharmony_ci  ASSERT_FALSE(TransformationEquationInstruction(50, spv::Op::OpConvertSToF,
1398fd4e5da5Sopenharmony_ci                                                 {7}, return_instruction)
1399fd4e5da5Sopenharmony_ci                   .IsApplicable(context.get(), transformation_context));
1400fd4e5da5Sopenharmony_ci
1401fd4e5da5Sopenharmony_ci  // OpConvertSToF and OpConvertUToF require an operand to have scalar or vector
1402fd4e5da5Sopenharmony_ci  // of integral components type.
1403fd4e5da5Sopenharmony_ci  ASSERT_FALSE(TransformationEquationInstruction(50, spv::Op::OpConvertSToF,
1404fd4e5da5Sopenharmony_ci                                                 {17}, return_instruction)
1405fd4e5da5Sopenharmony_ci                   .IsApplicable(context.get(), transformation_context));
1406fd4e5da5Sopenharmony_ci  ASSERT_FALSE(TransformationEquationInstruction(50, spv::Op::OpConvertSToF,
1407fd4e5da5Sopenharmony_ci                                                 {14}, return_instruction)
1408fd4e5da5Sopenharmony_ci                   .IsApplicable(context.get(), transformation_context));
1409fd4e5da5Sopenharmony_ci  ASSERT_FALSE(TransformationEquationInstruction(50, spv::Op::OpConvertUToF,
1410fd4e5da5Sopenharmony_ci                                                 {17}, return_instruction)
1411fd4e5da5Sopenharmony_ci                   .IsApplicable(context.get(), transformation_context));
1412fd4e5da5Sopenharmony_ci  ASSERT_FALSE(TransformationEquationInstruction(50, spv::Op::OpConvertUToF,
1413fd4e5da5Sopenharmony_ci                                                 {14}, return_instruction)
1414fd4e5da5Sopenharmony_ci                   .IsApplicable(context.get(), transformation_context));
1415fd4e5da5Sopenharmony_ci
1416fd4e5da5Sopenharmony_ci  {
1417fd4e5da5Sopenharmony_ci    TransformationEquationInstruction transformation(50, spv::Op::OpConvertSToF,
1418fd4e5da5Sopenharmony_ci                                                     {15}, return_instruction);
1419fd4e5da5Sopenharmony_ci    ASSERT_TRUE(
1420fd4e5da5Sopenharmony_ci        transformation.IsApplicable(context.get(), transformation_context));
1421fd4e5da5Sopenharmony_ci    ApplyAndCheckFreshIds(transformation, context.get(),
1422fd4e5da5Sopenharmony_ci                          &transformation_context);
1423fd4e5da5Sopenharmony_ci  }
1424fd4e5da5Sopenharmony_ci  {
1425fd4e5da5Sopenharmony_ci    TransformationEquationInstruction transformation(51, spv::Op::OpConvertSToF,
1426fd4e5da5Sopenharmony_ci                                                     {10}, return_instruction);
1427fd4e5da5Sopenharmony_ci    ASSERT_TRUE(
1428fd4e5da5Sopenharmony_ci        transformation.IsApplicable(context.get(), transformation_context));
1429fd4e5da5Sopenharmony_ci    ApplyAndCheckFreshIds(transformation, context.get(),
1430fd4e5da5Sopenharmony_ci                          &transformation_context);
1431fd4e5da5Sopenharmony_ci  }
1432fd4e5da5Sopenharmony_ci  {
1433fd4e5da5Sopenharmony_ci    TransformationEquationInstruction transformation(52, spv::Op::OpConvertUToF,
1434fd4e5da5Sopenharmony_ci                                                     {16}, return_instruction);
1435fd4e5da5Sopenharmony_ci    ASSERT_TRUE(
1436fd4e5da5Sopenharmony_ci        transformation.IsApplicable(context.get(), transformation_context));
1437fd4e5da5Sopenharmony_ci    ApplyAndCheckFreshIds(transformation, context.get(),
1438fd4e5da5Sopenharmony_ci                          &transformation_context);
1439fd4e5da5Sopenharmony_ci  }
1440fd4e5da5Sopenharmony_ci  {
1441fd4e5da5Sopenharmony_ci    TransformationEquationInstruction transformation(53, spv::Op::OpConvertUToF,
1442fd4e5da5Sopenharmony_ci                                                     {11}, return_instruction);
1443fd4e5da5Sopenharmony_ci    ASSERT_TRUE(
1444fd4e5da5Sopenharmony_ci        transformation.IsApplicable(context.get(), transformation_context));
1445fd4e5da5Sopenharmony_ci    ApplyAndCheckFreshIds(transformation, context.get(),
1446fd4e5da5Sopenharmony_ci                          &transformation_context);
1447fd4e5da5Sopenharmony_ci  }
1448fd4e5da5Sopenharmony_ci  {
1449fd4e5da5Sopenharmony_ci    TransformationEquationInstruction transformation(58, spv::Op::OpConvertSToF,
1450fd4e5da5Sopenharmony_ci                                                     {18}, return_instruction);
1451fd4e5da5Sopenharmony_ci    ASSERT_TRUE(
1452fd4e5da5Sopenharmony_ci        transformation.IsApplicable(context.get(), transformation_context));
1453fd4e5da5Sopenharmony_ci    ApplyAndCheckFreshIds(transformation, context.get(),
1454fd4e5da5Sopenharmony_ci                          &transformation_context);
1455fd4e5da5Sopenharmony_ci  }
1456fd4e5da5Sopenharmony_ci  {
1457fd4e5da5Sopenharmony_ci    TransformationEquationInstruction transformation(59, spv::Op::OpConvertUToF,
1458fd4e5da5Sopenharmony_ci                                                     {19}, return_instruction);
1459fd4e5da5Sopenharmony_ci    ASSERT_TRUE(
1460fd4e5da5Sopenharmony_ci        transformation.IsApplicable(context.get(), transformation_context));
1461fd4e5da5Sopenharmony_ci    ApplyAndCheckFreshIds(transformation, context.get(),
1462fd4e5da5Sopenharmony_ci                          &transformation_context);
1463fd4e5da5Sopenharmony_ci  }
1464fd4e5da5Sopenharmony_ci  {
1465fd4e5da5Sopenharmony_ci    TransformationEquationInstruction transformation(60, spv::Op::OpConvertSToF,
1466fd4e5da5Sopenharmony_ci                                                     {20}, return_instruction);
1467fd4e5da5Sopenharmony_ci    ASSERT_TRUE(
1468fd4e5da5Sopenharmony_ci        transformation.IsApplicable(context.get(), transformation_context));
1469fd4e5da5Sopenharmony_ci    ApplyAndCheckFreshIds(transformation, context.get(),
1470fd4e5da5Sopenharmony_ci                          &transformation_context);
1471fd4e5da5Sopenharmony_ci  }
1472fd4e5da5Sopenharmony_ci  {
1473fd4e5da5Sopenharmony_ci    TransformationEquationInstruction transformation(61, spv::Op::OpConvertUToF,
1474fd4e5da5Sopenharmony_ci                                                     {21}, return_instruction);
1475fd4e5da5Sopenharmony_ci    ASSERT_TRUE(
1476fd4e5da5Sopenharmony_ci        transformation.IsApplicable(context.get(), transformation_context));
1477fd4e5da5Sopenharmony_ci    ApplyAndCheckFreshIds(transformation, context.get(),
1478fd4e5da5Sopenharmony_ci                          &transformation_context);
1479fd4e5da5Sopenharmony_ci  }
1480fd4e5da5Sopenharmony_ci
1481fd4e5da5Sopenharmony_ci  ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
1482fd4e5da5Sopenharmony_ci                                               kConsoleMessageConsumer));
1483fd4e5da5Sopenharmony_ci
1484fd4e5da5Sopenharmony_ci  std::string after_transformations = R"(
1485fd4e5da5Sopenharmony_ci               OpCapability Shader
1486fd4e5da5Sopenharmony_ci          %1 = OpExtInstImport "GLSL.std.450"
1487fd4e5da5Sopenharmony_ci               OpMemoryModel Logical GLSL450
1488fd4e5da5Sopenharmony_ci               OpEntryPoint Fragment %12 "main"
1489fd4e5da5Sopenharmony_ci               OpExecutionMode %12 OriginUpperLeft
1490fd4e5da5Sopenharmony_ci               OpSource ESSL 310
1491fd4e5da5Sopenharmony_ci          %2 = OpTypeVoid
1492fd4e5da5Sopenharmony_ci          %3 = OpTypeFunction %2
1493fd4e5da5Sopenharmony_ci          %6 = OpTypeInt 32 1
1494fd4e5da5Sopenharmony_ci          %4 = OpTypeInt 32 0
1495fd4e5da5Sopenharmony_ci          %5 = OpTypeFloat 32
1496fd4e5da5Sopenharmony_ci          %7 = OpTypeVector %6 3
1497fd4e5da5Sopenharmony_ci          %8 = OpTypeVector %4 3
1498fd4e5da5Sopenharmony_ci          %9 = OpTypeVector %5 3
1499fd4e5da5Sopenharmony_ci         %10 = OpConstant %6 12
1500fd4e5da5Sopenharmony_ci         %20 = OpConstant %6 12
1501fd4e5da5Sopenharmony_ci         %11 = OpConstant %4 12
1502fd4e5da5Sopenharmony_ci         %21 = OpConstant %4 12
1503fd4e5da5Sopenharmony_ci         %14 = OpConstant %5 12
1504fd4e5da5Sopenharmony_ci         %15 = OpConstantComposite %7 %10 %10 %10
1505fd4e5da5Sopenharmony_ci         %18 = OpConstantComposite %7 %10 %10 %10
1506fd4e5da5Sopenharmony_ci         %16 = OpConstantComposite %8 %11 %11 %11
1507fd4e5da5Sopenharmony_ci         %19 = OpConstantComposite %8 %11 %11 %11
1508fd4e5da5Sopenharmony_ci         %17 = OpConstantComposite %9 %14 %14 %14
1509fd4e5da5Sopenharmony_ci         %12 = OpFunction %2 None %3
1510fd4e5da5Sopenharmony_ci         %13 = OpLabel
1511fd4e5da5Sopenharmony_ci         %50 = OpConvertSToF %9 %15
1512fd4e5da5Sopenharmony_ci         %51 = OpConvertSToF %5 %10
1513fd4e5da5Sopenharmony_ci         %52 = OpConvertUToF %9 %16
1514fd4e5da5Sopenharmony_ci         %53 = OpConvertUToF %5 %11
1515fd4e5da5Sopenharmony_ci         %58 = OpConvertSToF %9 %18
1516fd4e5da5Sopenharmony_ci         %59 = OpConvertUToF %9 %19
1517fd4e5da5Sopenharmony_ci         %60 = OpConvertSToF %5 %20
1518fd4e5da5Sopenharmony_ci         %61 = OpConvertUToF %5 %21
1519fd4e5da5Sopenharmony_ci               OpReturn
1520fd4e5da5Sopenharmony_ci               OpFunctionEnd
1521fd4e5da5Sopenharmony_ci  )";
1522fd4e5da5Sopenharmony_ci
1523fd4e5da5Sopenharmony_ci  ASSERT_TRUE(IsEqual(env, after_transformations, context.get()));
1524fd4e5da5Sopenharmony_ci}
1525fd4e5da5Sopenharmony_ci
1526fd4e5da5Sopenharmony_ciTEST(TransformationEquationInstructionTest, FloatResultTypeDoesNotExist) {
1527fd4e5da5Sopenharmony_ci  std::string shader = R"(
1528fd4e5da5Sopenharmony_ci               OpCapability Shader
1529fd4e5da5Sopenharmony_ci          %1 = OpExtInstImport "GLSL.std.450"
1530fd4e5da5Sopenharmony_ci               OpMemoryModel Logical GLSL450
1531fd4e5da5Sopenharmony_ci               OpEntryPoint Fragment %12 "main"
1532fd4e5da5Sopenharmony_ci               OpExecutionMode %12 OriginUpperLeft
1533fd4e5da5Sopenharmony_ci               OpSource ESSL 310
1534fd4e5da5Sopenharmony_ci          %2 = OpTypeVoid
1535fd4e5da5Sopenharmony_ci          %3 = OpTypeFunction %2
1536fd4e5da5Sopenharmony_ci          %6 = OpTypeInt 32 0
1537fd4e5da5Sopenharmony_ci          %7 = OpTypeInt 32 1
1538fd4e5da5Sopenharmony_ci          %8 = OpTypeVector %6 3
1539fd4e5da5Sopenharmony_ci          %9 = OpTypeVector %7 3
1540fd4e5da5Sopenharmony_ci         %10 = OpConstant %6 24
1541fd4e5da5Sopenharmony_ci         %11 = OpConstant %7 25
1542fd4e5da5Sopenharmony_ci         %14 = OpConstantComposite %8 %10 %10 %10
1543fd4e5da5Sopenharmony_ci         %15 = OpConstantComposite %9 %11 %11 %11
1544fd4e5da5Sopenharmony_ci         %12 = OpFunction %2 None %3
1545fd4e5da5Sopenharmony_ci         %13 = OpLabel
1546fd4e5da5Sopenharmony_ci               OpReturn
1547fd4e5da5Sopenharmony_ci               OpFunctionEnd
1548fd4e5da5Sopenharmony_ci  )";
1549fd4e5da5Sopenharmony_ci
1550fd4e5da5Sopenharmony_ci  const auto env = SPV_ENV_UNIVERSAL_1_3;
1551fd4e5da5Sopenharmony_ci  const auto consumer = nullptr;
1552fd4e5da5Sopenharmony_ci  const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption);
1553fd4e5da5Sopenharmony_ci  spvtools::ValidatorOptions validator_options;
1554fd4e5da5Sopenharmony_ci  ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
1555fd4e5da5Sopenharmony_ci                                               kConsoleMessageConsumer));
1556fd4e5da5Sopenharmony_ci  TransformationContext transformation_context(
1557fd4e5da5Sopenharmony_ci      MakeUnique<FactManager>(context.get()), validator_options);
1558fd4e5da5Sopenharmony_ci  protobufs::InstructionDescriptor return_instruction =
1559fd4e5da5Sopenharmony_ci      MakeInstructionDescriptor(13, spv::Op::OpReturn, 0);
1560fd4e5da5Sopenharmony_ci
1561fd4e5da5Sopenharmony_ci  // Scalar float type doesn't exist.
1562fd4e5da5Sopenharmony_ci  ASSERT_FALSE(TransformationEquationInstruction(16, spv::Op::OpConvertUToF,
1563fd4e5da5Sopenharmony_ci                                                 {10}, return_instruction)
1564fd4e5da5Sopenharmony_ci                   .IsApplicable(context.get(), transformation_context));
1565fd4e5da5Sopenharmony_ci  ASSERT_FALSE(TransformationEquationInstruction(16, spv::Op::OpConvertSToF,
1566fd4e5da5Sopenharmony_ci                                                 {11}, return_instruction)
1567fd4e5da5Sopenharmony_ci                   .IsApplicable(context.get(), transformation_context));
1568fd4e5da5Sopenharmony_ci
1569fd4e5da5Sopenharmony_ci  // Vector float type doesn't exist.
1570fd4e5da5Sopenharmony_ci  ASSERT_FALSE(TransformationEquationInstruction(16, spv::Op::OpConvertUToF,
1571fd4e5da5Sopenharmony_ci                                                 {14}, return_instruction)
1572fd4e5da5Sopenharmony_ci                   .IsApplicable(context.get(), transformation_context));
1573fd4e5da5Sopenharmony_ci  ASSERT_FALSE(TransformationEquationInstruction(16, spv::Op::OpConvertSToF,
1574fd4e5da5Sopenharmony_ci                                                 {15}, return_instruction)
1575fd4e5da5Sopenharmony_ci                   .IsApplicable(context.get(), transformation_context));
1576fd4e5da5Sopenharmony_ci}
1577fd4e5da5Sopenharmony_ci
1578fd4e5da5Sopenharmony_ciTEST(TransformationEquationInstructionTest, HandlesIrrelevantIds) {
1579fd4e5da5Sopenharmony_ci  std::string shader = R"(
1580fd4e5da5Sopenharmony_ci               OpCapability Shader
1581fd4e5da5Sopenharmony_ci          %1 = OpExtInstImport "GLSL.std.450"
1582fd4e5da5Sopenharmony_ci               OpMemoryModel Logical GLSL450
1583fd4e5da5Sopenharmony_ci               OpEntryPoint Fragment %12 "main"
1584fd4e5da5Sopenharmony_ci               OpExecutionMode %12 OriginUpperLeft
1585fd4e5da5Sopenharmony_ci               OpSource ESSL 310
1586fd4e5da5Sopenharmony_ci          %2 = OpTypeVoid
1587fd4e5da5Sopenharmony_ci          %3 = OpTypeFunction %2
1588fd4e5da5Sopenharmony_ci          %6 = OpTypeInt 32 1
1589fd4e5da5Sopenharmony_ci         %30 = OpTypeVector %6 3
1590fd4e5da5Sopenharmony_ci         %15 = OpConstant %6 24
1591fd4e5da5Sopenharmony_ci         %16 = OpConstant %6 37
1592fd4e5da5Sopenharmony_ci         %31 = OpConstantComposite %30 %15 %16 %15
1593fd4e5da5Sopenharmony_ci         %33 = OpTypeBool
1594fd4e5da5Sopenharmony_ci         %32 = OpConstantTrue %33
1595fd4e5da5Sopenharmony_ci         %12 = OpFunction %2 None %3
1596fd4e5da5Sopenharmony_ci         %13 = OpLabel
1597fd4e5da5Sopenharmony_ci               OpReturn
1598fd4e5da5Sopenharmony_ci               OpFunctionEnd
1599fd4e5da5Sopenharmony_ci  )";
1600fd4e5da5Sopenharmony_ci
1601fd4e5da5Sopenharmony_ci  const auto env = SPV_ENV_UNIVERSAL_1_3;
1602fd4e5da5Sopenharmony_ci  const auto consumer = nullptr;
1603fd4e5da5Sopenharmony_ci  const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption);
1604fd4e5da5Sopenharmony_ci  spvtools::ValidatorOptions validator_options;
1605fd4e5da5Sopenharmony_ci  ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
1606fd4e5da5Sopenharmony_ci                                               kConsoleMessageConsumer));
1607fd4e5da5Sopenharmony_ci  TransformationContext transformation_context(
1608fd4e5da5Sopenharmony_ci      MakeUnique<FactManager>(context.get()), validator_options);
1609fd4e5da5Sopenharmony_ci  auto return_instruction = MakeInstructionDescriptor(13, spv::Op::OpReturn, 0);
1610fd4e5da5Sopenharmony_ci
1611fd4e5da5Sopenharmony_ci  // Applicable.
1612fd4e5da5Sopenharmony_ci  TransformationEquationInstruction transformation(
1613fd4e5da5Sopenharmony_ci      14, spv::Op::OpIAdd, {15, 16}, return_instruction);
1614fd4e5da5Sopenharmony_ci  ASSERT_TRUE(
1615fd4e5da5Sopenharmony_ci      transformation.IsApplicable(context.get(), transformation_context));
1616fd4e5da5Sopenharmony_ci
1617fd4e5da5Sopenharmony_ci  // Handles irrelevant ids.
1618fd4e5da5Sopenharmony_ci  transformation_context.GetFactManager()->AddFactIdIsIrrelevant(16);
1619fd4e5da5Sopenharmony_ci  ASSERT_FALSE(
1620fd4e5da5Sopenharmony_ci      transformation.IsApplicable(context.get(), transformation_context));
1621fd4e5da5Sopenharmony_ci  transformation_context.GetFactManager()->AddFactIdIsIrrelevant(15);
1622fd4e5da5Sopenharmony_ci  ASSERT_FALSE(
1623fd4e5da5Sopenharmony_ci      transformation.IsApplicable(context.get(), transformation_context));
1624fd4e5da5Sopenharmony_ci}
1625fd4e5da5Sopenharmony_ci
1626fd4e5da5Sopenharmony_ciTEST(TransformationEquationInstructionTest, HandlesDeadBlock) {
1627fd4e5da5Sopenharmony_ci  std::string shader = R"(
1628fd4e5da5Sopenharmony_ci               OpCapability Shader
1629fd4e5da5Sopenharmony_ci          %1 = OpExtInstImport "GLSL.std.450"
1630fd4e5da5Sopenharmony_ci               OpMemoryModel Logical GLSL450
1631fd4e5da5Sopenharmony_ci               OpEntryPoint Fragment %12 "main"
1632fd4e5da5Sopenharmony_ci               OpExecutionMode %12 OriginUpperLeft
1633fd4e5da5Sopenharmony_ci               OpSource ESSL 310
1634fd4e5da5Sopenharmony_ci          %2 = OpTypeVoid
1635fd4e5da5Sopenharmony_ci          %3 = OpTypeFunction %2
1636fd4e5da5Sopenharmony_ci          %6 = OpTypeInt 32 1
1637fd4e5da5Sopenharmony_ci         %30 = OpTypeVector %6 3
1638fd4e5da5Sopenharmony_ci         %15 = OpConstant %6 24
1639fd4e5da5Sopenharmony_ci         %16 = OpConstant %6 37
1640fd4e5da5Sopenharmony_ci         %31 = OpConstantComposite %30 %15 %16 %15
1641fd4e5da5Sopenharmony_ci         %33 = OpTypeBool
1642fd4e5da5Sopenharmony_ci         %32 = OpConstantTrue %33
1643fd4e5da5Sopenharmony_ci         %12 = OpFunction %2 None %3
1644fd4e5da5Sopenharmony_ci         %13 = OpLabel
1645fd4e5da5Sopenharmony_ci               OpSelectionMerge %40 None
1646fd4e5da5Sopenharmony_ci               OpBranchConditional %32 %40 %41
1647fd4e5da5Sopenharmony_ci         %41 = OpLabel
1648fd4e5da5Sopenharmony_ci               OpBranch %40
1649fd4e5da5Sopenharmony_ci         %40 = OpLabel
1650fd4e5da5Sopenharmony_ci               OpReturn
1651fd4e5da5Sopenharmony_ci               OpFunctionEnd
1652fd4e5da5Sopenharmony_ci  )";
1653fd4e5da5Sopenharmony_ci
1654fd4e5da5Sopenharmony_ci  const auto env = SPV_ENV_UNIVERSAL_1_3;
1655fd4e5da5Sopenharmony_ci  const auto consumer = nullptr;
1656fd4e5da5Sopenharmony_ci  const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption);
1657fd4e5da5Sopenharmony_ci  spvtools::ValidatorOptions validator_options;
1658fd4e5da5Sopenharmony_ci  ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
1659fd4e5da5Sopenharmony_ci                                               kConsoleMessageConsumer));
1660fd4e5da5Sopenharmony_ci  TransformationContext transformation_context(
1661fd4e5da5Sopenharmony_ci      MakeUnique<FactManager>(context.get()), validator_options);
1662fd4e5da5Sopenharmony_ci
1663fd4e5da5Sopenharmony_ci  transformation_context.GetFactManager()->AddFactBlockIsDead(41);
1664fd4e5da5Sopenharmony_ci
1665fd4e5da5Sopenharmony_ci  TransformationEquationInstruction transformation1(
1666fd4e5da5Sopenharmony_ci      14, spv::Op::OpIAdd, {15, 16},
1667fd4e5da5Sopenharmony_ci      MakeInstructionDescriptor(13, spv::Op::OpSelectionMerge, 0));
1668fd4e5da5Sopenharmony_ci  // No synonym is created since block is dead.
1669fd4e5da5Sopenharmony_ci  TransformationEquationInstruction transformation2(
1670fd4e5da5Sopenharmony_ci      100, spv::Op::OpISub, {14, 16},
1671fd4e5da5Sopenharmony_ci      MakeInstructionDescriptor(41, spv::Op::OpBranch, 0));
1672fd4e5da5Sopenharmony_ci  ASSERT_TRUE(
1673fd4e5da5Sopenharmony_ci      transformation1.IsApplicable(context.get(), transformation_context));
1674fd4e5da5Sopenharmony_ci  ApplyAndCheckFreshIds(transformation1, context.get(),
1675fd4e5da5Sopenharmony_ci                        &transformation_context);
1676fd4e5da5Sopenharmony_ci  ASSERT_TRUE(
1677fd4e5da5Sopenharmony_ci      transformation2.IsApplicable(context.get(), transformation_context));
1678fd4e5da5Sopenharmony_ci  ApplyAndCheckFreshIds(transformation2, context.get(),
1679fd4e5da5Sopenharmony_ci                        &transformation_context);
1680fd4e5da5Sopenharmony_ci  ASSERT_FALSE(transformation_context.GetFactManager()->IsSynonymous(
1681fd4e5da5Sopenharmony_ci      MakeDataDescriptor(100, {}), MakeDataDescriptor(15, {})));
1682fd4e5da5Sopenharmony_ci}
1683fd4e5da5Sopenharmony_ci
1684fd4e5da5Sopenharmony_ci}  // namespace
1685fd4e5da5Sopenharmony_ci}  // namespace fuzz
1686fd4e5da5Sopenharmony_ci}  // namespace spvtools
1687