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_outline_function.h" 16fd4e5da5Sopenharmony_ci 17fd4e5da5Sopenharmony_ci#include "gtest/gtest.h" 18fd4e5da5Sopenharmony_ci#include "source/fuzz/counter_overflow_id_source.h" 19fd4e5da5Sopenharmony_ci#include "source/fuzz/fuzzer_util.h" 20fd4e5da5Sopenharmony_ci#include "test/fuzz/fuzz_test_util.h" 21fd4e5da5Sopenharmony_ci 22fd4e5da5Sopenharmony_cinamespace spvtools { 23fd4e5da5Sopenharmony_cinamespace fuzz { 24fd4e5da5Sopenharmony_cinamespace { 25fd4e5da5Sopenharmony_ci 26fd4e5da5Sopenharmony_ciTEST(TransformationOutlineFunctionTest, TrivialOutline) { 27fd4e5da5Sopenharmony_ci // This tests outlining of a single, empty basic block. 28fd4e5da5Sopenharmony_ci 29fd4e5da5Sopenharmony_ci std::string shader = R"( 30fd4e5da5Sopenharmony_ci OpCapability Shader 31fd4e5da5Sopenharmony_ci %1 = OpExtInstImport "GLSL.std.450" 32fd4e5da5Sopenharmony_ci OpMemoryModel Logical GLSL450 33fd4e5da5Sopenharmony_ci OpEntryPoint Fragment %4 "main" 34fd4e5da5Sopenharmony_ci OpExecutionMode %4 OriginUpperLeft 35fd4e5da5Sopenharmony_ci OpSource ESSL 310 36fd4e5da5Sopenharmony_ci OpName %4 "main" 37fd4e5da5Sopenharmony_ci %2 = OpTypeVoid 38fd4e5da5Sopenharmony_ci %3 = OpTypeFunction %2 39fd4e5da5Sopenharmony_ci %4 = OpFunction %2 None %3 40fd4e5da5Sopenharmony_ci %5 = OpLabel 41fd4e5da5Sopenharmony_ci OpReturn 42fd4e5da5Sopenharmony_ci OpFunctionEnd 43fd4e5da5Sopenharmony_ci )"; 44fd4e5da5Sopenharmony_ci 45fd4e5da5Sopenharmony_ci const auto env = SPV_ENV_UNIVERSAL_1_4; 46fd4e5da5Sopenharmony_ci const auto consumer = nullptr; 47fd4e5da5Sopenharmony_ci const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption); 48fd4e5da5Sopenharmony_ci spvtools::ValidatorOptions validator_options; 49fd4e5da5Sopenharmony_ci ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options, 50fd4e5da5Sopenharmony_ci kConsoleMessageConsumer)); 51fd4e5da5Sopenharmony_ci TransformationContext transformation_context( 52fd4e5da5Sopenharmony_ci MakeUnique<FactManager>(context.get()), validator_options); 53fd4e5da5Sopenharmony_ci TransformationOutlineFunction transformation(5, 5, /* not relevant */ 200, 54fd4e5da5Sopenharmony_ci 100, 101, 102, 103, 55fd4e5da5Sopenharmony_ci /* not relevant */ 201, {}, {}); 56fd4e5da5Sopenharmony_ci ASSERT_TRUE( 57fd4e5da5Sopenharmony_ci transformation.IsApplicable(context.get(), transformation_context)); 58fd4e5da5Sopenharmony_ci ApplyAndCheckFreshIds(transformation, context.get(), &transformation_context); 59fd4e5da5Sopenharmony_ci ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options, 60fd4e5da5Sopenharmony_ci kConsoleMessageConsumer)); 61fd4e5da5Sopenharmony_ci 62fd4e5da5Sopenharmony_ci std::string after_transformation = R"( 63fd4e5da5Sopenharmony_ci OpCapability Shader 64fd4e5da5Sopenharmony_ci %1 = OpExtInstImport "GLSL.std.450" 65fd4e5da5Sopenharmony_ci OpMemoryModel Logical GLSL450 66fd4e5da5Sopenharmony_ci OpEntryPoint Fragment %4 "main" 67fd4e5da5Sopenharmony_ci OpExecutionMode %4 OriginUpperLeft 68fd4e5da5Sopenharmony_ci OpSource ESSL 310 69fd4e5da5Sopenharmony_ci OpName %4 "main" 70fd4e5da5Sopenharmony_ci %2 = OpTypeVoid 71fd4e5da5Sopenharmony_ci %3 = OpTypeFunction %2 72fd4e5da5Sopenharmony_ci %4 = OpFunction %2 None %3 73fd4e5da5Sopenharmony_ci %5 = OpLabel 74fd4e5da5Sopenharmony_ci %103 = OpFunctionCall %2 %101 75fd4e5da5Sopenharmony_ci OpReturn 76fd4e5da5Sopenharmony_ci OpFunctionEnd 77fd4e5da5Sopenharmony_ci %101 = OpFunction %2 None %3 78fd4e5da5Sopenharmony_ci %102 = OpLabel 79fd4e5da5Sopenharmony_ci OpReturn 80fd4e5da5Sopenharmony_ci OpFunctionEnd 81fd4e5da5Sopenharmony_ci )"; 82fd4e5da5Sopenharmony_ci ASSERT_TRUE(IsEqual(env, after_transformation, context.get())); 83fd4e5da5Sopenharmony_ci} 84fd4e5da5Sopenharmony_ci 85fd4e5da5Sopenharmony_ciTEST(TransformationOutlineFunctionTest, 86fd4e5da5Sopenharmony_ci DoNotOutlineIfRegionStartsWithOpVariable) { 87fd4e5da5Sopenharmony_ci // This checks that we do not outline the first block of a function if it 88fd4e5da5Sopenharmony_ci // contains OpVariable. 89fd4e5da5Sopenharmony_ci 90fd4e5da5Sopenharmony_ci std::string shader = R"( 91fd4e5da5Sopenharmony_ci OpCapability Shader 92fd4e5da5Sopenharmony_ci %1 = OpExtInstImport "GLSL.std.450" 93fd4e5da5Sopenharmony_ci OpMemoryModel Logical GLSL450 94fd4e5da5Sopenharmony_ci OpEntryPoint Fragment %4 "main" 95fd4e5da5Sopenharmony_ci OpExecutionMode %4 OriginUpperLeft 96fd4e5da5Sopenharmony_ci OpSource ESSL 310 97fd4e5da5Sopenharmony_ci OpName %4 "main" 98fd4e5da5Sopenharmony_ci %2 = OpTypeVoid 99fd4e5da5Sopenharmony_ci %3 = OpTypeFunction %2 100fd4e5da5Sopenharmony_ci %7 = OpTypeBool 101fd4e5da5Sopenharmony_ci %8 = OpTypePointer Function %7 102fd4e5da5Sopenharmony_ci %4 = OpFunction %2 None %3 103fd4e5da5Sopenharmony_ci %5 = OpLabel 104fd4e5da5Sopenharmony_ci %6 = OpVariable %8 Function 105fd4e5da5Sopenharmony_ci OpReturn 106fd4e5da5Sopenharmony_ci OpFunctionEnd 107fd4e5da5Sopenharmony_ci )"; 108fd4e5da5Sopenharmony_ci 109fd4e5da5Sopenharmony_ci const auto env = SPV_ENV_UNIVERSAL_1_4; 110fd4e5da5Sopenharmony_ci const auto consumer = nullptr; 111fd4e5da5Sopenharmony_ci const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption); 112fd4e5da5Sopenharmony_ci spvtools::ValidatorOptions validator_options; 113fd4e5da5Sopenharmony_ci ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options, 114fd4e5da5Sopenharmony_ci kConsoleMessageConsumer)); 115fd4e5da5Sopenharmony_ci TransformationContext transformation_context( 116fd4e5da5Sopenharmony_ci MakeUnique<FactManager>(context.get()), validator_options); 117fd4e5da5Sopenharmony_ci TransformationOutlineFunction transformation(5, 5, /* not relevant */ 200, 118fd4e5da5Sopenharmony_ci 100, 101, 102, 103, 119fd4e5da5Sopenharmony_ci /* not relevant */ 201, {}, {}); 120fd4e5da5Sopenharmony_ci ASSERT_FALSE( 121fd4e5da5Sopenharmony_ci transformation.IsApplicable(context.get(), transformation_context)); 122fd4e5da5Sopenharmony_ci} 123fd4e5da5Sopenharmony_ci 124fd4e5da5Sopenharmony_ciTEST(TransformationOutlineFunctionTest, OutlineInterestingControlFlowNoState) { 125fd4e5da5Sopenharmony_ci // This tests outlining of some non-trivial control flow, but such that the 126fd4e5da5Sopenharmony_ci // basic blocks in the control flow do not actually do anything. 127fd4e5da5Sopenharmony_ci 128fd4e5da5Sopenharmony_ci std::string shader = R"( 129fd4e5da5Sopenharmony_ci OpCapability Shader 130fd4e5da5Sopenharmony_ci %1 = OpExtInstImport "GLSL.std.450" 131fd4e5da5Sopenharmony_ci OpMemoryModel Logical GLSL450 132fd4e5da5Sopenharmony_ci OpEntryPoint Fragment %4 "main" 133fd4e5da5Sopenharmony_ci OpExecutionMode %4 OriginUpperLeft 134fd4e5da5Sopenharmony_ci OpSource ESSL 310 135fd4e5da5Sopenharmony_ci OpName %4 "main" 136fd4e5da5Sopenharmony_ci %2 = OpTypeVoid 137fd4e5da5Sopenharmony_ci %20 = OpTypeBool 138fd4e5da5Sopenharmony_ci %21 = OpConstantTrue %20 139fd4e5da5Sopenharmony_ci %3 = OpTypeFunction %2 140fd4e5da5Sopenharmony_ci %4 = OpFunction %2 None %3 141fd4e5da5Sopenharmony_ci %5 = OpLabel 142fd4e5da5Sopenharmony_ci OpBranch %6 143fd4e5da5Sopenharmony_ci %6 = OpLabel 144fd4e5da5Sopenharmony_ci OpBranch %7 145fd4e5da5Sopenharmony_ci %7 = OpLabel 146fd4e5da5Sopenharmony_ci OpSelectionMerge %9 None 147fd4e5da5Sopenharmony_ci OpBranchConditional %21 %8 %9 148fd4e5da5Sopenharmony_ci %8 = OpLabel 149fd4e5da5Sopenharmony_ci OpBranch %9 150fd4e5da5Sopenharmony_ci %9 = OpLabel 151fd4e5da5Sopenharmony_ci OpLoopMerge %12 %11 None 152fd4e5da5Sopenharmony_ci OpBranch %10 153fd4e5da5Sopenharmony_ci %10 = OpLabel 154fd4e5da5Sopenharmony_ci OpBranchConditional %21 %11 %12 155fd4e5da5Sopenharmony_ci %11 = OpLabel 156fd4e5da5Sopenharmony_ci OpBranch %9 157fd4e5da5Sopenharmony_ci %12 = OpLabel 158fd4e5da5Sopenharmony_ci OpBranch %13 159fd4e5da5Sopenharmony_ci %13 = OpLabel 160fd4e5da5Sopenharmony_ci OpReturn 161fd4e5da5Sopenharmony_ci OpFunctionEnd 162fd4e5da5Sopenharmony_ci )"; 163fd4e5da5Sopenharmony_ci 164fd4e5da5Sopenharmony_ci const auto env = SPV_ENV_UNIVERSAL_1_4; 165fd4e5da5Sopenharmony_ci const auto consumer = nullptr; 166fd4e5da5Sopenharmony_ci const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption); 167fd4e5da5Sopenharmony_ci spvtools::ValidatorOptions validator_options; 168fd4e5da5Sopenharmony_ci ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options, 169fd4e5da5Sopenharmony_ci kConsoleMessageConsumer)); 170fd4e5da5Sopenharmony_ci TransformationContext transformation_context( 171fd4e5da5Sopenharmony_ci MakeUnique<FactManager>(context.get()), validator_options); 172fd4e5da5Sopenharmony_ci TransformationOutlineFunction transformation(6, 13, /* not relevant */ 173fd4e5da5Sopenharmony_ci 200, 100, 101, 102, 103, 174fd4e5da5Sopenharmony_ci /* not relevant */ 201, {}, {}); 175fd4e5da5Sopenharmony_ci ASSERT_TRUE( 176fd4e5da5Sopenharmony_ci transformation.IsApplicable(context.get(), transformation_context)); 177fd4e5da5Sopenharmony_ci ApplyAndCheckFreshIds(transformation, context.get(), &transformation_context); 178fd4e5da5Sopenharmony_ci ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options, 179fd4e5da5Sopenharmony_ci kConsoleMessageConsumer)); 180fd4e5da5Sopenharmony_ci 181fd4e5da5Sopenharmony_ci std::string after_transformation = R"( 182fd4e5da5Sopenharmony_ci OpCapability Shader 183fd4e5da5Sopenharmony_ci %1 = OpExtInstImport "GLSL.std.450" 184fd4e5da5Sopenharmony_ci OpMemoryModel Logical GLSL450 185fd4e5da5Sopenharmony_ci OpEntryPoint Fragment %4 "main" 186fd4e5da5Sopenharmony_ci OpExecutionMode %4 OriginUpperLeft 187fd4e5da5Sopenharmony_ci OpSource ESSL 310 188fd4e5da5Sopenharmony_ci OpName %4 "main" 189fd4e5da5Sopenharmony_ci %2 = OpTypeVoid 190fd4e5da5Sopenharmony_ci %20 = OpTypeBool 191fd4e5da5Sopenharmony_ci %21 = OpConstantTrue %20 192fd4e5da5Sopenharmony_ci %3 = OpTypeFunction %2 193fd4e5da5Sopenharmony_ci %4 = OpFunction %2 None %3 194fd4e5da5Sopenharmony_ci %5 = OpLabel 195fd4e5da5Sopenharmony_ci OpBranch %6 196fd4e5da5Sopenharmony_ci %6 = OpLabel 197fd4e5da5Sopenharmony_ci %103 = OpFunctionCall %2 %101 198fd4e5da5Sopenharmony_ci OpReturn 199fd4e5da5Sopenharmony_ci OpFunctionEnd 200fd4e5da5Sopenharmony_ci %101 = OpFunction %2 None %3 201fd4e5da5Sopenharmony_ci %102 = OpLabel 202fd4e5da5Sopenharmony_ci OpBranch %7 203fd4e5da5Sopenharmony_ci %7 = OpLabel 204fd4e5da5Sopenharmony_ci OpSelectionMerge %9 None 205fd4e5da5Sopenharmony_ci OpBranchConditional %21 %8 %9 206fd4e5da5Sopenharmony_ci %8 = OpLabel 207fd4e5da5Sopenharmony_ci OpBranch %9 208fd4e5da5Sopenharmony_ci %9 = OpLabel 209fd4e5da5Sopenharmony_ci OpLoopMerge %12 %11 None 210fd4e5da5Sopenharmony_ci OpBranch %10 211fd4e5da5Sopenharmony_ci %10 = OpLabel 212fd4e5da5Sopenharmony_ci OpBranchConditional %21 %11 %12 213fd4e5da5Sopenharmony_ci %11 = OpLabel 214fd4e5da5Sopenharmony_ci OpBranch %9 215fd4e5da5Sopenharmony_ci %12 = OpLabel 216fd4e5da5Sopenharmony_ci OpBranch %13 217fd4e5da5Sopenharmony_ci %13 = OpLabel 218fd4e5da5Sopenharmony_ci OpReturn 219fd4e5da5Sopenharmony_ci OpFunctionEnd 220fd4e5da5Sopenharmony_ci )"; 221fd4e5da5Sopenharmony_ci ASSERT_TRUE(IsEqual(env, after_transformation, context.get())); 222fd4e5da5Sopenharmony_ci} 223fd4e5da5Sopenharmony_ci 224fd4e5da5Sopenharmony_ciTEST(TransformationOutlineFunctionTest, OutlineCodeThatGeneratesUnusedIds) { 225fd4e5da5Sopenharmony_ci // This tests outlining of a single basic block that does some computation, 226fd4e5da5Sopenharmony_ci // but that does not use nor generate ids required outside of the outlined 227fd4e5da5Sopenharmony_ci // region. 228fd4e5da5Sopenharmony_ci 229fd4e5da5Sopenharmony_ci std::string shader = R"( 230fd4e5da5Sopenharmony_ci OpCapability Shader 231fd4e5da5Sopenharmony_ci %1 = OpExtInstImport "GLSL.std.450" 232fd4e5da5Sopenharmony_ci OpMemoryModel Logical GLSL450 233fd4e5da5Sopenharmony_ci OpEntryPoint Fragment %4 "main" 234fd4e5da5Sopenharmony_ci OpExecutionMode %4 OriginUpperLeft 235fd4e5da5Sopenharmony_ci OpSource ESSL 310 236fd4e5da5Sopenharmony_ci OpName %4 "main" 237fd4e5da5Sopenharmony_ci %2 = OpTypeVoid 238fd4e5da5Sopenharmony_ci %20 = OpTypeInt 32 1 239fd4e5da5Sopenharmony_ci %21 = OpConstant %20 5 240fd4e5da5Sopenharmony_ci %3 = OpTypeFunction %2 241fd4e5da5Sopenharmony_ci %4 = OpFunction %2 None %3 242fd4e5da5Sopenharmony_ci %5 = OpLabel 243fd4e5da5Sopenharmony_ci OpBranch %6 244fd4e5da5Sopenharmony_ci %6 = OpLabel 245fd4e5da5Sopenharmony_ci %7 = OpCopyObject %20 %21 246fd4e5da5Sopenharmony_ci %8 = OpCopyObject %20 %21 247fd4e5da5Sopenharmony_ci %9 = OpIAdd %20 %7 %8 248fd4e5da5Sopenharmony_ci OpReturn 249fd4e5da5Sopenharmony_ci OpFunctionEnd 250fd4e5da5Sopenharmony_ci )"; 251fd4e5da5Sopenharmony_ci 252fd4e5da5Sopenharmony_ci const auto env = SPV_ENV_UNIVERSAL_1_4; 253fd4e5da5Sopenharmony_ci const auto consumer = nullptr; 254fd4e5da5Sopenharmony_ci const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption); 255fd4e5da5Sopenharmony_ci spvtools::ValidatorOptions validator_options; 256fd4e5da5Sopenharmony_ci ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options, 257fd4e5da5Sopenharmony_ci kConsoleMessageConsumer)); 258fd4e5da5Sopenharmony_ci TransformationContext transformation_context( 259fd4e5da5Sopenharmony_ci MakeUnique<FactManager>(context.get()), validator_options); 260fd4e5da5Sopenharmony_ci TransformationOutlineFunction transformation(6, 6, /* not relevant */ 200, 261fd4e5da5Sopenharmony_ci 100, 101, 102, 103, 262fd4e5da5Sopenharmony_ci /* not relevant */ 201, {}, {}); 263fd4e5da5Sopenharmony_ci ASSERT_TRUE( 264fd4e5da5Sopenharmony_ci transformation.IsApplicable(context.get(), transformation_context)); 265fd4e5da5Sopenharmony_ci ApplyAndCheckFreshIds(transformation, context.get(), &transformation_context); 266fd4e5da5Sopenharmony_ci ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options, 267fd4e5da5Sopenharmony_ci kConsoleMessageConsumer)); 268fd4e5da5Sopenharmony_ci 269fd4e5da5Sopenharmony_ci std::string after_transformation = R"( 270fd4e5da5Sopenharmony_ci OpCapability Shader 271fd4e5da5Sopenharmony_ci %1 = OpExtInstImport "GLSL.std.450" 272fd4e5da5Sopenharmony_ci OpMemoryModel Logical GLSL450 273fd4e5da5Sopenharmony_ci OpEntryPoint Fragment %4 "main" 274fd4e5da5Sopenharmony_ci OpExecutionMode %4 OriginUpperLeft 275fd4e5da5Sopenharmony_ci OpSource ESSL 310 276fd4e5da5Sopenharmony_ci OpName %4 "main" 277fd4e5da5Sopenharmony_ci %2 = OpTypeVoid 278fd4e5da5Sopenharmony_ci %20 = OpTypeInt 32 1 279fd4e5da5Sopenharmony_ci %21 = OpConstant %20 5 280fd4e5da5Sopenharmony_ci %3 = OpTypeFunction %2 281fd4e5da5Sopenharmony_ci %4 = OpFunction %2 None %3 282fd4e5da5Sopenharmony_ci %5 = OpLabel 283fd4e5da5Sopenharmony_ci OpBranch %6 284fd4e5da5Sopenharmony_ci %6 = OpLabel 285fd4e5da5Sopenharmony_ci %103 = OpFunctionCall %2 %101 286fd4e5da5Sopenharmony_ci OpReturn 287fd4e5da5Sopenharmony_ci OpFunctionEnd 288fd4e5da5Sopenharmony_ci %101 = OpFunction %2 None %3 289fd4e5da5Sopenharmony_ci %102 = OpLabel 290fd4e5da5Sopenharmony_ci %7 = OpCopyObject %20 %21 291fd4e5da5Sopenharmony_ci %8 = OpCopyObject %20 %21 292fd4e5da5Sopenharmony_ci %9 = OpIAdd %20 %7 %8 293fd4e5da5Sopenharmony_ci OpReturn 294fd4e5da5Sopenharmony_ci OpFunctionEnd 295fd4e5da5Sopenharmony_ci )"; 296fd4e5da5Sopenharmony_ci ASSERT_TRUE(IsEqual(env, after_transformation, context.get())); 297fd4e5da5Sopenharmony_ci} 298fd4e5da5Sopenharmony_ci 299fd4e5da5Sopenharmony_ciTEST(TransformationOutlineFunctionTest, OutlineCodeThatGeneratesSingleUsedId) { 300fd4e5da5Sopenharmony_ci // This tests outlining of a block that generates an id that is used in a 301fd4e5da5Sopenharmony_ci // later block. 302fd4e5da5Sopenharmony_ci 303fd4e5da5Sopenharmony_ci std::string shader = R"( 304fd4e5da5Sopenharmony_ci OpCapability Shader 305fd4e5da5Sopenharmony_ci %1 = OpExtInstImport "GLSL.std.450" 306fd4e5da5Sopenharmony_ci OpMemoryModel Logical GLSL450 307fd4e5da5Sopenharmony_ci OpEntryPoint Fragment %4 "main" 308fd4e5da5Sopenharmony_ci OpExecutionMode %4 OriginUpperLeft 309fd4e5da5Sopenharmony_ci OpSource ESSL 310 310fd4e5da5Sopenharmony_ci OpName %4 "main" 311fd4e5da5Sopenharmony_ci %2 = OpTypeVoid 312fd4e5da5Sopenharmony_ci %20 = OpTypeInt 32 1 313fd4e5da5Sopenharmony_ci %21 = OpConstant %20 5 314fd4e5da5Sopenharmony_ci %3 = OpTypeFunction %2 315fd4e5da5Sopenharmony_ci %4 = OpFunction %2 None %3 316fd4e5da5Sopenharmony_ci %5 = OpLabel 317fd4e5da5Sopenharmony_ci OpBranch %6 318fd4e5da5Sopenharmony_ci %6 = OpLabel 319fd4e5da5Sopenharmony_ci %7 = OpCopyObject %20 %21 320fd4e5da5Sopenharmony_ci %8 = OpCopyObject %20 %21 321fd4e5da5Sopenharmony_ci %9 = OpIAdd %20 %7 %8 322fd4e5da5Sopenharmony_ci OpBranch %10 323fd4e5da5Sopenharmony_ci %10 = OpLabel 324fd4e5da5Sopenharmony_ci %11 = OpCopyObject %20 %9 325fd4e5da5Sopenharmony_ci OpReturn 326fd4e5da5Sopenharmony_ci OpFunctionEnd 327fd4e5da5Sopenharmony_ci )"; 328fd4e5da5Sopenharmony_ci 329fd4e5da5Sopenharmony_ci const auto env = SPV_ENV_UNIVERSAL_1_4; 330fd4e5da5Sopenharmony_ci const auto consumer = nullptr; 331fd4e5da5Sopenharmony_ci const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption); 332fd4e5da5Sopenharmony_ci spvtools::ValidatorOptions validator_options; 333fd4e5da5Sopenharmony_ci ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options, 334fd4e5da5Sopenharmony_ci kConsoleMessageConsumer)); 335fd4e5da5Sopenharmony_ci TransformationContext transformation_context( 336fd4e5da5Sopenharmony_ci MakeUnique<FactManager>(context.get()), validator_options); 337fd4e5da5Sopenharmony_ci TransformationOutlineFunction transformation(6, 6, 99, 100, 101, 102, 103, 338fd4e5da5Sopenharmony_ci 105, {}, {{9, 104}}); 339fd4e5da5Sopenharmony_ci ASSERT_TRUE( 340fd4e5da5Sopenharmony_ci transformation.IsApplicable(context.get(), transformation_context)); 341fd4e5da5Sopenharmony_ci ApplyAndCheckFreshIds(transformation, context.get(), &transformation_context); 342fd4e5da5Sopenharmony_ci ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options, 343fd4e5da5Sopenharmony_ci kConsoleMessageConsumer)); 344fd4e5da5Sopenharmony_ci 345fd4e5da5Sopenharmony_ci std::string after_transformation = R"( 346fd4e5da5Sopenharmony_ci OpCapability Shader 347fd4e5da5Sopenharmony_ci %1 = OpExtInstImport "GLSL.std.450" 348fd4e5da5Sopenharmony_ci OpMemoryModel Logical GLSL450 349fd4e5da5Sopenharmony_ci OpEntryPoint Fragment %4 "main" 350fd4e5da5Sopenharmony_ci OpExecutionMode %4 OriginUpperLeft 351fd4e5da5Sopenharmony_ci OpSource ESSL 310 352fd4e5da5Sopenharmony_ci OpName %4 "main" 353fd4e5da5Sopenharmony_ci %2 = OpTypeVoid 354fd4e5da5Sopenharmony_ci %20 = OpTypeInt 32 1 355fd4e5da5Sopenharmony_ci %21 = OpConstant %20 5 356fd4e5da5Sopenharmony_ci %3 = OpTypeFunction %2 357fd4e5da5Sopenharmony_ci %99 = OpTypeStruct %20 358fd4e5da5Sopenharmony_ci %100 = OpTypeFunction %99 359fd4e5da5Sopenharmony_ci %4 = OpFunction %2 None %3 360fd4e5da5Sopenharmony_ci %5 = OpLabel 361fd4e5da5Sopenharmony_ci OpBranch %6 362fd4e5da5Sopenharmony_ci %6 = OpLabel 363fd4e5da5Sopenharmony_ci %103 = OpFunctionCall %99 %101 364fd4e5da5Sopenharmony_ci %9 = OpCompositeExtract %20 %103 0 365fd4e5da5Sopenharmony_ci OpBranch %10 366fd4e5da5Sopenharmony_ci %10 = OpLabel 367fd4e5da5Sopenharmony_ci %11 = OpCopyObject %20 %9 368fd4e5da5Sopenharmony_ci OpReturn 369fd4e5da5Sopenharmony_ci OpFunctionEnd 370fd4e5da5Sopenharmony_ci %101 = OpFunction %99 None %100 371fd4e5da5Sopenharmony_ci %102 = OpLabel 372fd4e5da5Sopenharmony_ci %7 = OpCopyObject %20 %21 373fd4e5da5Sopenharmony_ci %8 = OpCopyObject %20 %21 374fd4e5da5Sopenharmony_ci %104 = OpIAdd %20 %7 %8 375fd4e5da5Sopenharmony_ci %105 = OpCompositeConstruct %99 %104 376fd4e5da5Sopenharmony_ci OpReturnValue %105 377fd4e5da5Sopenharmony_ci OpFunctionEnd 378fd4e5da5Sopenharmony_ci )"; 379fd4e5da5Sopenharmony_ci ASSERT_TRUE(IsEqual(env, after_transformation, context.get())); 380fd4e5da5Sopenharmony_ci} 381fd4e5da5Sopenharmony_ci 382fd4e5da5Sopenharmony_ciTEST(TransformationOutlineFunctionTest, OutlineDiamondThatGeneratesSeveralIds) { 383fd4e5da5Sopenharmony_ci // This tests outlining of several blocks that generate a number of ids that 384fd4e5da5Sopenharmony_ci // are used in later blocks. 385fd4e5da5Sopenharmony_ci 386fd4e5da5Sopenharmony_ci std::string shader = R"( 387fd4e5da5Sopenharmony_ci OpCapability Shader 388fd4e5da5Sopenharmony_ci %1 = OpExtInstImport "GLSL.std.450" 389fd4e5da5Sopenharmony_ci OpMemoryModel Logical GLSL450 390fd4e5da5Sopenharmony_ci OpEntryPoint Fragment %4 "main" 391fd4e5da5Sopenharmony_ci OpExecutionMode %4 OriginUpperLeft 392fd4e5da5Sopenharmony_ci OpSource ESSL 310 393fd4e5da5Sopenharmony_ci OpName %4 "main" 394fd4e5da5Sopenharmony_ci %2 = OpTypeVoid 395fd4e5da5Sopenharmony_ci %20 = OpTypeInt 32 1 396fd4e5da5Sopenharmony_ci %21 = OpConstant %20 5 397fd4e5da5Sopenharmony_ci %22 = OpTypeBool 398fd4e5da5Sopenharmony_ci %3 = OpTypeFunction %2 399fd4e5da5Sopenharmony_ci %4 = OpFunction %2 None %3 400fd4e5da5Sopenharmony_ci %5 = OpLabel 401fd4e5da5Sopenharmony_ci OpBranch %6 402fd4e5da5Sopenharmony_ci %6 = OpLabel 403fd4e5da5Sopenharmony_ci %7 = OpCopyObject %20 %21 404fd4e5da5Sopenharmony_ci %8 = OpCopyObject %20 %21 405fd4e5da5Sopenharmony_ci %9 = OpSLessThan %22 %7 %8 406fd4e5da5Sopenharmony_ci OpSelectionMerge %12 None 407fd4e5da5Sopenharmony_ci OpBranchConditional %9 %10 %11 408fd4e5da5Sopenharmony_ci %10 = OpLabel 409fd4e5da5Sopenharmony_ci %13 = OpIAdd %20 %7 %8 410fd4e5da5Sopenharmony_ci OpBranch %12 411fd4e5da5Sopenharmony_ci %11 = OpLabel 412fd4e5da5Sopenharmony_ci %14 = OpIAdd %20 %7 %7 413fd4e5da5Sopenharmony_ci OpBranch %12 414fd4e5da5Sopenharmony_ci %12 = OpLabel 415fd4e5da5Sopenharmony_ci %15 = OpPhi %20 %13 %10 %14 %11 416fd4e5da5Sopenharmony_ci OpBranch %80 417fd4e5da5Sopenharmony_ci %80 = OpLabel 418fd4e5da5Sopenharmony_ci OpBranch %16 419fd4e5da5Sopenharmony_ci %16 = OpLabel 420fd4e5da5Sopenharmony_ci %17 = OpCopyObject %20 %15 421fd4e5da5Sopenharmony_ci %18 = OpCopyObject %22 %9 422fd4e5da5Sopenharmony_ci %19 = OpIAdd %20 %7 %8 423fd4e5da5Sopenharmony_ci OpReturn 424fd4e5da5Sopenharmony_ci OpFunctionEnd 425fd4e5da5Sopenharmony_ci )"; 426fd4e5da5Sopenharmony_ci 427fd4e5da5Sopenharmony_ci const auto env = SPV_ENV_UNIVERSAL_1_4; 428fd4e5da5Sopenharmony_ci const auto consumer = nullptr; 429fd4e5da5Sopenharmony_ci const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption); 430fd4e5da5Sopenharmony_ci spvtools::ValidatorOptions validator_options; 431fd4e5da5Sopenharmony_ci ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options, 432fd4e5da5Sopenharmony_ci kConsoleMessageConsumer)); 433fd4e5da5Sopenharmony_ci TransformationContext transformation_context( 434fd4e5da5Sopenharmony_ci MakeUnique<FactManager>(context.get()), validator_options); 435fd4e5da5Sopenharmony_ci TransformationOutlineFunction transformation( 436fd4e5da5Sopenharmony_ci 6, 80, 100, 101, 102, 103, 104, 105, {}, 437fd4e5da5Sopenharmony_ci {{15, 106}, {9, 107}, {7, 108}, {8, 109}}); 438fd4e5da5Sopenharmony_ci ASSERT_TRUE( 439fd4e5da5Sopenharmony_ci transformation.IsApplicable(context.get(), transformation_context)); 440fd4e5da5Sopenharmony_ci ApplyAndCheckFreshIds(transformation, context.get(), &transformation_context); 441fd4e5da5Sopenharmony_ci ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options, 442fd4e5da5Sopenharmony_ci kConsoleMessageConsumer)); 443fd4e5da5Sopenharmony_ci 444fd4e5da5Sopenharmony_ci std::string after_transformation = R"( 445fd4e5da5Sopenharmony_ci OpCapability Shader 446fd4e5da5Sopenharmony_ci %1 = OpExtInstImport "GLSL.std.450" 447fd4e5da5Sopenharmony_ci OpMemoryModel Logical GLSL450 448fd4e5da5Sopenharmony_ci OpEntryPoint Fragment %4 "main" 449fd4e5da5Sopenharmony_ci OpExecutionMode %4 OriginUpperLeft 450fd4e5da5Sopenharmony_ci OpSource ESSL 310 451fd4e5da5Sopenharmony_ci OpName %4 "main" 452fd4e5da5Sopenharmony_ci %2 = OpTypeVoid 453fd4e5da5Sopenharmony_ci %20 = OpTypeInt 32 1 454fd4e5da5Sopenharmony_ci %21 = OpConstant %20 5 455fd4e5da5Sopenharmony_ci %22 = OpTypeBool 456fd4e5da5Sopenharmony_ci %3 = OpTypeFunction %2 457fd4e5da5Sopenharmony_ci %100 = OpTypeStruct %20 %20 %22 %20 458fd4e5da5Sopenharmony_ci %101 = OpTypeFunction %100 459fd4e5da5Sopenharmony_ci %4 = OpFunction %2 None %3 460fd4e5da5Sopenharmony_ci %5 = OpLabel 461fd4e5da5Sopenharmony_ci OpBranch %6 462fd4e5da5Sopenharmony_ci %6 = OpLabel 463fd4e5da5Sopenharmony_ci %104 = OpFunctionCall %100 %102 464fd4e5da5Sopenharmony_ci %7 = OpCompositeExtract %20 %104 0 465fd4e5da5Sopenharmony_ci %8 = OpCompositeExtract %20 %104 1 466fd4e5da5Sopenharmony_ci %9 = OpCompositeExtract %22 %104 2 467fd4e5da5Sopenharmony_ci %15 = OpCompositeExtract %20 %104 3 468fd4e5da5Sopenharmony_ci OpBranch %16 469fd4e5da5Sopenharmony_ci %16 = OpLabel 470fd4e5da5Sopenharmony_ci %17 = OpCopyObject %20 %15 471fd4e5da5Sopenharmony_ci %18 = OpCopyObject %22 %9 472fd4e5da5Sopenharmony_ci %19 = OpIAdd %20 %7 %8 473fd4e5da5Sopenharmony_ci OpReturn 474fd4e5da5Sopenharmony_ci OpFunctionEnd 475fd4e5da5Sopenharmony_ci %102 = OpFunction %100 None %101 476fd4e5da5Sopenharmony_ci %103 = OpLabel 477fd4e5da5Sopenharmony_ci %108 = OpCopyObject %20 %21 478fd4e5da5Sopenharmony_ci %109 = OpCopyObject %20 %21 479fd4e5da5Sopenharmony_ci %107 = OpSLessThan %22 %108 %109 480fd4e5da5Sopenharmony_ci OpSelectionMerge %12 None 481fd4e5da5Sopenharmony_ci OpBranchConditional %107 %10 %11 482fd4e5da5Sopenharmony_ci %10 = OpLabel 483fd4e5da5Sopenharmony_ci %13 = OpIAdd %20 %108 %109 484fd4e5da5Sopenharmony_ci OpBranch %12 485fd4e5da5Sopenharmony_ci %11 = OpLabel 486fd4e5da5Sopenharmony_ci %14 = OpIAdd %20 %108 %108 487fd4e5da5Sopenharmony_ci OpBranch %12 488fd4e5da5Sopenharmony_ci %12 = OpLabel 489fd4e5da5Sopenharmony_ci %106 = OpPhi %20 %13 %10 %14 %11 490fd4e5da5Sopenharmony_ci OpBranch %80 491fd4e5da5Sopenharmony_ci %80 = OpLabel 492fd4e5da5Sopenharmony_ci %105 = OpCompositeConstruct %100 %108 %109 %107 %106 493fd4e5da5Sopenharmony_ci OpReturnValue %105 494fd4e5da5Sopenharmony_ci OpFunctionEnd 495fd4e5da5Sopenharmony_ci )"; 496fd4e5da5Sopenharmony_ci ASSERT_TRUE(IsEqual(env, after_transformation, context.get())); 497fd4e5da5Sopenharmony_ci} 498fd4e5da5Sopenharmony_ci 499fd4e5da5Sopenharmony_ciTEST(TransformationOutlineFunctionTest, OutlineCodeThatUsesASingleId) { 500fd4e5da5Sopenharmony_ci // This tests outlining of a block that uses an id defined earlier. 501fd4e5da5Sopenharmony_ci 502fd4e5da5Sopenharmony_ci std::string shader = R"( 503fd4e5da5Sopenharmony_ci OpCapability Shader 504fd4e5da5Sopenharmony_ci %1 = OpExtInstImport "GLSL.std.450" 505fd4e5da5Sopenharmony_ci OpMemoryModel Logical GLSL450 506fd4e5da5Sopenharmony_ci OpEntryPoint Fragment %4 "main" 507fd4e5da5Sopenharmony_ci OpExecutionMode %4 OriginUpperLeft 508fd4e5da5Sopenharmony_ci OpSource ESSL 310 509fd4e5da5Sopenharmony_ci OpName %4 "main" 510fd4e5da5Sopenharmony_ci %2 = OpTypeVoid 511fd4e5da5Sopenharmony_ci %20 = OpTypeInt 32 1 512fd4e5da5Sopenharmony_ci %21 = OpConstant %20 5 513fd4e5da5Sopenharmony_ci %3 = OpTypeFunction %2 514fd4e5da5Sopenharmony_ci %4 = OpFunction %2 None %3 515fd4e5da5Sopenharmony_ci %5 = OpLabel 516fd4e5da5Sopenharmony_ci %7 = OpCopyObject %20 %21 517fd4e5da5Sopenharmony_ci OpBranch %6 518fd4e5da5Sopenharmony_ci %6 = OpLabel 519fd4e5da5Sopenharmony_ci %8 = OpCopyObject %20 %7 520fd4e5da5Sopenharmony_ci OpBranch %10 521fd4e5da5Sopenharmony_ci %10 = OpLabel 522fd4e5da5Sopenharmony_ci OpReturn 523fd4e5da5Sopenharmony_ci OpFunctionEnd 524fd4e5da5Sopenharmony_ci )"; 525fd4e5da5Sopenharmony_ci 526fd4e5da5Sopenharmony_ci const auto env = SPV_ENV_UNIVERSAL_1_4; 527fd4e5da5Sopenharmony_ci const auto consumer = nullptr; 528fd4e5da5Sopenharmony_ci const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption); 529fd4e5da5Sopenharmony_ci spvtools::ValidatorOptions validator_options; 530fd4e5da5Sopenharmony_ci ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options, 531fd4e5da5Sopenharmony_ci kConsoleMessageConsumer)); 532fd4e5da5Sopenharmony_ci TransformationContext transformation_context( 533fd4e5da5Sopenharmony_ci MakeUnique<FactManager>(context.get()), validator_options); 534fd4e5da5Sopenharmony_ci TransformationOutlineFunction transformation(6, 6, 100, 101, 102, 103, 104, 535fd4e5da5Sopenharmony_ci 105, {{7, 106}}, {}); 536fd4e5da5Sopenharmony_ci ASSERT_TRUE( 537fd4e5da5Sopenharmony_ci transformation.IsApplicable(context.get(), transformation_context)); 538fd4e5da5Sopenharmony_ci ApplyAndCheckFreshIds(transformation, context.get(), &transformation_context); 539fd4e5da5Sopenharmony_ci ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options, 540fd4e5da5Sopenharmony_ci kConsoleMessageConsumer)); 541fd4e5da5Sopenharmony_ci 542fd4e5da5Sopenharmony_ci std::string after_transformation = R"( 543fd4e5da5Sopenharmony_ci OpCapability Shader 544fd4e5da5Sopenharmony_ci %1 = OpExtInstImport "GLSL.std.450" 545fd4e5da5Sopenharmony_ci OpMemoryModel Logical GLSL450 546fd4e5da5Sopenharmony_ci OpEntryPoint Fragment %4 "main" 547fd4e5da5Sopenharmony_ci OpExecutionMode %4 OriginUpperLeft 548fd4e5da5Sopenharmony_ci OpSource ESSL 310 549fd4e5da5Sopenharmony_ci OpName %4 "main" 550fd4e5da5Sopenharmony_ci %2 = OpTypeVoid 551fd4e5da5Sopenharmony_ci %20 = OpTypeInt 32 1 552fd4e5da5Sopenharmony_ci %21 = OpConstant %20 5 553fd4e5da5Sopenharmony_ci %3 = OpTypeFunction %2 554fd4e5da5Sopenharmony_ci %101 = OpTypeFunction %2 %20 555fd4e5da5Sopenharmony_ci %4 = OpFunction %2 None %3 556fd4e5da5Sopenharmony_ci %5 = OpLabel 557fd4e5da5Sopenharmony_ci %7 = OpCopyObject %20 %21 558fd4e5da5Sopenharmony_ci OpBranch %6 559fd4e5da5Sopenharmony_ci %6 = OpLabel 560fd4e5da5Sopenharmony_ci %104 = OpFunctionCall %2 %102 %7 561fd4e5da5Sopenharmony_ci OpBranch %10 562fd4e5da5Sopenharmony_ci %10 = OpLabel 563fd4e5da5Sopenharmony_ci OpReturn 564fd4e5da5Sopenharmony_ci OpFunctionEnd 565fd4e5da5Sopenharmony_ci %102 = OpFunction %2 None %101 566fd4e5da5Sopenharmony_ci %106 = OpFunctionParameter %20 567fd4e5da5Sopenharmony_ci %103 = OpLabel 568fd4e5da5Sopenharmony_ci %8 = OpCopyObject %20 %106 569fd4e5da5Sopenharmony_ci OpReturn 570fd4e5da5Sopenharmony_ci OpFunctionEnd 571fd4e5da5Sopenharmony_ci )"; 572fd4e5da5Sopenharmony_ci ASSERT_TRUE(IsEqual(env, after_transformation, context.get())); 573fd4e5da5Sopenharmony_ci} 574fd4e5da5Sopenharmony_ci 575fd4e5da5Sopenharmony_ciTEST(TransformationOutlineFunctionTest, OutlineCodeThatUsesAVariable) { 576fd4e5da5Sopenharmony_ci // This tests outlining of a block that uses a variable. 577fd4e5da5Sopenharmony_ci 578fd4e5da5Sopenharmony_ci std::string shader = R"( 579fd4e5da5Sopenharmony_ci OpCapability Shader 580fd4e5da5Sopenharmony_ci %1 = OpExtInstImport "GLSL.std.450" 581fd4e5da5Sopenharmony_ci OpMemoryModel Logical GLSL450 582fd4e5da5Sopenharmony_ci OpEntryPoint Fragment %4 "main" 583fd4e5da5Sopenharmony_ci OpExecutionMode %4 OriginUpperLeft 584fd4e5da5Sopenharmony_ci OpSource ESSL 310 585fd4e5da5Sopenharmony_ci OpName %4 "main" 586fd4e5da5Sopenharmony_ci %2 = OpTypeVoid 587fd4e5da5Sopenharmony_ci %20 = OpTypeInt 32 1 588fd4e5da5Sopenharmony_ci %21 = OpConstant %20 5 589fd4e5da5Sopenharmony_ci %3 = OpTypeFunction %2 590fd4e5da5Sopenharmony_ci %12 = OpTypePointer Function %20 591fd4e5da5Sopenharmony_ci %4 = OpFunction %2 None %3 592fd4e5da5Sopenharmony_ci %5 = OpLabel 593fd4e5da5Sopenharmony_ci %13 = OpVariable %12 Function 594fd4e5da5Sopenharmony_ci OpBranch %6 595fd4e5da5Sopenharmony_ci %6 = OpLabel 596fd4e5da5Sopenharmony_ci %8 = OpLoad %20 %13 597fd4e5da5Sopenharmony_ci OpBranch %10 598fd4e5da5Sopenharmony_ci %10 = OpLabel 599fd4e5da5Sopenharmony_ci OpReturn 600fd4e5da5Sopenharmony_ci OpFunctionEnd 601fd4e5da5Sopenharmony_ci )"; 602fd4e5da5Sopenharmony_ci 603fd4e5da5Sopenharmony_ci const auto env = SPV_ENV_UNIVERSAL_1_4; 604fd4e5da5Sopenharmony_ci const auto consumer = nullptr; 605fd4e5da5Sopenharmony_ci const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption); 606fd4e5da5Sopenharmony_ci spvtools::ValidatorOptions validator_options; 607fd4e5da5Sopenharmony_ci ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options, 608fd4e5da5Sopenharmony_ci kConsoleMessageConsumer)); 609fd4e5da5Sopenharmony_ci TransformationContext transformation_context( 610fd4e5da5Sopenharmony_ci MakeUnique<FactManager>(context.get()), validator_options); 611fd4e5da5Sopenharmony_ci TransformationOutlineFunction transformation(6, 6, 100, 101, 102, 103, 104, 612fd4e5da5Sopenharmony_ci 105, {{13, 106}}, {}); 613fd4e5da5Sopenharmony_ci ASSERT_TRUE( 614fd4e5da5Sopenharmony_ci transformation.IsApplicable(context.get(), transformation_context)); 615fd4e5da5Sopenharmony_ci ApplyAndCheckFreshIds(transformation, context.get(), &transformation_context); 616fd4e5da5Sopenharmony_ci ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options, 617fd4e5da5Sopenharmony_ci kConsoleMessageConsumer)); 618fd4e5da5Sopenharmony_ci 619fd4e5da5Sopenharmony_ci std::string after_transformation = R"( 620fd4e5da5Sopenharmony_ci OpCapability Shader 621fd4e5da5Sopenharmony_ci %1 = OpExtInstImport "GLSL.std.450" 622fd4e5da5Sopenharmony_ci OpMemoryModel Logical GLSL450 623fd4e5da5Sopenharmony_ci OpEntryPoint Fragment %4 "main" 624fd4e5da5Sopenharmony_ci OpExecutionMode %4 OriginUpperLeft 625fd4e5da5Sopenharmony_ci OpSource ESSL 310 626fd4e5da5Sopenharmony_ci OpName %4 "main" 627fd4e5da5Sopenharmony_ci %2 = OpTypeVoid 628fd4e5da5Sopenharmony_ci %20 = OpTypeInt 32 1 629fd4e5da5Sopenharmony_ci %21 = OpConstant %20 5 630fd4e5da5Sopenharmony_ci %3 = OpTypeFunction %2 631fd4e5da5Sopenharmony_ci %12 = OpTypePointer Function %20 632fd4e5da5Sopenharmony_ci %101 = OpTypeFunction %2 %12 633fd4e5da5Sopenharmony_ci %4 = OpFunction %2 None %3 634fd4e5da5Sopenharmony_ci %5 = OpLabel 635fd4e5da5Sopenharmony_ci %13 = OpVariable %12 Function 636fd4e5da5Sopenharmony_ci OpBranch %6 637fd4e5da5Sopenharmony_ci %6 = OpLabel 638fd4e5da5Sopenharmony_ci %104 = OpFunctionCall %2 %102 %13 639fd4e5da5Sopenharmony_ci OpBranch %10 640fd4e5da5Sopenharmony_ci %10 = OpLabel 641fd4e5da5Sopenharmony_ci OpReturn 642fd4e5da5Sopenharmony_ci OpFunctionEnd 643fd4e5da5Sopenharmony_ci %102 = OpFunction %2 None %101 644fd4e5da5Sopenharmony_ci %106 = OpFunctionParameter %12 645fd4e5da5Sopenharmony_ci %103 = OpLabel 646fd4e5da5Sopenharmony_ci %8 = OpLoad %20 %106 647fd4e5da5Sopenharmony_ci OpReturn 648fd4e5da5Sopenharmony_ci OpFunctionEnd 649fd4e5da5Sopenharmony_ci )"; 650fd4e5da5Sopenharmony_ci ASSERT_TRUE(IsEqual(env, after_transformation, context.get())); 651fd4e5da5Sopenharmony_ci} 652fd4e5da5Sopenharmony_ci 653fd4e5da5Sopenharmony_ciTEST(TransformationOutlineFunctionTest, OutlineCodeThatUsesAParameter) { 654fd4e5da5Sopenharmony_ci // This tests outlining of a block that uses a function parameter. 655fd4e5da5Sopenharmony_ci 656fd4e5da5Sopenharmony_ci std::string shader = R"( 657fd4e5da5Sopenharmony_ci OpCapability Shader 658fd4e5da5Sopenharmony_ci %1 = OpExtInstImport "GLSL.std.450" 659fd4e5da5Sopenharmony_ci OpMemoryModel Logical GLSL450 660fd4e5da5Sopenharmony_ci OpEntryPoint Fragment %4 "main" 661fd4e5da5Sopenharmony_ci OpExecutionMode %4 OriginUpperLeft 662fd4e5da5Sopenharmony_ci OpSource ESSL 310 663fd4e5da5Sopenharmony_ci OpName %4 "main" 664fd4e5da5Sopenharmony_ci OpName %10 "foo(i1;" 665fd4e5da5Sopenharmony_ci OpName %9 "x" 666fd4e5da5Sopenharmony_ci OpName %18 "param" 667fd4e5da5Sopenharmony_ci %2 = OpTypeVoid 668fd4e5da5Sopenharmony_ci %3 = OpTypeFunction %2 669fd4e5da5Sopenharmony_ci %6 = OpTypeInt 32 1 670fd4e5da5Sopenharmony_ci %7 = OpTypePointer Function %6 671fd4e5da5Sopenharmony_ci %8 = OpTypeFunction %6 %7 672fd4e5da5Sopenharmony_ci %13 = OpConstant %6 1 673fd4e5da5Sopenharmony_ci %17 = OpConstant %6 3 674fd4e5da5Sopenharmony_ci %4 = OpFunction %2 None %3 675fd4e5da5Sopenharmony_ci %5 = OpLabel 676fd4e5da5Sopenharmony_ci %18 = OpVariable %7 Function 677fd4e5da5Sopenharmony_ci OpStore %18 %17 678fd4e5da5Sopenharmony_ci %19 = OpFunctionCall %6 %10 %18 679fd4e5da5Sopenharmony_ci OpReturn 680fd4e5da5Sopenharmony_ci OpFunctionEnd 681fd4e5da5Sopenharmony_ci %10 = OpFunction %6 None %8 682fd4e5da5Sopenharmony_ci %9 = OpFunctionParameter %7 683fd4e5da5Sopenharmony_ci %11 = OpLabel 684fd4e5da5Sopenharmony_ci %12 = OpLoad %6 %9 685fd4e5da5Sopenharmony_ci %14 = OpIAdd %6 %12 %13 686fd4e5da5Sopenharmony_ci OpReturnValue %14 687fd4e5da5Sopenharmony_ci OpFunctionEnd 688fd4e5da5Sopenharmony_ci )"; 689fd4e5da5Sopenharmony_ci 690fd4e5da5Sopenharmony_ci const auto env = SPV_ENV_UNIVERSAL_1_4; 691fd4e5da5Sopenharmony_ci const auto consumer = nullptr; 692fd4e5da5Sopenharmony_ci const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption); 693fd4e5da5Sopenharmony_ci spvtools::ValidatorOptions validator_options; 694fd4e5da5Sopenharmony_ci ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options, 695fd4e5da5Sopenharmony_ci kConsoleMessageConsumer)); 696fd4e5da5Sopenharmony_ci TransformationContext transformation_context( 697fd4e5da5Sopenharmony_ci MakeUnique<FactManager>(context.get()), validator_options); 698fd4e5da5Sopenharmony_ci TransformationOutlineFunction transformation(11, 11, 100, 101, 102, 103, 104, 699fd4e5da5Sopenharmony_ci 105, {{9, 106}}, {{14, 107}}); 700fd4e5da5Sopenharmony_ci ASSERT_TRUE( 701fd4e5da5Sopenharmony_ci transformation.IsApplicable(context.get(), transformation_context)); 702fd4e5da5Sopenharmony_ci ApplyAndCheckFreshIds(transformation, context.get(), &transformation_context); 703fd4e5da5Sopenharmony_ci ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options, 704fd4e5da5Sopenharmony_ci kConsoleMessageConsumer)); 705fd4e5da5Sopenharmony_ci 706fd4e5da5Sopenharmony_ci std::string after_transformation = R"( 707fd4e5da5Sopenharmony_ci OpCapability Shader 708fd4e5da5Sopenharmony_ci %1 = OpExtInstImport "GLSL.std.450" 709fd4e5da5Sopenharmony_ci OpMemoryModel Logical GLSL450 710fd4e5da5Sopenharmony_ci OpEntryPoint Fragment %4 "main" 711fd4e5da5Sopenharmony_ci OpExecutionMode %4 OriginUpperLeft 712fd4e5da5Sopenharmony_ci OpSource ESSL 310 713fd4e5da5Sopenharmony_ci OpName %4 "main" 714fd4e5da5Sopenharmony_ci OpName %10 "foo(i1;" 715fd4e5da5Sopenharmony_ci OpName %9 "x" 716fd4e5da5Sopenharmony_ci OpName %18 "param" 717fd4e5da5Sopenharmony_ci %2 = OpTypeVoid 718fd4e5da5Sopenharmony_ci %3 = OpTypeFunction %2 719fd4e5da5Sopenharmony_ci %6 = OpTypeInt 32 1 720fd4e5da5Sopenharmony_ci %7 = OpTypePointer Function %6 721fd4e5da5Sopenharmony_ci %8 = OpTypeFunction %6 %7 722fd4e5da5Sopenharmony_ci %13 = OpConstant %6 1 723fd4e5da5Sopenharmony_ci %17 = OpConstant %6 3 724fd4e5da5Sopenharmony_ci %100 = OpTypeStruct %6 725fd4e5da5Sopenharmony_ci %101 = OpTypeFunction %100 %7 726fd4e5da5Sopenharmony_ci %4 = OpFunction %2 None %3 727fd4e5da5Sopenharmony_ci %5 = OpLabel 728fd4e5da5Sopenharmony_ci %18 = OpVariable %7 Function 729fd4e5da5Sopenharmony_ci OpStore %18 %17 730fd4e5da5Sopenharmony_ci %19 = OpFunctionCall %6 %10 %18 731fd4e5da5Sopenharmony_ci OpReturn 732fd4e5da5Sopenharmony_ci OpFunctionEnd 733fd4e5da5Sopenharmony_ci %10 = OpFunction %6 None %8 734fd4e5da5Sopenharmony_ci %9 = OpFunctionParameter %7 735fd4e5da5Sopenharmony_ci %11 = OpLabel 736fd4e5da5Sopenharmony_ci %104 = OpFunctionCall %100 %102 %9 737fd4e5da5Sopenharmony_ci %14 = OpCompositeExtract %6 %104 0 738fd4e5da5Sopenharmony_ci OpReturnValue %14 739fd4e5da5Sopenharmony_ci OpFunctionEnd 740fd4e5da5Sopenharmony_ci %102 = OpFunction %100 None %101 741fd4e5da5Sopenharmony_ci %106 = OpFunctionParameter %7 742fd4e5da5Sopenharmony_ci %103 = OpLabel 743fd4e5da5Sopenharmony_ci %12 = OpLoad %6 %106 744fd4e5da5Sopenharmony_ci %107 = OpIAdd %6 %12 %13 745fd4e5da5Sopenharmony_ci %105 = OpCompositeConstruct %100 %107 746fd4e5da5Sopenharmony_ci OpReturnValue %105 747fd4e5da5Sopenharmony_ci OpFunctionEnd 748fd4e5da5Sopenharmony_ci )"; 749fd4e5da5Sopenharmony_ci ASSERT_TRUE(IsEqual(env, after_transformation, context.get())); 750fd4e5da5Sopenharmony_ci} 751fd4e5da5Sopenharmony_ci 752fd4e5da5Sopenharmony_ciTEST(TransformationOutlineFunctionTest, 753fd4e5da5Sopenharmony_ci DoNotOutlineIfLoopMergeIsOutsideRegion) { 754fd4e5da5Sopenharmony_ci std::string shader = R"( 755fd4e5da5Sopenharmony_ci OpCapability Shader 756fd4e5da5Sopenharmony_ci %1 = OpExtInstImport "GLSL.std.450" 757fd4e5da5Sopenharmony_ci OpMemoryModel Logical GLSL450 758fd4e5da5Sopenharmony_ci OpEntryPoint Fragment %4 "main" 759fd4e5da5Sopenharmony_ci OpExecutionMode %4 OriginUpperLeft 760fd4e5da5Sopenharmony_ci OpSource ESSL 310 761fd4e5da5Sopenharmony_ci OpName %4 "main" 762fd4e5da5Sopenharmony_ci %2 = OpTypeVoid 763fd4e5da5Sopenharmony_ci %3 = OpTypeFunction %2 764fd4e5da5Sopenharmony_ci %9 = OpTypeBool 765fd4e5da5Sopenharmony_ci %10 = OpConstantTrue %9 766fd4e5da5Sopenharmony_ci %4 = OpFunction %2 None %3 767fd4e5da5Sopenharmony_ci %5 = OpLabel 768fd4e5da5Sopenharmony_ci OpBranch %6 769fd4e5da5Sopenharmony_ci %6 = OpLabel 770fd4e5da5Sopenharmony_ci OpLoopMerge %7 %8 None 771fd4e5da5Sopenharmony_ci OpBranch %8 772fd4e5da5Sopenharmony_ci %8 = OpLabel 773fd4e5da5Sopenharmony_ci OpBranchConditional %10 %6 %7 774fd4e5da5Sopenharmony_ci %7 = OpLabel 775fd4e5da5Sopenharmony_ci OpReturn 776fd4e5da5Sopenharmony_ci OpFunctionEnd 777fd4e5da5Sopenharmony_ci )"; 778fd4e5da5Sopenharmony_ci 779fd4e5da5Sopenharmony_ci const auto env = SPV_ENV_UNIVERSAL_1_4; 780fd4e5da5Sopenharmony_ci const auto consumer = nullptr; 781fd4e5da5Sopenharmony_ci const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption); 782fd4e5da5Sopenharmony_ci spvtools::ValidatorOptions validator_options; 783fd4e5da5Sopenharmony_ci ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options, 784fd4e5da5Sopenharmony_ci kConsoleMessageConsumer)); 785fd4e5da5Sopenharmony_ci TransformationContext transformation_context( 786fd4e5da5Sopenharmony_ci MakeUnique<FactManager>(context.get()), validator_options); 787fd4e5da5Sopenharmony_ci TransformationOutlineFunction transformation(6, 8, 100, 101, 102, 103, 104, 788fd4e5da5Sopenharmony_ci 105, {}, {}); 789fd4e5da5Sopenharmony_ci ASSERT_FALSE( 790fd4e5da5Sopenharmony_ci transformation.IsApplicable(context.get(), transformation_context)); 791fd4e5da5Sopenharmony_ci} 792fd4e5da5Sopenharmony_ci 793fd4e5da5Sopenharmony_ciTEST(TransformationOutlineFunctionTest, DoNotOutlineIfRegionInvolvesReturn) { 794fd4e5da5Sopenharmony_ci std::string shader = R"( 795fd4e5da5Sopenharmony_ci OpCapability Shader 796fd4e5da5Sopenharmony_ci %1 = OpExtInstImport "GLSL.std.450" 797fd4e5da5Sopenharmony_ci OpMemoryModel Logical GLSL450 798fd4e5da5Sopenharmony_ci OpEntryPoint Fragment %4 "main" 799fd4e5da5Sopenharmony_ci OpExecutionMode %4 OriginUpperLeft 800fd4e5da5Sopenharmony_ci OpSource ESSL 310 801fd4e5da5Sopenharmony_ci OpName %4 "main" 802fd4e5da5Sopenharmony_ci %2 = OpTypeVoid 803fd4e5da5Sopenharmony_ci %20 = OpTypeBool 804fd4e5da5Sopenharmony_ci %21 = OpConstantTrue %20 805fd4e5da5Sopenharmony_ci %3 = OpTypeFunction %2 806fd4e5da5Sopenharmony_ci %4 = OpFunction %2 None %3 807fd4e5da5Sopenharmony_ci %5 = OpLabel 808fd4e5da5Sopenharmony_ci OpBranch %6 809fd4e5da5Sopenharmony_ci %6 = OpLabel 810fd4e5da5Sopenharmony_ci OpBranch %7 811fd4e5da5Sopenharmony_ci %7 = OpLabel 812fd4e5da5Sopenharmony_ci OpSelectionMerge %10 None 813fd4e5da5Sopenharmony_ci OpBranchConditional %21 %8 %9 814fd4e5da5Sopenharmony_ci %8 = OpLabel 815fd4e5da5Sopenharmony_ci OpReturn 816fd4e5da5Sopenharmony_ci %9 = OpLabel 817fd4e5da5Sopenharmony_ci OpBranch %10 818fd4e5da5Sopenharmony_ci %10 = OpLabel 819fd4e5da5Sopenharmony_ci OpBranch %11 820fd4e5da5Sopenharmony_ci %11 = OpLabel 821fd4e5da5Sopenharmony_ci OpBranch %12 822fd4e5da5Sopenharmony_ci %12 = OpLabel 823fd4e5da5Sopenharmony_ci OpReturn 824fd4e5da5Sopenharmony_ci OpFunctionEnd 825fd4e5da5Sopenharmony_ci )"; 826fd4e5da5Sopenharmony_ci 827fd4e5da5Sopenharmony_ci const auto env = SPV_ENV_UNIVERSAL_1_4; 828fd4e5da5Sopenharmony_ci const auto consumer = nullptr; 829fd4e5da5Sopenharmony_ci const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption); 830fd4e5da5Sopenharmony_ci spvtools::ValidatorOptions validator_options; 831fd4e5da5Sopenharmony_ci ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options, 832fd4e5da5Sopenharmony_ci kConsoleMessageConsumer)); 833fd4e5da5Sopenharmony_ci TransformationContext transformation_context( 834fd4e5da5Sopenharmony_ci MakeUnique<FactManager>(context.get()), validator_options); 835fd4e5da5Sopenharmony_ci TransformationOutlineFunction transformation(6, 11, /* not relevant */ 200, 836fd4e5da5Sopenharmony_ci 100, 101, 102, 103, 837fd4e5da5Sopenharmony_ci /* not relevant */ 201, {}, {}); 838fd4e5da5Sopenharmony_ci ASSERT_FALSE( 839fd4e5da5Sopenharmony_ci transformation.IsApplicable(context.get(), transformation_context)); 840fd4e5da5Sopenharmony_ci} 841fd4e5da5Sopenharmony_ci 842fd4e5da5Sopenharmony_ciTEST(TransformationOutlineFunctionTest, DoNotOutlineIfRegionInvolvesKill) { 843fd4e5da5Sopenharmony_ci std::string shader = R"( 844fd4e5da5Sopenharmony_ci OpCapability Shader 845fd4e5da5Sopenharmony_ci %1 = OpExtInstImport "GLSL.std.450" 846fd4e5da5Sopenharmony_ci OpMemoryModel Logical GLSL450 847fd4e5da5Sopenharmony_ci OpEntryPoint Fragment %4 "main" 848fd4e5da5Sopenharmony_ci OpExecutionMode %4 OriginUpperLeft 849fd4e5da5Sopenharmony_ci OpSource ESSL 310 850fd4e5da5Sopenharmony_ci OpName %4 "main" 851fd4e5da5Sopenharmony_ci %2 = OpTypeVoid 852fd4e5da5Sopenharmony_ci %20 = OpTypeBool 853fd4e5da5Sopenharmony_ci %21 = OpConstantTrue %20 854fd4e5da5Sopenharmony_ci %3 = OpTypeFunction %2 855fd4e5da5Sopenharmony_ci %4 = OpFunction %2 None %3 856fd4e5da5Sopenharmony_ci %5 = OpLabel 857fd4e5da5Sopenharmony_ci OpBranch %6 858fd4e5da5Sopenharmony_ci %6 = OpLabel 859fd4e5da5Sopenharmony_ci OpBranch %7 860fd4e5da5Sopenharmony_ci %7 = OpLabel 861fd4e5da5Sopenharmony_ci OpSelectionMerge %10 None 862fd4e5da5Sopenharmony_ci OpBranchConditional %21 %8 %9 863fd4e5da5Sopenharmony_ci %8 = OpLabel 864fd4e5da5Sopenharmony_ci OpKill 865fd4e5da5Sopenharmony_ci %9 = OpLabel 866fd4e5da5Sopenharmony_ci OpBranch %10 867fd4e5da5Sopenharmony_ci %10 = OpLabel 868fd4e5da5Sopenharmony_ci OpBranch %11 869fd4e5da5Sopenharmony_ci %11 = OpLabel 870fd4e5da5Sopenharmony_ci OpBranch %12 871fd4e5da5Sopenharmony_ci %12 = OpLabel 872fd4e5da5Sopenharmony_ci OpReturn 873fd4e5da5Sopenharmony_ci OpFunctionEnd 874fd4e5da5Sopenharmony_ci )"; 875fd4e5da5Sopenharmony_ci 876fd4e5da5Sopenharmony_ci const auto env = SPV_ENV_UNIVERSAL_1_4; 877fd4e5da5Sopenharmony_ci const auto consumer = nullptr; 878fd4e5da5Sopenharmony_ci const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption); 879fd4e5da5Sopenharmony_ci spvtools::ValidatorOptions validator_options; 880fd4e5da5Sopenharmony_ci ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options, 881fd4e5da5Sopenharmony_ci kConsoleMessageConsumer)); 882fd4e5da5Sopenharmony_ci TransformationContext transformation_context( 883fd4e5da5Sopenharmony_ci MakeUnique<FactManager>(context.get()), validator_options); 884fd4e5da5Sopenharmony_ci TransformationOutlineFunction transformation(6, 11, /* not relevant */ 200, 885fd4e5da5Sopenharmony_ci 100, 101, 102, 103, 886fd4e5da5Sopenharmony_ci /* not relevant */ 201, {}, {}); 887fd4e5da5Sopenharmony_ci ASSERT_FALSE( 888fd4e5da5Sopenharmony_ci transformation.IsApplicable(context.get(), transformation_context)); 889fd4e5da5Sopenharmony_ci} 890fd4e5da5Sopenharmony_ci 891fd4e5da5Sopenharmony_ciTEST(TransformationOutlineFunctionTest, 892fd4e5da5Sopenharmony_ci DoNotOutlineIfRegionInvolvesUnreachable) { 893fd4e5da5Sopenharmony_ci std::string shader = R"( 894fd4e5da5Sopenharmony_ci OpCapability Shader 895fd4e5da5Sopenharmony_ci %1 = OpExtInstImport "GLSL.std.450" 896fd4e5da5Sopenharmony_ci OpMemoryModel Logical GLSL450 897fd4e5da5Sopenharmony_ci OpEntryPoint Fragment %4 "main" 898fd4e5da5Sopenharmony_ci OpExecutionMode %4 OriginUpperLeft 899fd4e5da5Sopenharmony_ci OpSource ESSL 310 900fd4e5da5Sopenharmony_ci OpName %4 "main" 901fd4e5da5Sopenharmony_ci %2 = OpTypeVoid 902fd4e5da5Sopenharmony_ci %20 = OpTypeBool 903fd4e5da5Sopenharmony_ci %21 = OpConstantTrue %20 904fd4e5da5Sopenharmony_ci %3 = OpTypeFunction %2 905fd4e5da5Sopenharmony_ci %4 = OpFunction %2 None %3 906fd4e5da5Sopenharmony_ci %5 = OpLabel 907fd4e5da5Sopenharmony_ci OpBranch %6 908fd4e5da5Sopenharmony_ci %6 = OpLabel 909fd4e5da5Sopenharmony_ci OpBranch %7 910fd4e5da5Sopenharmony_ci %7 = OpLabel 911fd4e5da5Sopenharmony_ci OpSelectionMerge %10 None 912fd4e5da5Sopenharmony_ci OpBranchConditional %21 %8 %9 913fd4e5da5Sopenharmony_ci %8 = OpLabel 914fd4e5da5Sopenharmony_ci OpBranch %10 915fd4e5da5Sopenharmony_ci %9 = OpLabel 916fd4e5da5Sopenharmony_ci OpUnreachable 917fd4e5da5Sopenharmony_ci %10 = OpLabel 918fd4e5da5Sopenharmony_ci OpBranch %11 919fd4e5da5Sopenharmony_ci %11 = OpLabel 920fd4e5da5Sopenharmony_ci OpBranch %12 921fd4e5da5Sopenharmony_ci %12 = OpLabel 922fd4e5da5Sopenharmony_ci OpReturn 923fd4e5da5Sopenharmony_ci OpFunctionEnd 924fd4e5da5Sopenharmony_ci )"; 925fd4e5da5Sopenharmony_ci 926fd4e5da5Sopenharmony_ci const auto env = SPV_ENV_UNIVERSAL_1_4; 927fd4e5da5Sopenharmony_ci const auto consumer = nullptr; 928fd4e5da5Sopenharmony_ci const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption); 929fd4e5da5Sopenharmony_ci spvtools::ValidatorOptions validator_options; 930fd4e5da5Sopenharmony_ci ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options, 931fd4e5da5Sopenharmony_ci kConsoleMessageConsumer)); 932fd4e5da5Sopenharmony_ci TransformationContext transformation_context( 933fd4e5da5Sopenharmony_ci MakeUnique<FactManager>(context.get()), validator_options); 934fd4e5da5Sopenharmony_ci TransformationOutlineFunction transformation(6, 11, /* not relevant */ 200, 935fd4e5da5Sopenharmony_ci 100, 101, 102, 103, 936fd4e5da5Sopenharmony_ci /* not relevant */ 201, {}, {}); 937fd4e5da5Sopenharmony_ci ASSERT_FALSE( 938fd4e5da5Sopenharmony_ci transformation.IsApplicable(context.get(), transformation_context)); 939fd4e5da5Sopenharmony_ci} 940fd4e5da5Sopenharmony_ci 941fd4e5da5Sopenharmony_ciTEST(TransformationOutlineFunctionTest, 942fd4e5da5Sopenharmony_ci DoNotOutlineIfSelectionMergeIsOutsideRegion) { 943fd4e5da5Sopenharmony_ci std::string shader = R"( 944fd4e5da5Sopenharmony_ci OpCapability Shader 945fd4e5da5Sopenharmony_ci %1 = OpExtInstImport "GLSL.std.450" 946fd4e5da5Sopenharmony_ci OpMemoryModel Logical GLSL450 947fd4e5da5Sopenharmony_ci OpEntryPoint Fragment %4 "main" 948fd4e5da5Sopenharmony_ci OpExecutionMode %4 OriginUpperLeft 949fd4e5da5Sopenharmony_ci OpSource ESSL 310 950fd4e5da5Sopenharmony_ci OpName %4 "main" 951fd4e5da5Sopenharmony_ci %2 = OpTypeVoid 952fd4e5da5Sopenharmony_ci %3 = OpTypeFunction %2 953fd4e5da5Sopenharmony_ci %9 = OpTypeBool 954fd4e5da5Sopenharmony_ci %10 = OpConstantTrue %9 955fd4e5da5Sopenharmony_ci %4 = OpFunction %2 None %3 956fd4e5da5Sopenharmony_ci %5 = OpLabel 957fd4e5da5Sopenharmony_ci OpBranch %6 958fd4e5da5Sopenharmony_ci %6 = OpLabel 959fd4e5da5Sopenharmony_ci OpSelectionMerge %7 None 960fd4e5da5Sopenharmony_ci OpBranchConditional %10 %8 %7 961fd4e5da5Sopenharmony_ci %8 = OpLabel 962fd4e5da5Sopenharmony_ci OpBranch %7 963fd4e5da5Sopenharmony_ci %7 = OpLabel 964fd4e5da5Sopenharmony_ci OpReturn 965fd4e5da5Sopenharmony_ci OpFunctionEnd 966fd4e5da5Sopenharmony_ci )"; 967fd4e5da5Sopenharmony_ci 968fd4e5da5Sopenharmony_ci const auto env = SPV_ENV_UNIVERSAL_1_4; 969fd4e5da5Sopenharmony_ci const auto consumer = nullptr; 970fd4e5da5Sopenharmony_ci const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption); 971fd4e5da5Sopenharmony_ci spvtools::ValidatorOptions validator_options; 972fd4e5da5Sopenharmony_ci ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options, 973fd4e5da5Sopenharmony_ci kConsoleMessageConsumer)); 974fd4e5da5Sopenharmony_ci TransformationContext transformation_context( 975fd4e5da5Sopenharmony_ci MakeUnique<FactManager>(context.get()), validator_options); 976fd4e5da5Sopenharmony_ci TransformationOutlineFunction transformation(6, 8, 100, 101, 102, 103, 104, 977fd4e5da5Sopenharmony_ci 105, {}, {}); 978fd4e5da5Sopenharmony_ci ASSERT_FALSE( 979fd4e5da5Sopenharmony_ci transformation.IsApplicable(context.get(), transformation_context)); 980fd4e5da5Sopenharmony_ci} 981fd4e5da5Sopenharmony_ci 982fd4e5da5Sopenharmony_ciTEST(TransformationOutlineFunctionTest, DoNotOutlineIfLoopHeadIsOutsideRegion) { 983fd4e5da5Sopenharmony_ci std::string shader = R"( 984fd4e5da5Sopenharmony_ci OpCapability Shader 985fd4e5da5Sopenharmony_ci %1 = OpExtInstImport "GLSL.std.450" 986fd4e5da5Sopenharmony_ci OpMemoryModel Logical GLSL450 987fd4e5da5Sopenharmony_ci OpEntryPoint Fragment %4 "main" 988fd4e5da5Sopenharmony_ci OpExecutionMode %4 OriginUpperLeft 989fd4e5da5Sopenharmony_ci OpSource ESSL 310 990fd4e5da5Sopenharmony_ci OpName %4 "main" 991fd4e5da5Sopenharmony_ci %2 = OpTypeVoid 992fd4e5da5Sopenharmony_ci %3 = OpTypeFunction %2 993fd4e5da5Sopenharmony_ci %9 = OpTypeBool 994fd4e5da5Sopenharmony_ci %10 = OpConstantTrue %9 995fd4e5da5Sopenharmony_ci %4 = OpFunction %2 None %3 996fd4e5da5Sopenharmony_ci %5 = OpLabel 997fd4e5da5Sopenharmony_ci OpBranch %6 998fd4e5da5Sopenharmony_ci %6 = OpLabel 999fd4e5da5Sopenharmony_ci OpLoopMerge %8 %11 None 1000fd4e5da5Sopenharmony_ci OpBranch %7 1001fd4e5da5Sopenharmony_ci %7 = OpLabel 1002fd4e5da5Sopenharmony_ci OpBranchConditional %10 %11 %8 1003fd4e5da5Sopenharmony_ci %11 = OpLabel 1004fd4e5da5Sopenharmony_ci OpBranch %6 1005fd4e5da5Sopenharmony_ci %8 = OpLabel 1006fd4e5da5Sopenharmony_ci OpReturn 1007fd4e5da5Sopenharmony_ci OpFunctionEnd 1008fd4e5da5Sopenharmony_ci )"; 1009fd4e5da5Sopenharmony_ci 1010fd4e5da5Sopenharmony_ci const auto env = SPV_ENV_UNIVERSAL_1_4; 1011fd4e5da5Sopenharmony_ci const auto consumer = nullptr; 1012fd4e5da5Sopenharmony_ci const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption); 1013fd4e5da5Sopenharmony_ci spvtools::ValidatorOptions validator_options; 1014fd4e5da5Sopenharmony_ci ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options, 1015fd4e5da5Sopenharmony_ci kConsoleMessageConsumer)); 1016fd4e5da5Sopenharmony_ci TransformationContext transformation_context( 1017fd4e5da5Sopenharmony_ci MakeUnique<FactManager>(context.get()), validator_options); 1018fd4e5da5Sopenharmony_ci TransformationOutlineFunction transformation(7, 8, 100, 101, 102, 103, 104, 1019fd4e5da5Sopenharmony_ci 105, {}, {}); 1020fd4e5da5Sopenharmony_ci ASSERT_FALSE( 1021fd4e5da5Sopenharmony_ci transformation.IsApplicable(context.get(), transformation_context)); 1022fd4e5da5Sopenharmony_ci} 1023fd4e5da5Sopenharmony_ci 1024fd4e5da5Sopenharmony_ciTEST(TransformationOutlineFunctionTest, 1025fd4e5da5Sopenharmony_ci DoNotOutlineIfLoopContinueIsOutsideRegion) { 1026fd4e5da5Sopenharmony_ci std::string shader = R"( 1027fd4e5da5Sopenharmony_ci OpCapability Shader 1028fd4e5da5Sopenharmony_ci %1 = OpExtInstImport "GLSL.std.450" 1029fd4e5da5Sopenharmony_ci OpMemoryModel Logical GLSL450 1030fd4e5da5Sopenharmony_ci OpEntryPoint Fragment %4 "main" 1031fd4e5da5Sopenharmony_ci OpExecutionMode %4 OriginUpperLeft 1032fd4e5da5Sopenharmony_ci OpSource ESSL 310 1033fd4e5da5Sopenharmony_ci OpName %4 "main" 1034fd4e5da5Sopenharmony_ci %2 = OpTypeVoid 1035fd4e5da5Sopenharmony_ci %3 = OpTypeFunction %2 1036fd4e5da5Sopenharmony_ci %9 = OpTypeBool 1037fd4e5da5Sopenharmony_ci %10 = OpConstantTrue %9 1038fd4e5da5Sopenharmony_ci %4 = OpFunction %2 None %3 1039fd4e5da5Sopenharmony_ci %5 = OpLabel 1040fd4e5da5Sopenharmony_ci OpBranch %6 1041fd4e5da5Sopenharmony_ci %6 = OpLabel 1042fd4e5da5Sopenharmony_ci OpLoopMerge %7 %8 None 1043fd4e5da5Sopenharmony_ci OpBranch %7 1044fd4e5da5Sopenharmony_ci %8 = OpLabel 1045fd4e5da5Sopenharmony_ci OpBranch %6 1046fd4e5da5Sopenharmony_ci %7 = OpLabel 1047fd4e5da5Sopenharmony_ci OpReturn 1048fd4e5da5Sopenharmony_ci OpFunctionEnd 1049fd4e5da5Sopenharmony_ci )"; 1050fd4e5da5Sopenharmony_ci 1051fd4e5da5Sopenharmony_ci const auto env = SPV_ENV_UNIVERSAL_1_4; 1052fd4e5da5Sopenharmony_ci const auto consumer = nullptr; 1053fd4e5da5Sopenharmony_ci const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption); 1054fd4e5da5Sopenharmony_ci spvtools::ValidatorOptions validator_options; 1055fd4e5da5Sopenharmony_ci ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options, 1056fd4e5da5Sopenharmony_ci kConsoleMessageConsumer)); 1057fd4e5da5Sopenharmony_ci TransformationContext transformation_context( 1058fd4e5da5Sopenharmony_ci MakeUnique<FactManager>(context.get()), validator_options); 1059fd4e5da5Sopenharmony_ci TransformationOutlineFunction transformation(6, 7, 100, 101, 102, 103, 104, 1060fd4e5da5Sopenharmony_ci 105, {}, {}); 1061fd4e5da5Sopenharmony_ci ASSERT_FALSE( 1062fd4e5da5Sopenharmony_ci transformation.IsApplicable(context.get(), transformation_context)); 1063fd4e5da5Sopenharmony_ci} 1064fd4e5da5Sopenharmony_ci 1065fd4e5da5Sopenharmony_ciTEST(TransformationOutlineFunctionTest, 1066fd4e5da5Sopenharmony_ci DoNotOutlineWithLoopCarriedPhiDependence) { 1067fd4e5da5Sopenharmony_ci std::string shader = R"( 1068fd4e5da5Sopenharmony_ci OpCapability Shader 1069fd4e5da5Sopenharmony_ci %1 = OpExtInstImport "GLSL.std.450" 1070fd4e5da5Sopenharmony_ci OpMemoryModel Logical GLSL450 1071fd4e5da5Sopenharmony_ci OpEntryPoint Fragment %4 "main" 1072fd4e5da5Sopenharmony_ci OpExecutionMode %4 OriginUpperLeft 1073fd4e5da5Sopenharmony_ci OpSource ESSL 310 1074fd4e5da5Sopenharmony_ci OpName %4 "main" 1075fd4e5da5Sopenharmony_ci %2 = OpTypeVoid 1076fd4e5da5Sopenharmony_ci %3 = OpTypeFunction %2 1077fd4e5da5Sopenharmony_ci %9 = OpTypeBool 1078fd4e5da5Sopenharmony_ci %10 = OpConstantTrue %9 1079fd4e5da5Sopenharmony_ci %4 = OpFunction %2 None %3 1080fd4e5da5Sopenharmony_ci %5 = OpLabel 1081fd4e5da5Sopenharmony_ci OpBranch %6 1082fd4e5da5Sopenharmony_ci %6 = OpLabel 1083fd4e5da5Sopenharmony_ci %12 = OpPhi %9 %10 %5 %13 %8 1084fd4e5da5Sopenharmony_ci OpLoopMerge %7 %8 None 1085fd4e5da5Sopenharmony_ci OpBranch %8 1086fd4e5da5Sopenharmony_ci %8 = OpLabel 1087fd4e5da5Sopenharmony_ci %13 = OpCopyObject %9 %10 1088fd4e5da5Sopenharmony_ci OpBranchConditional %10 %6 %7 1089fd4e5da5Sopenharmony_ci %7 = OpLabel 1090fd4e5da5Sopenharmony_ci OpReturn 1091fd4e5da5Sopenharmony_ci OpFunctionEnd 1092fd4e5da5Sopenharmony_ci )"; 1093fd4e5da5Sopenharmony_ci 1094fd4e5da5Sopenharmony_ci const auto env = SPV_ENV_UNIVERSAL_1_4; 1095fd4e5da5Sopenharmony_ci const auto consumer = nullptr; 1096fd4e5da5Sopenharmony_ci const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption); 1097fd4e5da5Sopenharmony_ci spvtools::ValidatorOptions validator_options; 1098fd4e5da5Sopenharmony_ci ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options, 1099fd4e5da5Sopenharmony_ci kConsoleMessageConsumer)); 1100fd4e5da5Sopenharmony_ci TransformationContext transformation_context( 1101fd4e5da5Sopenharmony_ci MakeUnique<FactManager>(context.get()), validator_options); 1102fd4e5da5Sopenharmony_ci TransformationOutlineFunction transformation(6, 7, 100, 101, 102, 103, 104, 1103fd4e5da5Sopenharmony_ci 105, {}, {}); 1104fd4e5da5Sopenharmony_ci ASSERT_FALSE( 1105fd4e5da5Sopenharmony_ci transformation.IsApplicable(context.get(), transformation_context)); 1106fd4e5da5Sopenharmony_ci} 1107fd4e5da5Sopenharmony_ci 1108fd4e5da5Sopenharmony_ciTEST(TransformationOutlineFunctionTest, 1109fd4e5da5Sopenharmony_ci DoNotOutlineSelectionHeaderNotInRegion) { 1110fd4e5da5Sopenharmony_ci std::string shader = R"( 1111fd4e5da5Sopenharmony_ci OpCapability Shader 1112fd4e5da5Sopenharmony_ci %1 = OpExtInstImport "GLSL.std.450" 1113fd4e5da5Sopenharmony_ci OpMemoryModel Logical GLSL450 1114fd4e5da5Sopenharmony_ci OpEntryPoint Fragment %4 "main" 1115fd4e5da5Sopenharmony_ci OpExecutionMode %4 OriginUpperLeft 1116fd4e5da5Sopenharmony_ci OpSource ESSL 310 1117fd4e5da5Sopenharmony_ci OpName %4 "main" 1118fd4e5da5Sopenharmony_ci %2 = OpTypeVoid 1119fd4e5da5Sopenharmony_ci %3 = OpTypeFunction %2 1120fd4e5da5Sopenharmony_ci %6 = OpTypeBool 1121fd4e5da5Sopenharmony_ci %7 = OpConstantTrue %6 1122fd4e5da5Sopenharmony_ci %4 = OpFunction %2 None %3 1123fd4e5da5Sopenharmony_ci %5 = OpLabel 1124fd4e5da5Sopenharmony_ci OpSelectionMerge %10 None 1125fd4e5da5Sopenharmony_ci OpBranchConditional %7 %8 %8 1126fd4e5da5Sopenharmony_ci %8 = OpLabel 1127fd4e5da5Sopenharmony_ci OpBranch %9 1128fd4e5da5Sopenharmony_ci %9 = OpLabel 1129fd4e5da5Sopenharmony_ci OpBranch %10 1130fd4e5da5Sopenharmony_ci %10 = OpLabel 1131fd4e5da5Sopenharmony_ci OpBranch %11 1132fd4e5da5Sopenharmony_ci %11 = OpLabel 1133fd4e5da5Sopenharmony_ci OpReturn 1134fd4e5da5Sopenharmony_ci OpFunctionEnd 1135fd4e5da5Sopenharmony_ci )"; 1136fd4e5da5Sopenharmony_ci 1137fd4e5da5Sopenharmony_ci const auto env = SPV_ENV_UNIVERSAL_1_4; 1138fd4e5da5Sopenharmony_ci const auto consumer = nullptr; 1139fd4e5da5Sopenharmony_ci const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption); 1140fd4e5da5Sopenharmony_ci spvtools::ValidatorOptions validator_options; 1141fd4e5da5Sopenharmony_ci ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options, 1142fd4e5da5Sopenharmony_ci kConsoleMessageConsumer)); 1143fd4e5da5Sopenharmony_ci TransformationContext transformation_context( 1144fd4e5da5Sopenharmony_ci MakeUnique<FactManager>(context.get()), validator_options); 1145fd4e5da5Sopenharmony_ci TransformationOutlineFunction transformation(8, 11, 100, 101, 102, 103, 104, 1146fd4e5da5Sopenharmony_ci 105, {}, {}); 1147fd4e5da5Sopenharmony_ci ASSERT_FALSE( 1148fd4e5da5Sopenharmony_ci transformation.IsApplicable(context.get(), transformation_context)); 1149fd4e5da5Sopenharmony_ci} 1150fd4e5da5Sopenharmony_ci 1151fd4e5da5Sopenharmony_ciTEST(TransformationOutlineFunctionTest, OutlineRegionEndingWithReturnVoid) { 1152fd4e5da5Sopenharmony_ci std::string shader = R"( 1153fd4e5da5Sopenharmony_ci OpCapability Shader 1154fd4e5da5Sopenharmony_ci %1 = OpExtInstImport "GLSL.std.450" 1155fd4e5da5Sopenharmony_ci OpMemoryModel Logical GLSL450 1156fd4e5da5Sopenharmony_ci OpEntryPoint Fragment %4 "main" 1157fd4e5da5Sopenharmony_ci OpExecutionMode %4 OriginUpperLeft 1158fd4e5da5Sopenharmony_ci OpSource ESSL 310 1159fd4e5da5Sopenharmony_ci %20 = OpTypeInt 32 0 1160fd4e5da5Sopenharmony_ci %21 = OpConstant %20 1 1161fd4e5da5Sopenharmony_ci %2 = OpTypeVoid 1162fd4e5da5Sopenharmony_ci %3 = OpTypeFunction %2 1163fd4e5da5Sopenharmony_ci %4 = OpFunction %2 None %3 1164fd4e5da5Sopenharmony_ci %5 = OpLabel 1165fd4e5da5Sopenharmony_ci %22 = OpCopyObject %20 %21 1166fd4e5da5Sopenharmony_ci OpBranch %54 1167fd4e5da5Sopenharmony_ci %54 = OpLabel 1168fd4e5da5Sopenharmony_ci OpBranch %57 1169fd4e5da5Sopenharmony_ci %57 = OpLabel 1170fd4e5da5Sopenharmony_ci %23 = OpCopyObject %20 %22 1171fd4e5da5Sopenharmony_ci OpBranch %58 1172fd4e5da5Sopenharmony_ci %58 = OpLabel 1173fd4e5da5Sopenharmony_ci OpReturn 1174fd4e5da5Sopenharmony_ci OpFunctionEnd 1175fd4e5da5Sopenharmony_ci )"; 1176fd4e5da5Sopenharmony_ci 1177fd4e5da5Sopenharmony_ci const auto env = SPV_ENV_UNIVERSAL_1_5; 1178fd4e5da5Sopenharmony_ci const auto consumer = nullptr; 1179fd4e5da5Sopenharmony_ci const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption); 1180fd4e5da5Sopenharmony_ci spvtools::ValidatorOptions validator_options; 1181fd4e5da5Sopenharmony_ci ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options, 1182fd4e5da5Sopenharmony_ci kConsoleMessageConsumer)); 1183fd4e5da5Sopenharmony_ci TransformationContext transformation_context( 1184fd4e5da5Sopenharmony_ci MakeUnique<FactManager>(context.get()), validator_options); 1185fd4e5da5Sopenharmony_ci TransformationOutlineFunction transformation( 1186fd4e5da5Sopenharmony_ci /*entry_block*/ 54, 1187fd4e5da5Sopenharmony_ci /*exit_block*/ 58, 1188fd4e5da5Sopenharmony_ci /*new_function_struct_return_type_id*/ 200, 1189fd4e5da5Sopenharmony_ci /*new_function_type_id*/ 201, 1190fd4e5da5Sopenharmony_ci /*new_function_id*/ 202, 1191fd4e5da5Sopenharmony_ci /*new_function_region_entry_block*/ 203, 1192fd4e5da5Sopenharmony_ci /*new_caller_result_id*/ 204, 1193fd4e5da5Sopenharmony_ci /*new_callee_result_id*/ 205, 1194fd4e5da5Sopenharmony_ci /*input_id_to_fresh_id*/ {{22, 206}}, 1195fd4e5da5Sopenharmony_ci /*output_id_to_fresh_id*/ {}); 1196fd4e5da5Sopenharmony_ci 1197fd4e5da5Sopenharmony_ci ASSERT_TRUE( 1198fd4e5da5Sopenharmony_ci transformation.IsApplicable(context.get(), transformation_context)); 1199fd4e5da5Sopenharmony_ci ApplyAndCheckFreshIds(transformation, context.get(), &transformation_context); 1200fd4e5da5Sopenharmony_ci ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options, 1201fd4e5da5Sopenharmony_ci kConsoleMessageConsumer)); 1202fd4e5da5Sopenharmony_ci 1203fd4e5da5Sopenharmony_ci std::string after_transformation = R"( 1204fd4e5da5Sopenharmony_ci OpCapability Shader 1205fd4e5da5Sopenharmony_ci %1 = OpExtInstImport "GLSL.std.450" 1206fd4e5da5Sopenharmony_ci OpMemoryModel Logical GLSL450 1207fd4e5da5Sopenharmony_ci OpEntryPoint Fragment %4 "main" 1208fd4e5da5Sopenharmony_ci OpExecutionMode %4 OriginUpperLeft 1209fd4e5da5Sopenharmony_ci OpSource ESSL 310 1210fd4e5da5Sopenharmony_ci %20 = OpTypeInt 32 0 1211fd4e5da5Sopenharmony_ci %21 = OpConstant %20 1 1212fd4e5da5Sopenharmony_ci %2 = OpTypeVoid 1213fd4e5da5Sopenharmony_ci %3 = OpTypeFunction %2 1214fd4e5da5Sopenharmony_ci %201 = OpTypeFunction %2 %20 1215fd4e5da5Sopenharmony_ci %4 = OpFunction %2 None %3 1216fd4e5da5Sopenharmony_ci %5 = OpLabel 1217fd4e5da5Sopenharmony_ci %22 = OpCopyObject %20 %21 1218fd4e5da5Sopenharmony_ci OpBranch %54 1219fd4e5da5Sopenharmony_ci %54 = OpLabel 1220fd4e5da5Sopenharmony_ci %204 = OpFunctionCall %2 %202 %22 1221fd4e5da5Sopenharmony_ci OpReturn 1222fd4e5da5Sopenharmony_ci OpFunctionEnd 1223fd4e5da5Sopenharmony_ci %202 = OpFunction %2 None %201 1224fd4e5da5Sopenharmony_ci %206 = OpFunctionParameter %20 1225fd4e5da5Sopenharmony_ci %203 = OpLabel 1226fd4e5da5Sopenharmony_ci OpBranch %57 1227fd4e5da5Sopenharmony_ci %57 = OpLabel 1228fd4e5da5Sopenharmony_ci %23 = OpCopyObject %20 %206 1229fd4e5da5Sopenharmony_ci OpBranch %58 1230fd4e5da5Sopenharmony_ci %58 = OpLabel 1231fd4e5da5Sopenharmony_ci OpReturn 1232fd4e5da5Sopenharmony_ci OpFunctionEnd 1233fd4e5da5Sopenharmony_ci )"; 1234fd4e5da5Sopenharmony_ci ASSERT_TRUE(IsEqual(env, after_transformation, context.get())); 1235fd4e5da5Sopenharmony_ci} 1236fd4e5da5Sopenharmony_ci 1237fd4e5da5Sopenharmony_ciTEST(TransformationOutlineFunctionTest, OutlineRegionEndingWithReturnValue) { 1238fd4e5da5Sopenharmony_ci std::string shader = R"( 1239fd4e5da5Sopenharmony_ci OpCapability Shader 1240fd4e5da5Sopenharmony_ci %1 = OpExtInstImport "GLSL.std.450" 1241fd4e5da5Sopenharmony_ci OpMemoryModel Logical GLSL450 1242fd4e5da5Sopenharmony_ci OpEntryPoint Fragment %4 "main" 1243fd4e5da5Sopenharmony_ci OpExecutionMode %4 OriginUpperLeft 1244fd4e5da5Sopenharmony_ci OpSource ESSL 310 1245fd4e5da5Sopenharmony_ci %20 = OpTypeInt 32 0 1246fd4e5da5Sopenharmony_ci %21 = OpConstant %20 1 1247fd4e5da5Sopenharmony_ci %2 = OpTypeVoid 1248fd4e5da5Sopenharmony_ci %3 = OpTypeFunction %2 1249fd4e5da5Sopenharmony_ci %30 = OpTypeFunction %20 1250fd4e5da5Sopenharmony_ci %4 = OpFunction %2 None %3 1251fd4e5da5Sopenharmony_ci %5 = OpLabel 1252fd4e5da5Sopenharmony_ci %6 = OpFunctionCall %20 %100 1253fd4e5da5Sopenharmony_ci OpReturn 1254fd4e5da5Sopenharmony_ci OpFunctionEnd 1255fd4e5da5Sopenharmony_ci %100 = OpFunction %20 None %30 1256fd4e5da5Sopenharmony_ci %8 = OpLabel 1257fd4e5da5Sopenharmony_ci %31 = OpCopyObject %20 %21 1258fd4e5da5Sopenharmony_ci OpBranch %9 1259fd4e5da5Sopenharmony_ci %9 = OpLabel 1260fd4e5da5Sopenharmony_ci %32 = OpCopyObject %20 %31 1261fd4e5da5Sopenharmony_ci OpBranch %10 1262fd4e5da5Sopenharmony_ci %10 = OpLabel 1263fd4e5da5Sopenharmony_ci OpReturnValue %32 1264fd4e5da5Sopenharmony_ci OpFunctionEnd 1265fd4e5da5Sopenharmony_ci )"; 1266fd4e5da5Sopenharmony_ci 1267fd4e5da5Sopenharmony_ci const auto env = SPV_ENV_UNIVERSAL_1_5; 1268fd4e5da5Sopenharmony_ci const auto consumer = nullptr; 1269fd4e5da5Sopenharmony_ci const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption); 1270fd4e5da5Sopenharmony_ci spvtools::ValidatorOptions validator_options; 1271fd4e5da5Sopenharmony_ci ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options, 1272fd4e5da5Sopenharmony_ci kConsoleMessageConsumer)); 1273fd4e5da5Sopenharmony_ci TransformationContext transformation_context( 1274fd4e5da5Sopenharmony_ci MakeUnique<FactManager>(context.get()), validator_options); 1275fd4e5da5Sopenharmony_ci TransformationOutlineFunction transformation( 1276fd4e5da5Sopenharmony_ci /*entry_block*/ 9, 1277fd4e5da5Sopenharmony_ci /*exit_block*/ 10, 1278fd4e5da5Sopenharmony_ci /*new_function_struct_return_type_id*/ 200, 1279fd4e5da5Sopenharmony_ci /*new_function_type_id*/ 201, 1280fd4e5da5Sopenharmony_ci /*new_function_id*/ 202, 1281fd4e5da5Sopenharmony_ci /*new_function_region_entry_block*/ 203, 1282fd4e5da5Sopenharmony_ci /*new_caller_result_id*/ 204, 1283fd4e5da5Sopenharmony_ci /*new_callee_result_id*/ 205, 1284fd4e5da5Sopenharmony_ci /*input_id_to_fresh_id*/ {{31, 206}}, 1285fd4e5da5Sopenharmony_ci /*output_id_to_fresh_id*/ {{32, 207}}); 1286fd4e5da5Sopenharmony_ci 1287fd4e5da5Sopenharmony_ci ASSERT_TRUE( 1288fd4e5da5Sopenharmony_ci transformation.IsApplicable(context.get(), transformation_context)); 1289fd4e5da5Sopenharmony_ci ApplyAndCheckFreshIds(transformation, context.get(), &transformation_context); 1290fd4e5da5Sopenharmony_ci ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options, 1291fd4e5da5Sopenharmony_ci kConsoleMessageConsumer)); 1292fd4e5da5Sopenharmony_ci 1293fd4e5da5Sopenharmony_ci std::string after_transformation = R"( 1294fd4e5da5Sopenharmony_ci OpCapability Shader 1295fd4e5da5Sopenharmony_ci %1 = OpExtInstImport "GLSL.std.450" 1296fd4e5da5Sopenharmony_ci OpMemoryModel Logical GLSL450 1297fd4e5da5Sopenharmony_ci OpEntryPoint Fragment %4 "main" 1298fd4e5da5Sopenharmony_ci OpExecutionMode %4 OriginUpperLeft 1299fd4e5da5Sopenharmony_ci OpSource ESSL 310 1300fd4e5da5Sopenharmony_ci %20 = OpTypeInt 32 0 1301fd4e5da5Sopenharmony_ci %21 = OpConstant %20 1 1302fd4e5da5Sopenharmony_ci %2 = OpTypeVoid 1303fd4e5da5Sopenharmony_ci %3 = OpTypeFunction %2 1304fd4e5da5Sopenharmony_ci %30 = OpTypeFunction %20 1305fd4e5da5Sopenharmony_ci %200 = OpTypeStruct %20 1306fd4e5da5Sopenharmony_ci %201 = OpTypeFunction %200 %20 1307fd4e5da5Sopenharmony_ci %4 = OpFunction %2 None %3 1308fd4e5da5Sopenharmony_ci %5 = OpLabel 1309fd4e5da5Sopenharmony_ci %6 = OpFunctionCall %20 %100 1310fd4e5da5Sopenharmony_ci OpReturn 1311fd4e5da5Sopenharmony_ci OpFunctionEnd 1312fd4e5da5Sopenharmony_ci %100 = OpFunction %20 None %30 1313fd4e5da5Sopenharmony_ci %8 = OpLabel 1314fd4e5da5Sopenharmony_ci %31 = OpCopyObject %20 %21 1315fd4e5da5Sopenharmony_ci OpBranch %9 1316fd4e5da5Sopenharmony_ci %9 = OpLabel 1317fd4e5da5Sopenharmony_ci %204 = OpFunctionCall %200 %202 %31 1318fd4e5da5Sopenharmony_ci %32 = OpCompositeExtract %20 %204 0 1319fd4e5da5Sopenharmony_ci OpReturnValue %32 1320fd4e5da5Sopenharmony_ci OpFunctionEnd 1321fd4e5da5Sopenharmony_ci %202 = OpFunction %200 None %201 1322fd4e5da5Sopenharmony_ci %206 = OpFunctionParameter %20 1323fd4e5da5Sopenharmony_ci %203 = OpLabel 1324fd4e5da5Sopenharmony_ci %207 = OpCopyObject %20 %206 1325fd4e5da5Sopenharmony_ci OpBranch %10 1326fd4e5da5Sopenharmony_ci %10 = OpLabel 1327fd4e5da5Sopenharmony_ci %205 = OpCompositeConstruct %200 %207 1328fd4e5da5Sopenharmony_ci OpReturnValue %205 1329fd4e5da5Sopenharmony_ci OpFunctionEnd 1330fd4e5da5Sopenharmony_ci )"; 1331fd4e5da5Sopenharmony_ci ASSERT_TRUE(IsEqual(env, after_transformation, context.get())); 1332fd4e5da5Sopenharmony_ci} 1333fd4e5da5Sopenharmony_ci 1334fd4e5da5Sopenharmony_ciTEST(TransformationOutlineFunctionTest, 1335fd4e5da5Sopenharmony_ci OutlineRegionEndingWithConditionalBranch) { 1336fd4e5da5Sopenharmony_ci std::string shader = R"( 1337fd4e5da5Sopenharmony_ci OpCapability Shader 1338fd4e5da5Sopenharmony_ci %1 = OpExtInstImport "GLSL.std.450" 1339fd4e5da5Sopenharmony_ci OpMemoryModel Logical GLSL450 1340fd4e5da5Sopenharmony_ci OpEntryPoint Fragment %4 "main" 1341fd4e5da5Sopenharmony_ci OpExecutionMode %4 OriginUpperLeft 1342fd4e5da5Sopenharmony_ci OpSource ESSL 310 1343fd4e5da5Sopenharmony_ci %20 = OpTypeBool 1344fd4e5da5Sopenharmony_ci %21 = OpConstantTrue %20 1345fd4e5da5Sopenharmony_ci %2 = OpTypeVoid 1346fd4e5da5Sopenharmony_ci %3 = OpTypeFunction %2 1347fd4e5da5Sopenharmony_ci %4 = OpFunction %2 None %3 1348fd4e5da5Sopenharmony_ci %5 = OpLabel 1349fd4e5da5Sopenharmony_ci OpBranch %54 1350fd4e5da5Sopenharmony_ci %54 = OpLabel 1351fd4e5da5Sopenharmony_ci %6 = OpCopyObject %20 %21 1352fd4e5da5Sopenharmony_ci OpSelectionMerge %8 None 1353fd4e5da5Sopenharmony_ci OpBranchConditional %6 %7 %8 1354fd4e5da5Sopenharmony_ci %7 = OpLabel 1355fd4e5da5Sopenharmony_ci OpBranch %8 1356fd4e5da5Sopenharmony_ci %8 = OpLabel 1357fd4e5da5Sopenharmony_ci OpReturn 1358fd4e5da5Sopenharmony_ci OpFunctionEnd 1359fd4e5da5Sopenharmony_ci )"; 1360fd4e5da5Sopenharmony_ci 1361fd4e5da5Sopenharmony_ci const auto env = SPV_ENV_UNIVERSAL_1_5; 1362fd4e5da5Sopenharmony_ci const auto consumer = nullptr; 1363fd4e5da5Sopenharmony_ci const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption); 1364fd4e5da5Sopenharmony_ci spvtools::ValidatorOptions validator_options; 1365fd4e5da5Sopenharmony_ci ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options, 1366fd4e5da5Sopenharmony_ci kConsoleMessageConsumer)); 1367fd4e5da5Sopenharmony_ci TransformationContext transformation_context( 1368fd4e5da5Sopenharmony_ci MakeUnique<FactManager>(context.get()), validator_options); 1369fd4e5da5Sopenharmony_ci TransformationOutlineFunction transformation( 1370fd4e5da5Sopenharmony_ci /*entry_block*/ 54, 1371fd4e5da5Sopenharmony_ci /*exit_block*/ 54, 1372fd4e5da5Sopenharmony_ci /*new_function_struct_return_type_id*/ 200, 1373fd4e5da5Sopenharmony_ci /*new_function_type_id*/ 201, 1374fd4e5da5Sopenharmony_ci /*new_function_id*/ 202, 1375fd4e5da5Sopenharmony_ci /*new_function_region_entry_block*/ 203, 1376fd4e5da5Sopenharmony_ci /*new_caller_result_id*/ 204, 1377fd4e5da5Sopenharmony_ci /*new_callee_result_id*/ 205, 1378fd4e5da5Sopenharmony_ci /*input_id_to_fresh_id*/ {{}}, 1379fd4e5da5Sopenharmony_ci /*output_id_to_fresh_id*/ {{6, 206}}); 1380fd4e5da5Sopenharmony_ci 1381fd4e5da5Sopenharmony_ci ASSERT_TRUE( 1382fd4e5da5Sopenharmony_ci transformation.IsApplicable(context.get(), transformation_context)); 1383fd4e5da5Sopenharmony_ci ApplyAndCheckFreshIds(transformation, context.get(), &transformation_context); 1384fd4e5da5Sopenharmony_ci ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options, 1385fd4e5da5Sopenharmony_ci kConsoleMessageConsumer)); 1386fd4e5da5Sopenharmony_ci 1387fd4e5da5Sopenharmony_ci std::string after_transformation = R"( 1388fd4e5da5Sopenharmony_ci OpCapability Shader 1389fd4e5da5Sopenharmony_ci %1 = OpExtInstImport "GLSL.std.450" 1390fd4e5da5Sopenharmony_ci OpMemoryModel Logical GLSL450 1391fd4e5da5Sopenharmony_ci OpEntryPoint Fragment %4 "main" 1392fd4e5da5Sopenharmony_ci OpExecutionMode %4 OriginUpperLeft 1393fd4e5da5Sopenharmony_ci OpSource ESSL 310 1394fd4e5da5Sopenharmony_ci %20 = OpTypeBool 1395fd4e5da5Sopenharmony_ci %21 = OpConstantTrue %20 1396fd4e5da5Sopenharmony_ci %2 = OpTypeVoid 1397fd4e5da5Sopenharmony_ci %3 = OpTypeFunction %2 1398fd4e5da5Sopenharmony_ci %200 = OpTypeStruct %20 1399fd4e5da5Sopenharmony_ci %201 = OpTypeFunction %200 1400fd4e5da5Sopenharmony_ci %4 = OpFunction %2 None %3 1401fd4e5da5Sopenharmony_ci %5 = OpLabel 1402fd4e5da5Sopenharmony_ci OpBranch %54 1403fd4e5da5Sopenharmony_ci %54 = OpLabel 1404fd4e5da5Sopenharmony_ci %204 = OpFunctionCall %200 %202 1405fd4e5da5Sopenharmony_ci %6 = OpCompositeExtract %20 %204 0 1406fd4e5da5Sopenharmony_ci OpSelectionMerge %8 None 1407fd4e5da5Sopenharmony_ci OpBranchConditional %6 %7 %8 1408fd4e5da5Sopenharmony_ci %7 = OpLabel 1409fd4e5da5Sopenharmony_ci OpBranch %8 1410fd4e5da5Sopenharmony_ci %8 = OpLabel 1411fd4e5da5Sopenharmony_ci OpReturn 1412fd4e5da5Sopenharmony_ci OpFunctionEnd 1413fd4e5da5Sopenharmony_ci %202 = OpFunction %200 None %201 1414fd4e5da5Sopenharmony_ci %203 = OpLabel 1415fd4e5da5Sopenharmony_ci %206 = OpCopyObject %20 %21 1416fd4e5da5Sopenharmony_ci %205 = OpCompositeConstruct %200 %206 1417fd4e5da5Sopenharmony_ci OpReturnValue %205 1418fd4e5da5Sopenharmony_ci OpFunctionEnd 1419fd4e5da5Sopenharmony_ci )"; 1420fd4e5da5Sopenharmony_ci ASSERT_TRUE(IsEqual(env, after_transformation, context.get())); 1421fd4e5da5Sopenharmony_ci} 1422fd4e5da5Sopenharmony_ci 1423fd4e5da5Sopenharmony_ciTEST(TransformationOutlineFunctionTest, 1424fd4e5da5Sopenharmony_ci OutlineRegionEndingWithConditionalBranch2) { 1425fd4e5da5Sopenharmony_ci std::string shader = R"( 1426fd4e5da5Sopenharmony_ci OpCapability Shader 1427fd4e5da5Sopenharmony_ci %1 = OpExtInstImport "GLSL.std.450" 1428fd4e5da5Sopenharmony_ci OpMemoryModel Logical GLSL450 1429fd4e5da5Sopenharmony_ci OpEntryPoint Fragment %4 "main" 1430fd4e5da5Sopenharmony_ci OpExecutionMode %4 OriginUpperLeft 1431fd4e5da5Sopenharmony_ci OpSource ESSL 310 1432fd4e5da5Sopenharmony_ci %20 = OpTypeBool 1433fd4e5da5Sopenharmony_ci %21 = OpConstantTrue %20 1434fd4e5da5Sopenharmony_ci %2 = OpTypeVoid 1435fd4e5da5Sopenharmony_ci %3 = OpTypeFunction %2 1436fd4e5da5Sopenharmony_ci %4 = OpFunction %2 None %3 1437fd4e5da5Sopenharmony_ci %5 = OpLabel 1438fd4e5da5Sopenharmony_ci %6 = OpCopyObject %20 %21 1439fd4e5da5Sopenharmony_ci OpBranch %54 1440fd4e5da5Sopenharmony_ci %54 = OpLabel 1441fd4e5da5Sopenharmony_ci OpSelectionMerge %8 None 1442fd4e5da5Sopenharmony_ci OpBranchConditional %6 %7 %8 1443fd4e5da5Sopenharmony_ci %7 = OpLabel 1444fd4e5da5Sopenharmony_ci OpBranch %8 1445fd4e5da5Sopenharmony_ci %8 = OpLabel 1446fd4e5da5Sopenharmony_ci OpReturn 1447fd4e5da5Sopenharmony_ci OpFunctionEnd 1448fd4e5da5Sopenharmony_ci )"; 1449fd4e5da5Sopenharmony_ci 1450fd4e5da5Sopenharmony_ci const auto env = SPV_ENV_UNIVERSAL_1_5; 1451fd4e5da5Sopenharmony_ci const auto consumer = nullptr; 1452fd4e5da5Sopenharmony_ci const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption); 1453fd4e5da5Sopenharmony_ci spvtools::ValidatorOptions validator_options; 1454fd4e5da5Sopenharmony_ci ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options, 1455fd4e5da5Sopenharmony_ci kConsoleMessageConsumer)); 1456fd4e5da5Sopenharmony_ci TransformationContext transformation_context( 1457fd4e5da5Sopenharmony_ci MakeUnique<FactManager>(context.get()), validator_options); 1458fd4e5da5Sopenharmony_ci TransformationOutlineFunction transformation( 1459fd4e5da5Sopenharmony_ci /*entry_block*/ 54, 1460fd4e5da5Sopenharmony_ci /*exit_block*/ 54, 1461fd4e5da5Sopenharmony_ci /*new_function_struct_return_type_id*/ 200, 1462fd4e5da5Sopenharmony_ci /*new_function_type_id*/ 201, 1463fd4e5da5Sopenharmony_ci /*new_function_id*/ 202, 1464fd4e5da5Sopenharmony_ci /*new_function_region_entry_block*/ 203, 1465fd4e5da5Sopenharmony_ci /*new_caller_result_id*/ 204, 1466fd4e5da5Sopenharmony_ci /*new_callee_result_id*/ 205, 1467fd4e5da5Sopenharmony_ci /*input_id_to_fresh_id*/ {}, 1468fd4e5da5Sopenharmony_ci /*output_id_to_fresh_id*/ {}); 1469fd4e5da5Sopenharmony_ci 1470fd4e5da5Sopenharmony_ci ASSERT_TRUE( 1471fd4e5da5Sopenharmony_ci transformation.IsApplicable(context.get(), transformation_context)); 1472fd4e5da5Sopenharmony_ci ApplyAndCheckFreshIds(transformation, context.get(), &transformation_context); 1473fd4e5da5Sopenharmony_ci ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options, 1474fd4e5da5Sopenharmony_ci kConsoleMessageConsumer)); 1475fd4e5da5Sopenharmony_ci 1476fd4e5da5Sopenharmony_ci std::string after_transformation = R"( 1477fd4e5da5Sopenharmony_ci OpCapability Shader 1478fd4e5da5Sopenharmony_ci %1 = OpExtInstImport "GLSL.std.450" 1479fd4e5da5Sopenharmony_ci OpMemoryModel Logical GLSL450 1480fd4e5da5Sopenharmony_ci OpEntryPoint Fragment %4 "main" 1481fd4e5da5Sopenharmony_ci OpExecutionMode %4 OriginUpperLeft 1482fd4e5da5Sopenharmony_ci OpSource ESSL 310 1483fd4e5da5Sopenharmony_ci %20 = OpTypeBool 1484fd4e5da5Sopenharmony_ci %21 = OpConstantTrue %20 1485fd4e5da5Sopenharmony_ci %2 = OpTypeVoid 1486fd4e5da5Sopenharmony_ci %3 = OpTypeFunction %2 1487fd4e5da5Sopenharmony_ci %4 = OpFunction %2 None %3 1488fd4e5da5Sopenharmony_ci %5 = OpLabel 1489fd4e5da5Sopenharmony_ci %6 = OpCopyObject %20 %21 1490fd4e5da5Sopenharmony_ci OpBranch %54 1491fd4e5da5Sopenharmony_ci %54 = OpLabel 1492fd4e5da5Sopenharmony_ci %204 = OpFunctionCall %2 %202 1493fd4e5da5Sopenharmony_ci OpSelectionMerge %8 None 1494fd4e5da5Sopenharmony_ci OpBranchConditional %6 %7 %8 1495fd4e5da5Sopenharmony_ci %7 = OpLabel 1496fd4e5da5Sopenharmony_ci OpBranch %8 1497fd4e5da5Sopenharmony_ci %8 = OpLabel 1498fd4e5da5Sopenharmony_ci OpReturn 1499fd4e5da5Sopenharmony_ci OpFunctionEnd 1500fd4e5da5Sopenharmony_ci %202 = OpFunction %2 None %3 1501fd4e5da5Sopenharmony_ci %203 = OpLabel 1502fd4e5da5Sopenharmony_ci OpReturn 1503fd4e5da5Sopenharmony_ci OpFunctionEnd 1504fd4e5da5Sopenharmony_ci )"; 1505fd4e5da5Sopenharmony_ci ASSERT_TRUE(IsEqual(env, after_transformation, context.get())); 1506fd4e5da5Sopenharmony_ci} 1507fd4e5da5Sopenharmony_ci 1508fd4e5da5Sopenharmony_ciTEST(TransformationOutlineFunctionTest, DoNotOutlineRegionThatStartsWithOpPhi) { 1509fd4e5da5Sopenharmony_ci std::string shader = R"( 1510fd4e5da5Sopenharmony_ci OpCapability Shader 1511fd4e5da5Sopenharmony_ci %1 = OpExtInstImport "GLSL.std.450" 1512fd4e5da5Sopenharmony_ci OpMemoryModel Logical GLSL450 1513fd4e5da5Sopenharmony_ci OpEntryPoint Fragment %4 "main" 1514fd4e5da5Sopenharmony_ci OpExecutionMode %4 OriginUpperLeft 1515fd4e5da5Sopenharmony_ci OpSource ESSL 310 1516fd4e5da5Sopenharmony_ci OpName %4 "main" 1517fd4e5da5Sopenharmony_ci %2 = OpTypeVoid 1518fd4e5da5Sopenharmony_ci %3 = OpTypeFunction %2 1519fd4e5da5Sopenharmony_ci %6 = OpTypeBool 1520fd4e5da5Sopenharmony_ci %7 = OpConstantTrue %6 1521fd4e5da5Sopenharmony_ci %4 = OpFunction %2 None %3 1522fd4e5da5Sopenharmony_ci %5 = OpLabel 1523fd4e5da5Sopenharmony_ci OpBranch %21 1524fd4e5da5Sopenharmony_ci %21 = OpLabel 1525fd4e5da5Sopenharmony_ci %22 = OpPhi %6 %7 %5 1526fd4e5da5Sopenharmony_ci %23 = OpCopyObject %6 %22 1527fd4e5da5Sopenharmony_ci OpBranch %24 1528fd4e5da5Sopenharmony_ci %24 = OpLabel 1529fd4e5da5Sopenharmony_ci %25 = OpCopyObject %6 %23 1530fd4e5da5Sopenharmony_ci %26 = OpCopyObject %6 %22 1531fd4e5da5Sopenharmony_ci OpReturn 1532fd4e5da5Sopenharmony_ci OpFunctionEnd 1533fd4e5da5Sopenharmony_ci )"; 1534fd4e5da5Sopenharmony_ci 1535fd4e5da5Sopenharmony_ci const auto env = SPV_ENV_UNIVERSAL_1_5; 1536fd4e5da5Sopenharmony_ci const auto consumer = nullptr; 1537fd4e5da5Sopenharmony_ci const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption); 1538fd4e5da5Sopenharmony_ci spvtools::ValidatorOptions validator_options; 1539fd4e5da5Sopenharmony_ci ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options, 1540fd4e5da5Sopenharmony_ci kConsoleMessageConsumer)); 1541fd4e5da5Sopenharmony_ci TransformationContext transformation_context( 1542fd4e5da5Sopenharmony_ci MakeUnique<FactManager>(context.get()), validator_options); 1543fd4e5da5Sopenharmony_ci TransformationOutlineFunction transformation( 1544fd4e5da5Sopenharmony_ci /*entry_block*/ 21, 1545fd4e5da5Sopenharmony_ci /*exit_block*/ 21, 1546fd4e5da5Sopenharmony_ci /*new_function_struct_return_type_id*/ 200, 1547fd4e5da5Sopenharmony_ci /*new_function_type_id*/ 201, 1548fd4e5da5Sopenharmony_ci /*new_function_id*/ 202, 1549fd4e5da5Sopenharmony_ci /*new_function_region_entry_block*/ 204, 1550fd4e5da5Sopenharmony_ci /*new_caller_result_id*/ 205, 1551fd4e5da5Sopenharmony_ci /*new_callee_result_id*/ 206, 1552fd4e5da5Sopenharmony_ci /*input_id_to_fresh_id*/ {{22, 207}}, 1553fd4e5da5Sopenharmony_ci /*output_id_to_fresh_id*/ {{23, 208}}); 1554fd4e5da5Sopenharmony_ci 1555fd4e5da5Sopenharmony_ci ASSERT_FALSE( 1556fd4e5da5Sopenharmony_ci transformation.IsApplicable(context.get(), transformation_context)); 1557fd4e5da5Sopenharmony_ci} 1558fd4e5da5Sopenharmony_ci 1559fd4e5da5Sopenharmony_ciTEST(TransformationOutlineFunctionTest, 1560fd4e5da5Sopenharmony_ci DoNotOutlineRegionThatStartsWithLoopHeader) { 1561fd4e5da5Sopenharmony_ci std::string shader = R"( 1562fd4e5da5Sopenharmony_ci OpCapability Shader 1563fd4e5da5Sopenharmony_ci %1 = OpExtInstImport "GLSL.std.450" 1564fd4e5da5Sopenharmony_ci OpMemoryModel Logical GLSL450 1565fd4e5da5Sopenharmony_ci OpEntryPoint Fragment %4 "main" 1566fd4e5da5Sopenharmony_ci OpExecutionMode %4 OriginUpperLeft 1567fd4e5da5Sopenharmony_ci OpSource ESSL 310 1568fd4e5da5Sopenharmony_ci OpName %4 "main" 1569fd4e5da5Sopenharmony_ci %2 = OpTypeVoid 1570fd4e5da5Sopenharmony_ci %3 = OpTypeFunction %2 1571fd4e5da5Sopenharmony_ci %6 = OpTypeBool 1572fd4e5da5Sopenharmony_ci %7 = OpConstantTrue %6 1573fd4e5da5Sopenharmony_ci %4 = OpFunction %2 None %3 1574fd4e5da5Sopenharmony_ci %5 = OpLabel 1575fd4e5da5Sopenharmony_ci OpBranch %21 1576fd4e5da5Sopenharmony_ci %21 = OpLabel 1577fd4e5da5Sopenharmony_ci OpLoopMerge %22 %23 None 1578fd4e5da5Sopenharmony_ci OpBranch %24 1579fd4e5da5Sopenharmony_ci %24 = OpLabel 1580fd4e5da5Sopenharmony_ci OpBranchConditional %7 %22 %23 1581fd4e5da5Sopenharmony_ci %23 = OpLabel 1582fd4e5da5Sopenharmony_ci OpBranch %21 1583fd4e5da5Sopenharmony_ci %22 = OpLabel 1584fd4e5da5Sopenharmony_ci OpBranch %25 1585fd4e5da5Sopenharmony_ci %25 = OpLabel 1586fd4e5da5Sopenharmony_ci OpReturn 1587fd4e5da5Sopenharmony_ci OpFunctionEnd 1588fd4e5da5Sopenharmony_ci )"; 1589fd4e5da5Sopenharmony_ci 1590fd4e5da5Sopenharmony_ci const auto env = SPV_ENV_UNIVERSAL_1_5; 1591fd4e5da5Sopenharmony_ci const auto consumer = nullptr; 1592fd4e5da5Sopenharmony_ci const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption); 1593fd4e5da5Sopenharmony_ci spvtools::ValidatorOptions validator_options; 1594fd4e5da5Sopenharmony_ci ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options, 1595fd4e5da5Sopenharmony_ci kConsoleMessageConsumer)); 1596fd4e5da5Sopenharmony_ci TransformationContext transformation_context( 1597fd4e5da5Sopenharmony_ci MakeUnique<FactManager>(context.get()), validator_options); 1598fd4e5da5Sopenharmony_ci TransformationOutlineFunction transformation( 1599fd4e5da5Sopenharmony_ci /*entry_block*/ 21, 1600fd4e5da5Sopenharmony_ci /*exit_block*/ 24, 1601fd4e5da5Sopenharmony_ci /*new_function_struct_return_type_id*/ 200, 1602fd4e5da5Sopenharmony_ci /*new_function_type_id*/ 201, 1603fd4e5da5Sopenharmony_ci /*new_function_id*/ 202, 1604fd4e5da5Sopenharmony_ci /*new_function_region_entry_block*/ 204, 1605fd4e5da5Sopenharmony_ci /*new_caller_result_id*/ 205, 1606fd4e5da5Sopenharmony_ci /*new_callee_result_id*/ 206, 1607fd4e5da5Sopenharmony_ci /*input_id_to_fresh_id*/ {}, 1608fd4e5da5Sopenharmony_ci /*output_id_to_fresh_id*/ {}); 1609fd4e5da5Sopenharmony_ci 1610fd4e5da5Sopenharmony_ci ASSERT_FALSE( 1611fd4e5da5Sopenharmony_ci transformation.IsApplicable(context.get(), transformation_context)); 1612fd4e5da5Sopenharmony_ci} 1613fd4e5da5Sopenharmony_ci 1614fd4e5da5Sopenharmony_ciTEST(TransformationOutlineFunctionTest, 1615fd4e5da5Sopenharmony_ci DoNotOutlineRegionThatEndsWithLoopMerge) { 1616fd4e5da5Sopenharmony_ci std::string shader = R"( 1617fd4e5da5Sopenharmony_ci OpCapability Shader 1618fd4e5da5Sopenharmony_ci %1 = OpExtInstImport "GLSL.std.450" 1619fd4e5da5Sopenharmony_ci OpMemoryModel Logical GLSL450 1620fd4e5da5Sopenharmony_ci OpEntryPoint Fragment %4 "main" 1621fd4e5da5Sopenharmony_ci OpExecutionMode %4 OriginUpperLeft 1622fd4e5da5Sopenharmony_ci OpSource ESSL 310 1623fd4e5da5Sopenharmony_ci OpName %4 "main" 1624fd4e5da5Sopenharmony_ci %2 = OpTypeVoid 1625fd4e5da5Sopenharmony_ci %3 = OpTypeFunction %2 1626fd4e5da5Sopenharmony_ci %6 = OpTypeBool 1627fd4e5da5Sopenharmony_ci %7 = OpConstantTrue %6 1628fd4e5da5Sopenharmony_ci %4 = OpFunction %2 None %3 1629fd4e5da5Sopenharmony_ci %5 = OpLabel 1630fd4e5da5Sopenharmony_ci OpBranch %21 1631fd4e5da5Sopenharmony_ci %21 = OpLabel 1632fd4e5da5Sopenharmony_ci OpLoopMerge %22 %23 None 1633fd4e5da5Sopenharmony_ci OpBranch %24 1634fd4e5da5Sopenharmony_ci %24 = OpLabel 1635fd4e5da5Sopenharmony_ci OpBranchConditional %7 %22 %23 1636fd4e5da5Sopenharmony_ci %23 = OpLabel 1637fd4e5da5Sopenharmony_ci OpBranch %21 1638fd4e5da5Sopenharmony_ci %22 = OpLabel 1639fd4e5da5Sopenharmony_ci OpBranch %25 1640fd4e5da5Sopenharmony_ci %25 = OpLabel 1641fd4e5da5Sopenharmony_ci OpReturn 1642fd4e5da5Sopenharmony_ci OpFunctionEnd 1643fd4e5da5Sopenharmony_ci )"; 1644fd4e5da5Sopenharmony_ci 1645fd4e5da5Sopenharmony_ci const auto env = SPV_ENV_UNIVERSAL_1_5; 1646fd4e5da5Sopenharmony_ci const auto consumer = nullptr; 1647fd4e5da5Sopenharmony_ci const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption); 1648fd4e5da5Sopenharmony_ci spvtools::ValidatorOptions validator_options; 1649fd4e5da5Sopenharmony_ci ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options, 1650fd4e5da5Sopenharmony_ci kConsoleMessageConsumer)); 1651fd4e5da5Sopenharmony_ci TransformationContext transformation_context( 1652fd4e5da5Sopenharmony_ci MakeUnique<FactManager>(context.get()), validator_options); 1653fd4e5da5Sopenharmony_ci TransformationOutlineFunction transformation( 1654fd4e5da5Sopenharmony_ci /*entry_block*/ 5, 1655fd4e5da5Sopenharmony_ci /*exit_block*/ 22, 1656fd4e5da5Sopenharmony_ci /*new_function_struct_return_type_id*/ 200, 1657fd4e5da5Sopenharmony_ci /*new_function_type_id*/ 201, 1658fd4e5da5Sopenharmony_ci /*new_function_id*/ 202, 1659fd4e5da5Sopenharmony_ci /*new_function_region_entry_block*/ 204, 1660fd4e5da5Sopenharmony_ci /*new_caller_result_id*/ 205, 1661fd4e5da5Sopenharmony_ci /*new_callee_result_id*/ 206, 1662fd4e5da5Sopenharmony_ci /*input_id_to_fresh_id*/ {}, 1663fd4e5da5Sopenharmony_ci /*output_id_to_fresh_id*/ {}); 1664fd4e5da5Sopenharmony_ci 1665fd4e5da5Sopenharmony_ci ASSERT_FALSE( 1666fd4e5da5Sopenharmony_ci transformation.IsApplicable(context.get(), transformation_context)); 1667fd4e5da5Sopenharmony_ci} 1668fd4e5da5Sopenharmony_ci 1669fd4e5da5Sopenharmony_ciTEST(TransformationOutlineFunctionTest, DoNotOutlineRegionThatUsesAccessChain) { 1670fd4e5da5Sopenharmony_ci // An access chain result is a pointer, but it cannot be passed as a function 1671fd4e5da5Sopenharmony_ci // parameter, as it is not a memory object. 1672fd4e5da5Sopenharmony_ci std::string shader = R"( 1673fd4e5da5Sopenharmony_ci OpCapability Shader 1674fd4e5da5Sopenharmony_ci %1 = OpExtInstImport "GLSL.std.450" 1675fd4e5da5Sopenharmony_ci OpMemoryModel Logical GLSL450 1676fd4e5da5Sopenharmony_ci OpEntryPoint Fragment %4 "main" 1677fd4e5da5Sopenharmony_ci OpExecutionMode %4 OriginUpperLeft 1678fd4e5da5Sopenharmony_ci OpSource ESSL 310 1679fd4e5da5Sopenharmony_ci OpName %4 "main" 1680fd4e5da5Sopenharmony_ci %2 = OpTypeVoid 1681fd4e5da5Sopenharmony_ci %3 = OpTypeFunction %2 1682fd4e5da5Sopenharmony_ci %6 = OpTypeFloat 32 1683fd4e5da5Sopenharmony_ci %7 = OpTypeVector %6 4 1684fd4e5da5Sopenharmony_ci %8 = OpTypePointer Function %7 1685fd4e5da5Sopenharmony_ci %9 = OpTypePointer Function %6 1686fd4e5da5Sopenharmony_ci %18 = OpTypeInt 32 0 1687fd4e5da5Sopenharmony_ci %19 = OpConstant %18 0 1688fd4e5da5Sopenharmony_ci %4 = OpFunction %2 None %3 1689fd4e5da5Sopenharmony_ci %5 = OpLabel 1690fd4e5da5Sopenharmony_ci %10 = OpVariable %8 Function 1691fd4e5da5Sopenharmony_ci OpBranch %11 1692fd4e5da5Sopenharmony_ci %11 = OpLabel 1693fd4e5da5Sopenharmony_ci %12 = OpAccessChain %9 %10 %19 1694fd4e5da5Sopenharmony_ci OpBranch %13 1695fd4e5da5Sopenharmony_ci %13 = OpLabel 1696fd4e5da5Sopenharmony_ci %14 = OpLoad %6 %12 1697fd4e5da5Sopenharmony_ci OpBranch %15 1698fd4e5da5Sopenharmony_ci %15 = OpLabel 1699fd4e5da5Sopenharmony_ci OpReturn 1700fd4e5da5Sopenharmony_ci OpFunctionEnd 1701fd4e5da5Sopenharmony_ci )"; 1702fd4e5da5Sopenharmony_ci 1703fd4e5da5Sopenharmony_ci const auto env = SPV_ENV_UNIVERSAL_1_5; 1704fd4e5da5Sopenharmony_ci const auto consumer = nullptr; 1705fd4e5da5Sopenharmony_ci const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption); 1706fd4e5da5Sopenharmony_ci spvtools::ValidatorOptions validator_options; 1707fd4e5da5Sopenharmony_ci ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options, 1708fd4e5da5Sopenharmony_ci kConsoleMessageConsumer)); 1709fd4e5da5Sopenharmony_ci TransformationContext transformation_context( 1710fd4e5da5Sopenharmony_ci MakeUnique<FactManager>(context.get()), validator_options); 1711fd4e5da5Sopenharmony_ci TransformationOutlineFunction transformation( 1712fd4e5da5Sopenharmony_ci /*entry_block*/ 13, 1713fd4e5da5Sopenharmony_ci /*exit_block*/ 15, 1714fd4e5da5Sopenharmony_ci /*new_function_struct_return_type_id*/ 200, 1715fd4e5da5Sopenharmony_ci /*new_function_type_id*/ 201, 1716fd4e5da5Sopenharmony_ci /*new_function_id*/ 202, 1717fd4e5da5Sopenharmony_ci /*new_function_region_entry_block*/ 204, 1718fd4e5da5Sopenharmony_ci /*new_caller_result_id*/ 205, 1719fd4e5da5Sopenharmony_ci /*new_callee_result_id*/ 206, 1720fd4e5da5Sopenharmony_ci /*input_id_to_fresh_id*/ {{12, 207}}, 1721fd4e5da5Sopenharmony_ci /*output_id_to_fresh_id*/ {}); 1722fd4e5da5Sopenharmony_ci 1723fd4e5da5Sopenharmony_ci ASSERT_FALSE( 1724fd4e5da5Sopenharmony_ci transformation.IsApplicable(context.get(), transformation_context)); 1725fd4e5da5Sopenharmony_ci} 1726fd4e5da5Sopenharmony_ci 1727fd4e5da5Sopenharmony_ciTEST(TransformationOutlineFunctionTest, 1728fd4e5da5Sopenharmony_ci DoNotOutlineRegionThatUsesCopiedObject) { 1729fd4e5da5Sopenharmony_ci // Copying a variable leads to a pointer, but one that cannot be passed as a 1730fd4e5da5Sopenharmony_ci // function parameter, as it is not a memory object. 1731fd4e5da5Sopenharmony_ci std::string shader = R"( 1732fd4e5da5Sopenharmony_ci OpCapability Shader 1733fd4e5da5Sopenharmony_ci %1 = OpExtInstImport "GLSL.std.450" 1734fd4e5da5Sopenharmony_ci OpMemoryModel Logical GLSL450 1735fd4e5da5Sopenharmony_ci OpEntryPoint Fragment %4 "main" 1736fd4e5da5Sopenharmony_ci OpExecutionMode %4 OriginUpperLeft 1737fd4e5da5Sopenharmony_ci OpSource ESSL 310 1738fd4e5da5Sopenharmony_ci OpName %4 "main" 1739fd4e5da5Sopenharmony_ci %2 = OpTypeVoid 1740fd4e5da5Sopenharmony_ci %3 = OpTypeFunction %2 1741fd4e5da5Sopenharmony_ci %6 = OpTypeFloat 32 1742fd4e5da5Sopenharmony_ci %7 = OpTypeVector %6 4 1743fd4e5da5Sopenharmony_ci %8 = OpTypePointer Function %7 1744fd4e5da5Sopenharmony_ci %9 = OpTypePointer Function %6 1745fd4e5da5Sopenharmony_ci %18 = OpTypeInt 32 0 1746fd4e5da5Sopenharmony_ci %19 = OpConstant %18 0 1747fd4e5da5Sopenharmony_ci %4 = OpFunction %2 None %3 1748fd4e5da5Sopenharmony_ci %5 = OpLabel 1749fd4e5da5Sopenharmony_ci %10 = OpVariable %8 Function 1750fd4e5da5Sopenharmony_ci OpBranch %11 1751fd4e5da5Sopenharmony_ci %11 = OpLabel 1752fd4e5da5Sopenharmony_ci %20 = OpCopyObject %8 %10 1753fd4e5da5Sopenharmony_ci OpBranch %13 1754fd4e5da5Sopenharmony_ci %13 = OpLabel 1755fd4e5da5Sopenharmony_ci %12 = OpAccessChain %9 %20 %19 1756fd4e5da5Sopenharmony_ci %14 = OpLoad %6 %12 1757fd4e5da5Sopenharmony_ci OpBranch %15 1758fd4e5da5Sopenharmony_ci %15 = OpLabel 1759fd4e5da5Sopenharmony_ci OpReturn 1760fd4e5da5Sopenharmony_ci OpFunctionEnd 1761fd4e5da5Sopenharmony_ci )"; 1762fd4e5da5Sopenharmony_ci 1763fd4e5da5Sopenharmony_ci const auto env = SPV_ENV_UNIVERSAL_1_5; 1764fd4e5da5Sopenharmony_ci const auto consumer = nullptr; 1765fd4e5da5Sopenharmony_ci const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption); 1766fd4e5da5Sopenharmony_ci spvtools::ValidatorOptions validator_options; 1767fd4e5da5Sopenharmony_ci ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options, 1768fd4e5da5Sopenharmony_ci kConsoleMessageConsumer)); 1769fd4e5da5Sopenharmony_ci TransformationContext transformation_context( 1770fd4e5da5Sopenharmony_ci MakeUnique<FactManager>(context.get()), validator_options); 1771fd4e5da5Sopenharmony_ci TransformationOutlineFunction transformation( 1772fd4e5da5Sopenharmony_ci /*entry_block*/ 13, 1773fd4e5da5Sopenharmony_ci /*exit_block*/ 15, 1774fd4e5da5Sopenharmony_ci /*new_function_struct_return_type_id*/ 200, 1775fd4e5da5Sopenharmony_ci /*new_function_type_id*/ 201, 1776fd4e5da5Sopenharmony_ci /*new_function_id*/ 202, 1777fd4e5da5Sopenharmony_ci /*new_function_region_entry_block*/ 204, 1778fd4e5da5Sopenharmony_ci /*new_caller_result_id*/ 205, 1779fd4e5da5Sopenharmony_ci /*new_callee_result_id*/ 206, 1780fd4e5da5Sopenharmony_ci /*input_id_to_fresh_id*/ {{20, 207}}, 1781fd4e5da5Sopenharmony_ci /*output_id_to_fresh_id*/ {}); 1782fd4e5da5Sopenharmony_ci 1783fd4e5da5Sopenharmony_ci ASSERT_FALSE( 1784fd4e5da5Sopenharmony_ci transformation.IsApplicable(context.get(), transformation_context)); 1785fd4e5da5Sopenharmony_ci} 1786fd4e5da5Sopenharmony_ci 1787fd4e5da5Sopenharmony_ciTEST(TransformationOutlineFunctionTest, 1788fd4e5da5Sopenharmony_ci DoOutlineRegionThatUsesPointerParameter) { 1789fd4e5da5Sopenharmony_ci // The region being outlined reads from a function parameter of pointer type. 1790fd4e5da5Sopenharmony_ci // This is OK: the function parameter can itself be passed on as a function 1791fd4e5da5Sopenharmony_ci // parameter. 1792fd4e5da5Sopenharmony_ci std::string shader = R"( 1793fd4e5da5Sopenharmony_ci OpCapability Shader 1794fd4e5da5Sopenharmony_ci %1 = OpExtInstImport "GLSL.std.450" 1795fd4e5da5Sopenharmony_ci OpMemoryModel Logical GLSL450 1796fd4e5da5Sopenharmony_ci OpEntryPoint Fragment %4 "main" 1797fd4e5da5Sopenharmony_ci OpExecutionMode %4 OriginUpperLeft 1798fd4e5da5Sopenharmony_ci OpSource ESSL 310 1799fd4e5da5Sopenharmony_ci %2 = OpTypeVoid 1800fd4e5da5Sopenharmony_ci %3 = OpTypeFunction %2 1801fd4e5da5Sopenharmony_ci %6 = OpTypeInt 32 1 1802fd4e5da5Sopenharmony_ci %7 = OpTypePointer Function %6 1803fd4e5da5Sopenharmony_ci %8 = OpTypeFunction %2 %7 1804fd4e5da5Sopenharmony_ci %13 = OpConstant %6 2 1805fd4e5da5Sopenharmony_ci %4 = OpFunction %2 None %3 1806fd4e5da5Sopenharmony_ci %5 = OpLabel 1807fd4e5da5Sopenharmony_ci %15 = OpVariable %7 Function 1808fd4e5da5Sopenharmony_ci %16 = OpVariable %7 Function 1809fd4e5da5Sopenharmony_ci %17 = OpLoad %6 %15 1810fd4e5da5Sopenharmony_ci OpStore %16 %17 1811fd4e5da5Sopenharmony_ci %18 = OpFunctionCall %2 %10 %16 1812fd4e5da5Sopenharmony_ci %19 = OpLoad %6 %16 1813fd4e5da5Sopenharmony_ci OpStore %15 %19 1814fd4e5da5Sopenharmony_ci OpReturn 1815fd4e5da5Sopenharmony_ci OpFunctionEnd 1816fd4e5da5Sopenharmony_ci %10 = OpFunction %2 None %8 1817fd4e5da5Sopenharmony_ci %9 = OpFunctionParameter %7 1818fd4e5da5Sopenharmony_ci %11 = OpLabel 1819fd4e5da5Sopenharmony_ci %12 = OpLoad %6 %9 1820fd4e5da5Sopenharmony_ci %14 = OpIAdd %6 %12 %13 1821fd4e5da5Sopenharmony_ci OpBranch %20 1822fd4e5da5Sopenharmony_ci %20 = OpLabel 1823fd4e5da5Sopenharmony_ci OpStore %9 %14 1824fd4e5da5Sopenharmony_ci OpReturn 1825fd4e5da5Sopenharmony_ci OpFunctionEnd 1826fd4e5da5Sopenharmony_ci )"; 1827fd4e5da5Sopenharmony_ci 1828fd4e5da5Sopenharmony_ci const auto env = SPV_ENV_UNIVERSAL_1_5; 1829fd4e5da5Sopenharmony_ci const auto consumer = nullptr; 1830fd4e5da5Sopenharmony_ci const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption); 1831fd4e5da5Sopenharmony_ci spvtools::ValidatorOptions validator_options; 1832fd4e5da5Sopenharmony_ci ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options, 1833fd4e5da5Sopenharmony_ci kConsoleMessageConsumer)); 1834fd4e5da5Sopenharmony_ci TransformationContext transformation_context( 1835fd4e5da5Sopenharmony_ci MakeUnique<FactManager>(context.get()), validator_options); 1836fd4e5da5Sopenharmony_ci TransformationOutlineFunction transformation( 1837fd4e5da5Sopenharmony_ci /*entry_block*/ 11, 1838fd4e5da5Sopenharmony_ci /*exit_block*/ 11, 1839fd4e5da5Sopenharmony_ci /*new_function_struct_return_type_id*/ 200, 1840fd4e5da5Sopenharmony_ci /*new_function_type_id*/ 201, 1841fd4e5da5Sopenharmony_ci /*new_function_id*/ 202, 1842fd4e5da5Sopenharmony_ci /*new_function_region_entry_block*/ 204, 1843fd4e5da5Sopenharmony_ci /*new_caller_result_id*/ 205, 1844fd4e5da5Sopenharmony_ci /*new_callee_result_id*/ 206, 1845fd4e5da5Sopenharmony_ci /*input_id_to_fresh_id*/ {{9, 207}}, 1846fd4e5da5Sopenharmony_ci /*output_id_to_fresh_id*/ {{14, 208}}); 1847fd4e5da5Sopenharmony_ci 1848fd4e5da5Sopenharmony_ci ASSERT_TRUE( 1849fd4e5da5Sopenharmony_ci transformation.IsApplicable(context.get(), transformation_context)); 1850fd4e5da5Sopenharmony_ci ApplyAndCheckFreshIds(transformation, context.get(), &transformation_context); 1851fd4e5da5Sopenharmony_ci ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options, 1852fd4e5da5Sopenharmony_ci kConsoleMessageConsumer)); 1853fd4e5da5Sopenharmony_ci 1854fd4e5da5Sopenharmony_ci std::string after_transformation = R"( 1855fd4e5da5Sopenharmony_ci OpCapability Shader 1856fd4e5da5Sopenharmony_ci %1 = OpExtInstImport "GLSL.std.450" 1857fd4e5da5Sopenharmony_ci OpMemoryModel Logical GLSL450 1858fd4e5da5Sopenharmony_ci OpEntryPoint Fragment %4 "main" 1859fd4e5da5Sopenharmony_ci OpExecutionMode %4 OriginUpperLeft 1860fd4e5da5Sopenharmony_ci OpSource ESSL 310 1861fd4e5da5Sopenharmony_ci %2 = OpTypeVoid 1862fd4e5da5Sopenharmony_ci %3 = OpTypeFunction %2 1863fd4e5da5Sopenharmony_ci %6 = OpTypeInt 32 1 1864fd4e5da5Sopenharmony_ci %7 = OpTypePointer Function %6 1865fd4e5da5Sopenharmony_ci %8 = OpTypeFunction %2 %7 1866fd4e5da5Sopenharmony_ci %13 = OpConstant %6 2 1867fd4e5da5Sopenharmony_ci %200 = OpTypeStruct %6 1868fd4e5da5Sopenharmony_ci %201 = OpTypeFunction %200 %7 1869fd4e5da5Sopenharmony_ci %4 = OpFunction %2 None %3 1870fd4e5da5Sopenharmony_ci %5 = OpLabel 1871fd4e5da5Sopenharmony_ci %15 = OpVariable %7 Function 1872fd4e5da5Sopenharmony_ci %16 = OpVariable %7 Function 1873fd4e5da5Sopenharmony_ci %17 = OpLoad %6 %15 1874fd4e5da5Sopenharmony_ci OpStore %16 %17 1875fd4e5da5Sopenharmony_ci %18 = OpFunctionCall %2 %10 %16 1876fd4e5da5Sopenharmony_ci %19 = OpLoad %6 %16 1877fd4e5da5Sopenharmony_ci OpStore %15 %19 1878fd4e5da5Sopenharmony_ci OpReturn 1879fd4e5da5Sopenharmony_ci OpFunctionEnd 1880fd4e5da5Sopenharmony_ci %10 = OpFunction %2 None %8 1881fd4e5da5Sopenharmony_ci %9 = OpFunctionParameter %7 1882fd4e5da5Sopenharmony_ci %11 = OpLabel 1883fd4e5da5Sopenharmony_ci %205 = OpFunctionCall %200 %202 %9 1884fd4e5da5Sopenharmony_ci %14 = OpCompositeExtract %6 %205 0 1885fd4e5da5Sopenharmony_ci OpBranch %20 1886fd4e5da5Sopenharmony_ci %20 = OpLabel 1887fd4e5da5Sopenharmony_ci OpStore %9 %14 1888fd4e5da5Sopenharmony_ci OpReturn 1889fd4e5da5Sopenharmony_ci OpFunctionEnd 1890fd4e5da5Sopenharmony_ci %202 = OpFunction %200 None %201 1891fd4e5da5Sopenharmony_ci %207 = OpFunctionParameter %7 1892fd4e5da5Sopenharmony_ci %204 = OpLabel 1893fd4e5da5Sopenharmony_ci %12 = OpLoad %6 %207 1894fd4e5da5Sopenharmony_ci %208 = OpIAdd %6 %12 %13 1895fd4e5da5Sopenharmony_ci %206 = OpCompositeConstruct %200 %208 1896fd4e5da5Sopenharmony_ci OpReturnValue %206 1897fd4e5da5Sopenharmony_ci OpFunctionEnd 1898fd4e5da5Sopenharmony_ci )"; 1899fd4e5da5Sopenharmony_ci ASSERT_TRUE(IsEqual(env, after_transformation, context.get())); 1900fd4e5da5Sopenharmony_ci} 1901fd4e5da5Sopenharmony_ci 1902fd4e5da5Sopenharmony_ciTEST(TransformationOutlineFunctionTest, OutlineLivesafe) { 1903fd4e5da5Sopenharmony_ci // In the following, %30 is a livesafe function, with irrelevant parameter 1904fd4e5da5Sopenharmony_ci // %200 and irrelevant local variable %201. Variable %100 is a loop limiter, 1905fd4e5da5Sopenharmony_ci // which is not irrelevant. The test checks that the outlined function is 1906fd4e5da5Sopenharmony_ci // livesafe, and that the parameters corresponding to %200 and %201 have the 1907fd4e5da5Sopenharmony_ci // irrelevant fact associated with them. 1908fd4e5da5Sopenharmony_ci std::string shader = R"( 1909fd4e5da5Sopenharmony_ci OpCapability Shader 1910fd4e5da5Sopenharmony_ci %1 = OpExtInstImport "GLSL.std.450" 1911fd4e5da5Sopenharmony_ci OpMemoryModel Logical GLSL450 1912fd4e5da5Sopenharmony_ci OpEntryPoint Fragment %4 "main" 1913fd4e5da5Sopenharmony_ci OpExecutionMode %4 OriginUpperLeft 1914fd4e5da5Sopenharmony_ci OpSource ESSL 310 1915fd4e5da5Sopenharmony_ci %2 = OpTypeVoid 1916fd4e5da5Sopenharmony_ci %3 = OpTypeFunction %2 1917fd4e5da5Sopenharmony_ci %6 = OpTypeInt 32 0 1918fd4e5da5Sopenharmony_ci %7 = OpTypePointer Function %6 1919fd4e5da5Sopenharmony_ci %199 = OpTypeFunction %2 %7 1920fd4e5da5Sopenharmony_ci %8 = OpConstant %6 0 1921fd4e5da5Sopenharmony_ci %9 = OpConstant %6 1 1922fd4e5da5Sopenharmony_ci %10 = OpConstant %6 5 1923fd4e5da5Sopenharmony_ci %11 = OpTypeBool 1924fd4e5da5Sopenharmony_ci %12 = OpConstantTrue %11 1925fd4e5da5Sopenharmony_ci %4 = OpFunction %2 None %3 1926fd4e5da5Sopenharmony_ci %5 = OpLabel 1927fd4e5da5Sopenharmony_ci OpReturn 1928fd4e5da5Sopenharmony_ci OpFunctionEnd 1929fd4e5da5Sopenharmony_ci %30 = OpFunction %2 None %199 1930fd4e5da5Sopenharmony_ci %200 = OpFunctionParameter %7 1931fd4e5da5Sopenharmony_ci %31 = OpLabel 1932fd4e5da5Sopenharmony_ci %100 = OpVariable %7 Function %8 1933fd4e5da5Sopenharmony_ci %201 = OpVariable %7 Function %8 1934fd4e5da5Sopenharmony_ci OpBranch %198 1935fd4e5da5Sopenharmony_ci %198 = OpLabel 1936fd4e5da5Sopenharmony_ci OpBranch %20 1937fd4e5da5Sopenharmony_ci %20 = OpLabel 1938fd4e5da5Sopenharmony_ci %101 = OpLoad %6 %100 1939fd4e5da5Sopenharmony_ci %102 = OpIAdd %6 %101 %9 1940fd4e5da5Sopenharmony_ci %202 = OpLoad %6 %200 1941fd4e5da5Sopenharmony_ci OpStore %201 %202 1942fd4e5da5Sopenharmony_ci OpStore %100 %102 1943fd4e5da5Sopenharmony_ci %103 = OpUGreaterThanEqual %11 %101 %10 1944fd4e5da5Sopenharmony_ci OpLoopMerge %21 %22 None 1945fd4e5da5Sopenharmony_ci OpBranchConditional %103 %21 %104 1946fd4e5da5Sopenharmony_ci %104 = OpLabel 1947fd4e5da5Sopenharmony_ci OpBranchConditional %12 %23 %21 1948fd4e5da5Sopenharmony_ci %23 = OpLabel 1949fd4e5da5Sopenharmony_ci %105 = OpLoad %6 %100 1950fd4e5da5Sopenharmony_ci %106 = OpIAdd %6 %105 %9 1951fd4e5da5Sopenharmony_ci OpStore %100 %106 1952fd4e5da5Sopenharmony_ci %107 = OpUGreaterThanEqual %11 %105 %10 1953fd4e5da5Sopenharmony_ci OpLoopMerge %25 %26 None 1954fd4e5da5Sopenharmony_ci OpBranchConditional %107 %25 %108 1955fd4e5da5Sopenharmony_ci %108 = OpLabel 1956fd4e5da5Sopenharmony_ci OpBranch %28 1957fd4e5da5Sopenharmony_ci %28 = OpLabel 1958fd4e5da5Sopenharmony_ci OpBranchConditional %12 %26 %25 1959fd4e5da5Sopenharmony_ci %26 = OpLabel 1960fd4e5da5Sopenharmony_ci OpBranch %23 1961fd4e5da5Sopenharmony_ci %25 = OpLabel 1962fd4e5da5Sopenharmony_ci %109 = OpLoad %6 %100 1963fd4e5da5Sopenharmony_ci %110 = OpIAdd %6 %109 %9 1964fd4e5da5Sopenharmony_ci OpStore %100 %110 1965fd4e5da5Sopenharmony_ci %111 = OpUGreaterThanEqual %11 %109 %10 1966fd4e5da5Sopenharmony_ci OpLoopMerge %24 %27 None 1967fd4e5da5Sopenharmony_ci OpBranchConditional %111 %24 %112 1968fd4e5da5Sopenharmony_ci %112 = OpLabel 1969fd4e5da5Sopenharmony_ci OpBranchConditional %12 %24 %27 1970fd4e5da5Sopenharmony_ci %27 = OpLabel 1971fd4e5da5Sopenharmony_ci OpBranch %25 1972fd4e5da5Sopenharmony_ci %24 = OpLabel 1973fd4e5da5Sopenharmony_ci OpBranch %22 1974fd4e5da5Sopenharmony_ci %22 = OpLabel 1975fd4e5da5Sopenharmony_ci OpBranch %20 1976fd4e5da5Sopenharmony_ci %21 = OpLabel 1977fd4e5da5Sopenharmony_ci OpBranch %197 1978fd4e5da5Sopenharmony_ci %197 = OpLabel 1979fd4e5da5Sopenharmony_ci OpReturn 1980fd4e5da5Sopenharmony_ci OpFunctionEnd 1981fd4e5da5Sopenharmony_ci )"; 1982fd4e5da5Sopenharmony_ci 1983fd4e5da5Sopenharmony_ci const auto env = SPV_ENV_UNIVERSAL_1_5; 1984fd4e5da5Sopenharmony_ci const auto consumer = nullptr; 1985fd4e5da5Sopenharmony_ci const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption); 1986fd4e5da5Sopenharmony_ci spvtools::ValidatorOptions validator_options; 1987fd4e5da5Sopenharmony_ci ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options, 1988fd4e5da5Sopenharmony_ci kConsoleMessageConsumer)); 1989fd4e5da5Sopenharmony_ci TransformationContext transformation_context( 1990fd4e5da5Sopenharmony_ci MakeUnique<FactManager>(context.get()), validator_options); 1991fd4e5da5Sopenharmony_ci transformation_context.GetFactManager()->AddFactFunctionIsLivesafe(30); 1992fd4e5da5Sopenharmony_ci transformation_context.GetFactManager()->AddFactValueOfPointeeIsIrrelevant( 1993fd4e5da5Sopenharmony_ci 200); 1994fd4e5da5Sopenharmony_ci transformation_context.GetFactManager()->AddFactValueOfPointeeIsIrrelevant( 1995fd4e5da5Sopenharmony_ci 201); 1996fd4e5da5Sopenharmony_ci 1997fd4e5da5Sopenharmony_ci TransformationOutlineFunction transformation( 1998fd4e5da5Sopenharmony_ci /*entry_block*/ 198, 1999fd4e5da5Sopenharmony_ci /*exit_block*/ 197, 2000fd4e5da5Sopenharmony_ci /*new_function_struct_return_type_id*/ 400, 2001fd4e5da5Sopenharmony_ci /*new_function_type_id*/ 401, 2002fd4e5da5Sopenharmony_ci /*new_function_id*/ 402, 2003fd4e5da5Sopenharmony_ci /*new_function_region_entry_block*/ 404, 2004fd4e5da5Sopenharmony_ci /*new_caller_result_id*/ 405, 2005fd4e5da5Sopenharmony_ci /*new_callee_result_id*/ 406, 2006fd4e5da5Sopenharmony_ci /*input_id_to_fresh_id*/ {{100, 407}, {200, 408}, {201, 409}}, 2007fd4e5da5Sopenharmony_ci /*output_id_to_fresh_id*/ {}); 2008fd4e5da5Sopenharmony_ci 2009fd4e5da5Sopenharmony_ci ASSERT_TRUE( 2010fd4e5da5Sopenharmony_ci transformation.IsApplicable(context.get(), transformation_context)); 2011fd4e5da5Sopenharmony_ci ApplyAndCheckFreshIds(transformation, context.get(), &transformation_context); 2012fd4e5da5Sopenharmony_ci ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options, 2013fd4e5da5Sopenharmony_ci kConsoleMessageConsumer)); 2014fd4e5da5Sopenharmony_ci 2015fd4e5da5Sopenharmony_ci // The original function should still be livesafe. 2016fd4e5da5Sopenharmony_ci ASSERT_TRUE(transformation_context.GetFactManager()->FunctionIsLivesafe(30)); 2017fd4e5da5Sopenharmony_ci // The outlined function should be livesafe. 2018fd4e5da5Sopenharmony_ci ASSERT_TRUE(transformation_context.GetFactManager()->FunctionIsLivesafe(402)); 2019fd4e5da5Sopenharmony_ci // The variable and parameter that were originally irrelevant should still be. 2020fd4e5da5Sopenharmony_ci ASSERT_TRUE( 2021fd4e5da5Sopenharmony_ci transformation_context.GetFactManager()->PointeeValueIsIrrelevant(200)); 2022fd4e5da5Sopenharmony_ci ASSERT_TRUE( 2023fd4e5da5Sopenharmony_ci transformation_context.GetFactManager()->PointeeValueIsIrrelevant(201)); 2024fd4e5da5Sopenharmony_ci // The loop limiter should still be non-irrelevant. 2025fd4e5da5Sopenharmony_ci ASSERT_FALSE( 2026fd4e5da5Sopenharmony_ci transformation_context.GetFactManager()->PointeeValueIsIrrelevant(100)); 2027fd4e5da5Sopenharmony_ci // The parameters for the original irrelevant variables should be irrelevant. 2028fd4e5da5Sopenharmony_ci ASSERT_TRUE( 2029fd4e5da5Sopenharmony_ci transformation_context.GetFactManager()->PointeeValueIsIrrelevant(408)); 2030fd4e5da5Sopenharmony_ci ASSERT_TRUE( 2031fd4e5da5Sopenharmony_ci transformation_context.GetFactManager()->PointeeValueIsIrrelevant(409)); 2032fd4e5da5Sopenharmony_ci // The parameter for the loop limiter should not be irrelevant. 2033fd4e5da5Sopenharmony_ci ASSERT_FALSE( 2034fd4e5da5Sopenharmony_ci transformation_context.GetFactManager()->PointeeValueIsIrrelevant(407)); 2035fd4e5da5Sopenharmony_ci 2036fd4e5da5Sopenharmony_ci std::string after_transformation = R"( 2037fd4e5da5Sopenharmony_ci OpCapability Shader 2038fd4e5da5Sopenharmony_ci %1 = OpExtInstImport "GLSL.std.450" 2039fd4e5da5Sopenharmony_ci OpMemoryModel Logical GLSL450 2040fd4e5da5Sopenharmony_ci OpEntryPoint Fragment %4 "main" 2041fd4e5da5Sopenharmony_ci OpExecutionMode %4 OriginUpperLeft 2042fd4e5da5Sopenharmony_ci OpSource ESSL 310 2043fd4e5da5Sopenharmony_ci %2 = OpTypeVoid 2044fd4e5da5Sopenharmony_ci %3 = OpTypeFunction %2 2045fd4e5da5Sopenharmony_ci %6 = OpTypeInt 32 0 2046fd4e5da5Sopenharmony_ci %7 = OpTypePointer Function %6 2047fd4e5da5Sopenharmony_ci %199 = OpTypeFunction %2 %7 2048fd4e5da5Sopenharmony_ci %8 = OpConstant %6 0 2049fd4e5da5Sopenharmony_ci %9 = OpConstant %6 1 2050fd4e5da5Sopenharmony_ci %10 = OpConstant %6 5 2051fd4e5da5Sopenharmony_ci %11 = OpTypeBool 2052fd4e5da5Sopenharmony_ci %12 = OpConstantTrue %11 2053fd4e5da5Sopenharmony_ci %401 = OpTypeFunction %2 %7 %7 %7 2054fd4e5da5Sopenharmony_ci %4 = OpFunction %2 None %3 2055fd4e5da5Sopenharmony_ci %5 = OpLabel 2056fd4e5da5Sopenharmony_ci OpReturn 2057fd4e5da5Sopenharmony_ci OpFunctionEnd 2058fd4e5da5Sopenharmony_ci %30 = OpFunction %2 None %199 2059fd4e5da5Sopenharmony_ci %200 = OpFunctionParameter %7 2060fd4e5da5Sopenharmony_ci %31 = OpLabel 2061fd4e5da5Sopenharmony_ci %100 = OpVariable %7 Function %8 2062fd4e5da5Sopenharmony_ci %201 = OpVariable %7 Function %8 2063fd4e5da5Sopenharmony_ci OpBranch %198 2064fd4e5da5Sopenharmony_ci %198 = OpLabel 2065fd4e5da5Sopenharmony_ci %405 = OpFunctionCall %2 %402 %200 %100 %201 2066fd4e5da5Sopenharmony_ci OpReturn 2067fd4e5da5Sopenharmony_ci OpFunctionEnd 2068fd4e5da5Sopenharmony_ci %402 = OpFunction %2 None %401 2069fd4e5da5Sopenharmony_ci %408 = OpFunctionParameter %7 2070fd4e5da5Sopenharmony_ci %407 = OpFunctionParameter %7 2071fd4e5da5Sopenharmony_ci %409 = OpFunctionParameter %7 2072fd4e5da5Sopenharmony_ci %404 = OpLabel 2073fd4e5da5Sopenharmony_ci OpBranch %20 2074fd4e5da5Sopenharmony_ci %20 = OpLabel 2075fd4e5da5Sopenharmony_ci %101 = OpLoad %6 %407 2076fd4e5da5Sopenharmony_ci %102 = OpIAdd %6 %101 %9 2077fd4e5da5Sopenharmony_ci %202 = OpLoad %6 %408 2078fd4e5da5Sopenharmony_ci OpStore %409 %202 2079fd4e5da5Sopenharmony_ci OpStore %407 %102 2080fd4e5da5Sopenharmony_ci %103 = OpUGreaterThanEqual %11 %101 %10 2081fd4e5da5Sopenharmony_ci OpLoopMerge %21 %22 None 2082fd4e5da5Sopenharmony_ci OpBranchConditional %103 %21 %104 2083fd4e5da5Sopenharmony_ci %104 = OpLabel 2084fd4e5da5Sopenharmony_ci OpBranchConditional %12 %23 %21 2085fd4e5da5Sopenharmony_ci %23 = OpLabel 2086fd4e5da5Sopenharmony_ci %105 = OpLoad %6 %407 2087fd4e5da5Sopenharmony_ci %106 = OpIAdd %6 %105 %9 2088fd4e5da5Sopenharmony_ci OpStore %407 %106 2089fd4e5da5Sopenharmony_ci %107 = OpUGreaterThanEqual %11 %105 %10 2090fd4e5da5Sopenharmony_ci OpLoopMerge %25 %26 None 2091fd4e5da5Sopenharmony_ci OpBranchConditional %107 %25 %108 2092fd4e5da5Sopenharmony_ci %108 = OpLabel 2093fd4e5da5Sopenharmony_ci OpBranch %28 2094fd4e5da5Sopenharmony_ci %28 = OpLabel 2095fd4e5da5Sopenharmony_ci OpBranchConditional %12 %26 %25 2096fd4e5da5Sopenharmony_ci %26 = OpLabel 2097fd4e5da5Sopenharmony_ci OpBranch %23 2098fd4e5da5Sopenharmony_ci %25 = OpLabel 2099fd4e5da5Sopenharmony_ci %109 = OpLoad %6 %407 2100fd4e5da5Sopenharmony_ci %110 = OpIAdd %6 %109 %9 2101fd4e5da5Sopenharmony_ci OpStore %407 %110 2102fd4e5da5Sopenharmony_ci %111 = OpUGreaterThanEqual %11 %109 %10 2103fd4e5da5Sopenharmony_ci OpLoopMerge %24 %27 None 2104fd4e5da5Sopenharmony_ci OpBranchConditional %111 %24 %112 2105fd4e5da5Sopenharmony_ci %112 = OpLabel 2106fd4e5da5Sopenharmony_ci OpBranchConditional %12 %24 %27 2107fd4e5da5Sopenharmony_ci %27 = OpLabel 2108fd4e5da5Sopenharmony_ci OpBranch %25 2109fd4e5da5Sopenharmony_ci %24 = OpLabel 2110fd4e5da5Sopenharmony_ci OpBranch %22 2111fd4e5da5Sopenharmony_ci %22 = OpLabel 2112fd4e5da5Sopenharmony_ci OpBranch %20 2113fd4e5da5Sopenharmony_ci %21 = OpLabel 2114fd4e5da5Sopenharmony_ci OpBranch %197 2115fd4e5da5Sopenharmony_ci %197 = OpLabel 2116fd4e5da5Sopenharmony_ci OpReturn 2117fd4e5da5Sopenharmony_ci OpFunctionEnd 2118fd4e5da5Sopenharmony_ci )"; 2119fd4e5da5Sopenharmony_ci ASSERT_TRUE(IsEqual(env, after_transformation, context.get())); 2120fd4e5da5Sopenharmony_ci} 2121fd4e5da5Sopenharmony_ci 2122fd4e5da5Sopenharmony_ciTEST(TransformationOutlineFunctionTest, OutlineWithDeadBlocks1) { 2123fd4e5da5Sopenharmony_ci // This checks that if all blocks in the region being outlined were dead, all 2124fd4e5da5Sopenharmony_ci // blocks in the outlined function will be dead. 2125fd4e5da5Sopenharmony_ci std::string shader = R"( 2126fd4e5da5Sopenharmony_ci OpCapability Shader 2127fd4e5da5Sopenharmony_ci %1 = OpExtInstImport "GLSL.std.450" 2128fd4e5da5Sopenharmony_ci OpMemoryModel Logical GLSL450 2129fd4e5da5Sopenharmony_ci OpEntryPoint Fragment %4 "main" 2130fd4e5da5Sopenharmony_ci OpExecutionMode %4 OriginUpperLeft 2131fd4e5da5Sopenharmony_ci OpSource ESSL 310 2132fd4e5da5Sopenharmony_ci OpName %4 "main" 2133fd4e5da5Sopenharmony_ci OpName %10 "foo(i1;" 2134fd4e5da5Sopenharmony_ci OpName %9 "x" 2135fd4e5da5Sopenharmony_ci OpName %12 "y" 2136fd4e5da5Sopenharmony_ci OpName %21 "i" 2137fd4e5da5Sopenharmony_ci OpName %46 "param" 2138fd4e5da5Sopenharmony_ci %2 = OpTypeVoid 2139fd4e5da5Sopenharmony_ci %3 = OpTypeFunction %2 2140fd4e5da5Sopenharmony_ci %6 = OpTypeInt 32 1 2141fd4e5da5Sopenharmony_ci %7 = OpTypePointer Function %6 2142fd4e5da5Sopenharmony_ci %8 = OpTypeFunction %2 %7 2143fd4e5da5Sopenharmony_ci %13 = OpConstant %6 2 2144fd4e5da5Sopenharmony_ci %14 = OpTypeBool 2145fd4e5da5Sopenharmony_ci %15 = OpConstantFalse %14 2146fd4e5da5Sopenharmony_ci %22 = OpConstant %6 0 2147fd4e5da5Sopenharmony_ci %29 = OpConstant %6 10 2148fd4e5da5Sopenharmony_ci %41 = OpConstant %6 1 2149fd4e5da5Sopenharmony_ci %4 = OpFunction %2 None %3 2150fd4e5da5Sopenharmony_ci %5 = OpLabel 2151fd4e5da5Sopenharmony_ci %46 = OpVariable %7 Function 2152fd4e5da5Sopenharmony_ci OpStore %46 %13 2153fd4e5da5Sopenharmony_ci %47 = OpFunctionCall %2 %10 %46 2154fd4e5da5Sopenharmony_ci OpReturn 2155fd4e5da5Sopenharmony_ci OpFunctionEnd 2156fd4e5da5Sopenharmony_ci %10 = OpFunction %2 None %8 2157fd4e5da5Sopenharmony_ci %9 = OpFunctionParameter %7 2158fd4e5da5Sopenharmony_ci %11 = OpLabel 2159fd4e5da5Sopenharmony_ci %12 = OpVariable %7 Function 2160fd4e5da5Sopenharmony_ci %21 = OpVariable %7 Function 2161fd4e5da5Sopenharmony_ci OpStore %12 %13 2162fd4e5da5Sopenharmony_ci OpSelectionMerge %17 None 2163fd4e5da5Sopenharmony_ci OpBranchConditional %15 %16 %17 2164fd4e5da5Sopenharmony_ci %16 = OpLabel 2165fd4e5da5Sopenharmony_ci %18 = OpLoad %6 %9 2166fd4e5da5Sopenharmony_ci OpStore %12 %18 2167fd4e5da5Sopenharmony_ci %19 = OpLoad %6 %9 2168fd4e5da5Sopenharmony_ci %20 = OpIAdd %6 %19 %13 2169fd4e5da5Sopenharmony_ci OpStore %9 %20 2170fd4e5da5Sopenharmony_ci OpStore %21 %22 2171fd4e5da5Sopenharmony_ci OpBranch %23 2172fd4e5da5Sopenharmony_ci %23 = OpLabel 2173fd4e5da5Sopenharmony_ci OpLoopMerge %25 %26 None 2174fd4e5da5Sopenharmony_ci OpBranch %27 2175fd4e5da5Sopenharmony_ci %27 = OpLabel 2176fd4e5da5Sopenharmony_ci %28 = OpLoad %6 %21 2177fd4e5da5Sopenharmony_ci %30 = OpSLessThan %14 %28 %29 2178fd4e5da5Sopenharmony_ci OpBranchConditional %30 %24 %25 2179fd4e5da5Sopenharmony_ci %24 = OpLabel 2180fd4e5da5Sopenharmony_ci %31 = OpLoad %6 %9 2181fd4e5da5Sopenharmony_ci %32 = OpLoad %6 %21 2182fd4e5da5Sopenharmony_ci %33 = OpSGreaterThan %14 %31 %32 2183fd4e5da5Sopenharmony_ci OpSelectionMerge %35 None 2184fd4e5da5Sopenharmony_ci OpBranchConditional %33 %34 %35 2185fd4e5da5Sopenharmony_ci %34 = OpLabel 2186fd4e5da5Sopenharmony_ci OpBranch %26 2187fd4e5da5Sopenharmony_ci %35 = OpLabel 2188fd4e5da5Sopenharmony_ci %37 = OpLoad %6 %9 2189fd4e5da5Sopenharmony_ci %38 = OpLoad %6 %12 2190fd4e5da5Sopenharmony_ci %39 = OpIAdd %6 %38 %37 2191fd4e5da5Sopenharmony_ci OpStore %12 %39 2192fd4e5da5Sopenharmony_ci OpBranch %26 2193fd4e5da5Sopenharmony_ci %26 = OpLabel 2194fd4e5da5Sopenharmony_ci %40 = OpLoad %6 %21 2195fd4e5da5Sopenharmony_ci %42 = OpIAdd %6 %40 %41 2196fd4e5da5Sopenharmony_ci OpStore %21 %42 2197fd4e5da5Sopenharmony_ci OpBranch %23 2198fd4e5da5Sopenharmony_ci %25 = OpLabel 2199fd4e5da5Sopenharmony_ci OpBranch %50 2200fd4e5da5Sopenharmony_ci %50 = OpLabel 2201fd4e5da5Sopenharmony_ci OpBranch %17 2202fd4e5da5Sopenharmony_ci %17 = OpLabel 2203fd4e5da5Sopenharmony_ci %43 = OpLoad %6 %9 2204fd4e5da5Sopenharmony_ci %44 = OpLoad %6 %12 2205fd4e5da5Sopenharmony_ci %45 = OpIAdd %6 %44 %43 2206fd4e5da5Sopenharmony_ci OpStore %12 %45 2207fd4e5da5Sopenharmony_ci OpReturn 2208fd4e5da5Sopenharmony_ci OpFunctionEnd 2209fd4e5da5Sopenharmony_ci )"; 2210fd4e5da5Sopenharmony_ci 2211fd4e5da5Sopenharmony_ci const auto env = SPV_ENV_UNIVERSAL_1_5; 2212fd4e5da5Sopenharmony_ci const auto consumer = nullptr; 2213fd4e5da5Sopenharmony_ci const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption); 2214fd4e5da5Sopenharmony_ci spvtools::ValidatorOptions validator_options; 2215fd4e5da5Sopenharmony_ci ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options, 2216fd4e5da5Sopenharmony_ci kConsoleMessageConsumer)); 2217fd4e5da5Sopenharmony_ci TransformationContext transformation_context( 2218fd4e5da5Sopenharmony_ci MakeUnique<FactManager>(context.get()), validator_options); 2219fd4e5da5Sopenharmony_ci for (uint32_t block_id : {16u, 23u, 24u, 26u, 27u, 34u, 35u, 50u}) { 2220fd4e5da5Sopenharmony_ci transformation_context.GetFactManager()->AddFactBlockIsDead(block_id); 2221fd4e5da5Sopenharmony_ci } 2222fd4e5da5Sopenharmony_ci 2223fd4e5da5Sopenharmony_ci TransformationOutlineFunction transformation( 2224fd4e5da5Sopenharmony_ci /*entry_block*/ 16, 2225fd4e5da5Sopenharmony_ci /*exit_block*/ 50, 2226fd4e5da5Sopenharmony_ci /*new_function_struct_return_type_id*/ 200, 2227fd4e5da5Sopenharmony_ci /*new_function_type_id*/ 201, 2228fd4e5da5Sopenharmony_ci /*new_function_id*/ 202, 2229fd4e5da5Sopenharmony_ci /*new_function_region_entry_block*/ 203, 2230fd4e5da5Sopenharmony_ci /*new_caller_result_id*/ 204, 2231fd4e5da5Sopenharmony_ci /*new_callee_result_id*/ 205, 2232fd4e5da5Sopenharmony_ci /*input_id_to_fresh_id*/ {{9, 206}, {12, 207}, {21, 208}}, 2233fd4e5da5Sopenharmony_ci /*output_id_to_fresh_id*/ {}); 2234fd4e5da5Sopenharmony_ci 2235fd4e5da5Sopenharmony_ci ASSERT_TRUE( 2236fd4e5da5Sopenharmony_ci transformation.IsApplicable(context.get(), transformation_context)); 2237fd4e5da5Sopenharmony_ci ApplyAndCheckFreshIds(transformation, context.get(), &transformation_context); 2238fd4e5da5Sopenharmony_ci ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options, 2239fd4e5da5Sopenharmony_ci kConsoleMessageConsumer)); 2240fd4e5da5Sopenharmony_ci // All the original blocks, plus the new function entry block, should be dead. 2241fd4e5da5Sopenharmony_ci for (uint32_t block_id : {16u, 23u, 24u, 26u, 27u, 34u, 35u, 50u, 203u}) { 2242fd4e5da5Sopenharmony_ci ASSERT_TRUE(transformation_context.GetFactManager()->BlockIsDead(block_id)); 2243fd4e5da5Sopenharmony_ci } 2244fd4e5da5Sopenharmony_ci} 2245fd4e5da5Sopenharmony_ci 2246fd4e5da5Sopenharmony_ciTEST(TransformationOutlineFunctionTest, OutlineWithDeadBlocks2) { 2247fd4e5da5Sopenharmony_ci // This checks that if some, but not all, blocks in the outlined region are 2248fd4e5da5Sopenharmony_ci // dead, those (but not others) will be dead in the outlined function. 2249fd4e5da5Sopenharmony_ci std::string shader = R"( 2250fd4e5da5Sopenharmony_ci OpCapability Shader 2251fd4e5da5Sopenharmony_ci %1 = OpExtInstImport "GLSL.std.450" 2252fd4e5da5Sopenharmony_ci OpMemoryModel Logical GLSL450 2253fd4e5da5Sopenharmony_ci OpEntryPoint Fragment %4 "main" %8 2254fd4e5da5Sopenharmony_ci OpExecutionMode %4 OriginUpperLeft 2255fd4e5da5Sopenharmony_ci OpSource ESSL 310 2256fd4e5da5Sopenharmony_ci %2 = OpTypeVoid 2257fd4e5da5Sopenharmony_ci %3 = OpTypeFunction %2 2258fd4e5da5Sopenharmony_ci %6 = OpTypeBool 2259fd4e5da5Sopenharmony_ci %7 = OpTypePointer Private %6 2260fd4e5da5Sopenharmony_ci %8 = OpVariable %7 Private 2261fd4e5da5Sopenharmony_ci %9 = OpConstantFalse %6 2262fd4e5da5Sopenharmony_ci %10 = OpTypePointer Function %6 2263fd4e5da5Sopenharmony_ci %12 = OpConstantTrue %6 2264fd4e5da5Sopenharmony_ci %4 = OpFunction %2 None %3 2265fd4e5da5Sopenharmony_ci %5 = OpLabel 2266fd4e5da5Sopenharmony_ci %11 = OpVariable %10 Function 2267fd4e5da5Sopenharmony_ci OpBranch %30 2268fd4e5da5Sopenharmony_ci %30 = OpLabel 2269fd4e5da5Sopenharmony_ci OpStore %8 %9 2270fd4e5da5Sopenharmony_ci OpBranch %31 2271fd4e5da5Sopenharmony_ci %31 = OpLabel 2272fd4e5da5Sopenharmony_ci OpStore %11 %12 2273fd4e5da5Sopenharmony_ci OpSelectionMerge %36 None 2274fd4e5da5Sopenharmony_ci OpBranchConditional %9 %32 %33 2275fd4e5da5Sopenharmony_ci %32 = OpLabel 2276fd4e5da5Sopenharmony_ci OpBranch %34 2277fd4e5da5Sopenharmony_ci %33 = OpLabel 2278fd4e5da5Sopenharmony_ci OpBranch %36 2279fd4e5da5Sopenharmony_ci %34 = OpLabel 2280fd4e5da5Sopenharmony_ci OpBranch %35 2281fd4e5da5Sopenharmony_ci %35 = OpLabel 2282fd4e5da5Sopenharmony_ci OpBranch %36 2283fd4e5da5Sopenharmony_ci %36 = OpLabel 2284fd4e5da5Sopenharmony_ci OpBranch %37 2285fd4e5da5Sopenharmony_ci %37 = OpLabel 2286fd4e5da5Sopenharmony_ci %13 = OpLoad %6 %8 2287fd4e5da5Sopenharmony_ci OpStore %11 %13 2288fd4e5da5Sopenharmony_ci %14 = OpLoad %6 %11 2289fd4e5da5Sopenharmony_ci OpStore %8 %14 2290fd4e5da5Sopenharmony_ci OpReturn 2291fd4e5da5Sopenharmony_ci OpFunctionEnd 2292fd4e5da5Sopenharmony_ci )"; 2293fd4e5da5Sopenharmony_ci 2294fd4e5da5Sopenharmony_ci const auto env = SPV_ENV_UNIVERSAL_1_5; 2295fd4e5da5Sopenharmony_ci const auto consumer = nullptr; 2296fd4e5da5Sopenharmony_ci const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption); 2297fd4e5da5Sopenharmony_ci spvtools::ValidatorOptions validator_options; 2298fd4e5da5Sopenharmony_ci ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options, 2299fd4e5da5Sopenharmony_ci kConsoleMessageConsumer)); 2300fd4e5da5Sopenharmony_ci TransformationContext transformation_context( 2301fd4e5da5Sopenharmony_ci MakeUnique<FactManager>(context.get()), validator_options); 2302fd4e5da5Sopenharmony_ci for (uint32_t block_id : {32u, 34u, 35u}) { 2303fd4e5da5Sopenharmony_ci transformation_context.GetFactManager()->AddFactBlockIsDead(block_id); 2304fd4e5da5Sopenharmony_ci } 2305fd4e5da5Sopenharmony_ci 2306fd4e5da5Sopenharmony_ci TransformationOutlineFunction transformation( 2307fd4e5da5Sopenharmony_ci /*entry_block*/ 30, 2308fd4e5da5Sopenharmony_ci /*exit_block*/ 37, 2309fd4e5da5Sopenharmony_ci /*new_function_struct_return_type_id*/ 200, 2310fd4e5da5Sopenharmony_ci /*new_function_type_id*/ 201, 2311fd4e5da5Sopenharmony_ci /*new_function_id*/ 202, 2312fd4e5da5Sopenharmony_ci /*new_function_region_entry_block*/ 203, 2313fd4e5da5Sopenharmony_ci /*new_caller_result_id*/ 204, 2314fd4e5da5Sopenharmony_ci /*new_callee_result_id*/ 205, 2315fd4e5da5Sopenharmony_ci /*input_id_to_fresh_id*/ {{11, 206}}, 2316fd4e5da5Sopenharmony_ci /*output_id_to_fresh_id*/ {}); 2317fd4e5da5Sopenharmony_ci 2318fd4e5da5Sopenharmony_ci ASSERT_TRUE( 2319fd4e5da5Sopenharmony_ci transformation.IsApplicable(context.get(), transformation_context)); 2320fd4e5da5Sopenharmony_ci ApplyAndCheckFreshIds(transformation, context.get(), &transformation_context); 2321fd4e5da5Sopenharmony_ci ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options, 2322fd4e5da5Sopenharmony_ci kConsoleMessageConsumer)); 2323fd4e5da5Sopenharmony_ci // The blocks that were originally dead, but not others, should be dead. 2324fd4e5da5Sopenharmony_ci for (uint32_t block_id : {32u, 34u, 35u}) { 2325fd4e5da5Sopenharmony_ci ASSERT_TRUE(transformation_context.GetFactManager()->BlockIsDead(block_id)); 2326fd4e5da5Sopenharmony_ci } 2327fd4e5da5Sopenharmony_ci for (uint32_t block_id : {5u, 30u, 31u, 33u, 36u, 37u, 203u}) { 2328fd4e5da5Sopenharmony_ci ASSERT_FALSE( 2329fd4e5da5Sopenharmony_ci transformation_context.GetFactManager()->BlockIsDead(block_id)); 2330fd4e5da5Sopenharmony_ci } 2331fd4e5da5Sopenharmony_ci} 2332fd4e5da5Sopenharmony_ci 2333fd4e5da5Sopenharmony_ciTEST(TransformationOutlineFunctionTest, 2334fd4e5da5Sopenharmony_ci OutlineWithIrrelevantVariablesAndParameters) { 2335fd4e5da5Sopenharmony_ci // This checks that if the outlined region uses a mixture of irrelevant and 2336fd4e5da5Sopenharmony_ci // non-irrelevant variables and parameters, these properties are preserved 2337fd4e5da5Sopenharmony_ci // during outlining. 2338fd4e5da5Sopenharmony_ci std::string shader = R"( 2339fd4e5da5Sopenharmony_ci OpCapability Shader 2340fd4e5da5Sopenharmony_ci %1 = OpExtInstImport "GLSL.std.450" 2341fd4e5da5Sopenharmony_ci OpMemoryModel Logical GLSL450 2342fd4e5da5Sopenharmony_ci OpEntryPoint Fragment %4 "main" 2343fd4e5da5Sopenharmony_ci OpExecutionMode %4 OriginUpperLeft 2344fd4e5da5Sopenharmony_ci OpSource ESSL 310 2345fd4e5da5Sopenharmony_ci %2 = OpTypeVoid 2346fd4e5da5Sopenharmony_ci %3 = OpTypeFunction %2 2347fd4e5da5Sopenharmony_ci %6 = OpTypeInt 32 1 2348fd4e5da5Sopenharmony_ci %7 = OpTypePointer Function %6 2349fd4e5da5Sopenharmony_ci %8 = OpTypeFunction %2 %7 %7 2350fd4e5da5Sopenharmony_ci %13 = OpConstant %6 2 2351fd4e5da5Sopenharmony_ci %15 = OpConstant %6 3 2352fd4e5da5Sopenharmony_ci %4 = OpFunction %2 None %3 2353fd4e5da5Sopenharmony_ci %5 = OpLabel 2354fd4e5da5Sopenharmony_ci OpReturn 2355fd4e5da5Sopenharmony_ci OpFunctionEnd 2356fd4e5da5Sopenharmony_ci %11 = OpFunction %2 None %8 2357fd4e5da5Sopenharmony_ci %9 = OpFunctionParameter %7 2358fd4e5da5Sopenharmony_ci %10 = OpFunctionParameter %7 2359fd4e5da5Sopenharmony_ci %12 = OpLabel 2360fd4e5da5Sopenharmony_ci %14 = OpVariable %7 Function 2361fd4e5da5Sopenharmony_ci %20 = OpVariable %7 Function 2362fd4e5da5Sopenharmony_ci OpBranch %50 2363fd4e5da5Sopenharmony_ci %50 = OpLabel 2364fd4e5da5Sopenharmony_ci OpStore %9 %13 2365fd4e5da5Sopenharmony_ci OpStore %14 %15 2366fd4e5da5Sopenharmony_ci %16 = OpLoad %6 %14 2367fd4e5da5Sopenharmony_ci OpStore %10 %16 2368fd4e5da5Sopenharmony_ci %17 = OpLoad %6 %9 2369fd4e5da5Sopenharmony_ci %18 = OpLoad %6 %10 2370fd4e5da5Sopenharmony_ci %19 = OpIAdd %6 %17 %18 2371fd4e5da5Sopenharmony_ci OpStore %14 %19 2372fd4e5da5Sopenharmony_ci %21 = OpLoad %6 %9 2373fd4e5da5Sopenharmony_ci OpStore %20 %21 2374fd4e5da5Sopenharmony_ci OpReturn 2375fd4e5da5Sopenharmony_ci OpFunctionEnd 2376fd4e5da5Sopenharmony_ci )"; 2377fd4e5da5Sopenharmony_ci 2378fd4e5da5Sopenharmony_ci const auto env = SPV_ENV_UNIVERSAL_1_5; 2379fd4e5da5Sopenharmony_ci const auto consumer = nullptr; 2380fd4e5da5Sopenharmony_ci const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption); 2381fd4e5da5Sopenharmony_ci spvtools::ValidatorOptions validator_options; 2382fd4e5da5Sopenharmony_ci ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options, 2383fd4e5da5Sopenharmony_ci kConsoleMessageConsumer)); 2384fd4e5da5Sopenharmony_ci TransformationContext transformation_context( 2385fd4e5da5Sopenharmony_ci MakeUnique<FactManager>(context.get()), validator_options); 2386fd4e5da5Sopenharmony_ci transformation_context.GetFactManager()->AddFactValueOfPointeeIsIrrelevant(9); 2387fd4e5da5Sopenharmony_ci transformation_context.GetFactManager()->AddFactValueOfPointeeIsIrrelevant( 2388fd4e5da5Sopenharmony_ci 14); 2389fd4e5da5Sopenharmony_ci 2390fd4e5da5Sopenharmony_ci TransformationOutlineFunction transformation( 2391fd4e5da5Sopenharmony_ci /*entry_block*/ 50, 2392fd4e5da5Sopenharmony_ci /*exit_block*/ 50, 2393fd4e5da5Sopenharmony_ci /*new_function_struct_return_type_id*/ 200, 2394fd4e5da5Sopenharmony_ci /*new_function_type_id*/ 201, 2395fd4e5da5Sopenharmony_ci /*new_function_id*/ 202, 2396fd4e5da5Sopenharmony_ci /*new_function_region_entry_block*/ 203, 2397fd4e5da5Sopenharmony_ci /*new_caller_result_id*/ 204, 2398fd4e5da5Sopenharmony_ci /*new_callee_result_id*/ 205, 2399fd4e5da5Sopenharmony_ci /*input_id_to_fresh_id*/ {{9, 206}, {10, 207}, {14, 208}, {20, 209}}, 2400fd4e5da5Sopenharmony_ci /*output_id_to_fresh_id*/ {}); 2401fd4e5da5Sopenharmony_ci 2402fd4e5da5Sopenharmony_ci ASSERT_TRUE( 2403fd4e5da5Sopenharmony_ci transformation.IsApplicable(context.get(), transformation_context)); 2404fd4e5da5Sopenharmony_ci ApplyAndCheckFreshIds(transformation, context.get(), &transformation_context); 2405fd4e5da5Sopenharmony_ci ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options, 2406fd4e5da5Sopenharmony_ci kConsoleMessageConsumer)); 2407fd4e5da5Sopenharmony_ci // The variables that were originally irrelevant, plus input parameters 2408fd4e5da5Sopenharmony_ci // corresponding to them, should be irrelevant. The rest should not be. 2409fd4e5da5Sopenharmony_ci for (uint32_t variable_id : {9u, 14u, 206u, 208u}) { 2410fd4e5da5Sopenharmony_ci ASSERT_TRUE( 2411fd4e5da5Sopenharmony_ci transformation_context.GetFactManager()->PointeeValueIsIrrelevant( 2412fd4e5da5Sopenharmony_ci variable_id)); 2413fd4e5da5Sopenharmony_ci } 2414fd4e5da5Sopenharmony_ci for (uint32_t variable_id : {10u, 20u, 207u, 209u}) { 2415fd4e5da5Sopenharmony_ci ASSERT_FALSE( 2416fd4e5da5Sopenharmony_ci transformation_context.GetFactManager()->BlockIsDead(variable_id)); 2417fd4e5da5Sopenharmony_ci } 2418fd4e5da5Sopenharmony_ci} 2419fd4e5da5Sopenharmony_ci 2420fd4e5da5Sopenharmony_ciTEST(TransformationOutlineFunctionTest, 2421fd4e5da5Sopenharmony_ci DoNotOutlineCodeThatProducesUsedPointer) { 2422fd4e5da5Sopenharmony_ci // This checks that we cannot outline a region of code if it produces a 2423fd4e5da5Sopenharmony_ci // pointer result id that gets used outside the region. This avoids creating 2424fd4e5da5Sopenharmony_ci // a struct with a pointer member. 2425fd4e5da5Sopenharmony_ci std::string shader = R"( 2426fd4e5da5Sopenharmony_ci OpCapability Shader 2427fd4e5da5Sopenharmony_ci %1 = OpExtInstImport "GLSL.std.450" 2428fd4e5da5Sopenharmony_ci OpMemoryModel Logical GLSL450 2429fd4e5da5Sopenharmony_ci OpEntryPoint Fragment %6 "main" 2430fd4e5da5Sopenharmony_ci OpExecutionMode %6 OriginUpperLeft 2431fd4e5da5Sopenharmony_ci OpSource ESSL 310 2432fd4e5da5Sopenharmony_ci %2 = OpTypeVoid 2433fd4e5da5Sopenharmony_ci %3 = OpTypeFunction %2 2434fd4e5da5Sopenharmony_ci %21 = OpTypeBool 2435fd4e5da5Sopenharmony_ci %100 = OpTypeInt 32 0 2436fd4e5da5Sopenharmony_ci %99 = OpConstant %100 0 2437fd4e5da5Sopenharmony_ci %101 = OpTypeVector %100 2 2438fd4e5da5Sopenharmony_ci %102 = OpTypePointer Function %100 2439fd4e5da5Sopenharmony_ci %103 = OpTypePointer Function %101 2440fd4e5da5Sopenharmony_ci %6 = OpFunction %2 None %3 2441fd4e5da5Sopenharmony_ci %7 = OpLabel 2442fd4e5da5Sopenharmony_ci %104 = OpVariable %103 Function 2443fd4e5da5Sopenharmony_ci OpBranch %80 2444fd4e5da5Sopenharmony_ci %80 = OpLabel 2445fd4e5da5Sopenharmony_ci %105 = OpAccessChain %102 %104 %99 2446fd4e5da5Sopenharmony_ci OpBranch %106 2447fd4e5da5Sopenharmony_ci %106 = OpLabel 2448fd4e5da5Sopenharmony_ci OpStore %105 %99 2449fd4e5da5Sopenharmony_ci OpReturn 2450fd4e5da5Sopenharmony_ci OpFunctionEnd 2451fd4e5da5Sopenharmony_ci )"; 2452fd4e5da5Sopenharmony_ci 2453fd4e5da5Sopenharmony_ci const auto env = SPV_ENV_UNIVERSAL_1_5; 2454fd4e5da5Sopenharmony_ci const auto consumer = nullptr; 2455fd4e5da5Sopenharmony_ci const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption); 2456fd4e5da5Sopenharmony_ci spvtools::ValidatorOptions validator_options; 2457fd4e5da5Sopenharmony_ci ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options, 2458fd4e5da5Sopenharmony_ci kConsoleMessageConsumer)); 2459fd4e5da5Sopenharmony_ci TransformationContext transformation_context( 2460fd4e5da5Sopenharmony_ci MakeUnique<FactManager>(context.get()), validator_options); 2461fd4e5da5Sopenharmony_ci TransformationOutlineFunction transformation( 2462fd4e5da5Sopenharmony_ci /*entry_block*/ 80, 2463fd4e5da5Sopenharmony_ci /*exit_block*/ 80, 2464fd4e5da5Sopenharmony_ci /*new_function_struct_return_type_id*/ 300, 2465fd4e5da5Sopenharmony_ci /*new_function_type_id*/ 301, 2466fd4e5da5Sopenharmony_ci /*new_function_id*/ 302, 2467fd4e5da5Sopenharmony_ci /*new_function_region_entry_block*/ 304, 2468fd4e5da5Sopenharmony_ci /*new_caller_result_id*/ 305, 2469fd4e5da5Sopenharmony_ci /*new_callee_result_id*/ 306, 2470fd4e5da5Sopenharmony_ci /*input_id_to_fresh_id*/ {{104, 307}}, 2471fd4e5da5Sopenharmony_ci /*output_id_to_fresh_id*/ {{105, 308}}); 2472fd4e5da5Sopenharmony_ci 2473fd4e5da5Sopenharmony_ci ASSERT_FALSE( 2474fd4e5da5Sopenharmony_ci transformation.IsApplicable(context.get(), transformation_context)); 2475fd4e5da5Sopenharmony_ci} 2476fd4e5da5Sopenharmony_ci 2477fd4e5da5Sopenharmony_ciTEST(TransformationOutlineFunctionTest, ExitBlockHeadsLoop) { 2478fd4e5da5Sopenharmony_ci // This checks that it is not possible outline a region that ends in a loop 2479fd4e5da5Sopenharmony_ci // head. 2480fd4e5da5Sopenharmony_ci std::string shader = R"( 2481fd4e5da5Sopenharmony_ci OpCapability Shader 2482fd4e5da5Sopenharmony_ci %1 = OpExtInstImport "GLSL.std.450" 2483fd4e5da5Sopenharmony_ci OpMemoryModel Logical GLSL450 2484fd4e5da5Sopenharmony_ci OpEntryPoint Fragment %4 "main" 2485fd4e5da5Sopenharmony_ci OpExecutionMode %4 OriginUpperLeft 2486fd4e5da5Sopenharmony_ci OpSource ESSL 310 2487fd4e5da5Sopenharmony_ci %2 = OpTypeVoid 2488fd4e5da5Sopenharmony_ci %3 = OpTypeFunction %2 2489fd4e5da5Sopenharmony_ci %15 = OpTypeInt 32 1 2490fd4e5da5Sopenharmony_ci %35 = OpTypeBool 2491fd4e5da5Sopenharmony_ci %39 = OpConstant %15 1 2492fd4e5da5Sopenharmony_ci %40 = OpConstantTrue %35 2493fd4e5da5Sopenharmony_ci %4 = OpFunction %2 None %3 2494fd4e5da5Sopenharmony_ci %5 = OpLabel 2495fd4e5da5Sopenharmony_ci OpBranch %22 2496fd4e5da5Sopenharmony_ci %22 = OpLabel 2497fd4e5da5Sopenharmony_ci OpBranch %23 2498fd4e5da5Sopenharmony_ci %23 = OpLabel 2499fd4e5da5Sopenharmony_ci %24 = OpPhi %15 %39 %22 %39 %25 2500fd4e5da5Sopenharmony_ci OpLoopMerge %26 %25 None 2501fd4e5da5Sopenharmony_ci OpBranchConditional %40 %25 %26 2502fd4e5da5Sopenharmony_ci %25 = OpLabel 2503fd4e5da5Sopenharmony_ci OpBranch %23 2504fd4e5da5Sopenharmony_ci %26 = OpLabel 2505fd4e5da5Sopenharmony_ci OpReturn 2506fd4e5da5Sopenharmony_ci OpFunctionEnd 2507fd4e5da5Sopenharmony_ci )"; 2508fd4e5da5Sopenharmony_ci 2509fd4e5da5Sopenharmony_ci const auto env = SPV_ENV_UNIVERSAL_1_5; 2510fd4e5da5Sopenharmony_ci const auto consumer = nullptr; 2511fd4e5da5Sopenharmony_ci const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption); 2512fd4e5da5Sopenharmony_ci spvtools::ValidatorOptions validator_options; 2513fd4e5da5Sopenharmony_ci ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options, 2514fd4e5da5Sopenharmony_ci kConsoleMessageConsumer)); 2515fd4e5da5Sopenharmony_ci TransformationContext transformation_context( 2516fd4e5da5Sopenharmony_ci MakeUnique<FactManager>(context.get()), validator_options); 2517fd4e5da5Sopenharmony_ci TransformationOutlineFunction transformation( 2518fd4e5da5Sopenharmony_ci /*entry_block*/ 22, 2519fd4e5da5Sopenharmony_ci /*exit_block*/ 23, 2520fd4e5da5Sopenharmony_ci /*new_function_struct_return_type_id*/ 200, 2521fd4e5da5Sopenharmony_ci /*new_function_type_id*/ 201, 2522fd4e5da5Sopenharmony_ci /*new_function_id*/ 202, 2523fd4e5da5Sopenharmony_ci /*new_function_region_entry_block*/ 203, 2524fd4e5da5Sopenharmony_ci /*new_caller_result_id*/ 204, 2525fd4e5da5Sopenharmony_ci /*new_callee_result_id*/ 205, 2526fd4e5da5Sopenharmony_ci /*input_id_to_fresh_id*/ {}, 2527fd4e5da5Sopenharmony_ci /*output_id_to_fresh_id*/ {}); 2528fd4e5da5Sopenharmony_ci 2529fd4e5da5Sopenharmony_ci ASSERT_FALSE( 2530fd4e5da5Sopenharmony_ci transformation.IsApplicable(context.get(), transformation_context)); 2531fd4e5da5Sopenharmony_ci ApplyAndCheckFreshIds(transformation, context.get(), &transformation_context); 2532fd4e5da5Sopenharmony_ci} 2533fd4e5da5Sopenharmony_ci 2534fd4e5da5Sopenharmony_ciTEST(TransformationOutlineFunctionTest, Miscellaneous1) { 2535fd4e5da5Sopenharmony_ci // This tests outlining of some non-trivial code, and also tests the way 2536fd4e5da5Sopenharmony_ci // overflow ids are used by the transformation. 2537fd4e5da5Sopenharmony_ci 2538fd4e5da5Sopenharmony_ci std::string reference_shader = R"( 2539fd4e5da5Sopenharmony_ci OpCapability Shader 2540fd4e5da5Sopenharmony_ci %1 = OpExtInstImport "GLSL.std.450" 2541fd4e5da5Sopenharmony_ci OpMemoryModel Logical GLSL450 2542fd4e5da5Sopenharmony_ci OpEntryPoint Fragment %4 "main" %85 2543fd4e5da5Sopenharmony_ci OpExecutionMode %4 OriginUpperLeft 2544fd4e5da5Sopenharmony_ci OpSource ESSL 310 2545fd4e5da5Sopenharmony_ci OpName %4 "main" 2546fd4e5da5Sopenharmony_ci OpName %28 "buf" 2547fd4e5da5Sopenharmony_ci OpMemberName %28 0 "u1" 2548fd4e5da5Sopenharmony_ci OpMemberName %28 1 "u2" 2549fd4e5da5Sopenharmony_ci OpName %30 "" 2550fd4e5da5Sopenharmony_ci OpName %85 "color" 2551fd4e5da5Sopenharmony_ci OpMemberDecorate %28 0 Offset 0 2552fd4e5da5Sopenharmony_ci OpMemberDecorate %28 1 Offset 4 2553fd4e5da5Sopenharmony_ci OpDecorate %28 Block 2554fd4e5da5Sopenharmony_ci OpDecorate %30 DescriptorSet 0 2555fd4e5da5Sopenharmony_ci OpDecorate %30 Binding 0 2556fd4e5da5Sopenharmony_ci OpDecorate %85 Location 0 2557fd4e5da5Sopenharmony_ci %2 = OpTypeVoid 2558fd4e5da5Sopenharmony_ci %3 = OpTypeFunction %2 2559fd4e5da5Sopenharmony_ci %6 = OpTypeFloat 32 2560fd4e5da5Sopenharmony_ci %7 = OpTypeVector %6 4 2561fd4e5da5Sopenharmony_ci %10 = OpConstant %6 1 2562fd4e5da5Sopenharmony_ci %11 = OpConstant %6 2 2563fd4e5da5Sopenharmony_ci %12 = OpConstant %6 3 2564fd4e5da5Sopenharmony_ci %13 = OpConstant %6 4 2565fd4e5da5Sopenharmony_ci %14 = OpConstantComposite %7 %10 %11 %12 %13 2566fd4e5da5Sopenharmony_ci %15 = OpTypeInt 32 1 2567fd4e5da5Sopenharmony_ci %18 = OpConstant %15 0 2568fd4e5da5Sopenharmony_ci %28 = OpTypeStruct %6 %6 2569fd4e5da5Sopenharmony_ci %29 = OpTypePointer Uniform %28 2570fd4e5da5Sopenharmony_ci %30 = OpVariable %29 Uniform 2571fd4e5da5Sopenharmony_ci %31 = OpTypePointer Uniform %6 2572fd4e5da5Sopenharmony_ci %35 = OpTypeBool 2573fd4e5da5Sopenharmony_ci %39 = OpConstant %15 1 2574fd4e5da5Sopenharmony_ci %84 = OpTypePointer Output %7 2575fd4e5da5Sopenharmony_ci %85 = OpVariable %84 Output 2576fd4e5da5Sopenharmony_ci %114 = OpConstant %15 8 2577fd4e5da5Sopenharmony_ci %4 = OpFunction %2 None %3 2578fd4e5da5Sopenharmony_ci %5 = OpLabel 2579fd4e5da5Sopenharmony_ci OpBranch %22 2580fd4e5da5Sopenharmony_ci %22 = OpLabel 2581fd4e5da5Sopenharmony_ci %103 = OpPhi %15 %18 %5 %106 %43 2582fd4e5da5Sopenharmony_ci %102 = OpPhi %7 %14 %5 %107 %43 2583fd4e5da5Sopenharmony_ci %101 = OpPhi %15 %18 %5 %40 %43 2584fd4e5da5Sopenharmony_ci %32 = OpAccessChain %31 %30 %18 2585fd4e5da5Sopenharmony_ci %33 = OpLoad %6 %32 2586fd4e5da5Sopenharmony_ci %34 = OpConvertFToS %15 %33 2587fd4e5da5Sopenharmony_ci %36 = OpSLessThan %35 %101 %34 2588fd4e5da5Sopenharmony_ci OpLoopMerge %24 %43 None 2589fd4e5da5Sopenharmony_ci OpBranchConditional %36 %23 %24 2590fd4e5da5Sopenharmony_ci %23 = OpLabel 2591fd4e5da5Sopenharmony_ci %40 = OpIAdd %15 %101 %39 2592fd4e5da5Sopenharmony_ci OpBranch %150 2593fd4e5da5Sopenharmony_ci %150 = OpLabel 2594fd4e5da5Sopenharmony_ci OpBranch %41 2595fd4e5da5Sopenharmony_ci %41 = OpLabel 2596fd4e5da5Sopenharmony_ci %107 = OpPhi %7 %102 %150 %111 %65 2597fd4e5da5Sopenharmony_ci %106 = OpPhi %15 %103 %150 %110 %65 2598fd4e5da5Sopenharmony_ci %104 = OpPhi %15 %40 %150 %81 %65 2599fd4e5da5Sopenharmony_ci %47 = OpAccessChain %31 %30 %39 2600fd4e5da5Sopenharmony_ci %48 = OpLoad %6 %47 2601fd4e5da5Sopenharmony_ci %49 = OpConvertFToS %15 %48 2602fd4e5da5Sopenharmony_ci %50 = OpSLessThan %35 %104 %49 2603fd4e5da5Sopenharmony_ci OpLoopMerge %1000 %65 None 2604fd4e5da5Sopenharmony_ci OpBranchConditional %50 %42 %1000 2605fd4e5da5Sopenharmony_ci %42 = OpLabel 2606fd4e5da5Sopenharmony_ci %60 = OpIAdd %15 %106 %114 2607fd4e5da5Sopenharmony_ci %63 = OpSGreaterThan %35 %104 %60 2608fd4e5da5Sopenharmony_ci OpBranchConditional %63 %64 %65 2609fd4e5da5Sopenharmony_ci %64 = OpLabel 2610fd4e5da5Sopenharmony_ci %71 = OpCompositeExtract %6 %107 0 2611fd4e5da5Sopenharmony_ci %72 = OpFAdd %6 %71 %11 2612fd4e5da5Sopenharmony_ci %97 = OpCompositeInsert %7 %72 %107 0 2613fd4e5da5Sopenharmony_ci %76 = OpCompositeExtract %6 %107 3 2614fd4e5da5Sopenharmony_ci %77 = OpConvertFToS %15 %76 2615fd4e5da5Sopenharmony_ci %79 = OpIAdd %15 %60 %77 2616fd4e5da5Sopenharmony_ci OpBranch %65 2617fd4e5da5Sopenharmony_ci %65 = OpLabel 2618fd4e5da5Sopenharmony_ci %111 = OpPhi %7 %107 %42 %97 %64 2619fd4e5da5Sopenharmony_ci %110 = OpPhi %15 %60 %42 %79 %64 2620fd4e5da5Sopenharmony_ci %81 = OpIAdd %15 %104 %39 2621fd4e5da5Sopenharmony_ci OpBranch %41 2622fd4e5da5Sopenharmony_ci %1000 = OpLabel 2623fd4e5da5Sopenharmony_ci OpBranch %1001 2624fd4e5da5Sopenharmony_ci %1001 = OpLabel 2625fd4e5da5Sopenharmony_ci OpBranch %43 2626fd4e5da5Sopenharmony_ci %43 = OpLabel 2627fd4e5da5Sopenharmony_ci OpBranch %22 2628fd4e5da5Sopenharmony_ci %24 = OpLabel 2629fd4e5da5Sopenharmony_ci %87 = OpCompositeExtract %6 %102 0 2630fd4e5da5Sopenharmony_ci %91 = OpConvertSToF %6 %103 2631fd4e5da5Sopenharmony_ci %92 = OpCompositeConstruct %7 %87 %11 %91 %10 2632fd4e5da5Sopenharmony_ci OpStore %85 %92 2633fd4e5da5Sopenharmony_ci OpReturn 2634fd4e5da5Sopenharmony_ci OpFunctionEnd 2635fd4e5da5Sopenharmony_ci )"; 2636fd4e5da5Sopenharmony_ci 2637fd4e5da5Sopenharmony_ci const auto env = SPV_ENV_UNIVERSAL_1_3; 2638fd4e5da5Sopenharmony_ci const auto consumer = nullptr; 2639fd4e5da5Sopenharmony_ci spvtools::ValidatorOptions validator_options; 2640fd4e5da5Sopenharmony_ci 2641fd4e5da5Sopenharmony_ci TransformationOutlineFunction transformation( 2642fd4e5da5Sopenharmony_ci /*entry_block*/ 150, 2643fd4e5da5Sopenharmony_ci /*exit_block*/ 1001, 2644fd4e5da5Sopenharmony_ci /*new_function_struct_return_type_id*/ 200, 2645fd4e5da5Sopenharmony_ci /*new_function_type_id*/ 201, 2646fd4e5da5Sopenharmony_ci /*new_function_id*/ 202, 2647fd4e5da5Sopenharmony_ci /*new_function_region_entry_block*/ 203, 2648fd4e5da5Sopenharmony_ci /*new_caller_result_id*/ 204, 2649fd4e5da5Sopenharmony_ci /*new_callee_result_id*/ 205, 2650fd4e5da5Sopenharmony_ci /*input_id_to_fresh_id*/ {{102, 300}, {103, 301}, {40, 302}}, 2651fd4e5da5Sopenharmony_ci /*output_id_to_fresh_id*/ {{106, 400}, {107, 401}}); 2652fd4e5da5Sopenharmony_ci 2653fd4e5da5Sopenharmony_ci TransformationOutlineFunction transformation_with_missing_input_id( 2654fd4e5da5Sopenharmony_ci /*entry_block*/ 150, 2655fd4e5da5Sopenharmony_ci /*exit_block*/ 1001, 2656fd4e5da5Sopenharmony_ci /*new_function_struct_return_type_id*/ 200, 2657fd4e5da5Sopenharmony_ci /*new_function_type_id*/ 201, 2658fd4e5da5Sopenharmony_ci /*new_function_id*/ 202, 2659fd4e5da5Sopenharmony_ci /*new_function_region_entry_block*/ 203, 2660fd4e5da5Sopenharmony_ci /*new_caller_result_id*/ 204, 2661fd4e5da5Sopenharmony_ci /*new_callee_result_id*/ 205, 2662fd4e5da5Sopenharmony_ci /*input_id_to_fresh_id*/ {{102, 300}, {40, 302}}, 2663fd4e5da5Sopenharmony_ci /*output_id_to_fresh_id*/ {{106, 400}, {107, 401}}); 2664fd4e5da5Sopenharmony_ci 2665fd4e5da5Sopenharmony_ci TransformationOutlineFunction transformation_with_missing_output_id( 2666fd4e5da5Sopenharmony_ci /*entry_block*/ 150, 2667fd4e5da5Sopenharmony_ci /*exit_block*/ 1001, 2668fd4e5da5Sopenharmony_ci /*new_function_struct_return_type_id*/ 200, 2669fd4e5da5Sopenharmony_ci /*new_function_type_id*/ 201, 2670fd4e5da5Sopenharmony_ci /*new_function_id*/ 202, 2671fd4e5da5Sopenharmony_ci /*new_function_region_entry_block*/ 203, 2672fd4e5da5Sopenharmony_ci /*new_caller_result_id*/ 204, 2673fd4e5da5Sopenharmony_ci /*new_callee_result_id*/ 205, 2674fd4e5da5Sopenharmony_ci /*input_id_to_fresh_id*/ {{102, 300}, {103, 301}, {40, 302}}, 2675fd4e5da5Sopenharmony_ci /*output_id_to_fresh_id*/ {{106, 400}}); 2676fd4e5da5Sopenharmony_ci 2677fd4e5da5Sopenharmony_ci TransformationOutlineFunction 2678fd4e5da5Sopenharmony_ci transformation_with_missing_input_and_output_ids( 2679fd4e5da5Sopenharmony_ci /*entry_block*/ 150, 2680fd4e5da5Sopenharmony_ci /*exit_block*/ 1001, 2681fd4e5da5Sopenharmony_ci /*new_function_struct_return_type_id*/ 200, 2682fd4e5da5Sopenharmony_ci /*new_function_type_id*/ 201, 2683fd4e5da5Sopenharmony_ci /*new_function_id*/ 202, 2684fd4e5da5Sopenharmony_ci /*new_function_region_entry_block*/ 203, 2685fd4e5da5Sopenharmony_ci /*new_caller_result_id*/ 204, 2686fd4e5da5Sopenharmony_ci /*new_callee_result_id*/ 205, 2687fd4e5da5Sopenharmony_ci /*input_id_to_fresh_id*/ {{102, 300}, {40, 302}}, 2688fd4e5da5Sopenharmony_ci /*output_id_to_fresh_id*/ {{106, 400}}); 2689fd4e5da5Sopenharmony_ci 2690fd4e5da5Sopenharmony_ci { 2691fd4e5da5Sopenharmony_ci const auto context = 2692fd4e5da5Sopenharmony_ci BuildModule(env, consumer, reference_shader, kFuzzAssembleOption); 2693fd4e5da5Sopenharmony_ci ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed( 2694fd4e5da5Sopenharmony_ci context.get(), validator_options, kConsoleMessageConsumer)); 2695fd4e5da5Sopenharmony_ci 2696fd4e5da5Sopenharmony_ci TransformationContext transformation_context( 2697fd4e5da5Sopenharmony_ci MakeUnique<FactManager>(context.get()), validator_options); 2698fd4e5da5Sopenharmony_ci 2699fd4e5da5Sopenharmony_ci#ifndef NDEBUG 2700fd4e5da5Sopenharmony_ci // We expect the following applicability checks to lead to assertion 2701fd4e5da5Sopenharmony_ci // failures since the transformations are missing input or output ids, and 2702fd4e5da5Sopenharmony_ci // the transformation context does not have a source of overflow ids. 2703fd4e5da5Sopenharmony_ci ASSERT_DEATH(transformation_with_missing_input_id.IsApplicable( 2704fd4e5da5Sopenharmony_ci context.get(), transformation_context), 2705fd4e5da5Sopenharmony_ci "Bad attempt to query whether overflow ids are available."); 2706fd4e5da5Sopenharmony_ci ASSERT_DEATH(transformation_with_missing_output_id.IsApplicable( 2707fd4e5da5Sopenharmony_ci context.get(), transformation_context), 2708fd4e5da5Sopenharmony_ci "Bad attempt to query whether overflow ids are available."); 2709fd4e5da5Sopenharmony_ci ASSERT_DEATH(transformation_with_missing_input_and_output_ids.IsApplicable( 2710fd4e5da5Sopenharmony_ci context.get(), transformation_context), 2711fd4e5da5Sopenharmony_ci "Bad attempt to query whether overflow ids are available."); 2712fd4e5da5Sopenharmony_ci#endif 2713fd4e5da5Sopenharmony_ci 2714fd4e5da5Sopenharmony_ci ASSERT_TRUE( 2715fd4e5da5Sopenharmony_ci transformation.IsApplicable(context.get(), transformation_context)); 2716fd4e5da5Sopenharmony_ci ApplyAndCheckFreshIds(transformation, context.get(), 2717fd4e5da5Sopenharmony_ci &transformation_context); 2718fd4e5da5Sopenharmony_ci ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed( 2719fd4e5da5Sopenharmony_ci context.get(), validator_options, kConsoleMessageConsumer)); 2720fd4e5da5Sopenharmony_ci 2721fd4e5da5Sopenharmony_ci std::string variant_shader = R"( 2722fd4e5da5Sopenharmony_ci OpCapability Shader 2723fd4e5da5Sopenharmony_ci %1 = OpExtInstImport "GLSL.std.450" 2724fd4e5da5Sopenharmony_ci OpMemoryModel Logical GLSL450 2725fd4e5da5Sopenharmony_ci OpEntryPoint Fragment %4 "main" %85 2726fd4e5da5Sopenharmony_ci OpExecutionMode %4 OriginUpperLeft 2727fd4e5da5Sopenharmony_ci OpSource ESSL 310 2728fd4e5da5Sopenharmony_ci OpName %4 "main" 2729fd4e5da5Sopenharmony_ci OpName %28 "buf" 2730fd4e5da5Sopenharmony_ci OpMemberName %28 0 "u1" 2731fd4e5da5Sopenharmony_ci OpMemberName %28 1 "u2" 2732fd4e5da5Sopenharmony_ci OpName %30 "" 2733fd4e5da5Sopenharmony_ci OpName %85 "color" 2734fd4e5da5Sopenharmony_ci OpMemberDecorate %28 0 Offset 0 2735fd4e5da5Sopenharmony_ci OpMemberDecorate %28 1 Offset 4 2736fd4e5da5Sopenharmony_ci OpDecorate %28 Block 2737fd4e5da5Sopenharmony_ci OpDecorate %30 DescriptorSet 0 2738fd4e5da5Sopenharmony_ci OpDecorate %30 Binding 0 2739fd4e5da5Sopenharmony_ci OpDecorate %85 Location 0 2740fd4e5da5Sopenharmony_ci %2 = OpTypeVoid 2741fd4e5da5Sopenharmony_ci %3 = OpTypeFunction %2 2742fd4e5da5Sopenharmony_ci %6 = OpTypeFloat 32 2743fd4e5da5Sopenharmony_ci %7 = OpTypeVector %6 4 2744fd4e5da5Sopenharmony_ci %10 = OpConstant %6 1 2745fd4e5da5Sopenharmony_ci %11 = OpConstant %6 2 2746fd4e5da5Sopenharmony_ci %12 = OpConstant %6 3 2747fd4e5da5Sopenharmony_ci %13 = OpConstant %6 4 2748fd4e5da5Sopenharmony_ci %14 = OpConstantComposite %7 %10 %11 %12 %13 2749fd4e5da5Sopenharmony_ci %15 = OpTypeInt 32 1 2750fd4e5da5Sopenharmony_ci %18 = OpConstant %15 0 2751fd4e5da5Sopenharmony_ci %28 = OpTypeStruct %6 %6 2752fd4e5da5Sopenharmony_ci %29 = OpTypePointer Uniform %28 2753fd4e5da5Sopenharmony_ci %30 = OpVariable %29 Uniform 2754fd4e5da5Sopenharmony_ci %31 = OpTypePointer Uniform %6 2755fd4e5da5Sopenharmony_ci %35 = OpTypeBool 2756fd4e5da5Sopenharmony_ci %39 = OpConstant %15 1 2757fd4e5da5Sopenharmony_ci %84 = OpTypePointer Output %7 2758fd4e5da5Sopenharmony_ci %85 = OpVariable %84 Output 2759fd4e5da5Sopenharmony_ci %114 = OpConstant %15 8 2760fd4e5da5Sopenharmony_ci %200 = OpTypeStruct %7 %15 2761fd4e5da5Sopenharmony_ci %201 = OpTypeFunction %200 %15 %7 %15 2762fd4e5da5Sopenharmony_ci %4 = OpFunction %2 None %3 2763fd4e5da5Sopenharmony_ci %5 = OpLabel 2764fd4e5da5Sopenharmony_ci OpBranch %22 2765fd4e5da5Sopenharmony_ci %22 = OpLabel 2766fd4e5da5Sopenharmony_ci %103 = OpPhi %15 %18 %5 %106 %43 2767fd4e5da5Sopenharmony_ci %102 = OpPhi %7 %14 %5 %107 %43 2768fd4e5da5Sopenharmony_ci %101 = OpPhi %15 %18 %5 %40 %43 2769fd4e5da5Sopenharmony_ci %32 = OpAccessChain %31 %30 %18 2770fd4e5da5Sopenharmony_ci %33 = OpLoad %6 %32 2771fd4e5da5Sopenharmony_ci %34 = OpConvertFToS %15 %33 2772fd4e5da5Sopenharmony_ci %36 = OpSLessThan %35 %101 %34 2773fd4e5da5Sopenharmony_ci OpLoopMerge %24 %43 None 2774fd4e5da5Sopenharmony_ci OpBranchConditional %36 %23 %24 2775fd4e5da5Sopenharmony_ci %23 = OpLabel 2776fd4e5da5Sopenharmony_ci %40 = OpIAdd %15 %101 %39 2777fd4e5da5Sopenharmony_ci OpBranch %150 2778fd4e5da5Sopenharmony_ci %150 = OpLabel 2779fd4e5da5Sopenharmony_ci %204 = OpFunctionCall %200 %202 %103 %102 %40 2780fd4e5da5Sopenharmony_ci %107 = OpCompositeExtract %7 %204 0 2781fd4e5da5Sopenharmony_ci %106 = OpCompositeExtract %15 %204 1 2782fd4e5da5Sopenharmony_ci OpBranch %43 2783fd4e5da5Sopenharmony_ci %43 = OpLabel 2784fd4e5da5Sopenharmony_ci OpBranch %22 2785fd4e5da5Sopenharmony_ci %24 = OpLabel 2786fd4e5da5Sopenharmony_ci %87 = OpCompositeExtract %6 %102 0 2787fd4e5da5Sopenharmony_ci %91 = OpConvertSToF %6 %103 2788fd4e5da5Sopenharmony_ci %92 = OpCompositeConstruct %7 %87 %11 %91 %10 2789fd4e5da5Sopenharmony_ci OpStore %85 %92 2790fd4e5da5Sopenharmony_ci OpReturn 2791fd4e5da5Sopenharmony_ci OpFunctionEnd 2792fd4e5da5Sopenharmony_ci %202 = OpFunction %200 None %201 2793fd4e5da5Sopenharmony_ci %301 = OpFunctionParameter %15 2794fd4e5da5Sopenharmony_ci %300 = OpFunctionParameter %7 2795fd4e5da5Sopenharmony_ci %302 = OpFunctionParameter %15 2796fd4e5da5Sopenharmony_ci %203 = OpLabel 2797fd4e5da5Sopenharmony_ci OpBranch %41 2798fd4e5da5Sopenharmony_ci %41 = OpLabel 2799fd4e5da5Sopenharmony_ci %401 = OpPhi %7 %300 %203 %111 %65 2800fd4e5da5Sopenharmony_ci %400 = OpPhi %15 %301 %203 %110 %65 2801fd4e5da5Sopenharmony_ci %104 = OpPhi %15 %302 %203 %81 %65 2802fd4e5da5Sopenharmony_ci %47 = OpAccessChain %31 %30 %39 2803fd4e5da5Sopenharmony_ci %48 = OpLoad %6 %47 2804fd4e5da5Sopenharmony_ci %49 = OpConvertFToS %15 %48 2805fd4e5da5Sopenharmony_ci %50 = OpSLessThan %35 %104 %49 2806fd4e5da5Sopenharmony_ci OpLoopMerge %1000 %65 None 2807fd4e5da5Sopenharmony_ci OpBranchConditional %50 %42 %1000 2808fd4e5da5Sopenharmony_ci %42 = OpLabel 2809fd4e5da5Sopenharmony_ci %60 = OpIAdd %15 %400 %114 2810fd4e5da5Sopenharmony_ci %63 = OpSGreaterThan %35 %104 %60 2811fd4e5da5Sopenharmony_ci OpBranchConditional %63 %64 %65 2812fd4e5da5Sopenharmony_ci %64 = OpLabel 2813fd4e5da5Sopenharmony_ci %71 = OpCompositeExtract %6 %401 0 2814fd4e5da5Sopenharmony_ci %72 = OpFAdd %6 %71 %11 2815fd4e5da5Sopenharmony_ci %97 = OpCompositeInsert %7 %72 %401 0 2816fd4e5da5Sopenharmony_ci %76 = OpCompositeExtract %6 %401 3 2817fd4e5da5Sopenharmony_ci %77 = OpConvertFToS %15 %76 2818fd4e5da5Sopenharmony_ci %79 = OpIAdd %15 %60 %77 2819fd4e5da5Sopenharmony_ci OpBranch %65 2820fd4e5da5Sopenharmony_ci %65 = OpLabel 2821fd4e5da5Sopenharmony_ci %111 = OpPhi %7 %401 %42 %97 %64 2822fd4e5da5Sopenharmony_ci %110 = OpPhi %15 %60 %42 %79 %64 2823fd4e5da5Sopenharmony_ci %81 = OpIAdd %15 %104 %39 2824fd4e5da5Sopenharmony_ci OpBranch %41 2825fd4e5da5Sopenharmony_ci %1000 = OpLabel 2826fd4e5da5Sopenharmony_ci OpBranch %1001 2827fd4e5da5Sopenharmony_ci %1001 = OpLabel 2828fd4e5da5Sopenharmony_ci %205 = OpCompositeConstruct %200 %401 %400 2829fd4e5da5Sopenharmony_ci OpReturnValue %205 2830fd4e5da5Sopenharmony_ci OpFunctionEnd 2831fd4e5da5Sopenharmony_ci )"; 2832fd4e5da5Sopenharmony_ci ASSERT_TRUE(IsEqual(env, variant_shader, context.get())); 2833fd4e5da5Sopenharmony_ci } 2834fd4e5da5Sopenharmony_ci 2835fd4e5da5Sopenharmony_ci { 2836fd4e5da5Sopenharmony_ci const auto context = 2837fd4e5da5Sopenharmony_ci BuildModule(env, consumer, reference_shader, kFuzzAssembleOption); 2838fd4e5da5Sopenharmony_ci ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed( 2839fd4e5da5Sopenharmony_ci context.get(), validator_options, kConsoleMessageConsumer)); 2840fd4e5da5Sopenharmony_ci auto overflow_ids_unique_ptr = MakeUnique<CounterOverflowIdSource>(2000); 2841fd4e5da5Sopenharmony_ci auto overflow_ids_ptr = overflow_ids_unique_ptr.get(); 2842fd4e5da5Sopenharmony_ci TransformationContext new_transformation_context( 2843fd4e5da5Sopenharmony_ci MakeUnique<FactManager>(context.get()), validator_options, 2844fd4e5da5Sopenharmony_ci std::move(overflow_ids_unique_ptr)); 2845fd4e5da5Sopenharmony_ci ASSERT_TRUE(transformation_with_missing_input_id.IsApplicable( 2846fd4e5da5Sopenharmony_ci context.get(), new_transformation_context)); 2847fd4e5da5Sopenharmony_ci ASSERT_TRUE(transformation_with_missing_output_id.IsApplicable( 2848fd4e5da5Sopenharmony_ci context.get(), new_transformation_context)); 2849fd4e5da5Sopenharmony_ci ASSERT_TRUE(transformation_with_missing_input_and_output_ids.IsApplicable( 2850fd4e5da5Sopenharmony_ci context.get(), new_transformation_context)); 2851fd4e5da5Sopenharmony_ci ApplyAndCheckFreshIds(transformation_with_missing_input_and_output_ids, 2852fd4e5da5Sopenharmony_ci context.get(), &new_transformation_context, 2853fd4e5da5Sopenharmony_ci overflow_ids_ptr->GetIssuedOverflowIds()); 2854fd4e5da5Sopenharmony_ci ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed( 2855fd4e5da5Sopenharmony_ci context.get(), validator_options, kConsoleMessageConsumer)); 2856fd4e5da5Sopenharmony_ci 2857fd4e5da5Sopenharmony_ci std::string variant_shader = R"( 2858fd4e5da5Sopenharmony_ci OpCapability Shader 2859fd4e5da5Sopenharmony_ci %1 = OpExtInstImport "GLSL.std.450" 2860fd4e5da5Sopenharmony_ci OpMemoryModel Logical GLSL450 2861fd4e5da5Sopenharmony_ci OpEntryPoint Fragment %4 "main" %85 2862fd4e5da5Sopenharmony_ci OpExecutionMode %4 OriginUpperLeft 2863fd4e5da5Sopenharmony_ci OpSource ESSL 310 2864fd4e5da5Sopenharmony_ci OpName %4 "main" 2865fd4e5da5Sopenharmony_ci OpName %28 "buf" 2866fd4e5da5Sopenharmony_ci OpMemberName %28 0 "u1" 2867fd4e5da5Sopenharmony_ci OpMemberName %28 1 "u2" 2868fd4e5da5Sopenharmony_ci OpName %30 "" 2869fd4e5da5Sopenharmony_ci OpName %85 "color" 2870fd4e5da5Sopenharmony_ci OpMemberDecorate %28 0 Offset 0 2871fd4e5da5Sopenharmony_ci OpMemberDecorate %28 1 Offset 4 2872fd4e5da5Sopenharmony_ci OpDecorate %28 Block 2873fd4e5da5Sopenharmony_ci OpDecorate %30 DescriptorSet 0 2874fd4e5da5Sopenharmony_ci OpDecorate %30 Binding 0 2875fd4e5da5Sopenharmony_ci OpDecorate %85 Location 0 2876fd4e5da5Sopenharmony_ci %2 = OpTypeVoid 2877fd4e5da5Sopenharmony_ci %3 = OpTypeFunction %2 2878fd4e5da5Sopenharmony_ci %6 = OpTypeFloat 32 2879fd4e5da5Sopenharmony_ci %7 = OpTypeVector %6 4 2880fd4e5da5Sopenharmony_ci %10 = OpConstant %6 1 2881fd4e5da5Sopenharmony_ci %11 = OpConstant %6 2 2882fd4e5da5Sopenharmony_ci %12 = OpConstant %6 3 2883fd4e5da5Sopenharmony_ci %13 = OpConstant %6 4 2884fd4e5da5Sopenharmony_ci %14 = OpConstantComposite %7 %10 %11 %12 %13 2885fd4e5da5Sopenharmony_ci %15 = OpTypeInt 32 1 2886fd4e5da5Sopenharmony_ci %18 = OpConstant %15 0 2887fd4e5da5Sopenharmony_ci %28 = OpTypeStruct %6 %6 2888fd4e5da5Sopenharmony_ci %29 = OpTypePointer Uniform %28 2889fd4e5da5Sopenharmony_ci %30 = OpVariable %29 Uniform 2890fd4e5da5Sopenharmony_ci %31 = OpTypePointer Uniform %6 2891fd4e5da5Sopenharmony_ci %35 = OpTypeBool 2892fd4e5da5Sopenharmony_ci %39 = OpConstant %15 1 2893fd4e5da5Sopenharmony_ci %84 = OpTypePointer Output %7 2894fd4e5da5Sopenharmony_ci %85 = OpVariable %84 Output 2895fd4e5da5Sopenharmony_ci %114 = OpConstant %15 8 2896fd4e5da5Sopenharmony_ci %200 = OpTypeStruct %7 %15 2897fd4e5da5Sopenharmony_ci %201 = OpTypeFunction %200 %15 %7 %15 2898fd4e5da5Sopenharmony_ci %4 = OpFunction %2 None %3 2899fd4e5da5Sopenharmony_ci %5 = OpLabel 2900fd4e5da5Sopenharmony_ci OpBranch %22 2901fd4e5da5Sopenharmony_ci %22 = OpLabel 2902fd4e5da5Sopenharmony_ci %103 = OpPhi %15 %18 %5 %106 %43 2903fd4e5da5Sopenharmony_ci %102 = OpPhi %7 %14 %5 %107 %43 2904fd4e5da5Sopenharmony_ci %101 = OpPhi %15 %18 %5 %40 %43 2905fd4e5da5Sopenharmony_ci %32 = OpAccessChain %31 %30 %18 2906fd4e5da5Sopenharmony_ci %33 = OpLoad %6 %32 2907fd4e5da5Sopenharmony_ci %34 = OpConvertFToS %15 %33 2908fd4e5da5Sopenharmony_ci %36 = OpSLessThan %35 %101 %34 2909fd4e5da5Sopenharmony_ci OpLoopMerge %24 %43 None 2910fd4e5da5Sopenharmony_ci OpBranchConditional %36 %23 %24 2911fd4e5da5Sopenharmony_ci %23 = OpLabel 2912fd4e5da5Sopenharmony_ci %40 = OpIAdd %15 %101 %39 2913fd4e5da5Sopenharmony_ci OpBranch %150 2914fd4e5da5Sopenharmony_ci %150 = OpLabel 2915fd4e5da5Sopenharmony_ci %204 = OpFunctionCall %200 %202 %103 %102 %40 2916fd4e5da5Sopenharmony_ci %107 = OpCompositeExtract %7 %204 0 2917fd4e5da5Sopenharmony_ci %106 = OpCompositeExtract %15 %204 1 2918fd4e5da5Sopenharmony_ci OpBranch %43 2919fd4e5da5Sopenharmony_ci %43 = OpLabel 2920fd4e5da5Sopenharmony_ci OpBranch %22 2921fd4e5da5Sopenharmony_ci %24 = OpLabel 2922fd4e5da5Sopenharmony_ci %87 = OpCompositeExtract %6 %102 0 2923fd4e5da5Sopenharmony_ci %91 = OpConvertSToF %6 %103 2924fd4e5da5Sopenharmony_ci %92 = OpCompositeConstruct %7 %87 %11 %91 %10 2925fd4e5da5Sopenharmony_ci OpStore %85 %92 2926fd4e5da5Sopenharmony_ci OpReturn 2927fd4e5da5Sopenharmony_ci OpFunctionEnd 2928fd4e5da5Sopenharmony_ci %202 = OpFunction %200 None %201 2929fd4e5da5Sopenharmony_ci %2000 = OpFunctionParameter %15 2930fd4e5da5Sopenharmony_ci %300 = OpFunctionParameter %7 2931fd4e5da5Sopenharmony_ci %302 = OpFunctionParameter %15 2932fd4e5da5Sopenharmony_ci %203 = OpLabel 2933fd4e5da5Sopenharmony_ci OpBranch %41 2934fd4e5da5Sopenharmony_ci %41 = OpLabel 2935fd4e5da5Sopenharmony_ci %2001 = OpPhi %7 %300 %203 %111 %65 2936fd4e5da5Sopenharmony_ci %400 = OpPhi %15 %2000 %203 %110 %65 2937fd4e5da5Sopenharmony_ci %104 = OpPhi %15 %302 %203 %81 %65 2938fd4e5da5Sopenharmony_ci %47 = OpAccessChain %31 %30 %39 2939fd4e5da5Sopenharmony_ci %48 = OpLoad %6 %47 2940fd4e5da5Sopenharmony_ci %49 = OpConvertFToS %15 %48 2941fd4e5da5Sopenharmony_ci %50 = OpSLessThan %35 %104 %49 2942fd4e5da5Sopenharmony_ci OpLoopMerge %1000 %65 None 2943fd4e5da5Sopenharmony_ci OpBranchConditional %50 %42 %1000 2944fd4e5da5Sopenharmony_ci %42 = OpLabel 2945fd4e5da5Sopenharmony_ci %60 = OpIAdd %15 %400 %114 2946fd4e5da5Sopenharmony_ci %63 = OpSGreaterThan %35 %104 %60 2947fd4e5da5Sopenharmony_ci OpBranchConditional %63 %64 %65 2948fd4e5da5Sopenharmony_ci %64 = OpLabel 2949fd4e5da5Sopenharmony_ci %71 = OpCompositeExtract %6 %2001 0 2950fd4e5da5Sopenharmony_ci %72 = OpFAdd %6 %71 %11 2951fd4e5da5Sopenharmony_ci %97 = OpCompositeInsert %7 %72 %2001 0 2952fd4e5da5Sopenharmony_ci %76 = OpCompositeExtract %6 %2001 3 2953fd4e5da5Sopenharmony_ci %77 = OpConvertFToS %15 %76 2954fd4e5da5Sopenharmony_ci %79 = OpIAdd %15 %60 %77 2955fd4e5da5Sopenharmony_ci OpBranch %65 2956fd4e5da5Sopenharmony_ci %65 = OpLabel 2957fd4e5da5Sopenharmony_ci %111 = OpPhi %7 %2001 %42 %97 %64 2958fd4e5da5Sopenharmony_ci %110 = OpPhi %15 %60 %42 %79 %64 2959fd4e5da5Sopenharmony_ci %81 = OpIAdd %15 %104 %39 2960fd4e5da5Sopenharmony_ci OpBranch %41 2961fd4e5da5Sopenharmony_ci %1000 = OpLabel 2962fd4e5da5Sopenharmony_ci OpBranch %1001 2963fd4e5da5Sopenharmony_ci %1001 = OpLabel 2964fd4e5da5Sopenharmony_ci %205 = OpCompositeConstruct %200 %2001 %400 2965fd4e5da5Sopenharmony_ci OpReturnValue %205 2966fd4e5da5Sopenharmony_ci OpFunctionEnd 2967fd4e5da5Sopenharmony_ci )"; 2968fd4e5da5Sopenharmony_ci ASSERT_TRUE(IsEqual(env, variant_shader, context.get())); 2969fd4e5da5Sopenharmony_ci } 2970fd4e5da5Sopenharmony_ci} 2971fd4e5da5Sopenharmony_ci 2972fd4e5da5Sopenharmony_ciTEST(TransformationOutlineFunctionTest, Miscellaneous2) { 2973fd4e5da5Sopenharmony_ci std::string shader = R"( 2974fd4e5da5Sopenharmony_ci OpCapability Shader 2975fd4e5da5Sopenharmony_ci %1 = OpExtInstImport "GLSL.std.450" 2976fd4e5da5Sopenharmony_ci OpMemoryModel Logical GLSL450 2977fd4e5da5Sopenharmony_ci OpEntryPoint Fragment %4 "main" 2978fd4e5da5Sopenharmony_ci OpExecutionMode %4 OriginUpperLeft 2979fd4e5da5Sopenharmony_ci OpSource ESSL 310 2980fd4e5da5Sopenharmony_ci %2 = OpTypeVoid 2981fd4e5da5Sopenharmony_ci %3 = OpTypeFunction %2 2982fd4e5da5Sopenharmony_ci %21 = OpTypeBool 2983fd4e5da5Sopenharmony_ci %167 = OpConstantTrue %21 2984fd4e5da5Sopenharmony_ci %168 = OpConstantFalse %21 2985fd4e5da5Sopenharmony_ci %4 = OpFunction %2 None %3 2986fd4e5da5Sopenharmony_ci %5 = OpLabel 2987fd4e5da5Sopenharmony_ci OpBranch %34 2988fd4e5da5Sopenharmony_ci %34 = OpLabel 2989fd4e5da5Sopenharmony_ci OpLoopMerge %36 %37 None 2990fd4e5da5Sopenharmony_ci OpBranchConditional %168 %37 %38 2991fd4e5da5Sopenharmony_ci %38 = OpLabel 2992fd4e5da5Sopenharmony_ci OpBranchConditional %168 %37 %36 2993fd4e5da5Sopenharmony_ci %37 = OpLabel 2994fd4e5da5Sopenharmony_ci OpBranch %34 2995fd4e5da5Sopenharmony_ci %36 = OpLabel 2996fd4e5da5Sopenharmony_ci OpReturn 2997fd4e5da5Sopenharmony_ci OpFunctionEnd 2998fd4e5da5Sopenharmony_ci )"; 2999fd4e5da5Sopenharmony_ci 3000fd4e5da5Sopenharmony_ci const auto env = SPV_ENV_UNIVERSAL_1_5; 3001fd4e5da5Sopenharmony_ci const auto consumer = nullptr; 3002fd4e5da5Sopenharmony_ci const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption); 3003fd4e5da5Sopenharmony_ci spvtools::ValidatorOptions validator_options; 3004fd4e5da5Sopenharmony_ci ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options, 3005fd4e5da5Sopenharmony_ci kConsoleMessageConsumer)); 3006fd4e5da5Sopenharmony_ci TransformationContext transformation_context( 3007fd4e5da5Sopenharmony_ci MakeUnique<FactManager>(context.get()), validator_options); 3008fd4e5da5Sopenharmony_ci TransformationOutlineFunction transformation( 3009fd4e5da5Sopenharmony_ci /*entry_block*/ 38, 3010fd4e5da5Sopenharmony_ci /*exit_block*/ 36, 3011fd4e5da5Sopenharmony_ci /*new_function_struct_return_type_id*/ 200, 3012fd4e5da5Sopenharmony_ci /*new_function_type_id*/ 201, 3013fd4e5da5Sopenharmony_ci /*new_function_id*/ 202, 3014fd4e5da5Sopenharmony_ci /*new_function_region_entry_block*/ 203, 3015fd4e5da5Sopenharmony_ci /*new_caller_result_id*/ 204, 3016fd4e5da5Sopenharmony_ci /*new_callee_result_id*/ 205, 3017fd4e5da5Sopenharmony_ci /*input_id_to_fresh_id*/ {}, 3018fd4e5da5Sopenharmony_ci /*output_id_to_fresh_id*/ {}); 3019fd4e5da5Sopenharmony_ci 3020fd4e5da5Sopenharmony_ci ASSERT_FALSE( 3021fd4e5da5Sopenharmony_ci transformation.IsApplicable(context.get(), transformation_context)); 3022fd4e5da5Sopenharmony_ci} 3023fd4e5da5Sopenharmony_ci 3024fd4e5da5Sopenharmony_ciTEST(TransformationOutlineFunctionTest, Miscellaneous3) { 3025fd4e5da5Sopenharmony_ci std::string shader = R"( 3026fd4e5da5Sopenharmony_ci OpCapability Shader 3027fd4e5da5Sopenharmony_ci %1 = OpExtInstImport "GLSL.std.450" 3028fd4e5da5Sopenharmony_ci OpMemoryModel Logical GLSL450 3029fd4e5da5Sopenharmony_ci OpEntryPoint Fragment %6 "main" 3030fd4e5da5Sopenharmony_ci OpExecutionMode %6 OriginUpperLeft 3031fd4e5da5Sopenharmony_ci OpSource ESSL 310 3032fd4e5da5Sopenharmony_ci %2 = OpTypeVoid 3033fd4e5da5Sopenharmony_ci %3 = OpTypeFunction %2 3034fd4e5da5Sopenharmony_ci %21 = OpTypeBool 3035fd4e5da5Sopenharmony_ci %167 = OpConstantTrue %21 3036fd4e5da5Sopenharmony_ci %6 = OpFunction %2 None %3 3037fd4e5da5Sopenharmony_ci %7 = OpLabel 3038fd4e5da5Sopenharmony_ci OpBranch %80 3039fd4e5da5Sopenharmony_ci %80 = OpLabel 3040fd4e5da5Sopenharmony_ci OpBranch %14 3041fd4e5da5Sopenharmony_ci %14 = OpLabel 3042fd4e5da5Sopenharmony_ci OpLoopMerge %16 %17 None 3043fd4e5da5Sopenharmony_ci OpBranch %18 3044fd4e5da5Sopenharmony_ci %18 = OpLabel 3045fd4e5da5Sopenharmony_ci OpBranchConditional %167 %15 %16 3046fd4e5da5Sopenharmony_ci %15 = OpLabel 3047fd4e5da5Sopenharmony_ci OpBranch %17 3048fd4e5da5Sopenharmony_ci %16 = OpLabel 3049fd4e5da5Sopenharmony_ci OpBranch %81 3050fd4e5da5Sopenharmony_ci %81 = OpLabel 3051fd4e5da5Sopenharmony_ci OpReturn 3052fd4e5da5Sopenharmony_ci %17 = OpLabel 3053fd4e5da5Sopenharmony_ci OpBranch %14 3054fd4e5da5Sopenharmony_ci OpFunctionEnd 3055fd4e5da5Sopenharmony_ci )"; 3056fd4e5da5Sopenharmony_ci 3057fd4e5da5Sopenharmony_ci const auto env = SPV_ENV_UNIVERSAL_1_5; 3058fd4e5da5Sopenharmony_ci const auto consumer = nullptr; 3059fd4e5da5Sopenharmony_ci const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption); 3060fd4e5da5Sopenharmony_ci spvtools::ValidatorOptions validator_options; 3061fd4e5da5Sopenharmony_ci ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options, 3062fd4e5da5Sopenharmony_ci kConsoleMessageConsumer)); 3063fd4e5da5Sopenharmony_ci TransformationContext transformation_context( 3064fd4e5da5Sopenharmony_ci MakeUnique<FactManager>(context.get()), validator_options); 3065fd4e5da5Sopenharmony_ci TransformationOutlineFunction transformation( 3066fd4e5da5Sopenharmony_ci /*entry_block*/ 80, 3067fd4e5da5Sopenharmony_ci /*exit_block*/ 81, 3068fd4e5da5Sopenharmony_ci /*new_function_struct_return_type_id*/ 300, 3069fd4e5da5Sopenharmony_ci /*new_function_type_id*/ 301, 3070fd4e5da5Sopenharmony_ci /*new_function_id*/ 302, 3071fd4e5da5Sopenharmony_ci /*new_function_region_entry_block*/ 304, 3072fd4e5da5Sopenharmony_ci /*new_caller_result_id*/ 305, 3073fd4e5da5Sopenharmony_ci /*new_callee_result_id*/ 306, 3074fd4e5da5Sopenharmony_ci /*input_id_to_fresh_id*/ {}, 3075fd4e5da5Sopenharmony_ci /*output_id_to_fresh_id*/ {}); 3076fd4e5da5Sopenharmony_ci 3077fd4e5da5Sopenharmony_ci ASSERT_TRUE( 3078fd4e5da5Sopenharmony_ci transformation.IsApplicable(context.get(), transformation_context)); 3079fd4e5da5Sopenharmony_ci ApplyAndCheckFreshIds(transformation, context.get(), &transformation_context); 3080fd4e5da5Sopenharmony_ci ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options, 3081fd4e5da5Sopenharmony_ci kConsoleMessageConsumer)); 3082fd4e5da5Sopenharmony_ci 3083fd4e5da5Sopenharmony_ci std::string after_transformation = R"( 3084fd4e5da5Sopenharmony_ci OpCapability Shader 3085fd4e5da5Sopenharmony_ci %1 = OpExtInstImport "GLSL.std.450" 3086fd4e5da5Sopenharmony_ci OpMemoryModel Logical GLSL450 3087fd4e5da5Sopenharmony_ci OpEntryPoint Fragment %6 "main" 3088fd4e5da5Sopenharmony_ci OpExecutionMode %6 OriginUpperLeft 3089fd4e5da5Sopenharmony_ci OpSource ESSL 310 3090fd4e5da5Sopenharmony_ci %2 = OpTypeVoid 3091fd4e5da5Sopenharmony_ci %3 = OpTypeFunction %2 3092fd4e5da5Sopenharmony_ci %21 = OpTypeBool 3093fd4e5da5Sopenharmony_ci %167 = OpConstantTrue %21 3094fd4e5da5Sopenharmony_ci %6 = OpFunction %2 None %3 3095fd4e5da5Sopenharmony_ci %7 = OpLabel 3096fd4e5da5Sopenharmony_ci OpBranch %80 3097fd4e5da5Sopenharmony_ci %80 = OpLabel 3098fd4e5da5Sopenharmony_ci %305 = OpFunctionCall %2 %302 3099fd4e5da5Sopenharmony_ci OpReturn 3100fd4e5da5Sopenharmony_ci OpFunctionEnd 3101fd4e5da5Sopenharmony_ci %302 = OpFunction %2 None %3 3102fd4e5da5Sopenharmony_ci %304 = OpLabel 3103fd4e5da5Sopenharmony_ci OpBranch %14 3104fd4e5da5Sopenharmony_ci %14 = OpLabel 3105fd4e5da5Sopenharmony_ci OpLoopMerge %16 %17 None 3106fd4e5da5Sopenharmony_ci OpBranch %18 3107fd4e5da5Sopenharmony_ci %18 = OpLabel 3108fd4e5da5Sopenharmony_ci OpBranchConditional %167 %15 %16 3109fd4e5da5Sopenharmony_ci %15 = OpLabel 3110fd4e5da5Sopenharmony_ci OpBranch %17 3111fd4e5da5Sopenharmony_ci %16 = OpLabel 3112fd4e5da5Sopenharmony_ci OpBranch %81 3113fd4e5da5Sopenharmony_ci %81 = OpLabel 3114fd4e5da5Sopenharmony_ci OpReturn 3115fd4e5da5Sopenharmony_ci %17 = OpLabel 3116fd4e5da5Sopenharmony_ci OpBranch %14 3117fd4e5da5Sopenharmony_ci OpFunctionEnd 3118fd4e5da5Sopenharmony_ci )"; 3119fd4e5da5Sopenharmony_ci ASSERT_TRUE(IsEqual(env, after_transformation, context.get())); 3120fd4e5da5Sopenharmony_ci} 3121fd4e5da5Sopenharmony_ci 3122fd4e5da5Sopenharmony_ciTEST(TransformationOutlineFunctionTest, Miscellaneous4) { 3123fd4e5da5Sopenharmony_ci std::string shader = R"( 3124fd4e5da5Sopenharmony_ci OpCapability Shader 3125fd4e5da5Sopenharmony_ci %1 = OpExtInstImport "GLSL.std.450" 3126fd4e5da5Sopenharmony_ci OpMemoryModel Logical GLSL450 3127fd4e5da5Sopenharmony_ci OpEntryPoint Fragment %6 "main" 3128fd4e5da5Sopenharmony_ci OpExecutionMode %6 OriginUpperLeft 3129fd4e5da5Sopenharmony_ci OpSource ESSL 310 3130fd4e5da5Sopenharmony_ci %2 = OpTypeVoid 3131fd4e5da5Sopenharmony_ci %3 = OpTypeFunction %2 3132fd4e5da5Sopenharmony_ci %21 = OpTypeBool 3133fd4e5da5Sopenharmony_ci %100 = OpTypeInt 32 0 3134fd4e5da5Sopenharmony_ci %101 = OpTypePointer Function %100 3135fd4e5da5Sopenharmony_ci %102 = OpTypePointer Function %100 3136fd4e5da5Sopenharmony_ci %103 = OpTypeFunction %2 %101 3137fd4e5da5Sopenharmony_ci %6 = OpFunction %2 None %3 3138fd4e5da5Sopenharmony_ci %7 = OpLabel 3139fd4e5da5Sopenharmony_ci %104 = OpVariable %102 Function 3140fd4e5da5Sopenharmony_ci OpBranch %80 3141fd4e5da5Sopenharmony_ci %80 = OpLabel 3142fd4e5da5Sopenharmony_ci %105 = OpLoad %100 %104 3143fd4e5da5Sopenharmony_ci OpBranch %106 3144fd4e5da5Sopenharmony_ci %106 = OpLabel 3145fd4e5da5Sopenharmony_ci OpReturn 3146fd4e5da5Sopenharmony_ci OpFunctionEnd 3147fd4e5da5Sopenharmony_ci )"; 3148fd4e5da5Sopenharmony_ci 3149fd4e5da5Sopenharmony_ci const auto env = SPV_ENV_UNIVERSAL_1_5; 3150fd4e5da5Sopenharmony_ci const auto consumer = nullptr; 3151fd4e5da5Sopenharmony_ci const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption); 3152fd4e5da5Sopenharmony_ci spvtools::ValidatorOptions validator_options; 3153fd4e5da5Sopenharmony_ci ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options, 3154fd4e5da5Sopenharmony_ci kConsoleMessageConsumer)); 3155fd4e5da5Sopenharmony_ci TransformationContext transformation_context( 3156fd4e5da5Sopenharmony_ci MakeUnique<FactManager>(context.get()), validator_options); 3157fd4e5da5Sopenharmony_ci TransformationOutlineFunction transformation( 3158fd4e5da5Sopenharmony_ci /*entry_block*/ 80, 3159fd4e5da5Sopenharmony_ci /*exit_block*/ 106, 3160fd4e5da5Sopenharmony_ci /*new_function_struct_return_type_id*/ 300, 3161fd4e5da5Sopenharmony_ci /*new_function_type_id*/ 301, 3162fd4e5da5Sopenharmony_ci /*new_function_id*/ 302, 3163fd4e5da5Sopenharmony_ci /*new_function_region_entry_block*/ 304, 3164fd4e5da5Sopenharmony_ci /*new_caller_result_id*/ 305, 3165fd4e5da5Sopenharmony_ci /*new_callee_result_id*/ 306, 3166fd4e5da5Sopenharmony_ci /*input_id_to_fresh_id*/ {{104, 307}}, 3167fd4e5da5Sopenharmony_ci /*output_id_to_fresh_id*/ {}); 3168fd4e5da5Sopenharmony_ci 3169fd4e5da5Sopenharmony_ci ASSERT_TRUE( 3170fd4e5da5Sopenharmony_ci transformation.IsApplicable(context.get(), transformation_context)); 3171fd4e5da5Sopenharmony_ci ApplyAndCheckFreshIds(transformation, context.get(), &transformation_context); 3172fd4e5da5Sopenharmony_ci ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options, 3173fd4e5da5Sopenharmony_ci kConsoleMessageConsumer)); 3174fd4e5da5Sopenharmony_ci 3175fd4e5da5Sopenharmony_ci std::string after_transformation = R"( 3176fd4e5da5Sopenharmony_ci OpCapability Shader 3177fd4e5da5Sopenharmony_ci %1 = OpExtInstImport "GLSL.std.450" 3178fd4e5da5Sopenharmony_ci OpMemoryModel Logical GLSL450 3179fd4e5da5Sopenharmony_ci OpEntryPoint Fragment %6 "main" 3180fd4e5da5Sopenharmony_ci OpExecutionMode %6 OriginUpperLeft 3181fd4e5da5Sopenharmony_ci OpSource ESSL 310 3182fd4e5da5Sopenharmony_ci %2 = OpTypeVoid 3183fd4e5da5Sopenharmony_ci %3 = OpTypeFunction %2 3184fd4e5da5Sopenharmony_ci %21 = OpTypeBool 3185fd4e5da5Sopenharmony_ci %100 = OpTypeInt 32 0 3186fd4e5da5Sopenharmony_ci %101 = OpTypePointer Function %100 3187fd4e5da5Sopenharmony_ci %102 = OpTypePointer Function %100 3188fd4e5da5Sopenharmony_ci %103 = OpTypeFunction %2 %101 3189fd4e5da5Sopenharmony_ci %301 = OpTypeFunction %2 %102 3190fd4e5da5Sopenharmony_ci %6 = OpFunction %2 None %3 3191fd4e5da5Sopenharmony_ci %7 = OpLabel 3192fd4e5da5Sopenharmony_ci %104 = OpVariable %102 Function 3193fd4e5da5Sopenharmony_ci OpBranch %80 3194fd4e5da5Sopenharmony_ci %80 = OpLabel 3195fd4e5da5Sopenharmony_ci %305 = OpFunctionCall %2 %302 %104 3196fd4e5da5Sopenharmony_ci OpReturn 3197fd4e5da5Sopenharmony_ci OpFunctionEnd 3198fd4e5da5Sopenharmony_ci %302 = OpFunction %2 None %301 3199fd4e5da5Sopenharmony_ci %307 = OpFunctionParameter %102 3200fd4e5da5Sopenharmony_ci %304 = OpLabel 3201fd4e5da5Sopenharmony_ci %105 = OpLoad %100 %307 3202fd4e5da5Sopenharmony_ci OpBranch %106 3203fd4e5da5Sopenharmony_ci %106 = OpLabel 3204fd4e5da5Sopenharmony_ci OpReturn 3205fd4e5da5Sopenharmony_ci OpFunctionEnd 3206fd4e5da5Sopenharmony_ci )"; 3207fd4e5da5Sopenharmony_ci ASSERT_TRUE(IsEqual(env, after_transformation, context.get())); 3208fd4e5da5Sopenharmony_ci} 3209fd4e5da5Sopenharmony_ci 3210fd4e5da5Sopenharmony_ciTEST(TransformationOutlineFunctionTest, NoOutlineWithUnreachableBlocks) { 3211fd4e5da5Sopenharmony_ci // This checks that outlining will not be performed if a node in the region 3212fd4e5da5Sopenharmony_ci // has an unreachable predecessor. 3213fd4e5da5Sopenharmony_ci 3214fd4e5da5Sopenharmony_ci std::string shader = R"( 3215fd4e5da5Sopenharmony_ci OpCapability Shader 3216fd4e5da5Sopenharmony_ci %1 = OpExtInstImport "GLSL.std.450" 3217fd4e5da5Sopenharmony_ci OpMemoryModel Logical GLSL450 3218fd4e5da5Sopenharmony_ci OpEntryPoint Fragment %4 "main" 3219fd4e5da5Sopenharmony_ci OpExecutionMode %4 OriginUpperLeft 3220fd4e5da5Sopenharmony_ci OpSource ESSL 310 3221fd4e5da5Sopenharmony_ci OpName %4 "main" 3222fd4e5da5Sopenharmony_ci %2 = OpTypeVoid 3223fd4e5da5Sopenharmony_ci %3 = OpTypeFunction %2 3224fd4e5da5Sopenharmony_ci %4 = OpFunction %2 None %3 3225fd4e5da5Sopenharmony_ci %7 = OpLabel 3226fd4e5da5Sopenharmony_ci OpBranch %5 3227fd4e5da5Sopenharmony_ci %5 = OpLabel 3228fd4e5da5Sopenharmony_ci OpReturn 3229fd4e5da5Sopenharmony_ci %6 = OpLabel 3230fd4e5da5Sopenharmony_ci OpBranch %5 3231fd4e5da5Sopenharmony_ci OpFunctionEnd 3232fd4e5da5Sopenharmony_ci )"; 3233fd4e5da5Sopenharmony_ci 3234fd4e5da5Sopenharmony_ci const auto env = SPV_ENV_UNIVERSAL_1_4; 3235fd4e5da5Sopenharmony_ci const auto consumer = nullptr; 3236fd4e5da5Sopenharmony_ci const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption); 3237fd4e5da5Sopenharmony_ci spvtools::ValidatorOptions validator_options; 3238fd4e5da5Sopenharmony_ci ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options, 3239fd4e5da5Sopenharmony_ci kConsoleMessageConsumer)); 3240fd4e5da5Sopenharmony_ci TransformationContext transformation_context( 3241fd4e5da5Sopenharmony_ci MakeUnique<FactManager>(context.get()), validator_options); 3242fd4e5da5Sopenharmony_ci TransformationOutlineFunction transformation(5, 5, /* not relevant */ 200, 3243fd4e5da5Sopenharmony_ci 100, 101, 102, 103, 3244fd4e5da5Sopenharmony_ci /* not relevant */ 201, {}, {}); 3245fd4e5da5Sopenharmony_ci ASSERT_FALSE( 3246fd4e5da5Sopenharmony_ci transformation.IsApplicable(context.get(), transformation_context)); 3247fd4e5da5Sopenharmony_ci} 3248fd4e5da5Sopenharmony_ci 3249fd4e5da5Sopenharmony_ci} // namespace 3250fd4e5da5Sopenharmony_ci} // namespace fuzz 3251fd4e5da5Sopenharmony_ci} // namespace spvtools 3252