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