1fd4e5da5Sopenharmony_ci// Copyright (c) 2019 Google LLC
2fd4e5da5Sopenharmony_ci//
3fd4e5da5Sopenharmony_ci// Licensed under the Apache License, Version 2.0 (the "License");
4fd4e5da5Sopenharmony_ci// you may not use this file except in compliance with the License.
5fd4e5da5Sopenharmony_ci// You may obtain a copy of the License at
6fd4e5da5Sopenharmony_ci//
7fd4e5da5Sopenharmony_ci//     http://www.apache.org/licenses/LICENSE-2.0
8fd4e5da5Sopenharmony_ci//
9fd4e5da5Sopenharmony_ci// Unless required by applicable law or agreed to in writing, software
10fd4e5da5Sopenharmony_ci// distributed under the License is distributed on an "AS IS" BASIS,
11fd4e5da5Sopenharmony_ci// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12fd4e5da5Sopenharmony_ci// See the License for the specific language governing permissions and
13fd4e5da5Sopenharmony_ci// limitations under the License.
14fd4e5da5Sopenharmony_ci
15fd4e5da5Sopenharmony_ci#include "source/fuzz/transformation_composite_extract.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(TransformationCompositeExtractTest, BasicTest) {
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 %4 "main"
32fd4e5da5Sopenharmony_ci               OpExecutionMode %4 OriginUpperLeft
33fd4e5da5Sopenharmony_ci               OpSource ESSL 310
34fd4e5da5Sopenharmony_ci               OpName %4 "main"
35fd4e5da5Sopenharmony_ci               OpName %8 "a"
36fd4e5da5Sopenharmony_ci               OpName %10 "b"
37fd4e5da5Sopenharmony_ci               OpName %17 "FunnyPoint"
38fd4e5da5Sopenharmony_ci               OpMemberName %17 0 "x"
39fd4e5da5Sopenharmony_ci               OpMemberName %17 1 "y"
40fd4e5da5Sopenharmony_ci               OpMemberName %17 2 "z"
41fd4e5da5Sopenharmony_ci               OpName %19 "p"
42fd4e5da5Sopenharmony_ci          %2 = OpTypeVoid
43fd4e5da5Sopenharmony_ci          %3 = OpTypeFunction %2
44fd4e5da5Sopenharmony_ci          %6 = OpTypeInt 32 1
45fd4e5da5Sopenharmony_ci          %7 = OpTypePointer Function %6
46fd4e5da5Sopenharmony_ci         %12 = OpTypeBool
47fd4e5da5Sopenharmony_ci         %16 = OpTypeFloat 32
48fd4e5da5Sopenharmony_ci         %17 = OpTypeStruct %16 %16 %6
49fd4e5da5Sopenharmony_ci         %81 = OpTypeStruct %17 %16
50fd4e5da5Sopenharmony_ci         %18 = OpTypePointer Function %17
51fd4e5da5Sopenharmony_ci         %20 = OpConstant %6 0
52fd4e5da5Sopenharmony_ci         %23 = OpTypePointer Function %16
53fd4e5da5Sopenharmony_ci         %26 = OpConstant %6 1
54fd4e5da5Sopenharmony_ci         %30 = OpConstant %6 2
55fd4e5da5Sopenharmony_ci         %80 = OpUndef %16
56fd4e5da5Sopenharmony_ci          %4 = OpFunction %2 None %3
57fd4e5da5Sopenharmony_ci          %5 = OpLabel
58fd4e5da5Sopenharmony_ci          %8 = OpVariable %7 Function
59fd4e5da5Sopenharmony_ci         %10 = OpVariable %7 Function
60fd4e5da5Sopenharmony_ci         %19 = OpVariable %18 Function
61fd4e5da5Sopenharmony_ci          %9 = OpLoad %6 %8
62fd4e5da5Sopenharmony_ci         %11 = OpLoad %6 %10
63fd4e5da5Sopenharmony_ci        %100 = OpCompositeConstruct %17 %80 %80 %26
64fd4e5da5Sopenharmony_ci        %104 = OpCompositeConstruct %81 %100 %80
65fd4e5da5Sopenharmony_ci         %13 = OpIEqual %12 %9 %11
66fd4e5da5Sopenharmony_ci               OpSelectionMerge %15 None
67fd4e5da5Sopenharmony_ci               OpBranchConditional %13 %14 %25
68fd4e5da5Sopenharmony_ci         %14 = OpLabel
69fd4e5da5Sopenharmony_ci         %21 = OpLoad %6 %8
70fd4e5da5Sopenharmony_ci         %22 = OpConvertSToF %16 %21
71fd4e5da5Sopenharmony_ci        %101 = OpCompositeConstruct %17 %22 %80 %30
72fd4e5da5Sopenharmony_ci         %24 = OpAccessChain %23 %19 %20
73fd4e5da5Sopenharmony_ci               OpStore %24 %22
74fd4e5da5Sopenharmony_ci               OpBranch %15
75fd4e5da5Sopenharmony_ci         %25 = OpLabel
76fd4e5da5Sopenharmony_ci         %27 = OpLoad %6 %10
77fd4e5da5Sopenharmony_ci         %28 = OpConvertSToF %16 %27
78fd4e5da5Sopenharmony_ci        %102 = OpCompositeConstruct %17 %80 %28 %27
79fd4e5da5Sopenharmony_ci         %29 = OpAccessChain %23 %19 %26
80fd4e5da5Sopenharmony_ci               OpStore %29 %28
81fd4e5da5Sopenharmony_ci               OpBranch %15
82fd4e5da5Sopenharmony_ci         %15 = OpLabel
83fd4e5da5Sopenharmony_ci         %31 = OpAccessChain %23 %19 %20
84fd4e5da5Sopenharmony_ci         %32 = OpLoad %16 %31
85fd4e5da5Sopenharmony_ci         %33 = OpAccessChain %23 %19 %26
86fd4e5da5Sopenharmony_ci         %34 = OpLoad %16 %33
87fd4e5da5Sopenharmony_ci        %103 = OpCompositeConstruct %17 %34 %32 %9
88fd4e5da5Sopenharmony_ci         %35 = OpFAdd %16 %32 %34
89fd4e5da5Sopenharmony_ci         %36 = OpConvertFToS %6 %35
90fd4e5da5Sopenharmony_ci         %37 = OpAccessChain %7 %19 %30
91fd4e5da5Sopenharmony_ci               OpStore %37 %36
92fd4e5da5Sopenharmony_ci               OpReturn
93fd4e5da5Sopenharmony_ci               OpFunctionEnd
94fd4e5da5Sopenharmony_ci  )";
95fd4e5da5Sopenharmony_ci
96fd4e5da5Sopenharmony_ci  const auto env = SPV_ENV_UNIVERSAL_1_4;
97fd4e5da5Sopenharmony_ci  const auto consumer = nullptr;
98fd4e5da5Sopenharmony_ci  const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption);
99fd4e5da5Sopenharmony_ci  spvtools::ValidatorOptions validator_options;
100fd4e5da5Sopenharmony_ci  ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
101fd4e5da5Sopenharmony_ci                                               kConsoleMessageConsumer));
102fd4e5da5Sopenharmony_ci  TransformationContext transformation_context(
103fd4e5da5Sopenharmony_ci      MakeUnique<FactManager>(context.get()), validator_options);
104fd4e5da5Sopenharmony_ci  // Instruction does not exist.
105fd4e5da5Sopenharmony_ci  ASSERT_FALSE(
106fd4e5da5Sopenharmony_ci      TransformationCompositeExtract(
107fd4e5da5Sopenharmony_ci          MakeInstructionDescriptor(36, spv::Op::OpIAdd, 0), 200, 101, {0})
108fd4e5da5Sopenharmony_ci          .IsApplicable(context.get(), transformation_context));
109fd4e5da5Sopenharmony_ci
110fd4e5da5Sopenharmony_ci  // Id for composite is not a composite.
111fd4e5da5Sopenharmony_ci  ASSERT_FALSE(
112fd4e5da5Sopenharmony_ci      TransformationCompositeExtract(
113fd4e5da5Sopenharmony_ci          MakeInstructionDescriptor(37, spv::Op::OpAccessChain, 0), 200, 32, {})
114fd4e5da5Sopenharmony_ci          .IsApplicable(context.get(), transformation_context));
115fd4e5da5Sopenharmony_ci
116fd4e5da5Sopenharmony_ci  // Composite does not dominate instruction being inserted before.
117fd4e5da5Sopenharmony_ci  ASSERT_FALSE(TransformationCompositeExtract(
118fd4e5da5Sopenharmony_ci                   MakeInstructionDescriptor(37, spv::Op::OpAccessChain, 0),
119fd4e5da5Sopenharmony_ci                   200, 101, {0})
120fd4e5da5Sopenharmony_ci                   .IsApplicable(context.get(), transformation_context));
121fd4e5da5Sopenharmony_ci
122fd4e5da5Sopenharmony_ci  // Too many indices for extraction from struct composite.
123fd4e5da5Sopenharmony_ci  ASSERT_FALSE(TransformationCompositeExtract(
124fd4e5da5Sopenharmony_ci                   MakeInstructionDescriptor(24, spv::Op::OpAccessChain, 0),
125fd4e5da5Sopenharmony_ci                   200, 101, {0, 0})
126fd4e5da5Sopenharmony_ci                   .IsApplicable(context.get(), transformation_context));
127fd4e5da5Sopenharmony_ci
128fd4e5da5Sopenharmony_ci  // Too many indices for extraction from struct composite.
129fd4e5da5Sopenharmony_ci  ASSERT_FALSE(TransformationCompositeExtract(
130fd4e5da5Sopenharmony_ci                   MakeInstructionDescriptor(13, spv::Op::OpIEqual, 0), 200,
131fd4e5da5Sopenharmony_ci                   104, {0, 0, 0})
132fd4e5da5Sopenharmony_ci                   .IsApplicable(context.get(), transformation_context));
133fd4e5da5Sopenharmony_ci
134fd4e5da5Sopenharmony_ci  // Out of bounds index for extraction from struct composite.
135fd4e5da5Sopenharmony_ci  ASSERT_FALSE(
136fd4e5da5Sopenharmony_ci      TransformationCompositeExtract(
137fd4e5da5Sopenharmony_ci          MakeInstructionDescriptor(13, spv::Op::OpIEqual, 0), 200, 104, {0, 3})
138fd4e5da5Sopenharmony_ci          .IsApplicable(context.get(), transformation_context));
139fd4e5da5Sopenharmony_ci
140fd4e5da5Sopenharmony_ci  // Result id already used.
141fd4e5da5Sopenharmony_ci  ASSERT_FALSE(
142fd4e5da5Sopenharmony_ci      TransformationCompositeExtract(
143fd4e5da5Sopenharmony_ci          MakeInstructionDescriptor(35, spv::Op::OpFAdd, 0), 80, 103, {0})
144fd4e5da5Sopenharmony_ci          .IsApplicable(context.get(), transformation_context));
145fd4e5da5Sopenharmony_ci
146fd4e5da5Sopenharmony_ci  TransformationCompositeExtract transformation_1(
147fd4e5da5Sopenharmony_ci      MakeInstructionDescriptor(36, spv::Op::OpConvertFToS, 0), 201, 100, {2});
148fd4e5da5Sopenharmony_ci  ASSERT_EQ(nullptr, context->get_def_use_mgr()->GetDef(201));
149fd4e5da5Sopenharmony_ci  ASSERT_EQ(nullptr, context->get_instr_block(201));
150fd4e5da5Sopenharmony_ci  uint32_t num_uses_of_100_before = context->get_def_use_mgr()->NumUses(100);
151fd4e5da5Sopenharmony_ci  ASSERT_TRUE(
152fd4e5da5Sopenharmony_ci      transformation_1.IsApplicable(context.get(), transformation_context));
153fd4e5da5Sopenharmony_ci  ApplyAndCheckFreshIds(transformation_1, context.get(),
154fd4e5da5Sopenharmony_ci                        &transformation_context);
155fd4e5da5Sopenharmony_ci  ASSERT_EQ(spv::Op::OpCompositeExtract,
156fd4e5da5Sopenharmony_ci            context->get_def_use_mgr()->GetDef(201)->opcode());
157fd4e5da5Sopenharmony_ci  ASSERT_EQ(15, context->get_instr_block(201)->id());
158fd4e5da5Sopenharmony_ci  ASSERT_EQ(num_uses_of_100_before + 1,
159fd4e5da5Sopenharmony_ci            context->get_def_use_mgr()->NumUses(100));
160fd4e5da5Sopenharmony_ci  ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
161fd4e5da5Sopenharmony_ci                                               kConsoleMessageConsumer));
162fd4e5da5Sopenharmony_ci
163fd4e5da5Sopenharmony_ci  TransformationCompositeExtract transformation_2(
164fd4e5da5Sopenharmony_ci      MakeInstructionDescriptor(37, spv::Op::OpAccessChain, 0), 202, 104,
165fd4e5da5Sopenharmony_ci      {0, 2});
166fd4e5da5Sopenharmony_ci  ASSERT_TRUE(
167fd4e5da5Sopenharmony_ci      transformation_2.IsApplicable(context.get(), transformation_context));
168fd4e5da5Sopenharmony_ci  ApplyAndCheckFreshIds(transformation_2, context.get(),
169fd4e5da5Sopenharmony_ci                        &transformation_context);
170fd4e5da5Sopenharmony_ci  ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
171fd4e5da5Sopenharmony_ci                                               kConsoleMessageConsumer));
172fd4e5da5Sopenharmony_ci
173fd4e5da5Sopenharmony_ci  TransformationCompositeExtract transformation_3(
174fd4e5da5Sopenharmony_ci      MakeInstructionDescriptor(29, spv::Op::OpAccessChain, 0), 203, 104, {0});
175fd4e5da5Sopenharmony_ci  ASSERT_TRUE(
176fd4e5da5Sopenharmony_ci      transformation_3.IsApplicable(context.get(), transformation_context));
177fd4e5da5Sopenharmony_ci  ApplyAndCheckFreshIds(transformation_3, context.get(),
178fd4e5da5Sopenharmony_ci                        &transformation_context);
179fd4e5da5Sopenharmony_ci  ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
180fd4e5da5Sopenharmony_ci                                               kConsoleMessageConsumer));
181fd4e5da5Sopenharmony_ci
182fd4e5da5Sopenharmony_ci  TransformationCompositeExtract transformation_4(
183fd4e5da5Sopenharmony_ci      MakeInstructionDescriptor(24, spv::Op::OpStore, 0), 204, 101, {0});
184fd4e5da5Sopenharmony_ci  ASSERT_TRUE(
185fd4e5da5Sopenharmony_ci      transformation_4.IsApplicable(context.get(), transformation_context));
186fd4e5da5Sopenharmony_ci  ApplyAndCheckFreshIds(transformation_4, context.get(),
187fd4e5da5Sopenharmony_ci                        &transformation_context);
188fd4e5da5Sopenharmony_ci  ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
189fd4e5da5Sopenharmony_ci                                               kConsoleMessageConsumer));
190fd4e5da5Sopenharmony_ci
191fd4e5da5Sopenharmony_ci  TransformationCompositeExtract transformation_5(
192fd4e5da5Sopenharmony_ci      MakeInstructionDescriptor(29, spv::Op::OpBranch, 0), 205, 102, {2});
193fd4e5da5Sopenharmony_ci  ASSERT_TRUE(
194fd4e5da5Sopenharmony_ci      transformation_5.IsApplicable(context.get(), transformation_context));
195fd4e5da5Sopenharmony_ci  ApplyAndCheckFreshIds(transformation_5, context.get(),
196fd4e5da5Sopenharmony_ci                        &transformation_context);
197fd4e5da5Sopenharmony_ci  ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
198fd4e5da5Sopenharmony_ci                                               kConsoleMessageConsumer));
199fd4e5da5Sopenharmony_ci
200fd4e5da5Sopenharmony_ci  TransformationCompositeExtract transformation_6(
201fd4e5da5Sopenharmony_ci      MakeInstructionDescriptor(37, spv::Op::OpReturn, 0), 206, 103, {1});
202fd4e5da5Sopenharmony_ci  ASSERT_TRUE(
203fd4e5da5Sopenharmony_ci      transformation_6.IsApplicable(context.get(), transformation_context));
204fd4e5da5Sopenharmony_ci  ApplyAndCheckFreshIds(transformation_6, context.get(),
205fd4e5da5Sopenharmony_ci                        &transformation_context);
206fd4e5da5Sopenharmony_ci  ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
207fd4e5da5Sopenharmony_ci                                               kConsoleMessageConsumer));
208fd4e5da5Sopenharmony_ci
209fd4e5da5Sopenharmony_ci  ASSERT_TRUE(transformation_context.GetFactManager()->IsSynonymous(
210fd4e5da5Sopenharmony_ci      MakeDataDescriptor(201, {}), MakeDataDescriptor(100, {2})));
211fd4e5da5Sopenharmony_ci  ASSERT_TRUE(transformation_context.GetFactManager()->IsSynonymous(
212fd4e5da5Sopenharmony_ci      MakeDataDescriptor(202, {}), MakeDataDescriptor(104, {0, 2})));
213fd4e5da5Sopenharmony_ci  ASSERT_TRUE(transformation_context.GetFactManager()->IsSynonymous(
214fd4e5da5Sopenharmony_ci      MakeDataDescriptor(203, {}), MakeDataDescriptor(104, {0})));
215fd4e5da5Sopenharmony_ci  ASSERT_TRUE(transformation_context.GetFactManager()->IsSynonymous(
216fd4e5da5Sopenharmony_ci      MakeDataDescriptor(204, {}), MakeDataDescriptor(101, {0})));
217fd4e5da5Sopenharmony_ci  ASSERT_TRUE(transformation_context.GetFactManager()->IsSynonymous(
218fd4e5da5Sopenharmony_ci      MakeDataDescriptor(205, {}), MakeDataDescriptor(102, {2})));
219fd4e5da5Sopenharmony_ci  ASSERT_TRUE(transformation_context.GetFactManager()->IsSynonymous(
220fd4e5da5Sopenharmony_ci      MakeDataDescriptor(206, {}), MakeDataDescriptor(103, {1})));
221fd4e5da5Sopenharmony_ci
222fd4e5da5Sopenharmony_ci  std::string after_transformation = R"(
223fd4e5da5Sopenharmony_ci               OpCapability Shader
224fd4e5da5Sopenharmony_ci          %1 = OpExtInstImport "GLSL.std.450"
225fd4e5da5Sopenharmony_ci               OpMemoryModel Logical GLSL450
226fd4e5da5Sopenharmony_ci               OpEntryPoint Fragment %4 "main"
227fd4e5da5Sopenharmony_ci               OpExecutionMode %4 OriginUpperLeft
228fd4e5da5Sopenharmony_ci               OpSource ESSL 310
229fd4e5da5Sopenharmony_ci               OpName %4 "main"
230fd4e5da5Sopenharmony_ci               OpName %8 "a"
231fd4e5da5Sopenharmony_ci               OpName %10 "b"
232fd4e5da5Sopenharmony_ci               OpName %17 "FunnyPoint"
233fd4e5da5Sopenharmony_ci               OpMemberName %17 0 "x"
234fd4e5da5Sopenharmony_ci               OpMemberName %17 1 "y"
235fd4e5da5Sopenharmony_ci               OpMemberName %17 2 "z"
236fd4e5da5Sopenharmony_ci               OpName %19 "p"
237fd4e5da5Sopenharmony_ci          %2 = OpTypeVoid
238fd4e5da5Sopenharmony_ci          %3 = OpTypeFunction %2
239fd4e5da5Sopenharmony_ci          %6 = OpTypeInt 32 1
240fd4e5da5Sopenharmony_ci          %7 = OpTypePointer Function %6
241fd4e5da5Sopenharmony_ci         %12 = OpTypeBool
242fd4e5da5Sopenharmony_ci         %16 = OpTypeFloat 32
243fd4e5da5Sopenharmony_ci         %17 = OpTypeStruct %16 %16 %6
244fd4e5da5Sopenharmony_ci         %81 = OpTypeStruct %17 %16
245fd4e5da5Sopenharmony_ci         %18 = OpTypePointer Function %17
246fd4e5da5Sopenharmony_ci         %20 = OpConstant %6 0
247fd4e5da5Sopenharmony_ci         %23 = OpTypePointer Function %16
248fd4e5da5Sopenharmony_ci         %26 = OpConstant %6 1
249fd4e5da5Sopenharmony_ci         %30 = OpConstant %6 2
250fd4e5da5Sopenharmony_ci         %80 = OpUndef %16
251fd4e5da5Sopenharmony_ci          %4 = OpFunction %2 None %3
252fd4e5da5Sopenharmony_ci          %5 = OpLabel
253fd4e5da5Sopenharmony_ci          %8 = OpVariable %7 Function
254fd4e5da5Sopenharmony_ci         %10 = OpVariable %7 Function
255fd4e5da5Sopenharmony_ci         %19 = OpVariable %18 Function
256fd4e5da5Sopenharmony_ci          %9 = OpLoad %6 %8
257fd4e5da5Sopenharmony_ci         %11 = OpLoad %6 %10
258fd4e5da5Sopenharmony_ci        %100 = OpCompositeConstruct %17 %80 %80 %26
259fd4e5da5Sopenharmony_ci        %104 = OpCompositeConstruct %81 %100 %80
260fd4e5da5Sopenharmony_ci         %13 = OpIEqual %12 %9 %11
261fd4e5da5Sopenharmony_ci               OpSelectionMerge %15 None
262fd4e5da5Sopenharmony_ci               OpBranchConditional %13 %14 %25
263fd4e5da5Sopenharmony_ci         %14 = OpLabel
264fd4e5da5Sopenharmony_ci         %21 = OpLoad %6 %8
265fd4e5da5Sopenharmony_ci         %22 = OpConvertSToF %16 %21
266fd4e5da5Sopenharmony_ci        %101 = OpCompositeConstruct %17 %22 %80 %30
267fd4e5da5Sopenharmony_ci         %24 = OpAccessChain %23 %19 %20
268fd4e5da5Sopenharmony_ci        %204 = OpCompositeExtract %16 %101 0
269fd4e5da5Sopenharmony_ci               OpStore %24 %22
270fd4e5da5Sopenharmony_ci               OpBranch %15
271fd4e5da5Sopenharmony_ci         %25 = OpLabel
272fd4e5da5Sopenharmony_ci         %27 = OpLoad %6 %10
273fd4e5da5Sopenharmony_ci         %28 = OpConvertSToF %16 %27
274fd4e5da5Sopenharmony_ci        %102 = OpCompositeConstruct %17 %80 %28 %27
275fd4e5da5Sopenharmony_ci        %203 = OpCompositeExtract %17 %104 0
276fd4e5da5Sopenharmony_ci         %29 = OpAccessChain %23 %19 %26
277fd4e5da5Sopenharmony_ci               OpStore %29 %28
278fd4e5da5Sopenharmony_ci        %205 = OpCompositeExtract %6 %102 2
279fd4e5da5Sopenharmony_ci               OpBranch %15
280fd4e5da5Sopenharmony_ci         %15 = OpLabel
281fd4e5da5Sopenharmony_ci         %31 = OpAccessChain %23 %19 %20
282fd4e5da5Sopenharmony_ci         %32 = OpLoad %16 %31
283fd4e5da5Sopenharmony_ci         %33 = OpAccessChain %23 %19 %26
284fd4e5da5Sopenharmony_ci         %34 = OpLoad %16 %33
285fd4e5da5Sopenharmony_ci        %103 = OpCompositeConstruct %17 %34 %32 %9
286fd4e5da5Sopenharmony_ci         %35 = OpFAdd %16 %32 %34
287fd4e5da5Sopenharmony_ci        %201 = OpCompositeExtract %6 %100 2
288fd4e5da5Sopenharmony_ci         %36 = OpConvertFToS %6 %35
289fd4e5da5Sopenharmony_ci        %202 = OpCompositeExtract %6 %104 0 2
290fd4e5da5Sopenharmony_ci         %37 = OpAccessChain %7 %19 %30
291fd4e5da5Sopenharmony_ci               OpStore %37 %36
292fd4e5da5Sopenharmony_ci        %206 = OpCompositeExtract %16 %103 1
293fd4e5da5Sopenharmony_ci               OpReturn
294fd4e5da5Sopenharmony_ci               OpFunctionEnd
295fd4e5da5Sopenharmony_ci  )";
296fd4e5da5Sopenharmony_ci  ASSERT_TRUE(IsEqual(env, after_transformation, context.get()));
297fd4e5da5Sopenharmony_ci}
298fd4e5da5Sopenharmony_ci
299fd4e5da5Sopenharmony_ciTEST(TransformationCompositeExtractTest, IllegalInsertionPoints) {
300fd4e5da5Sopenharmony_ci  std::string shader = R"(
301fd4e5da5Sopenharmony_ci               OpCapability Shader
302fd4e5da5Sopenharmony_ci          %1 = OpExtInstImport "GLSL.std.450"
303fd4e5da5Sopenharmony_ci               OpMemoryModel Logical GLSL450
304fd4e5da5Sopenharmony_ci               OpEntryPoint Fragment %4 "main" %51 %27
305fd4e5da5Sopenharmony_ci               OpExecutionMode %4 OriginUpperLeft
306fd4e5da5Sopenharmony_ci               OpSource ESSL 310
307fd4e5da5Sopenharmony_ci               OpName %4 "main"
308fd4e5da5Sopenharmony_ci               OpName %25 "buf"
309fd4e5da5Sopenharmony_ci               OpMemberName %25 0 "value"
310fd4e5da5Sopenharmony_ci               OpName %27 ""
311fd4e5da5Sopenharmony_ci               OpName %51 "color"
312fd4e5da5Sopenharmony_ci               OpMemberDecorate %25 0 Offset 0
313fd4e5da5Sopenharmony_ci               OpDecorate %25 Block
314fd4e5da5Sopenharmony_ci               OpDecorate %27 DescriptorSet 0
315fd4e5da5Sopenharmony_ci               OpDecorate %27 Binding 0
316fd4e5da5Sopenharmony_ci               OpDecorate %51 Location 0
317fd4e5da5Sopenharmony_ci          %2 = OpTypeVoid
318fd4e5da5Sopenharmony_ci          %3 = OpTypeFunction %2
319fd4e5da5Sopenharmony_ci          %6 = OpTypeFloat 32
320fd4e5da5Sopenharmony_ci          %7 = OpTypeVector %6 4
321fd4e5da5Sopenharmony_ci         %10 = OpConstant %6 0.300000012
322fd4e5da5Sopenharmony_ci         %11 = OpConstant %6 0.400000006
323fd4e5da5Sopenharmony_ci         %12 = OpConstant %6 0.5
324fd4e5da5Sopenharmony_ci         %13 = OpConstant %6 1
325fd4e5da5Sopenharmony_ci         %14 = OpConstantComposite %7 %10 %11 %12 %13
326fd4e5da5Sopenharmony_ci         %15 = OpTypeInt 32 1
327fd4e5da5Sopenharmony_ci         %18 = OpConstant %15 0
328fd4e5da5Sopenharmony_ci         %25 = OpTypeStruct %6
329fd4e5da5Sopenharmony_ci         %26 = OpTypePointer Uniform %25
330fd4e5da5Sopenharmony_ci         %27 = OpVariable %26 Uniform
331fd4e5da5Sopenharmony_ci         %28 = OpTypePointer Uniform %6
332fd4e5da5Sopenharmony_ci         %32 = OpTypeBool
333fd4e5da5Sopenharmony_ci        %103 = OpConstantTrue %32
334fd4e5da5Sopenharmony_ci         %34 = OpConstant %6 0.100000001
335fd4e5da5Sopenharmony_ci         %48 = OpConstant %15 1
336fd4e5da5Sopenharmony_ci         %50 = OpTypePointer Output %7
337fd4e5da5Sopenharmony_ci         %51 = OpVariable %50 Output
338fd4e5da5Sopenharmony_ci        %100 = OpTypePointer Function %6
339fd4e5da5Sopenharmony_ci          %4 = OpFunction %2 None %3
340fd4e5da5Sopenharmony_ci          %5 = OpLabel
341fd4e5da5Sopenharmony_ci        %101 = OpVariable %100 Function
342fd4e5da5Sopenharmony_ci        %102 = OpVariable %100 Function
343fd4e5da5Sopenharmony_ci               OpBranch %19
344fd4e5da5Sopenharmony_ci         %19 = OpLabel
345fd4e5da5Sopenharmony_ci         %60 = OpPhi %7 %14 %5 %58 %20
346fd4e5da5Sopenharmony_ci         %59 = OpPhi %15 %18 %5 %49 %20
347fd4e5da5Sopenharmony_ci         %29 = OpAccessChain %28 %27 %18
348fd4e5da5Sopenharmony_ci         %30 = OpLoad %6 %29
349fd4e5da5Sopenharmony_ci         %31 = OpConvertFToS %15 %30
350fd4e5da5Sopenharmony_ci         %33 = OpSLessThan %32 %59 %31
351fd4e5da5Sopenharmony_ci               OpLoopMerge %21 %20 None
352fd4e5da5Sopenharmony_ci               OpBranchConditional %33 %20 %21
353fd4e5da5Sopenharmony_ci         %20 = OpLabel
354fd4e5da5Sopenharmony_ci         %39 = OpCompositeExtract %6 %60 0
355fd4e5da5Sopenharmony_ci         %40 = OpFAdd %6 %39 %34
356fd4e5da5Sopenharmony_ci         %55 = OpCompositeInsert %7 %40 %60 0
357fd4e5da5Sopenharmony_ci         %44 = OpCompositeExtract %6 %60 1
358fd4e5da5Sopenharmony_ci         %45 = OpFSub %6 %44 %34
359fd4e5da5Sopenharmony_ci         %58 = OpCompositeInsert %7 %45 %55 1
360fd4e5da5Sopenharmony_ci         %49 = OpIAdd %15 %59 %48
361fd4e5da5Sopenharmony_ci               OpBranch %19
362fd4e5da5Sopenharmony_ci         %21 = OpLabel
363fd4e5da5Sopenharmony_ci               OpStore %51 %60
364fd4e5da5Sopenharmony_ci               OpSelectionMerge %105 None
365fd4e5da5Sopenharmony_ci               OpBranchConditional %103 %104 %105
366fd4e5da5Sopenharmony_ci        %104 = OpLabel
367fd4e5da5Sopenharmony_ci               OpBranch %105
368fd4e5da5Sopenharmony_ci        %105 = OpLabel
369fd4e5da5Sopenharmony_ci               OpReturn
370fd4e5da5Sopenharmony_ci               OpFunctionEnd
371fd4e5da5Sopenharmony_ci  )";
372fd4e5da5Sopenharmony_ci
373fd4e5da5Sopenharmony_ci  const auto env = SPV_ENV_UNIVERSAL_1_4;
374fd4e5da5Sopenharmony_ci  const auto consumer = nullptr;
375fd4e5da5Sopenharmony_ci  const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption);
376fd4e5da5Sopenharmony_ci  spvtools::ValidatorOptions validator_options;
377fd4e5da5Sopenharmony_ci  ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
378fd4e5da5Sopenharmony_ci                                               kConsoleMessageConsumer));
379fd4e5da5Sopenharmony_ci  TransformationContext transformation_context(
380fd4e5da5Sopenharmony_ci      MakeUnique<FactManager>(context.get()), validator_options);
381fd4e5da5Sopenharmony_ci  // Cannot insert before the OpVariables of a function.
382fd4e5da5Sopenharmony_ci  ASSERT_FALSE(
383fd4e5da5Sopenharmony_ci      TransformationCompositeExtract(
384fd4e5da5Sopenharmony_ci          MakeInstructionDescriptor(101, spv::Op::OpVariable, 0), 200, 14, {0})
385fd4e5da5Sopenharmony_ci          .IsApplicable(context.get(), transformation_context));
386fd4e5da5Sopenharmony_ci  ASSERT_FALSE(
387fd4e5da5Sopenharmony_ci      TransformationCompositeExtract(
388fd4e5da5Sopenharmony_ci          MakeInstructionDescriptor(101, spv::Op::OpVariable, 1), 200, 14, {1})
389fd4e5da5Sopenharmony_ci          .IsApplicable(context.get(), transformation_context));
390fd4e5da5Sopenharmony_ci  ASSERT_FALSE(
391fd4e5da5Sopenharmony_ci      TransformationCompositeExtract(
392fd4e5da5Sopenharmony_ci          MakeInstructionDescriptor(102, spv::Op::OpVariable, 0), 200, 14, {1})
393fd4e5da5Sopenharmony_ci          .IsApplicable(context.get(), transformation_context));
394fd4e5da5Sopenharmony_ci  // OK to insert right after the OpVariables.
395fd4e5da5Sopenharmony_ci  ASSERT_FALSE(
396fd4e5da5Sopenharmony_ci      TransformationCompositeExtract(
397fd4e5da5Sopenharmony_ci          MakeInstructionDescriptor(102, spv::Op::OpBranch, 1), 200, 14, {1})
398fd4e5da5Sopenharmony_ci          .IsApplicable(context.get(), transformation_context));
399fd4e5da5Sopenharmony_ci
400fd4e5da5Sopenharmony_ci  // Cannot insert before the OpPhis of a block.
401fd4e5da5Sopenharmony_ci  ASSERT_FALSE(
402fd4e5da5Sopenharmony_ci      TransformationCompositeExtract(
403fd4e5da5Sopenharmony_ci          MakeInstructionDescriptor(60, spv::Op::OpPhi, 0), 200, 14, {2})
404fd4e5da5Sopenharmony_ci          .IsApplicable(context.get(), transformation_context));
405fd4e5da5Sopenharmony_ci  ASSERT_FALSE(
406fd4e5da5Sopenharmony_ci      TransformationCompositeExtract(
407fd4e5da5Sopenharmony_ci          MakeInstructionDescriptor(59, spv::Op::OpPhi, 0), 200, 14, {3})
408fd4e5da5Sopenharmony_ci          .IsApplicable(context.get(), transformation_context));
409fd4e5da5Sopenharmony_ci  // OK to insert after the OpPhis.
410fd4e5da5Sopenharmony_ci  ASSERT_TRUE(TransformationCompositeExtract(
411fd4e5da5Sopenharmony_ci                  MakeInstructionDescriptor(59, spv::Op::OpAccessChain, 0), 200,
412fd4e5da5Sopenharmony_ci                  14, {3})
413fd4e5da5Sopenharmony_ci                  .IsApplicable(context.get(), transformation_context));
414fd4e5da5Sopenharmony_ci
415fd4e5da5Sopenharmony_ci  // Cannot insert before OpLoopMerge
416fd4e5da5Sopenharmony_ci  ASSERT_FALSE(
417fd4e5da5Sopenharmony_ci      TransformationCompositeExtract(
418fd4e5da5Sopenharmony_ci          MakeInstructionDescriptor(33, spv::Op::OpBranchConditional, 0), 200,
419fd4e5da5Sopenharmony_ci          14, {3})
420fd4e5da5Sopenharmony_ci          .IsApplicable(context.get(), transformation_context));
421fd4e5da5Sopenharmony_ci
422fd4e5da5Sopenharmony_ci  // Cannot insert before OpSelectionMerge
423fd4e5da5Sopenharmony_ci  ASSERT_FALSE(
424fd4e5da5Sopenharmony_ci      TransformationCompositeExtract(
425fd4e5da5Sopenharmony_ci          MakeInstructionDescriptor(21, spv::Op::OpBranchConditional, 0), 200,
426fd4e5da5Sopenharmony_ci          14, {2})
427fd4e5da5Sopenharmony_ci          .IsApplicable(context.get(), transformation_context));
428fd4e5da5Sopenharmony_ci}
429fd4e5da5Sopenharmony_ci
430fd4e5da5Sopenharmony_ciTEST(TransformationCompositeExtractTest, AddSynonymsForRelevantIds) {
431fd4e5da5Sopenharmony_ci  std::string shader = R"(
432fd4e5da5Sopenharmony_ci               OpCapability Shader
433fd4e5da5Sopenharmony_ci          %1 = OpExtInstImport "GLSL.std.450"
434fd4e5da5Sopenharmony_ci               OpMemoryModel Logical GLSL450
435fd4e5da5Sopenharmony_ci               OpEntryPoint Fragment %4 "main"
436fd4e5da5Sopenharmony_ci               OpExecutionMode %4 OriginUpperLeft
437fd4e5da5Sopenharmony_ci               OpSource ESSL 310
438fd4e5da5Sopenharmony_ci               OpName %4 "main"
439fd4e5da5Sopenharmony_ci               OpName %8 "a"
440fd4e5da5Sopenharmony_ci               OpName %10 "b"
441fd4e5da5Sopenharmony_ci               OpName %17 "FunnyPoint"
442fd4e5da5Sopenharmony_ci               OpMemberName %17 0 "x"
443fd4e5da5Sopenharmony_ci               OpMemberName %17 1 "y"
444fd4e5da5Sopenharmony_ci               OpMemberName %17 2 "z"
445fd4e5da5Sopenharmony_ci               OpName %19 "p"
446fd4e5da5Sopenharmony_ci          %2 = OpTypeVoid
447fd4e5da5Sopenharmony_ci          %3 = OpTypeFunction %2
448fd4e5da5Sopenharmony_ci          %6 = OpTypeInt 32 1
449fd4e5da5Sopenharmony_ci          %7 = OpTypePointer Function %6
450fd4e5da5Sopenharmony_ci         %12 = OpTypeBool
451fd4e5da5Sopenharmony_ci         %16 = OpTypeFloat 32
452fd4e5da5Sopenharmony_ci         %17 = OpTypeStruct %16 %16 %6
453fd4e5da5Sopenharmony_ci         %81 = OpTypeStruct %17 %16
454fd4e5da5Sopenharmony_ci         %18 = OpTypePointer Function %17
455fd4e5da5Sopenharmony_ci         %20 = OpConstant %6 0
456fd4e5da5Sopenharmony_ci         %23 = OpTypePointer Function %16
457fd4e5da5Sopenharmony_ci         %26 = OpConstant %6 1
458fd4e5da5Sopenharmony_ci         %30 = OpConstant %6 2
459fd4e5da5Sopenharmony_ci         %80 = OpUndef %16
460fd4e5da5Sopenharmony_ci          %4 = OpFunction %2 None %3
461fd4e5da5Sopenharmony_ci          %5 = OpLabel
462fd4e5da5Sopenharmony_ci          %8 = OpVariable %7 Function
463fd4e5da5Sopenharmony_ci         %10 = OpVariable %7 Function
464fd4e5da5Sopenharmony_ci         %19 = OpVariable %18 Function
465fd4e5da5Sopenharmony_ci          %9 = OpLoad %6 %8
466fd4e5da5Sopenharmony_ci         %11 = OpLoad %6 %10
467fd4e5da5Sopenharmony_ci        %100 = OpCompositeConstruct %17 %80 %80 %26
468fd4e5da5Sopenharmony_ci        %104 = OpCompositeConstruct %81 %100 %80
469fd4e5da5Sopenharmony_ci         %13 = OpIEqual %12 %9 %11
470fd4e5da5Sopenharmony_ci               OpSelectionMerge %15 None
471fd4e5da5Sopenharmony_ci               OpBranchConditional %13 %14 %25
472fd4e5da5Sopenharmony_ci         %14 = OpLabel
473fd4e5da5Sopenharmony_ci         %21 = OpLoad %6 %8
474fd4e5da5Sopenharmony_ci         %22 = OpConvertSToF %16 %21
475fd4e5da5Sopenharmony_ci        %101 = OpCompositeConstruct %17 %22 %80 %30
476fd4e5da5Sopenharmony_ci         %24 = OpAccessChain %23 %19 %20
477fd4e5da5Sopenharmony_ci               OpStore %24 %22
478fd4e5da5Sopenharmony_ci               OpBranch %15
479fd4e5da5Sopenharmony_ci         %25 = OpLabel
480fd4e5da5Sopenharmony_ci         %27 = OpLoad %6 %10
481fd4e5da5Sopenharmony_ci         %28 = OpConvertSToF %16 %27
482fd4e5da5Sopenharmony_ci        %102 = OpCompositeConstruct %17 %80 %28 %27
483fd4e5da5Sopenharmony_ci         %29 = OpAccessChain %23 %19 %26
484fd4e5da5Sopenharmony_ci               OpStore %29 %28
485fd4e5da5Sopenharmony_ci               OpBranch %15
486fd4e5da5Sopenharmony_ci         %15 = OpLabel
487fd4e5da5Sopenharmony_ci         %31 = OpAccessChain %23 %19 %20
488fd4e5da5Sopenharmony_ci         %32 = OpLoad %16 %31
489fd4e5da5Sopenharmony_ci         %33 = OpAccessChain %23 %19 %26
490fd4e5da5Sopenharmony_ci         %34 = OpLoad %16 %33
491fd4e5da5Sopenharmony_ci        %103 = OpCompositeConstruct %17 %34 %32 %9
492fd4e5da5Sopenharmony_ci         %35 = OpFAdd %16 %32 %34
493fd4e5da5Sopenharmony_ci         %36 = OpConvertFToS %6 %35
494fd4e5da5Sopenharmony_ci         %37 = OpAccessChain %7 %19 %30
495fd4e5da5Sopenharmony_ci               OpStore %37 %36
496fd4e5da5Sopenharmony_ci               OpReturn
497fd4e5da5Sopenharmony_ci               OpFunctionEnd
498fd4e5da5Sopenharmony_ci  )";
499fd4e5da5Sopenharmony_ci
500fd4e5da5Sopenharmony_ci  const auto env = SPV_ENV_UNIVERSAL_1_4;
501fd4e5da5Sopenharmony_ci  const auto consumer = nullptr;
502fd4e5da5Sopenharmony_ci  const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption);
503fd4e5da5Sopenharmony_ci  spvtools::ValidatorOptions validator_options;
504fd4e5da5Sopenharmony_ci  ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
505fd4e5da5Sopenharmony_ci                                               kConsoleMessageConsumer));
506fd4e5da5Sopenharmony_ci  TransformationContext transformation_context(
507fd4e5da5Sopenharmony_ci      MakeUnique<FactManager>(context.get()), validator_options);
508fd4e5da5Sopenharmony_ci  TransformationCompositeExtract transformation(
509fd4e5da5Sopenharmony_ci      MakeInstructionDescriptor(36, spv::Op::OpConvertFToS, 0), 201, 100, {2});
510fd4e5da5Sopenharmony_ci  ASSERT_TRUE(
511fd4e5da5Sopenharmony_ci      transformation.IsApplicable(context.get(), transformation_context));
512fd4e5da5Sopenharmony_ci  ApplyAndCheckFreshIds(transformation, context.get(), &transformation_context);
513fd4e5da5Sopenharmony_ci  ASSERT_TRUE(transformation_context.GetFactManager()->IsSynonymous(
514fd4e5da5Sopenharmony_ci      MakeDataDescriptor(201, {}), MakeDataDescriptor(100, {2})));
515fd4e5da5Sopenharmony_ci}
516fd4e5da5Sopenharmony_ci
517fd4e5da5Sopenharmony_ciTEST(TransformationCompositeExtractTest, DontAddSynonymsForIrrelevantIds) {
518fd4e5da5Sopenharmony_ci  std::string shader = R"(
519fd4e5da5Sopenharmony_ci               OpCapability Shader
520fd4e5da5Sopenharmony_ci          %1 = OpExtInstImport "GLSL.std.450"
521fd4e5da5Sopenharmony_ci               OpMemoryModel Logical GLSL450
522fd4e5da5Sopenharmony_ci               OpEntryPoint Fragment %4 "main"
523fd4e5da5Sopenharmony_ci               OpExecutionMode %4 OriginUpperLeft
524fd4e5da5Sopenharmony_ci               OpSource ESSL 310
525fd4e5da5Sopenharmony_ci               OpName %4 "main"
526fd4e5da5Sopenharmony_ci               OpName %8 "a"
527fd4e5da5Sopenharmony_ci               OpName %10 "b"
528fd4e5da5Sopenharmony_ci               OpName %17 "FunnyPoint"
529fd4e5da5Sopenharmony_ci               OpMemberName %17 0 "x"
530fd4e5da5Sopenharmony_ci               OpMemberName %17 1 "y"
531fd4e5da5Sopenharmony_ci               OpMemberName %17 2 "z"
532fd4e5da5Sopenharmony_ci               OpName %19 "p"
533fd4e5da5Sopenharmony_ci          %2 = OpTypeVoid
534fd4e5da5Sopenharmony_ci          %3 = OpTypeFunction %2
535fd4e5da5Sopenharmony_ci          %6 = OpTypeInt 32 1
536fd4e5da5Sopenharmony_ci          %7 = OpTypePointer Function %6
537fd4e5da5Sopenharmony_ci         %12 = OpTypeBool
538fd4e5da5Sopenharmony_ci         %16 = OpTypeFloat 32
539fd4e5da5Sopenharmony_ci         %17 = OpTypeStruct %16 %16 %6
540fd4e5da5Sopenharmony_ci         %81 = OpTypeStruct %17 %16
541fd4e5da5Sopenharmony_ci         %18 = OpTypePointer Function %17
542fd4e5da5Sopenharmony_ci         %20 = OpConstant %6 0
543fd4e5da5Sopenharmony_ci         %23 = OpTypePointer Function %16
544fd4e5da5Sopenharmony_ci         %26 = OpConstant %6 1
545fd4e5da5Sopenharmony_ci         %30 = OpConstant %6 2
546fd4e5da5Sopenharmony_ci         %80 = OpUndef %16
547fd4e5da5Sopenharmony_ci          %4 = OpFunction %2 None %3
548fd4e5da5Sopenharmony_ci          %5 = OpLabel
549fd4e5da5Sopenharmony_ci          %8 = OpVariable %7 Function
550fd4e5da5Sopenharmony_ci         %10 = OpVariable %7 Function
551fd4e5da5Sopenharmony_ci         %19 = OpVariable %18 Function
552fd4e5da5Sopenharmony_ci          %9 = OpLoad %6 %8
553fd4e5da5Sopenharmony_ci         %11 = OpLoad %6 %10
554fd4e5da5Sopenharmony_ci        %100 = OpCompositeConstruct %17 %80 %80 %26
555fd4e5da5Sopenharmony_ci        %104 = OpCompositeConstruct %81 %100 %80
556fd4e5da5Sopenharmony_ci         %13 = OpIEqual %12 %9 %11
557fd4e5da5Sopenharmony_ci               OpSelectionMerge %15 None
558fd4e5da5Sopenharmony_ci               OpBranchConditional %13 %14 %25
559fd4e5da5Sopenharmony_ci         %14 = OpLabel
560fd4e5da5Sopenharmony_ci         %21 = OpLoad %6 %8
561fd4e5da5Sopenharmony_ci         %22 = OpConvertSToF %16 %21
562fd4e5da5Sopenharmony_ci        %101 = OpCompositeConstruct %17 %22 %80 %30
563fd4e5da5Sopenharmony_ci         %24 = OpAccessChain %23 %19 %20
564fd4e5da5Sopenharmony_ci               OpStore %24 %22
565fd4e5da5Sopenharmony_ci               OpBranch %15
566fd4e5da5Sopenharmony_ci         %25 = OpLabel
567fd4e5da5Sopenharmony_ci         %27 = OpLoad %6 %10
568fd4e5da5Sopenharmony_ci         %28 = OpConvertSToF %16 %27
569fd4e5da5Sopenharmony_ci        %102 = OpCompositeConstruct %17 %80 %28 %27
570fd4e5da5Sopenharmony_ci         %29 = OpAccessChain %23 %19 %26
571fd4e5da5Sopenharmony_ci               OpStore %29 %28
572fd4e5da5Sopenharmony_ci               OpBranch %15
573fd4e5da5Sopenharmony_ci         %15 = OpLabel
574fd4e5da5Sopenharmony_ci         %31 = OpAccessChain %23 %19 %20
575fd4e5da5Sopenharmony_ci         %32 = OpLoad %16 %31
576fd4e5da5Sopenharmony_ci         %33 = OpAccessChain %23 %19 %26
577fd4e5da5Sopenharmony_ci         %34 = OpLoad %16 %33
578fd4e5da5Sopenharmony_ci        %103 = OpCompositeConstruct %17 %34 %32 %9
579fd4e5da5Sopenharmony_ci         %35 = OpFAdd %16 %32 %34
580fd4e5da5Sopenharmony_ci         %36 = OpConvertFToS %6 %35
581fd4e5da5Sopenharmony_ci         %37 = OpAccessChain %7 %19 %30
582fd4e5da5Sopenharmony_ci               OpStore %37 %36
583fd4e5da5Sopenharmony_ci               OpReturn
584fd4e5da5Sopenharmony_ci               OpFunctionEnd
585fd4e5da5Sopenharmony_ci  )";
586fd4e5da5Sopenharmony_ci
587fd4e5da5Sopenharmony_ci  const auto env = SPV_ENV_UNIVERSAL_1_4;
588fd4e5da5Sopenharmony_ci  const auto consumer = nullptr;
589fd4e5da5Sopenharmony_ci  const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption);
590fd4e5da5Sopenharmony_ci  spvtools::ValidatorOptions validator_options;
591fd4e5da5Sopenharmony_ci  ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
592fd4e5da5Sopenharmony_ci                                               kConsoleMessageConsumer));
593fd4e5da5Sopenharmony_ci  TransformationContext transformation_context(
594fd4e5da5Sopenharmony_ci      MakeUnique<FactManager>(context.get()), validator_options);
595fd4e5da5Sopenharmony_ci  transformation_context.GetFactManager()->AddFactIdIsIrrelevant(100);
596fd4e5da5Sopenharmony_ci  TransformationCompositeExtract transformation(
597fd4e5da5Sopenharmony_ci      MakeInstructionDescriptor(36, spv::Op::OpConvertFToS, 0), 201, 100, {2});
598fd4e5da5Sopenharmony_ci  ASSERT_TRUE(
599fd4e5da5Sopenharmony_ci      transformation.IsApplicable(context.get(), transformation_context));
600fd4e5da5Sopenharmony_ci  ApplyAndCheckFreshIds(transformation, context.get(), &transformation_context);
601fd4e5da5Sopenharmony_ci  ASSERT_FALSE(transformation_context.GetFactManager()->IsSynonymous(
602fd4e5da5Sopenharmony_ci      MakeDataDescriptor(201, {}), MakeDataDescriptor(100, {2})));
603fd4e5da5Sopenharmony_ci}
604fd4e5da5Sopenharmony_ci
605fd4e5da5Sopenharmony_ciTEST(TransformationCompositeExtractTest, DontAddSynonymInDeadBlock) {
606fd4e5da5Sopenharmony_ci  std::string shader = R"(
607fd4e5da5Sopenharmony_ci               OpCapability Shader
608fd4e5da5Sopenharmony_ci          %1 = OpExtInstImport "GLSL.std.450"
609fd4e5da5Sopenharmony_ci               OpMemoryModel Logical GLSL450
610fd4e5da5Sopenharmony_ci               OpEntryPoint Fragment %4 "main"
611fd4e5da5Sopenharmony_ci               OpExecutionMode %4 OriginUpperLeft
612fd4e5da5Sopenharmony_ci               OpSource ESSL 320
613fd4e5da5Sopenharmony_ci          %2 = OpTypeVoid
614fd4e5da5Sopenharmony_ci          %3 = OpTypeFunction %2
615fd4e5da5Sopenharmony_ci          %6 = OpTypeInt 32 1
616fd4e5da5Sopenharmony_ci          %7 = OpTypeVector %6 2
617fd4e5da5Sopenharmony_ci          %8 = OpTypePointer Function %7
618fd4e5da5Sopenharmony_ci         %10 = OpConstant %6 0
619fd4e5da5Sopenharmony_ci         %11 = OpConstant %6 1
620fd4e5da5Sopenharmony_ci         %12 = OpConstantComposite %7 %10 %11
621fd4e5da5Sopenharmony_ci         %13 = OpTypeBool
622fd4e5da5Sopenharmony_ci         %14 = OpConstantFalse %13
623fd4e5da5Sopenharmony_ci          %4 = OpFunction %2 None %3
624fd4e5da5Sopenharmony_ci          %5 = OpLabel
625fd4e5da5Sopenharmony_ci          %9 = OpVariable %8 Function
626fd4e5da5Sopenharmony_ci               OpStore %9 %12
627fd4e5da5Sopenharmony_ci               OpSelectionMerge %16 None
628fd4e5da5Sopenharmony_ci               OpBranchConditional %14 %15 %16
629fd4e5da5Sopenharmony_ci         %15 = OpLabel
630fd4e5da5Sopenharmony_ci               OpBranch %16
631fd4e5da5Sopenharmony_ci         %16 = OpLabel
632fd4e5da5Sopenharmony_ci               OpReturn
633fd4e5da5Sopenharmony_ci               OpFunctionEnd
634fd4e5da5Sopenharmony_ci  )";
635fd4e5da5Sopenharmony_ci
636fd4e5da5Sopenharmony_ci  const auto env = SPV_ENV_UNIVERSAL_1_4;
637fd4e5da5Sopenharmony_ci  const auto consumer = nullptr;
638fd4e5da5Sopenharmony_ci  const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption);
639fd4e5da5Sopenharmony_ci  spvtools::ValidatorOptions validator_options;
640fd4e5da5Sopenharmony_ci  ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
641fd4e5da5Sopenharmony_ci                                               kConsoleMessageConsumer));
642fd4e5da5Sopenharmony_ci  TransformationContext transformation_context(
643fd4e5da5Sopenharmony_ci      MakeUnique<FactManager>(context.get()), validator_options);
644fd4e5da5Sopenharmony_ci  transformation_context.GetFactManager()->AddFactBlockIsDead(15);
645fd4e5da5Sopenharmony_ci  TransformationCompositeExtract transformation(
646fd4e5da5Sopenharmony_ci      MakeInstructionDescriptor(15, spv::Op::OpBranch, 0), 100, 12, {0});
647fd4e5da5Sopenharmony_ci  ASSERT_TRUE(
648fd4e5da5Sopenharmony_ci      transformation.IsApplicable(context.get(), transformation_context));
649fd4e5da5Sopenharmony_ci  ApplyAndCheckFreshIds(transformation, context.get(), &transformation_context);
650fd4e5da5Sopenharmony_ci  ASSERT_FALSE(transformation_context.GetFactManager()->IsSynonymous(
651fd4e5da5Sopenharmony_ci      MakeDataDescriptor(100, {}), MakeDataDescriptor(12, {0})));
652fd4e5da5Sopenharmony_ci}
653fd4e5da5Sopenharmony_ci
654fd4e5da5Sopenharmony_ci}  // namespace
655fd4e5da5Sopenharmony_ci}  // namespace fuzz
656fd4e5da5Sopenharmony_ci}  // namespace spvtools
657