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_composite_insert.h" 16fd4e5da5Sopenharmony_ci 17fd4e5da5Sopenharmony_ci#include "gtest/gtest.h" 18fd4e5da5Sopenharmony_ci#include "source/fuzz/data_descriptor.h" 19fd4e5da5Sopenharmony_ci#include "source/fuzz/fuzzer_util.h" 20fd4e5da5Sopenharmony_ci#include "source/fuzz/instruction_descriptor.h" 21fd4e5da5Sopenharmony_ci#include "test/fuzz/fuzz_test_util.h" 22fd4e5da5Sopenharmony_ci 23fd4e5da5Sopenharmony_cinamespace spvtools { 24fd4e5da5Sopenharmony_cinamespace fuzz { 25fd4e5da5Sopenharmony_cinamespace { 26fd4e5da5Sopenharmony_ci 27fd4e5da5Sopenharmony_ciTEST(TransformationCompositeInsertTest, NotApplicableScenarios) { 28fd4e5da5Sopenharmony_ci // This test handles cases where IsApplicable() returns false. 29fd4e5da5Sopenharmony_ci 30fd4e5da5Sopenharmony_ci std::string shader = R"( 31fd4e5da5Sopenharmony_ci OpCapability Shader 32fd4e5da5Sopenharmony_ci %1 = OpExtInstImport "GLSL.std.450" 33fd4e5da5Sopenharmony_ci OpMemoryModel Logical GLSL450 34fd4e5da5Sopenharmony_ci OpEntryPoint Fragment %4 "main" 35fd4e5da5Sopenharmony_ci OpExecutionMode %4 OriginUpperLeft 36fd4e5da5Sopenharmony_ci OpSource ESSL 310 37fd4e5da5Sopenharmony_ci OpName %4 "main" 38fd4e5da5Sopenharmony_ci OpName %8 "i1" 39fd4e5da5Sopenharmony_ci OpName %10 "i2" 40fd4e5da5Sopenharmony_ci OpName %12 "base" 41fd4e5da5Sopenharmony_ci OpMemberName %12 0 "a1" 42fd4e5da5Sopenharmony_ci OpMemberName %12 1 "a2" 43fd4e5da5Sopenharmony_ci OpName %14 "b" 44fd4e5da5Sopenharmony_ci OpName %18 "level_1" 45fd4e5da5Sopenharmony_ci OpMemberName %18 0 "b1" 46fd4e5da5Sopenharmony_ci OpMemberName %18 1 "b2" 47fd4e5da5Sopenharmony_ci OpName %20 "l1" 48fd4e5da5Sopenharmony_ci OpName %24 "level_2" 49fd4e5da5Sopenharmony_ci OpMemberName %24 0 "c1" 50fd4e5da5Sopenharmony_ci OpMemberName %24 1 "c2" 51fd4e5da5Sopenharmony_ci OpName %26 "l2" 52fd4e5da5Sopenharmony_ci %2 = OpTypeVoid 53fd4e5da5Sopenharmony_ci %3 = OpTypeFunction %2 54fd4e5da5Sopenharmony_ci %6 = OpTypeInt 32 1 55fd4e5da5Sopenharmony_ci %7 = OpTypePointer Function %6 56fd4e5da5Sopenharmony_ci %9 = OpConstant %6 1 57fd4e5da5Sopenharmony_ci %11 = OpConstant %6 2 58fd4e5da5Sopenharmony_ci %12 = OpTypeStruct %6 %6 59fd4e5da5Sopenharmony_ci %13 = OpTypePointer Function %12 60fd4e5da5Sopenharmony_ci %18 = OpTypeStruct %12 %12 61fd4e5da5Sopenharmony_ci %19 = OpTypePointer Function %18 62fd4e5da5Sopenharmony_ci %24 = OpTypeStruct %18 %18 63fd4e5da5Sopenharmony_ci %25 = OpTypePointer Function %24 64fd4e5da5Sopenharmony_ci %30 = OpTypeBool 65fd4e5da5Sopenharmony_ci %31 = OpConstantTrue %30 66fd4e5da5Sopenharmony_ci %4 = OpFunction %2 None %3 67fd4e5da5Sopenharmony_ci %5 = OpLabel 68fd4e5da5Sopenharmony_ci %8 = OpVariable %7 Function 69fd4e5da5Sopenharmony_ci %10 = OpVariable %7 Function 70fd4e5da5Sopenharmony_ci %14 = OpVariable %13 Function 71fd4e5da5Sopenharmony_ci %20 = OpVariable %19 Function 72fd4e5da5Sopenharmony_ci %26 = OpVariable %25 Function 73fd4e5da5Sopenharmony_ci OpStore %8 %9 74fd4e5da5Sopenharmony_ci OpStore %10 %11 75fd4e5da5Sopenharmony_ci %15 = OpLoad %6 %8 76fd4e5da5Sopenharmony_ci %16 = OpLoad %6 %10 77fd4e5da5Sopenharmony_ci %17 = OpCompositeConstruct %12 %15 %16 78fd4e5da5Sopenharmony_ci OpStore %14 %17 79fd4e5da5Sopenharmony_ci %21 = OpLoad %12 %14 80fd4e5da5Sopenharmony_ci %22 = OpLoad %12 %14 81fd4e5da5Sopenharmony_ci %23 = OpCompositeConstruct %18 %21 %22 82fd4e5da5Sopenharmony_ci OpStore %20 %23 83fd4e5da5Sopenharmony_ci %27 = OpLoad %18 %20 84fd4e5da5Sopenharmony_ci %28 = OpLoad %18 %20 85fd4e5da5Sopenharmony_ci %29 = OpCompositeConstruct %24 %27 %28 86fd4e5da5Sopenharmony_ci OpStore %26 %29 87fd4e5da5Sopenharmony_ci OpSelectionMerge %33 None 88fd4e5da5Sopenharmony_ci OpBranchConditional %31 %32 %33 89fd4e5da5Sopenharmony_ci %32 = OpLabel 90fd4e5da5Sopenharmony_ci OpBranch %33 91fd4e5da5Sopenharmony_ci %33 = OpLabel 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 // Bad: |fresh_id| is not fresh. 105fd4e5da5Sopenharmony_ci auto transformation_bad_1 = TransformationCompositeInsert( 106fd4e5da5Sopenharmony_ci MakeInstructionDescriptor(29, spv::Op::OpStore, 0), 20, 29, 11, 107fd4e5da5Sopenharmony_ci {1, 0, 0}); 108fd4e5da5Sopenharmony_ci ASSERT_FALSE( 109fd4e5da5Sopenharmony_ci transformation_bad_1.IsApplicable(context.get(), transformation_context)); 110fd4e5da5Sopenharmony_ci 111fd4e5da5Sopenharmony_ci // Bad: |composite_id| does not refer to a existing instruction. 112fd4e5da5Sopenharmony_ci auto transformation_bad_2 = TransformationCompositeInsert( 113fd4e5da5Sopenharmony_ci MakeInstructionDescriptor(29, spv::Op::OpStore, 0), 50, 40, 11, 114fd4e5da5Sopenharmony_ci {1, 0, 0}); 115fd4e5da5Sopenharmony_ci ASSERT_FALSE( 116fd4e5da5Sopenharmony_ci transformation_bad_2.IsApplicable(context.get(), transformation_context)); 117fd4e5da5Sopenharmony_ci 118fd4e5da5Sopenharmony_ci // Bad: |composite_id| does not refer to a composite value. 119fd4e5da5Sopenharmony_ci auto transformation_bad_3 = TransformationCompositeInsert( 120fd4e5da5Sopenharmony_ci MakeInstructionDescriptor(29, spv::Op::OpStore, 0), 50, 9, 11, {1, 0, 0}); 121fd4e5da5Sopenharmony_ci ASSERT_FALSE( 122fd4e5da5Sopenharmony_ci transformation_bad_3.IsApplicable(context.get(), transformation_context)); 123fd4e5da5Sopenharmony_ci 124fd4e5da5Sopenharmony_ci // Bad: |object_id| does not refer to a defined instruction. 125fd4e5da5Sopenharmony_ci auto transformation_bad_4 = TransformationCompositeInsert( 126fd4e5da5Sopenharmony_ci MakeInstructionDescriptor(29, spv::Op::OpStore, 0), 50, 29, 40, 127fd4e5da5Sopenharmony_ci {1, 0, 0}); 128fd4e5da5Sopenharmony_ci ASSERT_FALSE( 129fd4e5da5Sopenharmony_ci transformation_bad_4.IsApplicable(context.get(), transformation_context)); 130fd4e5da5Sopenharmony_ci 131fd4e5da5Sopenharmony_ci // Bad: |object_id| cannot refer to a pointer. 132fd4e5da5Sopenharmony_ci auto transformation_bad_5 = TransformationCompositeInsert( 133fd4e5da5Sopenharmony_ci MakeInstructionDescriptor(29, spv::Op::OpStore, 0), 50, 29, 8, {1, 0, 0}); 134fd4e5da5Sopenharmony_ci ASSERT_FALSE( 135fd4e5da5Sopenharmony_ci transformation_bad_5.IsApplicable(context.get(), transformation_context)); 136fd4e5da5Sopenharmony_ci 137fd4e5da5Sopenharmony_ci // Bad: |index| is not a correct index. 138fd4e5da5Sopenharmony_ci auto transformation_bad_6 = TransformationCompositeInsert( 139fd4e5da5Sopenharmony_ci MakeInstructionDescriptor(29, spv::Op::OpStore, 0), 50, 29, 11, 140fd4e5da5Sopenharmony_ci {2, 0, 0}); 141fd4e5da5Sopenharmony_ci ASSERT_FALSE( 142fd4e5da5Sopenharmony_ci transformation_bad_6.IsApplicable(context.get(), transformation_context)); 143fd4e5da5Sopenharmony_ci 144fd4e5da5Sopenharmony_ci // Bad: Type id of the object to be inserted and the type id of the 145fd4e5da5Sopenharmony_ci // component at |index| are not the same. 146fd4e5da5Sopenharmony_ci auto transformation_bad_7 = TransformationCompositeInsert( 147fd4e5da5Sopenharmony_ci MakeInstructionDescriptor(29, spv::Op::OpStore, 0), 50, 29, 11, {1, 0}); 148fd4e5da5Sopenharmony_ci ASSERT_FALSE( 149fd4e5da5Sopenharmony_ci transformation_bad_7.IsApplicable(context.get(), transformation_context)); 150fd4e5da5Sopenharmony_ci 151fd4e5da5Sopenharmony_ci // Bad: |instruction_to_insert_before| does not refer to a defined 152fd4e5da5Sopenharmony_ci // instruction. 153fd4e5da5Sopenharmony_ci auto transformation_bad_8 = TransformationCompositeInsert( 154fd4e5da5Sopenharmony_ci MakeInstructionDescriptor(29, spv::Op::OpIMul, 0), 50, 29, 11, {1, 0, 0}); 155fd4e5da5Sopenharmony_ci ASSERT_FALSE( 156fd4e5da5Sopenharmony_ci transformation_bad_8.IsApplicable(context.get(), transformation_context)); 157fd4e5da5Sopenharmony_ci 158fd4e5da5Sopenharmony_ci // Bad: OpCompositeInsert cannot be inserted before OpBranchConditional with 159fd4e5da5Sopenharmony_ci // OpSelectionMerge above it. 160fd4e5da5Sopenharmony_ci auto transformation_bad_9 = TransformationCompositeInsert( 161fd4e5da5Sopenharmony_ci MakeInstructionDescriptor(29, spv::Op::OpBranchConditional, 0), 50, 29, 162fd4e5da5Sopenharmony_ci 11, {1, 0, 0}); 163fd4e5da5Sopenharmony_ci ASSERT_FALSE( 164fd4e5da5Sopenharmony_ci transformation_bad_9.IsApplicable(context.get(), transformation_context)); 165fd4e5da5Sopenharmony_ci 166fd4e5da5Sopenharmony_ci // Bad: |composite_id| does not have a type_id. 167fd4e5da5Sopenharmony_ci auto transformation_bad_10 = TransformationCompositeInsert( 168fd4e5da5Sopenharmony_ci MakeInstructionDescriptor(29, spv::Op::OpStore, 0), 50, 1, 11, {1, 0, 0}); 169fd4e5da5Sopenharmony_ci ASSERT_FALSE(transformation_bad_10.IsApplicable(context.get(), 170fd4e5da5Sopenharmony_ci transformation_context)); 171fd4e5da5Sopenharmony_ci} 172fd4e5da5Sopenharmony_ci 173fd4e5da5Sopenharmony_ciTEST(TransformationCompositeInsertTest, EmptyCompositeScenarios) { 174fd4e5da5Sopenharmony_ci // This test handles cases where either the composite is empty or the 175fd4e5da5Sopenharmony_ci // composite contains an empty composite. 176fd4e5da5Sopenharmony_ci 177fd4e5da5Sopenharmony_ci std::string shader = R"( 178fd4e5da5Sopenharmony_ci OpCapability Shader 179fd4e5da5Sopenharmony_ci %1 = OpExtInstImport "GLSL.std.450" 180fd4e5da5Sopenharmony_ci OpMemoryModel Logical GLSL450 181fd4e5da5Sopenharmony_ci OpEntryPoint Fragment %4 "main" 182fd4e5da5Sopenharmony_ci OpExecutionMode %4 OriginUpperLeft 183fd4e5da5Sopenharmony_ci OpSource ESSL 310 184fd4e5da5Sopenharmony_ci OpName %4 "main" 185fd4e5da5Sopenharmony_ci OpName %8 "i1" 186fd4e5da5Sopenharmony_ci OpName %10 "i2" 187fd4e5da5Sopenharmony_ci OpName %12 "base" 188fd4e5da5Sopenharmony_ci OpMemberName %12 0 "a1" 189fd4e5da5Sopenharmony_ci OpMemberName %12 1 "a2" 190fd4e5da5Sopenharmony_ci OpName %14 "b" 191fd4e5da5Sopenharmony_ci %2 = OpTypeVoid 192fd4e5da5Sopenharmony_ci %60 = OpTypeStruct 193fd4e5da5Sopenharmony_ci %3 = OpTypeFunction %2 194fd4e5da5Sopenharmony_ci %6 = OpTypeInt 32 1 195fd4e5da5Sopenharmony_ci %7 = OpTypePointer Function %6 196fd4e5da5Sopenharmony_ci %9 = OpConstant %6 1 197fd4e5da5Sopenharmony_ci %11 = OpConstant %6 2 198fd4e5da5Sopenharmony_ci %61 = OpConstantComposite %60 199fd4e5da5Sopenharmony_ci %62 = OpConstantComposite %60 200fd4e5da5Sopenharmony_ci %12 = OpTypeStruct %6 %6 201fd4e5da5Sopenharmony_ci %63 = OpTypeStruct %6 %60 202fd4e5da5Sopenharmony_ci %13 = OpTypePointer Function %12 203fd4e5da5Sopenharmony_ci %4 = OpFunction %2 None %3 204fd4e5da5Sopenharmony_ci %5 = OpLabel 205fd4e5da5Sopenharmony_ci %8 = OpVariable %7 Function 206fd4e5da5Sopenharmony_ci %10 = OpVariable %7 Function 207fd4e5da5Sopenharmony_ci %14 = OpVariable %13 Function 208fd4e5da5Sopenharmony_ci OpStore %8 %9 209fd4e5da5Sopenharmony_ci OpStore %10 %11 210fd4e5da5Sopenharmony_ci %15 = OpLoad %6 %8 211fd4e5da5Sopenharmony_ci %16 = OpLoad %6 %10 212fd4e5da5Sopenharmony_ci %17 = OpCompositeConstruct %12 %15 %16 213fd4e5da5Sopenharmony_ci %64 = OpCompositeConstruct %63 %15 %61 214fd4e5da5Sopenharmony_ci OpStore %14 %17 215fd4e5da5Sopenharmony_ci OpReturn 216fd4e5da5Sopenharmony_ci OpFunctionEnd 217fd4e5da5Sopenharmony_ci )"; 218fd4e5da5Sopenharmony_ci 219fd4e5da5Sopenharmony_ci const auto env = SPV_ENV_UNIVERSAL_1_4; 220fd4e5da5Sopenharmony_ci const auto consumer = nullptr; 221fd4e5da5Sopenharmony_ci const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption); 222fd4e5da5Sopenharmony_ci spvtools::ValidatorOptions validator_options; 223fd4e5da5Sopenharmony_ci ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options, 224fd4e5da5Sopenharmony_ci kConsoleMessageConsumer)); 225fd4e5da5Sopenharmony_ci TransformationContext transformation_context( 226fd4e5da5Sopenharmony_ci MakeUnique<FactManager>(context.get()), validator_options); 227fd4e5da5Sopenharmony_ci // Bad: The composite with |composite_id| cannot be empty. 228fd4e5da5Sopenharmony_ci auto transformation_bad_1 = TransformationCompositeInsert( 229fd4e5da5Sopenharmony_ci MakeInstructionDescriptor(64, spv::Op::OpStore, 0), 50, 61, 62, {1}); 230fd4e5da5Sopenharmony_ci ASSERT_FALSE( 231fd4e5da5Sopenharmony_ci transformation_bad_1.IsApplicable(context.get(), transformation_context)); 232fd4e5da5Sopenharmony_ci 233fd4e5da5Sopenharmony_ci // Good: It is possible to insert into a composite an element which is an 234fd4e5da5Sopenharmony_ci // empty composite. 235fd4e5da5Sopenharmony_ci auto transformation_good_1 = TransformationCompositeInsert( 236fd4e5da5Sopenharmony_ci MakeInstructionDescriptor(64, spv::Op::OpStore, 0), 50, 64, 62, {1}); 237fd4e5da5Sopenharmony_ci ASSERT_TRUE(transformation_good_1.IsApplicable(context.get(), 238fd4e5da5Sopenharmony_ci transformation_context)); 239fd4e5da5Sopenharmony_ci ApplyAndCheckFreshIds(transformation_good_1, context.get(), 240fd4e5da5Sopenharmony_ci &transformation_context); 241fd4e5da5Sopenharmony_ci ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options, 242fd4e5da5Sopenharmony_ci kConsoleMessageConsumer)); 243fd4e5da5Sopenharmony_ci 244fd4e5da5Sopenharmony_ci std::string after_transformations = R"( 245fd4e5da5Sopenharmony_ci OpCapability Shader 246fd4e5da5Sopenharmony_ci %1 = OpExtInstImport "GLSL.std.450" 247fd4e5da5Sopenharmony_ci OpMemoryModel Logical GLSL450 248fd4e5da5Sopenharmony_ci OpEntryPoint Fragment %4 "main" 249fd4e5da5Sopenharmony_ci OpExecutionMode %4 OriginUpperLeft 250fd4e5da5Sopenharmony_ci OpSource ESSL 310 251fd4e5da5Sopenharmony_ci OpName %4 "main" 252fd4e5da5Sopenharmony_ci OpName %8 "i1" 253fd4e5da5Sopenharmony_ci OpName %10 "i2" 254fd4e5da5Sopenharmony_ci OpName %12 "base" 255fd4e5da5Sopenharmony_ci OpMemberName %12 0 "a1" 256fd4e5da5Sopenharmony_ci OpMemberName %12 1 "a2" 257fd4e5da5Sopenharmony_ci OpName %14 "b" 258fd4e5da5Sopenharmony_ci %2 = OpTypeVoid 259fd4e5da5Sopenharmony_ci %60 = OpTypeStruct 260fd4e5da5Sopenharmony_ci %3 = OpTypeFunction %2 261fd4e5da5Sopenharmony_ci %6 = OpTypeInt 32 1 262fd4e5da5Sopenharmony_ci %7 = OpTypePointer Function %6 263fd4e5da5Sopenharmony_ci %9 = OpConstant %6 1 264fd4e5da5Sopenharmony_ci %11 = OpConstant %6 2 265fd4e5da5Sopenharmony_ci %61 = OpConstantComposite %60 266fd4e5da5Sopenharmony_ci %62 = OpConstantComposite %60 267fd4e5da5Sopenharmony_ci %12 = OpTypeStruct %6 %6 268fd4e5da5Sopenharmony_ci %63 = OpTypeStruct %6 %60 269fd4e5da5Sopenharmony_ci %13 = OpTypePointer Function %12 270fd4e5da5Sopenharmony_ci %4 = OpFunction %2 None %3 271fd4e5da5Sopenharmony_ci %5 = OpLabel 272fd4e5da5Sopenharmony_ci %8 = OpVariable %7 Function 273fd4e5da5Sopenharmony_ci %10 = OpVariable %7 Function 274fd4e5da5Sopenharmony_ci %14 = OpVariable %13 Function 275fd4e5da5Sopenharmony_ci OpStore %8 %9 276fd4e5da5Sopenharmony_ci OpStore %10 %11 277fd4e5da5Sopenharmony_ci %15 = OpLoad %6 %8 278fd4e5da5Sopenharmony_ci %16 = OpLoad %6 %10 279fd4e5da5Sopenharmony_ci %17 = OpCompositeConstruct %12 %15 %16 280fd4e5da5Sopenharmony_ci %64 = OpCompositeConstruct %63 %15 %61 281fd4e5da5Sopenharmony_ci %50 = OpCompositeInsert %63 %62 %64 1 282fd4e5da5Sopenharmony_ci OpStore %14 %17 283fd4e5da5Sopenharmony_ci OpReturn 284fd4e5da5Sopenharmony_ci OpFunctionEnd 285fd4e5da5Sopenharmony_ci )"; 286fd4e5da5Sopenharmony_ci ASSERT_TRUE(IsEqual(env, after_transformations, context.get())); 287fd4e5da5Sopenharmony_ci} 288fd4e5da5Sopenharmony_ci 289fd4e5da5Sopenharmony_ciTEST(TransformationCompositeInsertTest, IrrelevantCompositeNoSynonyms) { 290fd4e5da5Sopenharmony_ci // This test handles cases where either |composite| is irrelevant. 291fd4e5da5Sopenharmony_ci // The transformation shouldn't create any synonyms. 292fd4e5da5Sopenharmony_ci // The member composite has a different number of elements than the parent 293fd4e5da5Sopenharmony_ci // composite. 294fd4e5da5Sopenharmony_ci 295fd4e5da5Sopenharmony_ci std::string shader = R"( 296fd4e5da5Sopenharmony_ci OpCapability Shader 297fd4e5da5Sopenharmony_ci %1 = OpExtInstImport "GLSL.std.450" 298fd4e5da5Sopenharmony_ci OpMemoryModel Logical GLSL450 299fd4e5da5Sopenharmony_ci OpEntryPoint Fragment %4 "main" 300fd4e5da5Sopenharmony_ci OpExecutionMode %4 OriginUpperLeft 301fd4e5da5Sopenharmony_ci OpSource ESSL 310 302fd4e5da5Sopenharmony_ci OpName %4 "main" 303fd4e5da5Sopenharmony_ci OpName %8 "i1" 304fd4e5da5Sopenharmony_ci OpName %10 "i2" 305fd4e5da5Sopenharmony_ci OpName %12 "base" 306fd4e5da5Sopenharmony_ci OpMemberName %12 0 "a1" 307fd4e5da5Sopenharmony_ci OpMemberName %12 1 "a2" 308fd4e5da5Sopenharmony_ci OpName %14 "b" 309fd4e5da5Sopenharmony_ci OpName %18 "level_1" 310fd4e5da5Sopenharmony_ci OpMemberName %18 0 "b1" 311fd4e5da5Sopenharmony_ci OpMemberName %18 1 "b2" 312fd4e5da5Sopenharmony_ci OpMemberName %18 2 "b3" 313fd4e5da5Sopenharmony_ci OpName %20 "l1" 314fd4e5da5Sopenharmony_ci OpName %25 "level_2" 315fd4e5da5Sopenharmony_ci OpMemberName %25 0 "c1" 316fd4e5da5Sopenharmony_ci OpMemberName %25 1 "c2" 317fd4e5da5Sopenharmony_ci OpName %27 "l2" 318fd4e5da5Sopenharmony_ci %2 = OpTypeVoid 319fd4e5da5Sopenharmony_ci %3 = OpTypeFunction %2 320fd4e5da5Sopenharmony_ci %6 = OpTypeInt 32 1 321fd4e5da5Sopenharmony_ci %7 = OpTypePointer Function %6 322fd4e5da5Sopenharmony_ci %9 = OpConstant %6 1 323fd4e5da5Sopenharmony_ci %11 = OpConstant %6 2 324fd4e5da5Sopenharmony_ci %12 = OpTypeStruct %6 %6 325fd4e5da5Sopenharmony_ci %13 = OpTypePointer Function %12 326fd4e5da5Sopenharmony_ci %18 = OpTypeStruct %12 %12 %12 327fd4e5da5Sopenharmony_ci %19 = OpTypePointer Function %18 328fd4e5da5Sopenharmony_ci %25 = OpTypeStruct %18 %18 329fd4e5da5Sopenharmony_ci %26 = OpTypePointer Function %25 330fd4e5da5Sopenharmony_ci %31 = OpTypeBool 331fd4e5da5Sopenharmony_ci %32 = OpConstantTrue %31 332fd4e5da5Sopenharmony_ci %4 = OpFunction %2 None %3 333fd4e5da5Sopenharmony_ci %5 = OpLabel 334fd4e5da5Sopenharmony_ci %8 = OpVariable %7 Function 335fd4e5da5Sopenharmony_ci %10 = OpVariable %7 Function 336fd4e5da5Sopenharmony_ci %14 = OpVariable %13 Function 337fd4e5da5Sopenharmony_ci %20 = OpVariable %19 Function 338fd4e5da5Sopenharmony_ci %27 = OpVariable %26 Function 339fd4e5da5Sopenharmony_ci OpStore %8 %9 340fd4e5da5Sopenharmony_ci OpStore %10 %11 341fd4e5da5Sopenharmony_ci %15 = OpLoad %6 %8 342fd4e5da5Sopenharmony_ci %16 = OpLoad %6 %10 343fd4e5da5Sopenharmony_ci %17 = OpCompositeConstruct %12 %15 %16 344fd4e5da5Sopenharmony_ci OpStore %14 %17 345fd4e5da5Sopenharmony_ci %21 = OpLoad %12 %14 346fd4e5da5Sopenharmony_ci %22 = OpLoad %12 %14 347fd4e5da5Sopenharmony_ci %23 = OpLoad %12 %14 348fd4e5da5Sopenharmony_ci %24 = OpCompositeConstruct %18 %21 %22 %23 349fd4e5da5Sopenharmony_ci OpStore %20 %24 350fd4e5da5Sopenharmony_ci %28 = OpLoad %18 %20 351fd4e5da5Sopenharmony_ci %29 = OpLoad %18 %20 352fd4e5da5Sopenharmony_ci %30 = OpCompositeConstruct %25 %28 %29 353fd4e5da5Sopenharmony_ci OpStore %27 %30 354fd4e5da5Sopenharmony_ci OpSelectionMerge %34 None 355fd4e5da5Sopenharmony_ci OpBranchConditional %32 %33 %34 356fd4e5da5Sopenharmony_ci %33 = OpLabel 357fd4e5da5Sopenharmony_ci OpBranch %34 358fd4e5da5Sopenharmony_ci %34 = OpLabel 359fd4e5da5Sopenharmony_ci OpReturn 360fd4e5da5Sopenharmony_ci OpFunctionEnd 361fd4e5da5Sopenharmony_ci )"; 362fd4e5da5Sopenharmony_ci 363fd4e5da5Sopenharmony_ci const auto env = SPV_ENV_UNIVERSAL_1_4; 364fd4e5da5Sopenharmony_ci const auto consumer = nullptr; 365fd4e5da5Sopenharmony_ci const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption); 366fd4e5da5Sopenharmony_ci spvtools::ValidatorOptions validator_options; 367fd4e5da5Sopenharmony_ci ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options, 368fd4e5da5Sopenharmony_ci kConsoleMessageConsumer)); 369fd4e5da5Sopenharmony_ci TransformationContext transformation_context( 370fd4e5da5Sopenharmony_ci MakeUnique<FactManager>(context.get()), validator_options); 371fd4e5da5Sopenharmony_ci // Add fact that the composite is irrelevant. 372fd4e5da5Sopenharmony_ci transformation_context.GetFactManager()->AddFactIdIsIrrelevant(30); 373fd4e5da5Sopenharmony_ci 374fd4e5da5Sopenharmony_ci auto transformation_good_1 = TransformationCompositeInsert( 375fd4e5da5Sopenharmony_ci MakeInstructionDescriptor(30, spv::Op::OpStore, 0), 50, 30, 11, 376fd4e5da5Sopenharmony_ci {1, 0, 0}); 377fd4e5da5Sopenharmony_ci ASSERT_TRUE(transformation_good_1.IsApplicable(context.get(), 378fd4e5da5Sopenharmony_ci transformation_context)); 379fd4e5da5Sopenharmony_ci ApplyAndCheckFreshIds(transformation_good_1, context.get(), 380fd4e5da5Sopenharmony_ci &transformation_context); 381fd4e5da5Sopenharmony_ci ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options, 382fd4e5da5Sopenharmony_ci kConsoleMessageConsumer)); 383fd4e5da5Sopenharmony_ci 384fd4e5da5Sopenharmony_ci // No synonyms that involve the original object - %30 - should have been 385fd4e5da5Sopenharmony_ci // added. 386fd4e5da5Sopenharmony_ci ASSERT_FALSE(transformation_context.GetFactManager()->IsSynonymous( 387fd4e5da5Sopenharmony_ci MakeDataDescriptor(30, {0}), MakeDataDescriptor(50, {0}))); 388fd4e5da5Sopenharmony_ci ASSERT_FALSE(transformation_context.GetFactManager()->IsSynonymous( 389fd4e5da5Sopenharmony_ci MakeDataDescriptor(30, {1, 1}), MakeDataDescriptor(50, {1, 1}))); 390fd4e5da5Sopenharmony_ci ASSERT_FALSE(transformation_context.GetFactManager()->IsSynonymous( 391fd4e5da5Sopenharmony_ci MakeDataDescriptor(30, {1, 2}), MakeDataDescriptor(50, {1, 2}))); 392fd4e5da5Sopenharmony_ci ASSERT_FALSE(transformation_context.GetFactManager()->IsSynonymous( 393fd4e5da5Sopenharmony_ci MakeDataDescriptor(30, {1, 0, 1}), MakeDataDescriptor(50, {1, 0, 1}))); 394fd4e5da5Sopenharmony_ci // We *should* have a synonym between %11 and the component of %50 into which 395fd4e5da5Sopenharmony_ci // it has been inserted. 396fd4e5da5Sopenharmony_ci ASSERT_TRUE(transformation_context.GetFactManager()->IsSynonymous( 397fd4e5da5Sopenharmony_ci MakeDataDescriptor(50, {1, 0, 0}), MakeDataDescriptor(11, {}))); 398fd4e5da5Sopenharmony_ci} 399fd4e5da5Sopenharmony_ci 400fd4e5da5Sopenharmony_ciTEST(TransformationCompositeInsertTest, IrrelevantObjectNoSynonyms) { 401fd4e5da5Sopenharmony_ci std::string shader = R"( 402fd4e5da5Sopenharmony_ci OpCapability Shader 403fd4e5da5Sopenharmony_ci %1 = OpExtInstImport "GLSL.std.450" 404fd4e5da5Sopenharmony_ci OpMemoryModel Logical GLSL450 405fd4e5da5Sopenharmony_ci OpEntryPoint Fragment %4 "main" 406fd4e5da5Sopenharmony_ci OpExecutionMode %4 OriginUpperLeft 407fd4e5da5Sopenharmony_ci OpSource ESSL 310 408fd4e5da5Sopenharmony_ci OpName %4 "main" 409fd4e5da5Sopenharmony_ci OpName %8 "i1" 410fd4e5da5Sopenharmony_ci OpName %10 "i2" 411fd4e5da5Sopenharmony_ci OpName %12 "base" 412fd4e5da5Sopenharmony_ci OpMemberName %12 0 "a1" 413fd4e5da5Sopenharmony_ci OpMemberName %12 1 "a2" 414fd4e5da5Sopenharmony_ci OpName %14 "b" 415fd4e5da5Sopenharmony_ci OpName %18 "level_1" 416fd4e5da5Sopenharmony_ci OpMemberName %18 0 "b1" 417fd4e5da5Sopenharmony_ci OpMemberName %18 1 "b2" 418fd4e5da5Sopenharmony_ci OpMemberName %18 2 "b3" 419fd4e5da5Sopenharmony_ci OpName %20 "l1" 420fd4e5da5Sopenharmony_ci OpName %25 "level_2" 421fd4e5da5Sopenharmony_ci OpMemberName %25 0 "c1" 422fd4e5da5Sopenharmony_ci OpMemberName %25 1 "c2" 423fd4e5da5Sopenharmony_ci OpName %27 "l2" 424fd4e5da5Sopenharmony_ci %2 = OpTypeVoid 425fd4e5da5Sopenharmony_ci %3 = OpTypeFunction %2 426fd4e5da5Sopenharmony_ci %6 = OpTypeInt 32 1 427fd4e5da5Sopenharmony_ci %7 = OpTypePointer Function %6 428fd4e5da5Sopenharmony_ci %9 = OpConstant %6 1 429fd4e5da5Sopenharmony_ci %11 = OpConstant %6 2 430fd4e5da5Sopenharmony_ci %12 = OpTypeStruct %6 %6 431fd4e5da5Sopenharmony_ci %13 = OpTypePointer Function %12 432fd4e5da5Sopenharmony_ci %18 = OpTypeStruct %12 %12 %12 433fd4e5da5Sopenharmony_ci %19 = OpTypePointer Function %18 434fd4e5da5Sopenharmony_ci %25 = OpTypeStruct %18 %18 435fd4e5da5Sopenharmony_ci %26 = OpTypePointer Function %25 436fd4e5da5Sopenharmony_ci %31 = OpTypeBool 437fd4e5da5Sopenharmony_ci %32 = OpConstantTrue %31 438fd4e5da5Sopenharmony_ci %4 = OpFunction %2 None %3 439fd4e5da5Sopenharmony_ci %5 = OpLabel 440fd4e5da5Sopenharmony_ci %8 = OpVariable %7 Function 441fd4e5da5Sopenharmony_ci %10 = OpVariable %7 Function 442fd4e5da5Sopenharmony_ci %14 = OpVariable %13 Function 443fd4e5da5Sopenharmony_ci %20 = OpVariable %19 Function 444fd4e5da5Sopenharmony_ci %27 = OpVariable %26 Function 445fd4e5da5Sopenharmony_ci OpStore %8 %9 446fd4e5da5Sopenharmony_ci OpStore %10 %11 447fd4e5da5Sopenharmony_ci %15 = OpLoad %6 %8 448fd4e5da5Sopenharmony_ci %16 = OpLoad %6 %10 449fd4e5da5Sopenharmony_ci %17 = OpCompositeConstruct %12 %15 %16 450fd4e5da5Sopenharmony_ci OpStore %14 %17 451fd4e5da5Sopenharmony_ci %21 = OpLoad %12 %14 452fd4e5da5Sopenharmony_ci %22 = OpLoad %12 %14 453fd4e5da5Sopenharmony_ci %23 = OpLoad %12 %14 454fd4e5da5Sopenharmony_ci %24 = OpCompositeConstruct %18 %21 %22 %23 455fd4e5da5Sopenharmony_ci OpStore %20 %24 456fd4e5da5Sopenharmony_ci %28 = OpLoad %18 %20 457fd4e5da5Sopenharmony_ci %29 = OpLoad %18 %20 458fd4e5da5Sopenharmony_ci %30 = OpCompositeConstruct %25 %28 %29 459fd4e5da5Sopenharmony_ci OpStore %27 %30 460fd4e5da5Sopenharmony_ci OpSelectionMerge %34 None 461fd4e5da5Sopenharmony_ci OpBranchConditional %32 %33 %34 462fd4e5da5Sopenharmony_ci %33 = OpLabel 463fd4e5da5Sopenharmony_ci OpBranch %34 464fd4e5da5Sopenharmony_ci %34 = OpLabel 465fd4e5da5Sopenharmony_ci OpReturn 466fd4e5da5Sopenharmony_ci OpFunctionEnd 467fd4e5da5Sopenharmony_ci )"; 468fd4e5da5Sopenharmony_ci 469fd4e5da5Sopenharmony_ci const auto env = SPV_ENV_UNIVERSAL_1_4; 470fd4e5da5Sopenharmony_ci const auto consumer = nullptr; 471fd4e5da5Sopenharmony_ci const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption); 472fd4e5da5Sopenharmony_ci spvtools::ValidatorOptions validator_options; 473fd4e5da5Sopenharmony_ci ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options, 474fd4e5da5Sopenharmony_ci kConsoleMessageConsumer)); 475fd4e5da5Sopenharmony_ci TransformationContext transformation_context( 476fd4e5da5Sopenharmony_ci MakeUnique<FactManager>(context.get()), validator_options); 477fd4e5da5Sopenharmony_ci // Add fact that the object is irrelevant. 478fd4e5da5Sopenharmony_ci transformation_context.GetFactManager()->AddFactIdIsIrrelevant(11); 479fd4e5da5Sopenharmony_ci 480fd4e5da5Sopenharmony_ci auto transformation_good_1 = TransformationCompositeInsert( 481fd4e5da5Sopenharmony_ci MakeInstructionDescriptor(30, spv::Op::OpStore, 0), 50, 30, 11, 482fd4e5da5Sopenharmony_ci {1, 0, 0}); 483fd4e5da5Sopenharmony_ci ASSERT_TRUE(transformation_good_1.IsApplicable(context.get(), 484fd4e5da5Sopenharmony_ci transformation_context)); 485fd4e5da5Sopenharmony_ci ApplyAndCheckFreshIds(transformation_good_1, context.get(), 486fd4e5da5Sopenharmony_ci &transformation_context); 487fd4e5da5Sopenharmony_ci ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options, 488fd4e5da5Sopenharmony_ci kConsoleMessageConsumer)); 489fd4e5da5Sopenharmony_ci 490fd4e5da5Sopenharmony_ci // Since %30 and %50 are not irrelevant, they should be synonymous at all 491fd4e5da5Sopenharmony_ci // indices unaffected by the insertion. 492fd4e5da5Sopenharmony_ci ASSERT_TRUE(transformation_context.GetFactManager()->IsSynonymous( 493fd4e5da5Sopenharmony_ci MakeDataDescriptor(30, {0}), MakeDataDescriptor(50, {0}))); 494fd4e5da5Sopenharmony_ci ASSERT_TRUE(transformation_context.GetFactManager()->IsSynonymous( 495fd4e5da5Sopenharmony_ci MakeDataDescriptor(30, {1, 1}), MakeDataDescriptor(50, {1, 1}))); 496fd4e5da5Sopenharmony_ci ASSERT_TRUE(transformation_context.GetFactManager()->IsSynonymous( 497fd4e5da5Sopenharmony_ci MakeDataDescriptor(30, {1, 2}), MakeDataDescriptor(50, {1, 2}))); 498fd4e5da5Sopenharmony_ci ASSERT_TRUE(transformation_context.GetFactManager()->IsSynonymous( 499fd4e5da5Sopenharmony_ci MakeDataDescriptor(30, {1, 0, 1}), MakeDataDescriptor(50, {1, 0, 1}))); 500fd4e5da5Sopenharmony_ci // Since %11 is irrelevant it should not be synonymous with the component into 501fd4e5da5Sopenharmony_ci // which it has been inserted. 502fd4e5da5Sopenharmony_ci ASSERT_FALSE(transformation_context.GetFactManager()->IsSynonymous( 503fd4e5da5Sopenharmony_ci MakeDataDescriptor(50, {1, 0, 0}), MakeDataDescriptor(11, {}))); 504fd4e5da5Sopenharmony_ci} 505fd4e5da5Sopenharmony_ci 506fd4e5da5Sopenharmony_ciTEST(TransformationCompositeInsertTest, ApplicableCreatedSynonyms) { 507fd4e5da5Sopenharmony_ci // This test handles cases where neither |composite| nor |object| is 508fd4e5da5Sopenharmony_ci // irrelevant. The transformation should create synonyms. 509fd4e5da5Sopenharmony_ci // The member composite has a different number of elements than the parent 510fd4e5da5Sopenharmony_ci // composite. 511fd4e5da5Sopenharmony_ci 512fd4e5da5Sopenharmony_ci std::string shader = R"( 513fd4e5da5Sopenharmony_ci OpCapability Shader 514fd4e5da5Sopenharmony_ci %1 = OpExtInstImport "GLSL.std.450" 515fd4e5da5Sopenharmony_ci OpMemoryModel Logical GLSL450 516fd4e5da5Sopenharmony_ci OpEntryPoint Fragment %4 "main" 517fd4e5da5Sopenharmony_ci OpExecutionMode %4 OriginUpperLeft 518fd4e5da5Sopenharmony_ci OpSource ESSL 310 519fd4e5da5Sopenharmony_ci OpName %4 "main" 520fd4e5da5Sopenharmony_ci OpName %8 "i1" 521fd4e5da5Sopenharmony_ci OpName %10 "i2" 522fd4e5da5Sopenharmony_ci OpName %12 "base" 523fd4e5da5Sopenharmony_ci OpMemberName %12 0 "a1" 524fd4e5da5Sopenharmony_ci OpMemberName %12 1 "a2" 525fd4e5da5Sopenharmony_ci OpName %14 "b" 526fd4e5da5Sopenharmony_ci OpName %18 "level_1" 527fd4e5da5Sopenharmony_ci OpMemberName %18 0 "b1" 528fd4e5da5Sopenharmony_ci OpMemberName %18 1 "b2" 529fd4e5da5Sopenharmony_ci OpMemberName %18 2 "b3" 530fd4e5da5Sopenharmony_ci OpName %20 "l1" 531fd4e5da5Sopenharmony_ci OpName %25 "level_2" 532fd4e5da5Sopenharmony_ci OpMemberName %25 0 "c1" 533fd4e5da5Sopenharmony_ci OpMemberName %25 1 "c2" 534fd4e5da5Sopenharmony_ci OpName %27 "l2" 535fd4e5da5Sopenharmony_ci %2 = OpTypeVoid 536fd4e5da5Sopenharmony_ci %3 = OpTypeFunction %2 537fd4e5da5Sopenharmony_ci %6 = OpTypeInt 32 1 538fd4e5da5Sopenharmony_ci %7 = OpTypePointer Function %6 539fd4e5da5Sopenharmony_ci %9 = OpConstant %6 1 540fd4e5da5Sopenharmony_ci %11 = OpConstant %6 2 541fd4e5da5Sopenharmony_ci %12 = OpTypeStruct %6 %6 542fd4e5da5Sopenharmony_ci %13 = OpTypePointer Function %12 543fd4e5da5Sopenharmony_ci %18 = OpTypeStruct %12 %12 %12 544fd4e5da5Sopenharmony_ci %19 = OpTypePointer Function %18 545fd4e5da5Sopenharmony_ci %25 = OpTypeStruct %18 %18 546fd4e5da5Sopenharmony_ci %26 = OpTypePointer Function %25 547fd4e5da5Sopenharmony_ci %31 = OpTypeBool 548fd4e5da5Sopenharmony_ci %32 = OpConstantTrue %31 549fd4e5da5Sopenharmony_ci %4 = OpFunction %2 None %3 550fd4e5da5Sopenharmony_ci %5 = OpLabel 551fd4e5da5Sopenharmony_ci %8 = OpVariable %7 Function 552fd4e5da5Sopenharmony_ci %10 = OpVariable %7 Function 553fd4e5da5Sopenharmony_ci %14 = OpVariable %13 Function 554fd4e5da5Sopenharmony_ci %20 = OpVariable %19 Function 555fd4e5da5Sopenharmony_ci %27 = OpVariable %26 Function 556fd4e5da5Sopenharmony_ci OpStore %8 %9 557fd4e5da5Sopenharmony_ci OpStore %10 %11 558fd4e5da5Sopenharmony_ci %15 = OpLoad %6 %8 559fd4e5da5Sopenharmony_ci %16 = OpLoad %6 %10 560fd4e5da5Sopenharmony_ci %17 = OpCompositeConstruct %12 %15 %16 561fd4e5da5Sopenharmony_ci OpStore %14 %17 562fd4e5da5Sopenharmony_ci %21 = OpLoad %12 %14 563fd4e5da5Sopenharmony_ci %22 = OpLoad %12 %14 564fd4e5da5Sopenharmony_ci %23 = OpLoad %12 %14 565fd4e5da5Sopenharmony_ci %24 = OpCompositeConstruct %18 %21 %22 %23 566fd4e5da5Sopenharmony_ci OpStore %20 %24 567fd4e5da5Sopenharmony_ci %28 = OpLoad %18 %20 568fd4e5da5Sopenharmony_ci %29 = OpLoad %18 %20 569fd4e5da5Sopenharmony_ci %30 = OpCompositeConstruct %25 %28 %29 570fd4e5da5Sopenharmony_ci OpStore %27 %30 571fd4e5da5Sopenharmony_ci OpSelectionMerge %34 None 572fd4e5da5Sopenharmony_ci OpBranchConditional %32 %33 %34 573fd4e5da5Sopenharmony_ci %33 = OpLabel 574fd4e5da5Sopenharmony_ci OpBranch %34 575fd4e5da5Sopenharmony_ci %34 = OpLabel 576fd4e5da5Sopenharmony_ci OpReturn 577fd4e5da5Sopenharmony_ci OpFunctionEnd 578fd4e5da5Sopenharmony_ci )"; 579fd4e5da5Sopenharmony_ci 580fd4e5da5Sopenharmony_ci const auto env = SPV_ENV_UNIVERSAL_1_4; 581fd4e5da5Sopenharmony_ci const auto consumer = nullptr; 582fd4e5da5Sopenharmony_ci const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption); 583fd4e5da5Sopenharmony_ci spvtools::ValidatorOptions validator_options; 584fd4e5da5Sopenharmony_ci ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options, 585fd4e5da5Sopenharmony_ci kConsoleMessageConsumer)); 586fd4e5da5Sopenharmony_ci TransformationContext transformation_context( 587fd4e5da5Sopenharmony_ci MakeUnique<FactManager>(context.get()), validator_options); 588fd4e5da5Sopenharmony_ci auto transformation_good_1 = TransformationCompositeInsert( 589fd4e5da5Sopenharmony_ci MakeInstructionDescriptor(30, spv::Op::OpStore, 0), 50, 30, 11, 590fd4e5da5Sopenharmony_ci {1, 0, 0}); 591fd4e5da5Sopenharmony_ci ASSERT_TRUE(transformation_good_1.IsApplicable(context.get(), 592fd4e5da5Sopenharmony_ci transformation_context)); 593fd4e5da5Sopenharmony_ci ApplyAndCheckFreshIds(transformation_good_1, context.get(), 594fd4e5da5Sopenharmony_ci &transformation_context); 595fd4e5da5Sopenharmony_ci ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options, 596fd4e5da5Sopenharmony_ci kConsoleMessageConsumer)); 597fd4e5da5Sopenharmony_ci 598fd4e5da5Sopenharmony_ci // These synonyms should have been added. 599fd4e5da5Sopenharmony_ci ASSERT_TRUE(transformation_context.GetFactManager()->IsSynonymous( 600fd4e5da5Sopenharmony_ci MakeDataDescriptor(30, {0}), MakeDataDescriptor(50, {0}))); 601fd4e5da5Sopenharmony_ci ASSERT_TRUE(transformation_context.GetFactManager()->IsSynonymous( 602fd4e5da5Sopenharmony_ci MakeDataDescriptor(30, {1, 1}), MakeDataDescriptor(50, {1, 1}))); 603fd4e5da5Sopenharmony_ci ASSERT_TRUE(transformation_context.GetFactManager()->IsSynonymous( 604fd4e5da5Sopenharmony_ci MakeDataDescriptor(30, {1, 2}), MakeDataDescriptor(50, {1, 2}))); 605fd4e5da5Sopenharmony_ci ASSERT_TRUE(transformation_context.GetFactManager()->IsSynonymous( 606fd4e5da5Sopenharmony_ci MakeDataDescriptor(30, {1, 0, 1}), MakeDataDescriptor(50, {1, 0, 1}))); 607fd4e5da5Sopenharmony_ci ASSERT_TRUE(transformation_context.GetFactManager()->IsSynonymous( 608fd4e5da5Sopenharmony_ci MakeDataDescriptor(50, {1, 0, 0}), MakeDataDescriptor(11, {}))); 609fd4e5da5Sopenharmony_ci 610fd4e5da5Sopenharmony_ci // These synonyms should not have been added. 611fd4e5da5Sopenharmony_ci ASSERT_FALSE(transformation_context.GetFactManager()->IsSynonymous( 612fd4e5da5Sopenharmony_ci MakeDataDescriptor(30, {1}), MakeDataDescriptor(50, {1}))); 613fd4e5da5Sopenharmony_ci ASSERT_FALSE(transformation_context.GetFactManager()->IsSynonymous( 614fd4e5da5Sopenharmony_ci MakeDataDescriptor(30, {1, 0}), MakeDataDescriptor(50, {1, 0}))); 615fd4e5da5Sopenharmony_ci ASSERT_FALSE(transformation_context.GetFactManager()->IsSynonymous( 616fd4e5da5Sopenharmony_ci MakeDataDescriptor(30, {1, 0, 0}), MakeDataDescriptor(50, {1, 0, 0}))); 617fd4e5da5Sopenharmony_ci 618fd4e5da5Sopenharmony_ci auto transformation_good_2 = TransformationCompositeInsert( 619fd4e5da5Sopenharmony_ci MakeInstructionDescriptor(50, spv::Op::OpStore, 0), 51, 50, 11, 620fd4e5da5Sopenharmony_ci {0, 1, 1}); 621fd4e5da5Sopenharmony_ci ASSERT_TRUE(transformation_good_2.IsApplicable(context.get(), 622fd4e5da5Sopenharmony_ci transformation_context)); 623fd4e5da5Sopenharmony_ci ApplyAndCheckFreshIds(transformation_good_2, context.get(), 624fd4e5da5Sopenharmony_ci &transformation_context); 625fd4e5da5Sopenharmony_ci ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options, 626fd4e5da5Sopenharmony_ci kConsoleMessageConsumer)); 627fd4e5da5Sopenharmony_ci 628fd4e5da5Sopenharmony_ci // These synonyms should have been added. 629fd4e5da5Sopenharmony_ci ASSERT_TRUE(transformation_context.GetFactManager()->IsSynonymous( 630fd4e5da5Sopenharmony_ci MakeDataDescriptor(50, {1}), MakeDataDescriptor(51, {1}))); 631fd4e5da5Sopenharmony_ci ASSERT_TRUE(transformation_context.GetFactManager()->IsSynonymous( 632fd4e5da5Sopenharmony_ci MakeDataDescriptor(50, {0, 0}), MakeDataDescriptor(51, {0, 0}))); 633fd4e5da5Sopenharmony_ci ASSERT_TRUE(transformation_context.GetFactManager()->IsSynonymous( 634fd4e5da5Sopenharmony_ci MakeDataDescriptor(50, {0, 2}), MakeDataDescriptor(51, {0, 2}))); 635fd4e5da5Sopenharmony_ci ASSERT_TRUE(transformation_context.GetFactManager()->IsSynonymous( 636fd4e5da5Sopenharmony_ci MakeDataDescriptor(50, {0, 1, 0}), MakeDataDescriptor(51, {0, 1, 0}))); 637fd4e5da5Sopenharmony_ci ASSERT_TRUE(transformation_context.GetFactManager()->IsSynonymous( 638fd4e5da5Sopenharmony_ci MakeDataDescriptor(51, {0, 1, 1}), MakeDataDescriptor(11, {}))); 639fd4e5da5Sopenharmony_ci 640fd4e5da5Sopenharmony_ci // These synonyms should not have been added. 641fd4e5da5Sopenharmony_ci ASSERT_FALSE(transformation_context.GetFactManager()->IsSynonymous( 642fd4e5da5Sopenharmony_ci MakeDataDescriptor(50, {0}), MakeDataDescriptor(51, {0}))); 643fd4e5da5Sopenharmony_ci ASSERT_FALSE(transformation_context.GetFactManager()->IsSynonymous( 644fd4e5da5Sopenharmony_ci MakeDataDescriptor(50, {0, 1}), MakeDataDescriptor(51, {0, 1}))); 645fd4e5da5Sopenharmony_ci ASSERT_FALSE(transformation_context.GetFactManager()->IsSynonymous( 646fd4e5da5Sopenharmony_ci MakeDataDescriptor(50, {0, 1, 1}), MakeDataDescriptor(51, {0, 1, 1}))); 647fd4e5da5Sopenharmony_ci 648fd4e5da5Sopenharmony_ci std::string after_transformations = R"( 649fd4e5da5Sopenharmony_ci OpCapability Shader 650fd4e5da5Sopenharmony_ci %1 = OpExtInstImport "GLSL.std.450" 651fd4e5da5Sopenharmony_ci OpMemoryModel Logical GLSL450 652fd4e5da5Sopenharmony_ci OpEntryPoint Fragment %4 "main" 653fd4e5da5Sopenharmony_ci OpExecutionMode %4 OriginUpperLeft 654fd4e5da5Sopenharmony_ci OpSource ESSL 310 655fd4e5da5Sopenharmony_ci OpName %4 "main" 656fd4e5da5Sopenharmony_ci OpName %8 "i1" 657fd4e5da5Sopenharmony_ci OpName %10 "i2" 658fd4e5da5Sopenharmony_ci OpName %12 "base" 659fd4e5da5Sopenharmony_ci OpMemberName %12 0 "a1" 660fd4e5da5Sopenharmony_ci OpMemberName %12 1 "a2" 661fd4e5da5Sopenharmony_ci OpName %14 "b" 662fd4e5da5Sopenharmony_ci OpName %18 "level_1" 663fd4e5da5Sopenharmony_ci OpMemberName %18 0 "b1" 664fd4e5da5Sopenharmony_ci OpMemberName %18 1 "b2" 665fd4e5da5Sopenharmony_ci OpMemberName %18 2 "b3" 666fd4e5da5Sopenharmony_ci OpName %20 "l1" 667fd4e5da5Sopenharmony_ci OpName %25 "level_2" 668fd4e5da5Sopenharmony_ci OpMemberName %25 0 "c1" 669fd4e5da5Sopenharmony_ci OpMemberName %25 1 "c2" 670fd4e5da5Sopenharmony_ci OpName %27 "l2" 671fd4e5da5Sopenharmony_ci %2 = OpTypeVoid 672fd4e5da5Sopenharmony_ci %3 = OpTypeFunction %2 673fd4e5da5Sopenharmony_ci %6 = OpTypeInt 32 1 674fd4e5da5Sopenharmony_ci %7 = OpTypePointer Function %6 675fd4e5da5Sopenharmony_ci %9 = OpConstant %6 1 676fd4e5da5Sopenharmony_ci %11 = OpConstant %6 2 677fd4e5da5Sopenharmony_ci %12 = OpTypeStruct %6 %6 678fd4e5da5Sopenharmony_ci %13 = OpTypePointer Function %12 679fd4e5da5Sopenharmony_ci %18 = OpTypeStruct %12 %12 %12 680fd4e5da5Sopenharmony_ci %19 = OpTypePointer Function %18 681fd4e5da5Sopenharmony_ci %25 = OpTypeStruct %18 %18 682fd4e5da5Sopenharmony_ci %26 = OpTypePointer Function %25 683fd4e5da5Sopenharmony_ci %31 = OpTypeBool 684fd4e5da5Sopenharmony_ci %32 = OpConstantTrue %31 685fd4e5da5Sopenharmony_ci %4 = OpFunction %2 None %3 686fd4e5da5Sopenharmony_ci %5 = OpLabel 687fd4e5da5Sopenharmony_ci %8 = OpVariable %7 Function 688fd4e5da5Sopenharmony_ci %10 = OpVariable %7 Function 689fd4e5da5Sopenharmony_ci %14 = OpVariable %13 Function 690fd4e5da5Sopenharmony_ci %20 = OpVariable %19 Function 691fd4e5da5Sopenharmony_ci %27 = OpVariable %26 Function 692fd4e5da5Sopenharmony_ci OpStore %8 %9 693fd4e5da5Sopenharmony_ci OpStore %10 %11 694fd4e5da5Sopenharmony_ci %15 = OpLoad %6 %8 695fd4e5da5Sopenharmony_ci %16 = OpLoad %6 %10 696fd4e5da5Sopenharmony_ci %17 = OpCompositeConstruct %12 %15 %16 697fd4e5da5Sopenharmony_ci OpStore %14 %17 698fd4e5da5Sopenharmony_ci %21 = OpLoad %12 %14 699fd4e5da5Sopenharmony_ci %22 = OpLoad %12 %14 700fd4e5da5Sopenharmony_ci %23 = OpLoad %12 %14 701fd4e5da5Sopenharmony_ci %24 = OpCompositeConstruct %18 %21 %22 %23 702fd4e5da5Sopenharmony_ci OpStore %20 %24 703fd4e5da5Sopenharmony_ci %28 = OpLoad %18 %20 704fd4e5da5Sopenharmony_ci %29 = OpLoad %18 %20 705fd4e5da5Sopenharmony_ci %30 = OpCompositeConstruct %25 %28 %29 706fd4e5da5Sopenharmony_ci %50 = OpCompositeInsert %25 %11 %30 1 0 0 707fd4e5da5Sopenharmony_ci %51 = OpCompositeInsert %25 %11 %50 0 1 1 708fd4e5da5Sopenharmony_ci OpStore %27 %30 709fd4e5da5Sopenharmony_ci OpSelectionMerge %34 None 710fd4e5da5Sopenharmony_ci OpBranchConditional %32 %33 %34 711fd4e5da5Sopenharmony_ci %33 = OpLabel 712fd4e5da5Sopenharmony_ci OpBranch %34 713fd4e5da5Sopenharmony_ci %34 = OpLabel 714fd4e5da5Sopenharmony_ci OpReturn 715fd4e5da5Sopenharmony_ci OpFunctionEnd 716fd4e5da5Sopenharmony_ci )"; 717fd4e5da5Sopenharmony_ci 718fd4e5da5Sopenharmony_ci ASSERT_TRUE(IsEqual(env, after_transformations, context.get())); 719fd4e5da5Sopenharmony_ci} 720fd4e5da5Sopenharmony_ci 721fd4e5da5Sopenharmony_ciTEST(TransformationCompositeInsertTest, IdNotAvailableScenarios) { 722fd4e5da5Sopenharmony_ci // This test handles cases where either the composite or the object is not 723fd4e5da5Sopenharmony_ci // available before the |instruction_to_insert_before|. 724fd4e5da5Sopenharmony_ci 725fd4e5da5Sopenharmony_ci std::string shader = R"( 726fd4e5da5Sopenharmony_ci OpCapability Shader 727fd4e5da5Sopenharmony_ci %1 = OpExtInstImport "GLSL.std.450" 728fd4e5da5Sopenharmony_ci OpMemoryModel Logical GLSL450 729fd4e5da5Sopenharmony_ci OpEntryPoint Fragment %4 "main" 730fd4e5da5Sopenharmony_ci OpExecutionMode %4 OriginUpperLeft 731fd4e5da5Sopenharmony_ci OpSource ESSL 310 732fd4e5da5Sopenharmony_ci OpName %4 "main" 733fd4e5da5Sopenharmony_ci OpName %8 "i1" 734fd4e5da5Sopenharmony_ci OpName %10 "i2" 735fd4e5da5Sopenharmony_ci OpName %12 "base" 736fd4e5da5Sopenharmony_ci OpMemberName %12 0 "a1" 737fd4e5da5Sopenharmony_ci OpMemberName %12 1 "a2" 738fd4e5da5Sopenharmony_ci OpName %14 "b1" 739fd4e5da5Sopenharmony_ci OpName %18 "b2" 740fd4e5da5Sopenharmony_ci OpName %22 "lvl1" 741fd4e5da5Sopenharmony_ci OpMemberName %22 0 "b1" 742fd4e5da5Sopenharmony_ci OpMemberName %22 1 "b2" 743fd4e5da5Sopenharmony_ci OpName %24 "l1" 744fd4e5da5Sopenharmony_ci OpName %28 "i3" 745fd4e5da5Sopenharmony_ci %2 = OpTypeVoid 746fd4e5da5Sopenharmony_ci %3 = OpTypeFunction %2 747fd4e5da5Sopenharmony_ci %6 = OpTypeInt 32 1 748fd4e5da5Sopenharmony_ci %7 = OpTypePointer Function %6 749fd4e5da5Sopenharmony_ci %9 = OpConstant %6 1 750fd4e5da5Sopenharmony_ci %11 = OpConstant %6 2 751fd4e5da5Sopenharmony_ci %12 = OpTypeStruct %6 %6 752fd4e5da5Sopenharmony_ci %13 = OpTypePointer Function %12 753fd4e5da5Sopenharmony_ci %22 = OpTypeStruct %12 %12 754fd4e5da5Sopenharmony_ci %23 = OpTypePointer Function %22 755fd4e5da5Sopenharmony_ci %4 = OpFunction %2 None %3 756fd4e5da5Sopenharmony_ci %5 = OpLabel 757fd4e5da5Sopenharmony_ci %8 = OpVariable %7 Function 758fd4e5da5Sopenharmony_ci %10 = OpVariable %7 Function 759fd4e5da5Sopenharmony_ci %14 = OpVariable %13 Function 760fd4e5da5Sopenharmony_ci %18 = OpVariable %13 Function 761fd4e5da5Sopenharmony_ci %24 = OpVariable %23 Function 762fd4e5da5Sopenharmony_ci %28 = OpVariable %7 Function 763fd4e5da5Sopenharmony_ci OpStore %8 %9 764fd4e5da5Sopenharmony_ci OpStore %10 %11 765fd4e5da5Sopenharmony_ci %15 = OpLoad %6 %8 766fd4e5da5Sopenharmony_ci %16 = OpLoad %6 %10 767fd4e5da5Sopenharmony_ci %17 = OpCompositeConstruct %12 %15 %16 768fd4e5da5Sopenharmony_ci OpStore %14 %17 769fd4e5da5Sopenharmony_ci %19 = OpLoad %6 %10 770fd4e5da5Sopenharmony_ci %20 = OpLoad %6 %8 771fd4e5da5Sopenharmony_ci %21 = OpCompositeConstruct %12 %19 %20 772fd4e5da5Sopenharmony_ci OpStore %18 %21 773fd4e5da5Sopenharmony_ci %25 = OpLoad %12 %14 774fd4e5da5Sopenharmony_ci %26 = OpLoad %12 %18 775fd4e5da5Sopenharmony_ci %27 = OpCompositeConstruct %22 %25 %26 776fd4e5da5Sopenharmony_ci OpStore %24 %27 777fd4e5da5Sopenharmony_ci %29 = OpLoad %6 %8 778fd4e5da5Sopenharmony_ci %30 = OpLoad %6 %10 779fd4e5da5Sopenharmony_ci %31 = OpIMul %6 %29 %30 780fd4e5da5Sopenharmony_ci OpStore %28 %31 781fd4e5da5Sopenharmony_ci %60 = OpCompositeConstruct %12 %20 %19 782fd4e5da5Sopenharmony_ci %61 = OpCompositeConstruct %22 %26 %25 783fd4e5da5Sopenharmony_ci OpReturn 784fd4e5da5Sopenharmony_ci OpFunctionEnd 785fd4e5da5Sopenharmony_ci )"; 786fd4e5da5Sopenharmony_ci 787fd4e5da5Sopenharmony_ci const auto env = SPV_ENV_UNIVERSAL_1_4; 788fd4e5da5Sopenharmony_ci const auto consumer = nullptr; 789fd4e5da5Sopenharmony_ci const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption); 790fd4e5da5Sopenharmony_ci spvtools::ValidatorOptions validator_options; 791fd4e5da5Sopenharmony_ci ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options, 792fd4e5da5Sopenharmony_ci kConsoleMessageConsumer)); 793fd4e5da5Sopenharmony_ci TransformationContext transformation_context( 794fd4e5da5Sopenharmony_ci MakeUnique<FactManager>(context.get()), validator_options); 795fd4e5da5Sopenharmony_ci // Bad: The object with |object_id| is not available at 796fd4e5da5Sopenharmony_ci // |instruction_to_insert_before|. 797fd4e5da5Sopenharmony_ci auto transformation_bad_1 = TransformationCompositeInsert( 798fd4e5da5Sopenharmony_ci MakeInstructionDescriptor(31, spv::Op::OpIMul, 0), 50, 27, 60, {1}); 799fd4e5da5Sopenharmony_ci ASSERT_FALSE( 800fd4e5da5Sopenharmony_ci transformation_bad_1.IsApplicable(context.get(), transformation_context)); 801fd4e5da5Sopenharmony_ci 802fd4e5da5Sopenharmony_ci // Bad: The composite with |composite_id| is not available at 803fd4e5da5Sopenharmony_ci // |instruction_to_insert_before|. 804fd4e5da5Sopenharmony_ci auto transformation_bad_2 = TransformationCompositeInsert( 805fd4e5da5Sopenharmony_ci MakeInstructionDescriptor(31, spv::Op::OpIMul, 0), 50, 61, 21, {1}); 806fd4e5da5Sopenharmony_ci ASSERT_FALSE( 807fd4e5da5Sopenharmony_ci transformation_bad_2.IsApplicable(context.get(), transformation_context)); 808fd4e5da5Sopenharmony_ci 809fd4e5da5Sopenharmony_ci // Bad: The |instruction_to_insert_before| is the composite itself and is 810fd4e5da5Sopenharmony_ci // available. 811fd4e5da5Sopenharmony_ci auto transformation_bad_3 = TransformationCompositeInsert( 812fd4e5da5Sopenharmony_ci MakeInstructionDescriptor(61, spv::Op::OpCompositeConstruct, 0), 50, 61, 813fd4e5da5Sopenharmony_ci 21, {1}); 814fd4e5da5Sopenharmony_ci ASSERT_FALSE( 815fd4e5da5Sopenharmony_ci transformation_bad_3.IsApplicable(context.get(), transformation_context)); 816fd4e5da5Sopenharmony_ci 817fd4e5da5Sopenharmony_ci // Bad: The |instruction_to_insert_before| is the object itself and is not 818fd4e5da5Sopenharmony_ci // available. 819fd4e5da5Sopenharmony_ci auto transformation_bad_4 = TransformationCompositeInsert( 820fd4e5da5Sopenharmony_ci MakeInstructionDescriptor(60, spv::Op::OpCompositeConstruct, 0), 50, 27, 821fd4e5da5Sopenharmony_ci 60, {1}); 822fd4e5da5Sopenharmony_ci ASSERT_FALSE( 823fd4e5da5Sopenharmony_ci transformation_bad_4.IsApplicable(context.get(), transformation_context)); 824fd4e5da5Sopenharmony_ci} 825fd4e5da5Sopenharmony_ci 826fd4e5da5Sopenharmony_ciTEST(TransformationCompositeInsertTest, CompositeInsertionWithIrrelevantIds) { 827fd4e5da5Sopenharmony_ci // This checks that we do *not* get data synonym facts when we do composite 828fd4e5da5Sopenharmony_ci // insertion using irrelevant ids or in dead blocks. 829fd4e5da5Sopenharmony_ci 830fd4e5da5Sopenharmony_ci std::string shader = R"( 831fd4e5da5Sopenharmony_ci OpCapability Shader 832fd4e5da5Sopenharmony_ci %1 = OpExtInstImport "GLSL.std.450" 833fd4e5da5Sopenharmony_ci OpMemoryModel Logical GLSL450 834fd4e5da5Sopenharmony_ci OpEntryPoint Fragment %12 "main" 835fd4e5da5Sopenharmony_ci OpExecutionMode %12 OriginUpperLeft 836fd4e5da5Sopenharmony_ci OpSource ESSL 310 837fd4e5da5Sopenharmony_ci %2 = OpTypeVoid 838fd4e5da5Sopenharmony_ci %3 = OpTypeFunction %2 839fd4e5da5Sopenharmony_ci %6 = OpTypeInt 32 1 840fd4e5da5Sopenharmony_ci %7 = OpTypeVector %6 2 841fd4e5da5Sopenharmony_ci %8 = OpConstant %6 0 842fd4e5da5Sopenharmony_ci %9 = OpConstantComposite %7 %8 %8 843fd4e5da5Sopenharmony_ci %10 = OpTypeBool 844fd4e5da5Sopenharmony_ci %11 = OpConstantFalse %10 845fd4e5da5Sopenharmony_ci %16 = OpConstant %6 0 846fd4e5da5Sopenharmony_ci %17 = OpConstant %6 1 847fd4e5da5Sopenharmony_ci %18 = OpConstantComposite %7 %8 %8 848fd4e5da5Sopenharmony_ci %12 = OpFunction %2 None %3 849fd4e5da5Sopenharmony_ci %13 = OpLabel 850fd4e5da5Sopenharmony_ci OpSelectionMerge %15 None 851fd4e5da5Sopenharmony_ci OpBranchConditional %11 %14 %15 852fd4e5da5Sopenharmony_ci %14 = OpLabel 853fd4e5da5Sopenharmony_ci OpBranch %15 854fd4e5da5Sopenharmony_ci %15 = OpLabel 855fd4e5da5Sopenharmony_ci OpReturn 856fd4e5da5Sopenharmony_ci OpFunctionEnd 857fd4e5da5Sopenharmony_ci )"; 858fd4e5da5Sopenharmony_ci 859fd4e5da5Sopenharmony_ci const auto env = SPV_ENV_UNIVERSAL_1_3; 860fd4e5da5Sopenharmony_ci const auto consumer = nullptr; 861fd4e5da5Sopenharmony_ci const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption); 862fd4e5da5Sopenharmony_ci spvtools::ValidatorOptions validator_options; 863fd4e5da5Sopenharmony_ci ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options, 864fd4e5da5Sopenharmony_ci kConsoleMessageConsumer)); 865fd4e5da5Sopenharmony_ci TransformationContext transformation_context( 866fd4e5da5Sopenharmony_ci MakeUnique<FactManager>(context.get()), validator_options); 867fd4e5da5Sopenharmony_ci 868fd4e5da5Sopenharmony_ci transformation_context.GetFactManager()->AddFactBlockIsDead(14); 869fd4e5da5Sopenharmony_ci transformation_context.GetFactManager()->AddFactIdIsIrrelevant(16); 870fd4e5da5Sopenharmony_ci transformation_context.GetFactManager()->AddFactIdIsIrrelevant(18); 871fd4e5da5Sopenharmony_ci 872fd4e5da5Sopenharmony_ci // Leads to synonyms - nothing is irrelevant. 873fd4e5da5Sopenharmony_ci auto transformation1 = TransformationCompositeInsert( 874fd4e5da5Sopenharmony_ci MakeInstructionDescriptor(13, spv::Op::OpSelectionMerge, 0), 100, 9, 17, 875fd4e5da5Sopenharmony_ci {0}); 876fd4e5da5Sopenharmony_ci ASSERT_TRUE( 877fd4e5da5Sopenharmony_ci transformation1.IsApplicable(context.get(), transformation_context)); 878fd4e5da5Sopenharmony_ci ApplyAndCheckFreshIds(transformation1, context.get(), 879fd4e5da5Sopenharmony_ci &transformation_context); 880fd4e5da5Sopenharmony_ci ASSERT_TRUE(transformation_context.GetFactManager()->IsSynonymous( 881fd4e5da5Sopenharmony_ci MakeDataDescriptor(100, {0}), MakeDataDescriptor(17, {}))); 882fd4e5da5Sopenharmony_ci ASSERT_TRUE(transformation_context.GetFactManager()->IsSynonymous( 883fd4e5da5Sopenharmony_ci MakeDataDescriptor(100, {1}), MakeDataDescriptor(9, {1}))); 884fd4e5da5Sopenharmony_ci 885fd4e5da5Sopenharmony_ci // Because %16 is irrelevant, we don't get a synonym with the component to 886fd4e5da5Sopenharmony_ci // which it has been inserted (but we do for the other component). 887fd4e5da5Sopenharmony_ci auto transformation2 = TransformationCompositeInsert( 888fd4e5da5Sopenharmony_ci MakeInstructionDescriptor(13, spv::Op::OpSelectionMerge, 0), 101, 9, 16, 889fd4e5da5Sopenharmony_ci {0}); 890fd4e5da5Sopenharmony_ci ASSERT_TRUE( 891fd4e5da5Sopenharmony_ci transformation2.IsApplicable(context.get(), transformation_context)); 892fd4e5da5Sopenharmony_ci ApplyAndCheckFreshIds(transformation2, context.get(), 893fd4e5da5Sopenharmony_ci &transformation_context); 894fd4e5da5Sopenharmony_ci ASSERT_FALSE(transformation_context.GetFactManager()->IsSynonymous( 895fd4e5da5Sopenharmony_ci MakeDataDescriptor(101, {0}), MakeDataDescriptor(16, {}))); 896fd4e5da5Sopenharmony_ci ASSERT_TRUE(transformation_context.GetFactManager()->IsSynonymous( 897fd4e5da5Sopenharmony_ci MakeDataDescriptor(101, {1}), MakeDataDescriptor(9, {1}))); 898fd4e5da5Sopenharmony_ci 899fd4e5da5Sopenharmony_ci // Because %18 is irrelevant we only get a synonym for the component into 900fd4e5da5Sopenharmony_ci // which insertion has taken place. 901fd4e5da5Sopenharmony_ci auto transformation3 = TransformationCompositeInsert( 902fd4e5da5Sopenharmony_ci MakeInstructionDescriptor(13, spv::Op::OpSelectionMerge, 0), 102, 18, 17, 903fd4e5da5Sopenharmony_ci {0}); 904fd4e5da5Sopenharmony_ci ASSERT_TRUE( 905fd4e5da5Sopenharmony_ci transformation3.IsApplicable(context.get(), transformation_context)); 906fd4e5da5Sopenharmony_ci ApplyAndCheckFreshIds(transformation3, context.get(), 907fd4e5da5Sopenharmony_ci &transformation_context); 908fd4e5da5Sopenharmony_ci ASSERT_TRUE(transformation_context.GetFactManager()->IsSynonymous( 909fd4e5da5Sopenharmony_ci MakeDataDescriptor(102, {0}), MakeDataDescriptor(17, {}))); 910fd4e5da5Sopenharmony_ci ASSERT_FALSE(transformation_context.GetFactManager()->IsSynonymous( 911fd4e5da5Sopenharmony_ci MakeDataDescriptor(102, {1}), MakeDataDescriptor(18, {1}))); 912fd4e5da5Sopenharmony_ci 913fd4e5da5Sopenharmony_ci // Does not lead to synonyms as block %14 is dead. 914fd4e5da5Sopenharmony_ci auto transformation4 = TransformationCompositeInsert( 915fd4e5da5Sopenharmony_ci MakeInstructionDescriptor(14, spv::Op::OpBranch, 0), 103, 9, 17, {0}); 916fd4e5da5Sopenharmony_ci ASSERT_TRUE( 917fd4e5da5Sopenharmony_ci transformation4.IsApplicable(context.get(), transformation_context)); 918fd4e5da5Sopenharmony_ci ApplyAndCheckFreshIds(transformation4, context.get(), 919fd4e5da5Sopenharmony_ci &transformation_context); 920fd4e5da5Sopenharmony_ci ASSERT_FALSE(transformation_context.GetFactManager()->IsSynonymous( 921fd4e5da5Sopenharmony_ci MakeDataDescriptor(103, {0}), MakeDataDescriptor(17, {}))); 922fd4e5da5Sopenharmony_ci ASSERT_FALSE(transformation_context.GetFactManager()->IsSynonymous( 923fd4e5da5Sopenharmony_ci MakeDataDescriptor(103, {1}), MakeDataDescriptor(9, {1}))); 924fd4e5da5Sopenharmony_ci 925fd4e5da5Sopenharmony_ci ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options, 926fd4e5da5Sopenharmony_ci kConsoleMessageConsumer)); 927fd4e5da5Sopenharmony_ci} 928fd4e5da5Sopenharmony_ci 929fd4e5da5Sopenharmony_ci} // namespace 930fd4e5da5Sopenharmony_ci} // namespace fuzz 931fd4e5da5Sopenharmony_ci} // namespace spvtools 932