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/fuzzer_pass_outline_functions.h" 16fd4e5da5Sopenharmony_ci 17fd4e5da5Sopenharmony_ci#include "gtest/gtest.h" 18fd4e5da5Sopenharmony_ci#include "source/fuzz/fuzzer_util.h" 19fd4e5da5Sopenharmony_ci#include "source/fuzz/pseudo_random_generator.h" 20fd4e5da5Sopenharmony_ci#include "test/fuzz/fuzz_test_util.h" 21fd4e5da5Sopenharmony_ci 22fd4e5da5Sopenharmony_cinamespace spvtools { 23fd4e5da5Sopenharmony_cinamespace fuzz { 24fd4e5da5Sopenharmony_cinamespace { 25fd4e5da5Sopenharmony_ci 26fd4e5da5Sopenharmony_cistd::string shader = R"( 27fd4e5da5Sopenharmony_ci OpCapability Shader 28fd4e5da5Sopenharmony_ci %1 = OpExtInstImport "GLSL.std.450" 29fd4e5da5Sopenharmony_ci OpMemoryModel Logical GLSL450 30fd4e5da5Sopenharmony_ci OpEntryPoint Fragment %2 "main" 31fd4e5da5Sopenharmony_ci OpExecutionMode %2 OriginUpperLeft 32fd4e5da5Sopenharmony_ci OpSource ESSL 310 33fd4e5da5Sopenharmony_ci OpName %2 "main" 34fd4e5da5Sopenharmony_ci OpName %3 "a" 35fd4e5da5Sopenharmony_ci OpName %4 "b" 36fd4e5da5Sopenharmony_ci OpDecorate %3 RelaxedPrecision 37fd4e5da5Sopenharmony_ci OpDecorate %4 RelaxedPrecision 38fd4e5da5Sopenharmony_ci OpDecorate %5 RelaxedPrecision 39fd4e5da5Sopenharmony_ci OpDecorate %6 RelaxedPrecision 40fd4e5da5Sopenharmony_ci OpDecorate %7 RelaxedPrecision 41fd4e5da5Sopenharmony_ci OpDecorate %8 RelaxedPrecision 42fd4e5da5Sopenharmony_ci OpDecorate %9 RelaxedPrecision 43fd4e5da5Sopenharmony_ci %10 = OpTypeVoid 44fd4e5da5Sopenharmony_ci %11 = OpTypeFunction %10 45fd4e5da5Sopenharmony_ci %12 = OpTypeInt 32 1 46fd4e5da5Sopenharmony_ci %13 = OpTypePointer Function %12 47fd4e5da5Sopenharmony_ci %14 = OpConstant %12 8 48fd4e5da5Sopenharmony_ci %15 = OpConstant %12 23 49fd4e5da5Sopenharmony_ci %16 = OpTypeBool 50fd4e5da5Sopenharmony_ci %17 = OpConstantTrue %16 51fd4e5da5Sopenharmony_ci %18 = OpConstant %12 0 52fd4e5da5Sopenharmony_ci %19 = OpConstant %12 1 53fd4e5da5Sopenharmony_ci %2 = OpFunction %10 None %11 54fd4e5da5Sopenharmony_ci %20 = OpLabel 55fd4e5da5Sopenharmony_ci %3 = OpVariable %13 Function 56fd4e5da5Sopenharmony_ci %4 = OpVariable %13 Function 57fd4e5da5Sopenharmony_ci OpStore %3 %14 58fd4e5da5Sopenharmony_ci OpStore %4 %15 59fd4e5da5Sopenharmony_ci OpBranch %21 60fd4e5da5Sopenharmony_ci %21 = OpLabel 61fd4e5da5Sopenharmony_ci OpLoopMerge %22 %23 None 62fd4e5da5Sopenharmony_ci OpBranch %24 63fd4e5da5Sopenharmony_ci %24 = OpLabel 64fd4e5da5Sopenharmony_ci %25 = OpPhi %12 %19 %21 %18 %26 65fd4e5da5Sopenharmony_ci OpLoopMerge %27 %26 None 66fd4e5da5Sopenharmony_ci OpBranch %28 67fd4e5da5Sopenharmony_ci %28 = OpLabel 68fd4e5da5Sopenharmony_ci %5 = OpLoad %12 %3 69fd4e5da5Sopenharmony_ci %29 = OpSGreaterThan %16 %5 %18 70fd4e5da5Sopenharmony_ci OpBranchConditional %29 %30 %27 71fd4e5da5Sopenharmony_ci %30 = OpLabel 72fd4e5da5Sopenharmony_ci %6 = OpLoad %12 %4 73fd4e5da5Sopenharmony_ci %7 = OpISub %12 %6 %19 74fd4e5da5Sopenharmony_ci OpStore %4 %7 75fd4e5da5Sopenharmony_ci OpBranch %26 76fd4e5da5Sopenharmony_ci %26 = OpLabel 77fd4e5da5Sopenharmony_ci %8 = OpLoad %12 %3 78fd4e5da5Sopenharmony_ci %9 = OpISub %12 %8 %19 79fd4e5da5Sopenharmony_ci OpStore %3 %9 80fd4e5da5Sopenharmony_ci OpBranch %24 81fd4e5da5Sopenharmony_ci %27 = OpLabel 82fd4e5da5Sopenharmony_ci OpBranch %23 83fd4e5da5Sopenharmony_ci %23 = OpLabel 84fd4e5da5Sopenharmony_ci OpBranch %21 85fd4e5da5Sopenharmony_ci %22 = OpLabel 86fd4e5da5Sopenharmony_ci OpBranch %31 87fd4e5da5Sopenharmony_ci %31 = OpLabel 88fd4e5da5Sopenharmony_ci OpLoopMerge %32 %31 None 89fd4e5da5Sopenharmony_ci OpBranchConditional %17 %31 %32 90fd4e5da5Sopenharmony_ci %32 = OpLabel 91fd4e5da5Sopenharmony_ci OpSelectionMerge %33 None 92fd4e5da5Sopenharmony_ci OpBranchConditional %17 %34 %35 93fd4e5da5Sopenharmony_ci %34 = OpLabel 94fd4e5da5Sopenharmony_ci OpBranch %33 95fd4e5da5Sopenharmony_ci %35 = OpLabel 96fd4e5da5Sopenharmony_ci OpBranch %33 97fd4e5da5Sopenharmony_ci %33 = OpLabel 98fd4e5da5Sopenharmony_ci %42 = OpPhi %12 %19 %33 %18 %34 %18 %35 99fd4e5da5Sopenharmony_ci OpLoopMerge %36 %33 None 100fd4e5da5Sopenharmony_ci OpBranchConditional %17 %36 %33 101fd4e5da5Sopenharmony_ci %36 = OpLabel 102fd4e5da5Sopenharmony_ci %43 = OpPhi %12 %18 %33 %18 %41 103fd4e5da5Sopenharmony_ci OpReturn 104fd4e5da5Sopenharmony_ci %37 = OpLabel 105fd4e5da5Sopenharmony_ci OpLoopMerge %38 %39 None 106fd4e5da5Sopenharmony_ci OpBranch %40 107fd4e5da5Sopenharmony_ci %40 = OpLabel 108fd4e5da5Sopenharmony_ci OpBranchConditional %17 %41 %38 109fd4e5da5Sopenharmony_ci %41 = OpLabel 110fd4e5da5Sopenharmony_ci OpBranchConditional %17 %36 %39 111fd4e5da5Sopenharmony_ci %39 = OpLabel 112fd4e5da5Sopenharmony_ci OpBranch %37 113fd4e5da5Sopenharmony_ci %38 = OpLabel 114fd4e5da5Sopenharmony_ci OpReturn 115fd4e5da5Sopenharmony_ci OpFunctionEnd 116fd4e5da5Sopenharmony_ci)"; 117fd4e5da5Sopenharmony_ci 118fd4e5da5Sopenharmony_ciTEST(FuzzerPassOutlineFunctionsTest, EntryIsAlreadySuitable) { 119fd4e5da5Sopenharmony_ci const auto env = SPV_ENV_UNIVERSAL_1_5; 120fd4e5da5Sopenharmony_ci const auto consumer = nullptr; 121fd4e5da5Sopenharmony_ci const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption); 122fd4e5da5Sopenharmony_ci spvtools::ValidatorOptions validator_options; 123fd4e5da5Sopenharmony_ci ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options, 124fd4e5da5Sopenharmony_ci kConsoleMessageConsumer)); 125fd4e5da5Sopenharmony_ci TransformationContext transformation_context( 126fd4e5da5Sopenharmony_ci MakeUnique<FactManager>(context.get()), validator_options); 127fd4e5da5Sopenharmony_ci FuzzerContext fuzzer_context(MakeUnique<PseudoRandomGenerator>(0), 100, 128fd4e5da5Sopenharmony_ci false); 129fd4e5da5Sopenharmony_ci protobufs::TransformationSequence transformation_sequence; 130fd4e5da5Sopenharmony_ci 131fd4e5da5Sopenharmony_ci FuzzerPassOutlineFunctions fuzzer_pass(context.get(), &transformation_context, 132fd4e5da5Sopenharmony_ci &fuzzer_context, 133fd4e5da5Sopenharmony_ci &transformation_sequence, false); 134fd4e5da5Sopenharmony_ci 135fd4e5da5Sopenharmony_ci // Block 28 136fd4e5da5Sopenharmony_ci auto suitable_entry_block = 137fd4e5da5Sopenharmony_ci fuzzer_pass.MaybeGetEntryBlockSuitableForOutlining( 138fd4e5da5Sopenharmony_ci context->get_instr_block(28)); 139fd4e5da5Sopenharmony_ci 140fd4e5da5Sopenharmony_ci ASSERT_TRUE(suitable_entry_block); 141fd4e5da5Sopenharmony_ci ASSERT_TRUE(suitable_entry_block->GetLabel()->result_id() == 28); 142fd4e5da5Sopenharmony_ci 143fd4e5da5Sopenharmony_ci // Block 32 144fd4e5da5Sopenharmony_ci suitable_entry_block = fuzzer_pass.MaybeGetEntryBlockSuitableForOutlining( 145fd4e5da5Sopenharmony_ci context->get_instr_block(32)); 146fd4e5da5Sopenharmony_ci 147fd4e5da5Sopenharmony_ci ASSERT_TRUE(suitable_entry_block); 148fd4e5da5Sopenharmony_ci ASSERT_TRUE(suitable_entry_block->GetLabel()->result_id() == 32); 149fd4e5da5Sopenharmony_ci 150fd4e5da5Sopenharmony_ci // Block 41 151fd4e5da5Sopenharmony_ci suitable_entry_block = fuzzer_pass.MaybeGetEntryBlockSuitableForOutlining( 152fd4e5da5Sopenharmony_ci context->get_instr_block(41)); 153fd4e5da5Sopenharmony_ci 154fd4e5da5Sopenharmony_ci ASSERT_TRUE(suitable_entry_block); 155fd4e5da5Sopenharmony_ci ASSERT_TRUE(suitable_entry_block->GetLabel()->result_id() == 41); 156fd4e5da5Sopenharmony_ci 157fd4e5da5Sopenharmony_ci // The module should not have been changed. 158fd4e5da5Sopenharmony_ci ASSERT_TRUE(IsEqual(env, shader, context.get())); 159fd4e5da5Sopenharmony_ci} 160fd4e5da5Sopenharmony_ci 161fd4e5da5Sopenharmony_ciTEST(FuzzerPassOutlineFunctionsTest, EntryHasOpVariable) { 162fd4e5da5Sopenharmony_ci const auto env = SPV_ENV_UNIVERSAL_1_5; 163fd4e5da5Sopenharmony_ci const auto consumer = nullptr; 164fd4e5da5Sopenharmony_ci const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption); 165fd4e5da5Sopenharmony_ci spvtools::ValidatorOptions validator_options; 166fd4e5da5Sopenharmony_ci ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options, 167fd4e5da5Sopenharmony_ci kConsoleMessageConsumer)); 168fd4e5da5Sopenharmony_ci TransformationContext transformation_context( 169fd4e5da5Sopenharmony_ci MakeUnique<FactManager>(context.get()), validator_options); 170fd4e5da5Sopenharmony_ci FuzzerContext fuzzer_context(MakeUnique<PseudoRandomGenerator>(0), 100, 171fd4e5da5Sopenharmony_ci false); 172fd4e5da5Sopenharmony_ci protobufs::TransformationSequence transformation_sequence; 173fd4e5da5Sopenharmony_ci 174fd4e5da5Sopenharmony_ci FuzzerPassOutlineFunctions fuzzer_pass(context.get(), &transformation_context, 175fd4e5da5Sopenharmony_ci &fuzzer_context, 176fd4e5da5Sopenharmony_ci &transformation_sequence, false); 177fd4e5da5Sopenharmony_ci 178fd4e5da5Sopenharmony_ci // Block 20 179fd4e5da5Sopenharmony_ci auto suitable_entry_block = 180fd4e5da5Sopenharmony_ci fuzzer_pass.MaybeGetEntryBlockSuitableForOutlining( 181fd4e5da5Sopenharmony_ci context->get_instr_block(20)); 182fd4e5da5Sopenharmony_ci 183fd4e5da5Sopenharmony_ci // The block should have been split, the new entry block being the block 184fd4e5da5Sopenharmony_ci // generated by the splitting. 185fd4e5da5Sopenharmony_ci ASSERT_TRUE(suitable_entry_block); 186fd4e5da5Sopenharmony_ci ASSERT_TRUE(suitable_entry_block->GetLabel()->result_id() == 100); 187fd4e5da5Sopenharmony_ci 188fd4e5da5Sopenharmony_ci std::string after_adjustment = R"( 189fd4e5da5Sopenharmony_ci OpCapability Shader 190fd4e5da5Sopenharmony_ci %1 = OpExtInstImport "GLSL.std.450" 191fd4e5da5Sopenharmony_ci OpMemoryModel Logical GLSL450 192fd4e5da5Sopenharmony_ci OpEntryPoint Fragment %2 "main" 193fd4e5da5Sopenharmony_ci OpExecutionMode %2 OriginUpperLeft 194fd4e5da5Sopenharmony_ci OpSource ESSL 310 195fd4e5da5Sopenharmony_ci OpName %2 "main" 196fd4e5da5Sopenharmony_ci OpName %3 "a" 197fd4e5da5Sopenharmony_ci OpName %4 "b" 198fd4e5da5Sopenharmony_ci OpDecorate %3 RelaxedPrecision 199fd4e5da5Sopenharmony_ci OpDecorate %4 RelaxedPrecision 200fd4e5da5Sopenharmony_ci OpDecorate %5 RelaxedPrecision 201fd4e5da5Sopenharmony_ci OpDecorate %6 RelaxedPrecision 202fd4e5da5Sopenharmony_ci OpDecorate %7 RelaxedPrecision 203fd4e5da5Sopenharmony_ci OpDecorate %8 RelaxedPrecision 204fd4e5da5Sopenharmony_ci OpDecorate %9 RelaxedPrecision 205fd4e5da5Sopenharmony_ci %10 = OpTypeVoid 206fd4e5da5Sopenharmony_ci %11 = OpTypeFunction %10 207fd4e5da5Sopenharmony_ci %12 = OpTypeInt 32 1 208fd4e5da5Sopenharmony_ci %13 = OpTypePointer Function %12 209fd4e5da5Sopenharmony_ci %14 = OpConstant %12 8 210fd4e5da5Sopenharmony_ci %15 = OpConstant %12 23 211fd4e5da5Sopenharmony_ci %16 = OpTypeBool 212fd4e5da5Sopenharmony_ci %17 = OpConstantTrue %16 213fd4e5da5Sopenharmony_ci %18 = OpConstant %12 0 214fd4e5da5Sopenharmony_ci %19 = OpConstant %12 1 215fd4e5da5Sopenharmony_ci %2 = OpFunction %10 None %11 216fd4e5da5Sopenharmony_ci %20 = OpLabel 217fd4e5da5Sopenharmony_ci %3 = OpVariable %13 Function 218fd4e5da5Sopenharmony_ci %4 = OpVariable %13 Function 219fd4e5da5Sopenharmony_ci OpBranch %100 220fd4e5da5Sopenharmony_ci %100 = OpLabel 221fd4e5da5Sopenharmony_ci OpStore %3 %14 222fd4e5da5Sopenharmony_ci OpStore %4 %15 223fd4e5da5Sopenharmony_ci OpBranch %21 224fd4e5da5Sopenharmony_ci %21 = OpLabel 225fd4e5da5Sopenharmony_ci OpLoopMerge %22 %23 None 226fd4e5da5Sopenharmony_ci OpBranch %24 227fd4e5da5Sopenharmony_ci %24 = OpLabel 228fd4e5da5Sopenharmony_ci %25 = OpPhi %12 %19 %21 %18 %26 229fd4e5da5Sopenharmony_ci OpLoopMerge %27 %26 None 230fd4e5da5Sopenharmony_ci OpBranch %28 231fd4e5da5Sopenharmony_ci %28 = OpLabel 232fd4e5da5Sopenharmony_ci %5 = OpLoad %12 %3 233fd4e5da5Sopenharmony_ci %29 = OpSGreaterThan %16 %5 %18 234fd4e5da5Sopenharmony_ci OpBranchConditional %29 %30 %27 235fd4e5da5Sopenharmony_ci %30 = OpLabel 236fd4e5da5Sopenharmony_ci %6 = OpLoad %12 %4 237fd4e5da5Sopenharmony_ci %7 = OpISub %12 %6 %19 238fd4e5da5Sopenharmony_ci OpStore %4 %7 239fd4e5da5Sopenharmony_ci OpBranch %26 240fd4e5da5Sopenharmony_ci %26 = OpLabel 241fd4e5da5Sopenharmony_ci %8 = OpLoad %12 %3 242fd4e5da5Sopenharmony_ci %9 = OpISub %12 %8 %19 243fd4e5da5Sopenharmony_ci OpStore %3 %9 244fd4e5da5Sopenharmony_ci OpBranch %24 245fd4e5da5Sopenharmony_ci %27 = OpLabel 246fd4e5da5Sopenharmony_ci OpBranch %23 247fd4e5da5Sopenharmony_ci %23 = OpLabel 248fd4e5da5Sopenharmony_ci OpBranch %21 249fd4e5da5Sopenharmony_ci %22 = OpLabel 250fd4e5da5Sopenharmony_ci OpBranch %31 251fd4e5da5Sopenharmony_ci %31 = OpLabel 252fd4e5da5Sopenharmony_ci OpLoopMerge %32 %31 None 253fd4e5da5Sopenharmony_ci OpBranchConditional %17 %31 %32 254fd4e5da5Sopenharmony_ci %32 = OpLabel 255fd4e5da5Sopenharmony_ci OpSelectionMerge %33 None 256fd4e5da5Sopenharmony_ci OpBranchConditional %17 %34 %35 257fd4e5da5Sopenharmony_ci %34 = OpLabel 258fd4e5da5Sopenharmony_ci OpBranch %33 259fd4e5da5Sopenharmony_ci %35 = OpLabel 260fd4e5da5Sopenharmony_ci OpBranch %33 261fd4e5da5Sopenharmony_ci %33 = OpLabel 262fd4e5da5Sopenharmony_ci %42 = OpPhi %12 %19 %33 %18 %34 %18 %35 263fd4e5da5Sopenharmony_ci OpLoopMerge %36 %33 None 264fd4e5da5Sopenharmony_ci OpBranchConditional %17 %36 %33 265fd4e5da5Sopenharmony_ci %36 = OpLabel 266fd4e5da5Sopenharmony_ci %43 = OpPhi %12 %18 %33 %18 %41 267fd4e5da5Sopenharmony_ci OpReturn 268fd4e5da5Sopenharmony_ci %37 = OpLabel 269fd4e5da5Sopenharmony_ci OpLoopMerge %38 %39 None 270fd4e5da5Sopenharmony_ci OpBranch %40 271fd4e5da5Sopenharmony_ci %40 = OpLabel 272fd4e5da5Sopenharmony_ci OpBranchConditional %17 %41 %38 273fd4e5da5Sopenharmony_ci %41 = OpLabel 274fd4e5da5Sopenharmony_ci OpBranchConditional %17 %36 %39 275fd4e5da5Sopenharmony_ci %39 = OpLabel 276fd4e5da5Sopenharmony_ci OpBranch %37 277fd4e5da5Sopenharmony_ci %38 = OpLabel 278fd4e5da5Sopenharmony_ci OpReturn 279fd4e5da5Sopenharmony_ci OpFunctionEnd 280fd4e5da5Sopenharmony_ci)"; 281fd4e5da5Sopenharmony_ci 282fd4e5da5Sopenharmony_ci ASSERT_TRUE(IsEqual(env, after_adjustment, context.get())); 283fd4e5da5Sopenharmony_ci} 284fd4e5da5Sopenharmony_ci 285fd4e5da5Sopenharmony_ciTEST(FuzzerPassOutlineFunctionsTest, EntryBlockIsHeader) { 286fd4e5da5Sopenharmony_ci const auto env = SPV_ENV_UNIVERSAL_1_5; 287fd4e5da5Sopenharmony_ci const auto consumer = nullptr; 288fd4e5da5Sopenharmony_ci const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption); 289fd4e5da5Sopenharmony_ci spvtools::ValidatorOptions validator_options; 290fd4e5da5Sopenharmony_ci ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options, 291fd4e5da5Sopenharmony_ci kConsoleMessageConsumer)); 292fd4e5da5Sopenharmony_ci TransformationContext transformation_context( 293fd4e5da5Sopenharmony_ci MakeUnique<FactManager>(context.get()), validator_options); 294fd4e5da5Sopenharmony_ci FuzzerContext fuzzer_context(MakeUnique<PseudoRandomGenerator>(0), 100, 295fd4e5da5Sopenharmony_ci false); 296fd4e5da5Sopenharmony_ci protobufs::TransformationSequence transformation_sequence; 297fd4e5da5Sopenharmony_ci 298fd4e5da5Sopenharmony_ci FuzzerPassOutlineFunctions fuzzer_pass(context.get(), &transformation_context, 299fd4e5da5Sopenharmony_ci &fuzzer_context, 300fd4e5da5Sopenharmony_ci &transformation_sequence, false); 301fd4e5da5Sopenharmony_ci 302fd4e5da5Sopenharmony_ci // Block 21 303fd4e5da5Sopenharmony_ci auto suitable_entry_block = 304fd4e5da5Sopenharmony_ci fuzzer_pass.MaybeGetEntryBlockSuitableForOutlining( 305fd4e5da5Sopenharmony_ci context->get_instr_block(21)); 306fd4e5da5Sopenharmony_ci 307fd4e5da5Sopenharmony_ci // A suitable entry block should have been found by finding the preheader 308fd4e5da5Sopenharmony_ci // (%20) and then splitting it. 309fd4e5da5Sopenharmony_ci ASSERT_TRUE(suitable_entry_block); 310fd4e5da5Sopenharmony_ci ASSERT_TRUE(suitable_entry_block->GetLabel()->result_id() == 100); 311fd4e5da5Sopenharmony_ci 312fd4e5da5Sopenharmony_ci // Block 24 313fd4e5da5Sopenharmony_ci suitable_entry_block = fuzzer_pass.MaybeGetEntryBlockSuitableForOutlining( 314fd4e5da5Sopenharmony_ci context->get_instr_block(24)); 315fd4e5da5Sopenharmony_ci 316fd4e5da5Sopenharmony_ci // A preheader should have been created, because the current one is a loop 317fd4e5da5Sopenharmony_ci // header. 318fd4e5da5Sopenharmony_ci ASSERT_TRUE(suitable_entry_block); 319fd4e5da5Sopenharmony_ci ASSERT_TRUE(suitable_entry_block->GetLabel()->result_id() == 101); 320fd4e5da5Sopenharmony_ci 321fd4e5da5Sopenharmony_ci // Block 31 322fd4e5da5Sopenharmony_ci suitable_entry_block = fuzzer_pass.MaybeGetEntryBlockSuitableForOutlining( 323fd4e5da5Sopenharmony_ci context->get_instr_block(31)); 324fd4e5da5Sopenharmony_ci 325fd4e5da5Sopenharmony_ci // An existing suitable entry block should have been found by finding the 326fd4e5da5Sopenharmony_ci // preheader (%22), which is already suitable. 327fd4e5da5Sopenharmony_ci ASSERT_TRUE(suitable_entry_block); 328fd4e5da5Sopenharmony_ci ASSERT_TRUE(suitable_entry_block->GetLabel()->result_id() == 22); 329fd4e5da5Sopenharmony_ci 330fd4e5da5Sopenharmony_ci // Block 33 331fd4e5da5Sopenharmony_ci suitable_entry_block = fuzzer_pass.MaybeGetEntryBlockSuitableForOutlining( 332fd4e5da5Sopenharmony_ci context->get_instr_block(33)); 333fd4e5da5Sopenharmony_ci 334fd4e5da5Sopenharmony_ci // An existing suitable entry block should have been found by creating a new 335fd4e5da5Sopenharmony_ci // preheader (there is not one already), and then splitting it (as it contains 336fd4e5da5Sopenharmony_ci // OpPhi). 337fd4e5da5Sopenharmony_ci ASSERT_TRUE(suitable_entry_block); 338fd4e5da5Sopenharmony_ci ASSERT_TRUE(suitable_entry_block->GetLabel()->result_id() == 104); 339fd4e5da5Sopenharmony_ci 340fd4e5da5Sopenharmony_ci // Block 37 341fd4e5da5Sopenharmony_ci suitable_entry_block = fuzzer_pass.MaybeGetEntryBlockSuitableForOutlining( 342fd4e5da5Sopenharmony_ci context->get_instr_block(37)); 343fd4e5da5Sopenharmony_ci 344fd4e5da5Sopenharmony_ci // No suitable entry block can be found for block 37, since it is a loop 345fd4e5da5Sopenharmony_ci // header with only one predecessor (the back-edge block). 346fd4e5da5Sopenharmony_ci ASSERT_FALSE(suitable_entry_block); 347fd4e5da5Sopenharmony_ci 348fd4e5da5Sopenharmony_ci std::string after_adjustments = R"( 349fd4e5da5Sopenharmony_ci OpCapability Shader 350fd4e5da5Sopenharmony_ci %1 = OpExtInstImport "GLSL.std.450" 351fd4e5da5Sopenharmony_ci OpMemoryModel Logical GLSL450 352fd4e5da5Sopenharmony_ci OpEntryPoint Fragment %2 "main" 353fd4e5da5Sopenharmony_ci OpExecutionMode %2 OriginUpperLeft 354fd4e5da5Sopenharmony_ci OpSource ESSL 310 355fd4e5da5Sopenharmony_ci OpName %2 "main" 356fd4e5da5Sopenharmony_ci OpName %3 "a" 357fd4e5da5Sopenharmony_ci OpName %4 "b" 358fd4e5da5Sopenharmony_ci OpDecorate %3 RelaxedPrecision 359fd4e5da5Sopenharmony_ci OpDecorate %4 RelaxedPrecision 360fd4e5da5Sopenharmony_ci OpDecorate %5 RelaxedPrecision 361fd4e5da5Sopenharmony_ci OpDecorate %6 RelaxedPrecision 362fd4e5da5Sopenharmony_ci OpDecorate %7 RelaxedPrecision 363fd4e5da5Sopenharmony_ci OpDecorate %8 RelaxedPrecision 364fd4e5da5Sopenharmony_ci OpDecorate %9 RelaxedPrecision 365fd4e5da5Sopenharmony_ci %10 = OpTypeVoid 366fd4e5da5Sopenharmony_ci %11 = OpTypeFunction %10 367fd4e5da5Sopenharmony_ci %12 = OpTypeInt 32 1 368fd4e5da5Sopenharmony_ci %13 = OpTypePointer Function %12 369fd4e5da5Sopenharmony_ci %14 = OpConstant %12 8 370fd4e5da5Sopenharmony_ci %15 = OpConstant %12 23 371fd4e5da5Sopenharmony_ci %16 = OpTypeBool 372fd4e5da5Sopenharmony_ci %17 = OpConstantTrue %16 373fd4e5da5Sopenharmony_ci %18 = OpConstant %12 0 374fd4e5da5Sopenharmony_ci %19 = OpConstant %12 1 375fd4e5da5Sopenharmony_ci %2 = OpFunction %10 None %11 376fd4e5da5Sopenharmony_ci %20 = OpLabel 377fd4e5da5Sopenharmony_ci %3 = OpVariable %13 Function 378fd4e5da5Sopenharmony_ci %4 = OpVariable %13 Function 379fd4e5da5Sopenharmony_ci OpBranch %100 380fd4e5da5Sopenharmony_ci %100 = OpLabel 381fd4e5da5Sopenharmony_ci OpStore %3 %14 382fd4e5da5Sopenharmony_ci OpStore %4 %15 383fd4e5da5Sopenharmony_ci OpBranch %21 384fd4e5da5Sopenharmony_ci %21 = OpLabel 385fd4e5da5Sopenharmony_ci OpLoopMerge %22 %23 None 386fd4e5da5Sopenharmony_ci OpBranch %101 387fd4e5da5Sopenharmony_ci %101 = OpLabel 388fd4e5da5Sopenharmony_ci OpBranch %24 389fd4e5da5Sopenharmony_ci %24 = OpLabel 390fd4e5da5Sopenharmony_ci %25 = OpPhi %12 %19 %101 %18 %26 391fd4e5da5Sopenharmony_ci OpLoopMerge %27 %26 None 392fd4e5da5Sopenharmony_ci OpBranch %28 393fd4e5da5Sopenharmony_ci %28 = OpLabel 394fd4e5da5Sopenharmony_ci %5 = OpLoad %12 %3 395fd4e5da5Sopenharmony_ci %29 = OpSGreaterThan %16 %5 %18 396fd4e5da5Sopenharmony_ci OpBranchConditional %29 %30 %27 397fd4e5da5Sopenharmony_ci %30 = OpLabel 398fd4e5da5Sopenharmony_ci %6 = OpLoad %12 %4 399fd4e5da5Sopenharmony_ci %7 = OpISub %12 %6 %19 400fd4e5da5Sopenharmony_ci OpStore %4 %7 401fd4e5da5Sopenharmony_ci OpBranch %26 402fd4e5da5Sopenharmony_ci %26 = OpLabel 403fd4e5da5Sopenharmony_ci %8 = OpLoad %12 %3 404fd4e5da5Sopenharmony_ci %9 = OpISub %12 %8 %19 405fd4e5da5Sopenharmony_ci OpStore %3 %9 406fd4e5da5Sopenharmony_ci OpBranch %24 407fd4e5da5Sopenharmony_ci %27 = OpLabel 408fd4e5da5Sopenharmony_ci OpBranch %23 409fd4e5da5Sopenharmony_ci %23 = OpLabel 410fd4e5da5Sopenharmony_ci OpBranch %21 411fd4e5da5Sopenharmony_ci %22 = OpLabel 412fd4e5da5Sopenharmony_ci OpBranch %31 413fd4e5da5Sopenharmony_ci %31 = OpLabel 414fd4e5da5Sopenharmony_ci OpLoopMerge %32 %31 None 415fd4e5da5Sopenharmony_ci OpBranchConditional %17 %31 %32 416fd4e5da5Sopenharmony_ci %32 = OpLabel 417fd4e5da5Sopenharmony_ci OpSelectionMerge %102 None 418fd4e5da5Sopenharmony_ci OpBranchConditional %17 %34 %35 419fd4e5da5Sopenharmony_ci %34 = OpLabel 420fd4e5da5Sopenharmony_ci OpBranch %102 421fd4e5da5Sopenharmony_ci %35 = OpLabel 422fd4e5da5Sopenharmony_ci OpBranch %102 423fd4e5da5Sopenharmony_ci %102 = OpLabel 424fd4e5da5Sopenharmony_ci %103 = OpPhi %12 %18 %34 %18 %35 425fd4e5da5Sopenharmony_ci OpBranch %104 426fd4e5da5Sopenharmony_ci %104 = OpLabel 427fd4e5da5Sopenharmony_ci OpBranch %33 428fd4e5da5Sopenharmony_ci %33 = OpLabel 429fd4e5da5Sopenharmony_ci %42 = OpPhi %12 %103 %104 %19 %33 430fd4e5da5Sopenharmony_ci OpLoopMerge %36 %33 None 431fd4e5da5Sopenharmony_ci OpBranchConditional %17 %36 %33 432fd4e5da5Sopenharmony_ci %36 = OpLabel 433fd4e5da5Sopenharmony_ci %43 = OpPhi %12 %18 %33 %18 %41 434fd4e5da5Sopenharmony_ci OpReturn 435fd4e5da5Sopenharmony_ci %37 = OpLabel 436fd4e5da5Sopenharmony_ci OpLoopMerge %38 %39 None 437fd4e5da5Sopenharmony_ci OpBranch %40 438fd4e5da5Sopenharmony_ci %40 = OpLabel 439fd4e5da5Sopenharmony_ci OpBranchConditional %17 %41 %38 440fd4e5da5Sopenharmony_ci %41 = OpLabel 441fd4e5da5Sopenharmony_ci OpBranchConditional %17 %36 %39 442fd4e5da5Sopenharmony_ci %39 = OpLabel 443fd4e5da5Sopenharmony_ci OpBranch %37 444fd4e5da5Sopenharmony_ci %38 = OpLabel 445fd4e5da5Sopenharmony_ci OpReturn 446fd4e5da5Sopenharmony_ci OpFunctionEnd 447fd4e5da5Sopenharmony_ci)"; 448fd4e5da5Sopenharmony_ci 449fd4e5da5Sopenharmony_ci ASSERT_TRUE(IsEqual(env, after_adjustments, context.get())); 450fd4e5da5Sopenharmony_ci} 451fd4e5da5Sopenharmony_ci 452fd4e5da5Sopenharmony_ciTEST(FuzzerPassOutlineFunctionsTest, ExitBlock) { 453fd4e5da5Sopenharmony_ci const auto env = SPV_ENV_UNIVERSAL_1_5; 454fd4e5da5Sopenharmony_ci const auto consumer = nullptr; 455fd4e5da5Sopenharmony_ci const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption); 456fd4e5da5Sopenharmony_ci spvtools::ValidatorOptions validator_options; 457fd4e5da5Sopenharmony_ci ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options, 458fd4e5da5Sopenharmony_ci kConsoleMessageConsumer)); 459fd4e5da5Sopenharmony_ci TransformationContext transformation_context( 460fd4e5da5Sopenharmony_ci MakeUnique<FactManager>(context.get()), validator_options); 461fd4e5da5Sopenharmony_ci FuzzerContext fuzzer_context(MakeUnique<PseudoRandomGenerator>(0), 100, 462fd4e5da5Sopenharmony_ci false); 463fd4e5da5Sopenharmony_ci protobufs::TransformationSequence transformation_sequence; 464fd4e5da5Sopenharmony_ci 465fd4e5da5Sopenharmony_ci FuzzerPassOutlineFunctions fuzzer_pass(context.get(), &transformation_context, 466fd4e5da5Sopenharmony_ci &fuzzer_context, 467fd4e5da5Sopenharmony_ci &transformation_sequence, false); 468fd4e5da5Sopenharmony_ci 469fd4e5da5Sopenharmony_ci // Block 39 is not a merge block, so it is already suitable. 470fd4e5da5Sopenharmony_ci auto suitable_exit_block = fuzzer_pass.MaybeGetExitBlockSuitableForOutlining( 471fd4e5da5Sopenharmony_ci context->get_instr_block(39)); 472fd4e5da5Sopenharmony_ci ASSERT_TRUE(suitable_exit_block); 473fd4e5da5Sopenharmony_ci ASSERT_TRUE(suitable_exit_block->GetLabel()->result_id() == 39); 474fd4e5da5Sopenharmony_ci 475fd4e5da5Sopenharmony_ci // The following are merge blocks and, thus, they will need to be split. 476fd4e5da5Sopenharmony_ci 477fd4e5da5Sopenharmony_ci // Block 22 478fd4e5da5Sopenharmony_ci suitable_exit_block = fuzzer_pass.MaybeGetExitBlockSuitableForOutlining( 479fd4e5da5Sopenharmony_ci context->get_instr_block(22)); 480fd4e5da5Sopenharmony_ci ASSERT_TRUE(suitable_exit_block); 481fd4e5da5Sopenharmony_ci ASSERT_TRUE(suitable_exit_block->GetLabel()->result_id() == 100); 482fd4e5da5Sopenharmony_ci 483fd4e5da5Sopenharmony_ci // Block 27 484fd4e5da5Sopenharmony_ci suitable_exit_block = fuzzer_pass.MaybeGetExitBlockSuitableForOutlining( 485fd4e5da5Sopenharmony_ci context->get_instr_block(27)); 486fd4e5da5Sopenharmony_ci ASSERT_TRUE(suitable_exit_block); 487fd4e5da5Sopenharmony_ci ASSERT_TRUE(suitable_exit_block->GetLabel()->result_id() == 101); 488fd4e5da5Sopenharmony_ci 489fd4e5da5Sopenharmony_ci // Block 36 490fd4e5da5Sopenharmony_ci suitable_exit_block = fuzzer_pass.MaybeGetExitBlockSuitableForOutlining( 491fd4e5da5Sopenharmony_ci context->get_instr_block(36)); 492fd4e5da5Sopenharmony_ci ASSERT_TRUE(suitable_exit_block); 493fd4e5da5Sopenharmony_ci ASSERT_TRUE(suitable_exit_block->GetLabel()->result_id() == 102); 494fd4e5da5Sopenharmony_ci 495fd4e5da5Sopenharmony_ci std::string after_adjustments = R"( 496fd4e5da5Sopenharmony_ci OpCapability Shader 497fd4e5da5Sopenharmony_ci %1 = OpExtInstImport "GLSL.std.450" 498fd4e5da5Sopenharmony_ci OpMemoryModel Logical GLSL450 499fd4e5da5Sopenharmony_ci OpEntryPoint Fragment %2 "main" 500fd4e5da5Sopenharmony_ci OpExecutionMode %2 OriginUpperLeft 501fd4e5da5Sopenharmony_ci OpSource ESSL 310 502fd4e5da5Sopenharmony_ci OpName %2 "main" 503fd4e5da5Sopenharmony_ci OpName %3 "a" 504fd4e5da5Sopenharmony_ci OpName %4 "b" 505fd4e5da5Sopenharmony_ci OpDecorate %3 RelaxedPrecision 506fd4e5da5Sopenharmony_ci OpDecorate %4 RelaxedPrecision 507fd4e5da5Sopenharmony_ci OpDecorate %5 RelaxedPrecision 508fd4e5da5Sopenharmony_ci OpDecorate %6 RelaxedPrecision 509fd4e5da5Sopenharmony_ci OpDecorate %7 RelaxedPrecision 510fd4e5da5Sopenharmony_ci OpDecorate %8 RelaxedPrecision 511fd4e5da5Sopenharmony_ci OpDecorate %9 RelaxedPrecision 512fd4e5da5Sopenharmony_ci %10 = OpTypeVoid 513fd4e5da5Sopenharmony_ci %11 = OpTypeFunction %10 514fd4e5da5Sopenharmony_ci %12 = OpTypeInt 32 1 515fd4e5da5Sopenharmony_ci %13 = OpTypePointer Function %12 516fd4e5da5Sopenharmony_ci %14 = OpConstant %12 8 517fd4e5da5Sopenharmony_ci %15 = OpConstant %12 23 518fd4e5da5Sopenharmony_ci %16 = OpTypeBool 519fd4e5da5Sopenharmony_ci %17 = OpConstantTrue %16 520fd4e5da5Sopenharmony_ci %18 = OpConstant %12 0 521fd4e5da5Sopenharmony_ci %19 = OpConstant %12 1 522fd4e5da5Sopenharmony_ci %2 = OpFunction %10 None %11 523fd4e5da5Sopenharmony_ci %20 = OpLabel 524fd4e5da5Sopenharmony_ci %3 = OpVariable %13 Function 525fd4e5da5Sopenharmony_ci %4 = OpVariable %13 Function 526fd4e5da5Sopenharmony_ci OpStore %3 %14 527fd4e5da5Sopenharmony_ci OpStore %4 %15 528fd4e5da5Sopenharmony_ci OpBranch %21 529fd4e5da5Sopenharmony_ci %21 = OpLabel 530fd4e5da5Sopenharmony_ci OpLoopMerge %22 %23 None 531fd4e5da5Sopenharmony_ci OpBranch %24 532fd4e5da5Sopenharmony_ci %24 = OpLabel 533fd4e5da5Sopenharmony_ci %25 = OpPhi %12 %19 %21 %18 %26 534fd4e5da5Sopenharmony_ci OpLoopMerge %27 %26 None 535fd4e5da5Sopenharmony_ci OpBranch %28 536fd4e5da5Sopenharmony_ci %28 = OpLabel 537fd4e5da5Sopenharmony_ci %5 = OpLoad %12 %3 538fd4e5da5Sopenharmony_ci %29 = OpSGreaterThan %16 %5 %18 539fd4e5da5Sopenharmony_ci OpBranchConditional %29 %30 %27 540fd4e5da5Sopenharmony_ci %30 = OpLabel 541fd4e5da5Sopenharmony_ci %6 = OpLoad %12 %4 542fd4e5da5Sopenharmony_ci %7 = OpISub %12 %6 %19 543fd4e5da5Sopenharmony_ci OpStore %4 %7 544fd4e5da5Sopenharmony_ci OpBranch %26 545fd4e5da5Sopenharmony_ci %26 = OpLabel 546fd4e5da5Sopenharmony_ci %8 = OpLoad %12 %3 547fd4e5da5Sopenharmony_ci %9 = OpISub %12 %8 %19 548fd4e5da5Sopenharmony_ci OpStore %3 %9 549fd4e5da5Sopenharmony_ci OpBranch %24 550fd4e5da5Sopenharmony_ci %27 = OpLabel 551fd4e5da5Sopenharmony_ci OpBranch %101 552fd4e5da5Sopenharmony_ci %101 = OpLabel 553fd4e5da5Sopenharmony_ci OpBranch %23 554fd4e5da5Sopenharmony_ci %23 = OpLabel 555fd4e5da5Sopenharmony_ci OpBranch %21 556fd4e5da5Sopenharmony_ci %22 = OpLabel 557fd4e5da5Sopenharmony_ci OpBranch %100 558fd4e5da5Sopenharmony_ci %100 = OpLabel 559fd4e5da5Sopenharmony_ci OpBranch %31 560fd4e5da5Sopenharmony_ci %31 = OpLabel 561fd4e5da5Sopenharmony_ci OpLoopMerge %32 %31 None 562fd4e5da5Sopenharmony_ci OpBranchConditional %17 %31 %32 563fd4e5da5Sopenharmony_ci %32 = OpLabel 564fd4e5da5Sopenharmony_ci OpSelectionMerge %33 None 565fd4e5da5Sopenharmony_ci OpBranchConditional %17 %34 %35 566fd4e5da5Sopenharmony_ci %34 = OpLabel 567fd4e5da5Sopenharmony_ci OpBranch %33 568fd4e5da5Sopenharmony_ci %35 = OpLabel 569fd4e5da5Sopenharmony_ci OpBranch %33 570fd4e5da5Sopenharmony_ci %33 = OpLabel 571fd4e5da5Sopenharmony_ci %42 = OpPhi %12 %19 %33 %18 %34 %18 %35 572fd4e5da5Sopenharmony_ci OpLoopMerge %36 %33 None 573fd4e5da5Sopenharmony_ci OpBranchConditional %17 %36 %33 574fd4e5da5Sopenharmony_ci %36 = OpLabel 575fd4e5da5Sopenharmony_ci %43 = OpPhi %12 %18 %33 %18 %41 576fd4e5da5Sopenharmony_ci OpBranch %102 577fd4e5da5Sopenharmony_ci %102 = OpLabel 578fd4e5da5Sopenharmony_ci OpReturn 579fd4e5da5Sopenharmony_ci %37 = OpLabel 580fd4e5da5Sopenharmony_ci OpLoopMerge %38 %39 None 581fd4e5da5Sopenharmony_ci OpBranch %40 582fd4e5da5Sopenharmony_ci %40 = OpLabel 583fd4e5da5Sopenharmony_ci OpBranchConditional %17 %41 %38 584fd4e5da5Sopenharmony_ci %41 = OpLabel 585fd4e5da5Sopenharmony_ci OpBranchConditional %17 %36 %39 586fd4e5da5Sopenharmony_ci %39 = OpLabel 587fd4e5da5Sopenharmony_ci OpBranch %37 588fd4e5da5Sopenharmony_ci %38 = OpLabel 589fd4e5da5Sopenharmony_ci OpReturn 590fd4e5da5Sopenharmony_ci OpFunctionEnd 591fd4e5da5Sopenharmony_ci)"; 592fd4e5da5Sopenharmony_ci 593fd4e5da5Sopenharmony_ci ASSERT_TRUE(IsEqual(env, after_adjustments, context.get())); 594fd4e5da5Sopenharmony_ci} 595fd4e5da5Sopenharmony_ci} // namespace 596fd4e5da5Sopenharmony_ci} // namespace fuzz 597fd4e5da5Sopenharmony_ci} // namespace spvtools 598