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/reduce/merge_blocks_reduction_opportunity_finder.h" 16fd4e5da5Sopenharmony_ci 17fd4e5da5Sopenharmony_ci#include "source/opt/build_module.h" 18fd4e5da5Sopenharmony_ci#include "source/reduce/reduction_opportunity.h" 19fd4e5da5Sopenharmony_ci#include "test/reduce/reduce_test_util.h" 20fd4e5da5Sopenharmony_ci 21fd4e5da5Sopenharmony_cinamespace spvtools { 22fd4e5da5Sopenharmony_cinamespace reduce { 23fd4e5da5Sopenharmony_cinamespace { 24fd4e5da5Sopenharmony_ci 25fd4e5da5Sopenharmony_ciTEST(MergeBlocksReductionPassTest, BasicCheck) { 26fd4e5da5Sopenharmony_ci std::string shader = R"( 27fd4e5da5Sopenharmony_ci OpCapability Shader 28fd4e5da5Sopenharmony_ci %1 = OpExtInstImport "GLSL.std.450" 29fd4e5da5Sopenharmony_ci OpMemoryModel Logical GLSL450 30fd4e5da5Sopenharmony_ci OpEntryPoint Fragment %4 "main" 31fd4e5da5Sopenharmony_ci OpExecutionMode %4 OriginUpperLeft 32fd4e5da5Sopenharmony_ci OpSource ESSL 310 33fd4e5da5Sopenharmony_ci OpName %4 "main" 34fd4e5da5Sopenharmony_ci OpName %8 "x" 35fd4e5da5Sopenharmony_ci %2 = OpTypeVoid 36fd4e5da5Sopenharmony_ci %3 = OpTypeFunction %2 37fd4e5da5Sopenharmony_ci %6 = OpTypeInt 32 1 38fd4e5da5Sopenharmony_ci %7 = OpTypePointer Function %6 39fd4e5da5Sopenharmony_ci %9 = OpConstant %6 1 40fd4e5da5Sopenharmony_ci %10 = OpConstant %6 2 41fd4e5da5Sopenharmony_ci %11 = OpConstant %6 3 42fd4e5da5Sopenharmony_ci %12 = OpConstant %6 4 43fd4e5da5Sopenharmony_ci %4 = OpFunction %2 None %3 44fd4e5da5Sopenharmony_ci %5 = OpLabel 45fd4e5da5Sopenharmony_ci %8 = OpVariable %7 Function 46fd4e5da5Sopenharmony_ci OpBranch %13 47fd4e5da5Sopenharmony_ci %13 = OpLabel 48fd4e5da5Sopenharmony_ci OpStore %8 %9 49fd4e5da5Sopenharmony_ci OpBranch %14 50fd4e5da5Sopenharmony_ci %14 = OpLabel 51fd4e5da5Sopenharmony_ci OpStore %8 %10 52fd4e5da5Sopenharmony_ci OpBranch %15 53fd4e5da5Sopenharmony_ci %15 = OpLabel 54fd4e5da5Sopenharmony_ci OpStore %8 %11 55fd4e5da5Sopenharmony_ci OpBranch %16 56fd4e5da5Sopenharmony_ci %16 = OpLabel 57fd4e5da5Sopenharmony_ci OpStore %8 %12 58fd4e5da5Sopenharmony_ci OpBranch %17 59fd4e5da5Sopenharmony_ci %17 = OpLabel 60fd4e5da5Sopenharmony_ci OpReturn 61fd4e5da5Sopenharmony_ci OpFunctionEnd 62fd4e5da5Sopenharmony_ci )"; 63fd4e5da5Sopenharmony_ci const auto env = SPV_ENV_UNIVERSAL_1_3; 64fd4e5da5Sopenharmony_ci const auto consumer = nullptr; 65fd4e5da5Sopenharmony_ci const auto context = 66fd4e5da5Sopenharmony_ci BuildModule(env, consumer, shader, kReduceAssembleOption); 67fd4e5da5Sopenharmony_ci const auto ops = 68fd4e5da5Sopenharmony_ci MergeBlocksReductionOpportunityFinder().GetAvailableOpportunities( 69fd4e5da5Sopenharmony_ci context.get(), 0); 70fd4e5da5Sopenharmony_ci ASSERT_EQ(5, ops.size()); 71fd4e5da5Sopenharmony_ci 72fd4e5da5Sopenharmony_ci // Try order 3, 0, 2, 4, 1 73fd4e5da5Sopenharmony_ci 74fd4e5da5Sopenharmony_ci ASSERT_TRUE(ops[3]->PreconditionHolds()); 75fd4e5da5Sopenharmony_ci ops[3]->TryToApply(); 76fd4e5da5Sopenharmony_ci 77fd4e5da5Sopenharmony_ci std::string after_op_3 = R"( 78fd4e5da5Sopenharmony_ci OpCapability Shader 79fd4e5da5Sopenharmony_ci %1 = OpExtInstImport "GLSL.std.450" 80fd4e5da5Sopenharmony_ci OpMemoryModel Logical GLSL450 81fd4e5da5Sopenharmony_ci OpEntryPoint Fragment %4 "main" 82fd4e5da5Sopenharmony_ci OpExecutionMode %4 OriginUpperLeft 83fd4e5da5Sopenharmony_ci OpSource ESSL 310 84fd4e5da5Sopenharmony_ci OpName %4 "main" 85fd4e5da5Sopenharmony_ci OpName %8 "x" 86fd4e5da5Sopenharmony_ci %2 = OpTypeVoid 87fd4e5da5Sopenharmony_ci %3 = OpTypeFunction %2 88fd4e5da5Sopenharmony_ci %6 = OpTypeInt 32 1 89fd4e5da5Sopenharmony_ci %7 = OpTypePointer Function %6 90fd4e5da5Sopenharmony_ci %9 = OpConstant %6 1 91fd4e5da5Sopenharmony_ci %10 = OpConstant %6 2 92fd4e5da5Sopenharmony_ci %11 = OpConstant %6 3 93fd4e5da5Sopenharmony_ci %12 = OpConstant %6 4 94fd4e5da5Sopenharmony_ci %4 = OpFunction %2 None %3 95fd4e5da5Sopenharmony_ci %5 = OpLabel 96fd4e5da5Sopenharmony_ci %8 = OpVariable %7 Function 97fd4e5da5Sopenharmony_ci OpBranch %13 98fd4e5da5Sopenharmony_ci %13 = OpLabel 99fd4e5da5Sopenharmony_ci OpStore %8 %9 100fd4e5da5Sopenharmony_ci OpBranch %14 101fd4e5da5Sopenharmony_ci %14 = OpLabel 102fd4e5da5Sopenharmony_ci OpStore %8 %10 103fd4e5da5Sopenharmony_ci OpBranch %15 104fd4e5da5Sopenharmony_ci %15 = OpLabel 105fd4e5da5Sopenharmony_ci OpStore %8 %11 106fd4e5da5Sopenharmony_ci OpStore %8 %12 107fd4e5da5Sopenharmony_ci OpBranch %17 108fd4e5da5Sopenharmony_ci %17 = OpLabel 109fd4e5da5Sopenharmony_ci OpReturn 110fd4e5da5Sopenharmony_ci OpFunctionEnd 111fd4e5da5Sopenharmony_ci )"; 112fd4e5da5Sopenharmony_ci 113fd4e5da5Sopenharmony_ci CheckEqual(env, after_op_3, context.get()); 114fd4e5da5Sopenharmony_ci 115fd4e5da5Sopenharmony_ci ASSERT_TRUE(ops[0]->PreconditionHolds()); 116fd4e5da5Sopenharmony_ci ops[0]->TryToApply(); 117fd4e5da5Sopenharmony_ci 118fd4e5da5Sopenharmony_ci std::string after_op_0 = R"( 119fd4e5da5Sopenharmony_ci OpCapability Shader 120fd4e5da5Sopenharmony_ci %1 = OpExtInstImport "GLSL.std.450" 121fd4e5da5Sopenharmony_ci OpMemoryModel Logical GLSL450 122fd4e5da5Sopenharmony_ci OpEntryPoint Fragment %4 "main" 123fd4e5da5Sopenharmony_ci OpExecutionMode %4 OriginUpperLeft 124fd4e5da5Sopenharmony_ci OpSource ESSL 310 125fd4e5da5Sopenharmony_ci OpName %4 "main" 126fd4e5da5Sopenharmony_ci OpName %8 "x" 127fd4e5da5Sopenharmony_ci %2 = OpTypeVoid 128fd4e5da5Sopenharmony_ci %3 = OpTypeFunction %2 129fd4e5da5Sopenharmony_ci %6 = OpTypeInt 32 1 130fd4e5da5Sopenharmony_ci %7 = OpTypePointer Function %6 131fd4e5da5Sopenharmony_ci %9 = OpConstant %6 1 132fd4e5da5Sopenharmony_ci %10 = OpConstant %6 2 133fd4e5da5Sopenharmony_ci %11 = OpConstant %6 3 134fd4e5da5Sopenharmony_ci %12 = OpConstant %6 4 135fd4e5da5Sopenharmony_ci %4 = OpFunction %2 None %3 136fd4e5da5Sopenharmony_ci %5 = OpLabel 137fd4e5da5Sopenharmony_ci %8 = OpVariable %7 Function 138fd4e5da5Sopenharmony_ci OpStore %8 %9 139fd4e5da5Sopenharmony_ci OpBranch %14 140fd4e5da5Sopenharmony_ci %14 = OpLabel 141fd4e5da5Sopenharmony_ci OpStore %8 %10 142fd4e5da5Sopenharmony_ci OpBranch %15 143fd4e5da5Sopenharmony_ci %15 = OpLabel 144fd4e5da5Sopenharmony_ci OpStore %8 %11 145fd4e5da5Sopenharmony_ci OpStore %8 %12 146fd4e5da5Sopenharmony_ci OpBranch %17 147fd4e5da5Sopenharmony_ci %17 = OpLabel 148fd4e5da5Sopenharmony_ci OpReturn 149fd4e5da5Sopenharmony_ci OpFunctionEnd 150fd4e5da5Sopenharmony_ci )"; 151fd4e5da5Sopenharmony_ci 152fd4e5da5Sopenharmony_ci CheckEqual(env, after_op_0, context.get()); 153fd4e5da5Sopenharmony_ci 154fd4e5da5Sopenharmony_ci ASSERT_TRUE(ops[2]->PreconditionHolds()); 155fd4e5da5Sopenharmony_ci ops[2]->TryToApply(); 156fd4e5da5Sopenharmony_ci 157fd4e5da5Sopenharmony_ci std::string after_op_2 = R"( 158fd4e5da5Sopenharmony_ci OpCapability Shader 159fd4e5da5Sopenharmony_ci %1 = OpExtInstImport "GLSL.std.450" 160fd4e5da5Sopenharmony_ci OpMemoryModel Logical GLSL450 161fd4e5da5Sopenharmony_ci OpEntryPoint Fragment %4 "main" 162fd4e5da5Sopenharmony_ci OpExecutionMode %4 OriginUpperLeft 163fd4e5da5Sopenharmony_ci OpSource ESSL 310 164fd4e5da5Sopenharmony_ci OpName %4 "main" 165fd4e5da5Sopenharmony_ci OpName %8 "x" 166fd4e5da5Sopenharmony_ci %2 = OpTypeVoid 167fd4e5da5Sopenharmony_ci %3 = OpTypeFunction %2 168fd4e5da5Sopenharmony_ci %6 = OpTypeInt 32 1 169fd4e5da5Sopenharmony_ci %7 = OpTypePointer Function %6 170fd4e5da5Sopenharmony_ci %9 = OpConstant %6 1 171fd4e5da5Sopenharmony_ci %10 = OpConstant %6 2 172fd4e5da5Sopenharmony_ci %11 = OpConstant %6 3 173fd4e5da5Sopenharmony_ci %12 = OpConstant %6 4 174fd4e5da5Sopenharmony_ci %4 = OpFunction %2 None %3 175fd4e5da5Sopenharmony_ci %5 = OpLabel 176fd4e5da5Sopenharmony_ci %8 = OpVariable %7 Function 177fd4e5da5Sopenharmony_ci OpStore %8 %9 178fd4e5da5Sopenharmony_ci OpBranch %14 179fd4e5da5Sopenharmony_ci %14 = OpLabel 180fd4e5da5Sopenharmony_ci OpStore %8 %10 181fd4e5da5Sopenharmony_ci OpStore %8 %11 182fd4e5da5Sopenharmony_ci OpStore %8 %12 183fd4e5da5Sopenharmony_ci OpBranch %17 184fd4e5da5Sopenharmony_ci %17 = OpLabel 185fd4e5da5Sopenharmony_ci OpReturn 186fd4e5da5Sopenharmony_ci OpFunctionEnd 187fd4e5da5Sopenharmony_ci )"; 188fd4e5da5Sopenharmony_ci 189fd4e5da5Sopenharmony_ci CheckEqual(env, after_op_2, context.get()); 190fd4e5da5Sopenharmony_ci 191fd4e5da5Sopenharmony_ci ASSERT_TRUE(ops[4]->PreconditionHolds()); 192fd4e5da5Sopenharmony_ci ops[4]->TryToApply(); 193fd4e5da5Sopenharmony_ci 194fd4e5da5Sopenharmony_ci std::string after_op_4 = R"( 195fd4e5da5Sopenharmony_ci OpCapability Shader 196fd4e5da5Sopenharmony_ci %1 = OpExtInstImport "GLSL.std.450" 197fd4e5da5Sopenharmony_ci OpMemoryModel Logical GLSL450 198fd4e5da5Sopenharmony_ci OpEntryPoint Fragment %4 "main" 199fd4e5da5Sopenharmony_ci OpExecutionMode %4 OriginUpperLeft 200fd4e5da5Sopenharmony_ci OpSource ESSL 310 201fd4e5da5Sopenharmony_ci OpName %4 "main" 202fd4e5da5Sopenharmony_ci OpName %8 "x" 203fd4e5da5Sopenharmony_ci %2 = OpTypeVoid 204fd4e5da5Sopenharmony_ci %3 = OpTypeFunction %2 205fd4e5da5Sopenharmony_ci %6 = OpTypeInt 32 1 206fd4e5da5Sopenharmony_ci %7 = OpTypePointer Function %6 207fd4e5da5Sopenharmony_ci %9 = OpConstant %6 1 208fd4e5da5Sopenharmony_ci %10 = OpConstant %6 2 209fd4e5da5Sopenharmony_ci %11 = OpConstant %6 3 210fd4e5da5Sopenharmony_ci %12 = OpConstant %6 4 211fd4e5da5Sopenharmony_ci %4 = OpFunction %2 None %3 212fd4e5da5Sopenharmony_ci %5 = OpLabel 213fd4e5da5Sopenharmony_ci %8 = OpVariable %7 Function 214fd4e5da5Sopenharmony_ci OpStore %8 %9 215fd4e5da5Sopenharmony_ci OpBranch %14 216fd4e5da5Sopenharmony_ci %14 = OpLabel 217fd4e5da5Sopenharmony_ci OpStore %8 %10 218fd4e5da5Sopenharmony_ci OpStore %8 %11 219fd4e5da5Sopenharmony_ci OpStore %8 %12 220fd4e5da5Sopenharmony_ci OpReturn 221fd4e5da5Sopenharmony_ci OpFunctionEnd 222fd4e5da5Sopenharmony_ci )"; 223fd4e5da5Sopenharmony_ci 224fd4e5da5Sopenharmony_ci CheckEqual(env, after_op_4, context.get()); 225fd4e5da5Sopenharmony_ci 226fd4e5da5Sopenharmony_ci ASSERT_TRUE(ops[1]->PreconditionHolds()); 227fd4e5da5Sopenharmony_ci ops[1]->TryToApply(); 228fd4e5da5Sopenharmony_ci 229fd4e5da5Sopenharmony_ci std::string after_op_1 = 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 OpName %8 "x" 238fd4e5da5Sopenharmony_ci %2 = OpTypeVoid 239fd4e5da5Sopenharmony_ci %3 = OpTypeFunction %2 240fd4e5da5Sopenharmony_ci %6 = OpTypeInt 32 1 241fd4e5da5Sopenharmony_ci %7 = OpTypePointer Function %6 242fd4e5da5Sopenharmony_ci %9 = OpConstant %6 1 243fd4e5da5Sopenharmony_ci %10 = OpConstant %6 2 244fd4e5da5Sopenharmony_ci %11 = OpConstant %6 3 245fd4e5da5Sopenharmony_ci %12 = OpConstant %6 4 246fd4e5da5Sopenharmony_ci %4 = OpFunction %2 None %3 247fd4e5da5Sopenharmony_ci %5 = OpLabel 248fd4e5da5Sopenharmony_ci %8 = OpVariable %7 Function 249fd4e5da5Sopenharmony_ci OpStore %8 %9 250fd4e5da5Sopenharmony_ci OpStore %8 %10 251fd4e5da5Sopenharmony_ci OpStore %8 %11 252fd4e5da5Sopenharmony_ci OpStore %8 %12 253fd4e5da5Sopenharmony_ci OpReturn 254fd4e5da5Sopenharmony_ci OpFunctionEnd 255fd4e5da5Sopenharmony_ci )"; 256fd4e5da5Sopenharmony_ci 257fd4e5da5Sopenharmony_ci CheckEqual(env, after_op_1, context.get()); 258fd4e5da5Sopenharmony_ci} 259fd4e5da5Sopenharmony_ci 260fd4e5da5Sopenharmony_ciTEST(MergeBlocksReductionPassTest, Loops) { 261fd4e5da5Sopenharmony_ci std::string shader = R"( 262fd4e5da5Sopenharmony_ci OpCapability Shader 263fd4e5da5Sopenharmony_ci %1 = OpExtInstImport "GLSL.std.450" 264fd4e5da5Sopenharmony_ci OpMemoryModel Logical GLSL450 265fd4e5da5Sopenharmony_ci OpEntryPoint Fragment %4 "main" 266fd4e5da5Sopenharmony_ci OpExecutionMode %4 OriginUpperLeft 267fd4e5da5Sopenharmony_ci OpSource ESSL 310 268fd4e5da5Sopenharmony_ci OpName %4 "main" 269fd4e5da5Sopenharmony_ci OpName %8 "x" 270fd4e5da5Sopenharmony_ci OpName %10 "i" 271fd4e5da5Sopenharmony_ci OpName %29 "i" 272fd4e5da5Sopenharmony_ci %2 = OpTypeVoid 273fd4e5da5Sopenharmony_ci %3 = OpTypeFunction %2 274fd4e5da5Sopenharmony_ci %6 = OpTypeInt 32 1 275fd4e5da5Sopenharmony_ci %7 = OpTypePointer Function %6 276fd4e5da5Sopenharmony_ci %9 = OpConstant %6 1 277fd4e5da5Sopenharmony_ci %11 = OpConstant %6 0 278fd4e5da5Sopenharmony_ci %18 = OpConstant %6 10 279fd4e5da5Sopenharmony_ci %19 = OpTypeBool 280fd4e5da5Sopenharmony_ci %4 = OpFunction %2 None %3 281fd4e5da5Sopenharmony_ci %5 = OpLabel 282fd4e5da5Sopenharmony_ci %8 = OpVariable %7 Function 283fd4e5da5Sopenharmony_ci %10 = OpVariable %7 Function 284fd4e5da5Sopenharmony_ci %29 = OpVariable %7 Function 285fd4e5da5Sopenharmony_ci OpStore %8 %9 286fd4e5da5Sopenharmony_ci OpBranch %45 287fd4e5da5Sopenharmony_ci %45 = OpLabel 288fd4e5da5Sopenharmony_ci OpStore %10 %11 289fd4e5da5Sopenharmony_ci OpBranch %12 290fd4e5da5Sopenharmony_ci %12 = OpLabel 291fd4e5da5Sopenharmony_ci OpLoopMerge %14 %15 None 292fd4e5da5Sopenharmony_ci OpBranch %16 293fd4e5da5Sopenharmony_ci %16 = OpLabel 294fd4e5da5Sopenharmony_ci %17 = OpLoad %6 %10 295fd4e5da5Sopenharmony_ci OpBranch %46 296fd4e5da5Sopenharmony_ci %46 = OpLabel 297fd4e5da5Sopenharmony_ci %20 = OpSLessThan %19 %17 %18 298fd4e5da5Sopenharmony_ci OpBranchConditional %20 %13 %14 299fd4e5da5Sopenharmony_ci %13 = OpLabel 300fd4e5da5Sopenharmony_ci %21 = OpLoad %6 %10 301fd4e5da5Sopenharmony_ci OpBranch %47 302fd4e5da5Sopenharmony_ci %47 = OpLabel 303fd4e5da5Sopenharmony_ci %22 = OpLoad %6 %8 304fd4e5da5Sopenharmony_ci %23 = OpIAdd %6 %22 %21 305fd4e5da5Sopenharmony_ci OpStore %8 %23 306fd4e5da5Sopenharmony_ci %24 = OpLoad %6 %10 307fd4e5da5Sopenharmony_ci %25 = OpLoad %6 %8 308fd4e5da5Sopenharmony_ci %26 = OpIAdd %6 %25 %24 309fd4e5da5Sopenharmony_ci OpStore %8 %26 310fd4e5da5Sopenharmony_ci OpBranch %48 311fd4e5da5Sopenharmony_ci %48 = OpLabel 312fd4e5da5Sopenharmony_ci OpBranch %15 313fd4e5da5Sopenharmony_ci %15 = OpLabel 314fd4e5da5Sopenharmony_ci %27 = OpLoad %6 %10 315fd4e5da5Sopenharmony_ci %28 = OpIAdd %6 %27 %9 316fd4e5da5Sopenharmony_ci OpStore %10 %28 317fd4e5da5Sopenharmony_ci OpBranch %12 318fd4e5da5Sopenharmony_ci %14 = OpLabel 319fd4e5da5Sopenharmony_ci OpStore %29 %11 320fd4e5da5Sopenharmony_ci OpBranch %49 321fd4e5da5Sopenharmony_ci %49 = OpLabel 322fd4e5da5Sopenharmony_ci OpBranch %30 323fd4e5da5Sopenharmony_ci %30 = OpLabel 324fd4e5da5Sopenharmony_ci OpLoopMerge %32 %33 None 325fd4e5da5Sopenharmony_ci OpBranch %34 326fd4e5da5Sopenharmony_ci %34 = OpLabel 327fd4e5da5Sopenharmony_ci %35 = OpLoad %6 %29 328fd4e5da5Sopenharmony_ci %36 = OpSLessThan %19 %35 %18 329fd4e5da5Sopenharmony_ci OpBranch %50 330fd4e5da5Sopenharmony_ci %50 = OpLabel 331fd4e5da5Sopenharmony_ci OpBranchConditional %36 %31 %32 332fd4e5da5Sopenharmony_ci %31 = OpLabel 333fd4e5da5Sopenharmony_ci %37 = OpLoad %6 %29 334fd4e5da5Sopenharmony_ci %38 = OpLoad %6 %8 335fd4e5da5Sopenharmony_ci %39 = OpIAdd %6 %38 %37 336fd4e5da5Sopenharmony_ci OpStore %8 %39 337fd4e5da5Sopenharmony_ci %40 = OpLoad %6 %29 338fd4e5da5Sopenharmony_ci %41 = OpLoad %6 %8 339fd4e5da5Sopenharmony_ci %42 = OpIAdd %6 %41 %40 340fd4e5da5Sopenharmony_ci OpStore %8 %42 341fd4e5da5Sopenharmony_ci OpBranch %33 342fd4e5da5Sopenharmony_ci %33 = OpLabel 343fd4e5da5Sopenharmony_ci %43 = OpLoad %6 %29 344fd4e5da5Sopenharmony_ci %44 = OpIAdd %6 %43 %9 345fd4e5da5Sopenharmony_ci OpBranch %51 346fd4e5da5Sopenharmony_ci %51 = OpLabel 347fd4e5da5Sopenharmony_ci OpStore %29 %44 348fd4e5da5Sopenharmony_ci OpBranch %30 349fd4e5da5Sopenharmony_ci %32 = OpLabel 350fd4e5da5Sopenharmony_ci OpReturn 351fd4e5da5Sopenharmony_ci OpFunctionEnd 352fd4e5da5Sopenharmony_ci )"; 353fd4e5da5Sopenharmony_ci const auto env = SPV_ENV_UNIVERSAL_1_3; 354fd4e5da5Sopenharmony_ci const auto consumer = nullptr; 355fd4e5da5Sopenharmony_ci const auto context = 356fd4e5da5Sopenharmony_ci BuildModule(env, consumer, shader, kReduceAssembleOption); 357fd4e5da5Sopenharmony_ci const auto ops = 358fd4e5da5Sopenharmony_ci MergeBlocksReductionOpportunityFinder().GetAvailableOpportunities( 359fd4e5da5Sopenharmony_ci context.get(), 0); 360fd4e5da5Sopenharmony_ci ASSERT_EQ(11, ops.size()); 361fd4e5da5Sopenharmony_ci 362fd4e5da5Sopenharmony_ci for (auto& ri : ops) { 363fd4e5da5Sopenharmony_ci ASSERT_TRUE(ri->PreconditionHolds()); 364fd4e5da5Sopenharmony_ci ri->TryToApply(); 365fd4e5da5Sopenharmony_ci } 366fd4e5da5Sopenharmony_ci 367fd4e5da5Sopenharmony_ci std::string after = R"( 368fd4e5da5Sopenharmony_ci OpCapability Shader 369fd4e5da5Sopenharmony_ci %1 = OpExtInstImport "GLSL.std.450" 370fd4e5da5Sopenharmony_ci OpMemoryModel Logical GLSL450 371fd4e5da5Sopenharmony_ci OpEntryPoint Fragment %4 "main" 372fd4e5da5Sopenharmony_ci OpExecutionMode %4 OriginUpperLeft 373fd4e5da5Sopenharmony_ci OpSource ESSL 310 374fd4e5da5Sopenharmony_ci OpName %4 "main" 375fd4e5da5Sopenharmony_ci OpName %8 "x" 376fd4e5da5Sopenharmony_ci OpName %10 "i" 377fd4e5da5Sopenharmony_ci OpName %29 "i" 378fd4e5da5Sopenharmony_ci %2 = OpTypeVoid 379fd4e5da5Sopenharmony_ci %3 = OpTypeFunction %2 380fd4e5da5Sopenharmony_ci %6 = OpTypeInt 32 1 381fd4e5da5Sopenharmony_ci %7 = OpTypePointer Function %6 382fd4e5da5Sopenharmony_ci %9 = OpConstant %6 1 383fd4e5da5Sopenharmony_ci %11 = OpConstant %6 0 384fd4e5da5Sopenharmony_ci %18 = OpConstant %6 10 385fd4e5da5Sopenharmony_ci %19 = OpTypeBool 386fd4e5da5Sopenharmony_ci %4 = OpFunction %2 None %3 387fd4e5da5Sopenharmony_ci %5 = OpLabel 388fd4e5da5Sopenharmony_ci %8 = OpVariable %7 Function 389fd4e5da5Sopenharmony_ci %10 = OpVariable %7 Function 390fd4e5da5Sopenharmony_ci %29 = OpVariable %7 Function 391fd4e5da5Sopenharmony_ci OpStore %8 %9 392fd4e5da5Sopenharmony_ci OpStore %10 %11 393fd4e5da5Sopenharmony_ci OpBranch %12 394fd4e5da5Sopenharmony_ci %12 = OpLabel 395fd4e5da5Sopenharmony_ci %17 = OpLoad %6 %10 396fd4e5da5Sopenharmony_ci %20 = OpSLessThan %19 %17 %18 397fd4e5da5Sopenharmony_ci OpLoopMerge %14 %13 None 398fd4e5da5Sopenharmony_ci OpBranchConditional %20 %13 %14 399fd4e5da5Sopenharmony_ci %13 = OpLabel 400fd4e5da5Sopenharmony_ci %21 = OpLoad %6 %10 401fd4e5da5Sopenharmony_ci %22 = OpLoad %6 %8 402fd4e5da5Sopenharmony_ci %23 = OpIAdd %6 %22 %21 403fd4e5da5Sopenharmony_ci OpStore %8 %23 404fd4e5da5Sopenharmony_ci %24 = OpLoad %6 %10 405fd4e5da5Sopenharmony_ci %25 = OpLoad %6 %8 406fd4e5da5Sopenharmony_ci %26 = OpIAdd %6 %25 %24 407fd4e5da5Sopenharmony_ci OpStore %8 %26 408fd4e5da5Sopenharmony_ci %27 = OpLoad %6 %10 409fd4e5da5Sopenharmony_ci %28 = OpIAdd %6 %27 %9 410fd4e5da5Sopenharmony_ci OpStore %10 %28 411fd4e5da5Sopenharmony_ci OpBranch %12 412fd4e5da5Sopenharmony_ci %14 = OpLabel 413fd4e5da5Sopenharmony_ci OpStore %29 %11 414fd4e5da5Sopenharmony_ci OpBranch %30 415fd4e5da5Sopenharmony_ci %30 = OpLabel 416fd4e5da5Sopenharmony_ci %35 = OpLoad %6 %29 417fd4e5da5Sopenharmony_ci %36 = OpSLessThan %19 %35 %18 418fd4e5da5Sopenharmony_ci OpLoopMerge %32 %31 None 419fd4e5da5Sopenharmony_ci OpBranchConditional %36 %31 %32 420fd4e5da5Sopenharmony_ci %31 = OpLabel 421fd4e5da5Sopenharmony_ci %37 = OpLoad %6 %29 422fd4e5da5Sopenharmony_ci %38 = OpLoad %6 %8 423fd4e5da5Sopenharmony_ci %39 = OpIAdd %6 %38 %37 424fd4e5da5Sopenharmony_ci OpStore %8 %39 425fd4e5da5Sopenharmony_ci %40 = OpLoad %6 %29 426fd4e5da5Sopenharmony_ci %41 = OpLoad %6 %8 427fd4e5da5Sopenharmony_ci %42 = OpIAdd %6 %41 %40 428fd4e5da5Sopenharmony_ci OpStore %8 %42 429fd4e5da5Sopenharmony_ci %43 = OpLoad %6 %29 430fd4e5da5Sopenharmony_ci %44 = OpIAdd %6 %43 %9 431fd4e5da5Sopenharmony_ci OpStore %29 %44 432fd4e5da5Sopenharmony_ci OpBranch %30 433fd4e5da5Sopenharmony_ci %32 = OpLabel 434fd4e5da5Sopenharmony_ci OpReturn 435fd4e5da5Sopenharmony_ci OpFunctionEnd 436fd4e5da5Sopenharmony_ci )"; 437fd4e5da5Sopenharmony_ci 438fd4e5da5Sopenharmony_ci CheckEqual(env, after, context.get()); 439fd4e5da5Sopenharmony_ci} 440fd4e5da5Sopenharmony_ci 441fd4e5da5Sopenharmony_ciTEST(MergeBlocksReductionPassTest, MergeWithOpPhi) { 442fd4e5da5Sopenharmony_ci std::string shader = R"( 443fd4e5da5Sopenharmony_ci OpCapability Shader 444fd4e5da5Sopenharmony_ci %1 = OpExtInstImport "GLSL.std.450" 445fd4e5da5Sopenharmony_ci OpMemoryModel Logical GLSL450 446fd4e5da5Sopenharmony_ci OpEntryPoint Fragment %4 "main" 447fd4e5da5Sopenharmony_ci OpExecutionMode %4 OriginUpperLeft 448fd4e5da5Sopenharmony_ci OpSource ESSL 310 449fd4e5da5Sopenharmony_ci OpName %4 "main" 450fd4e5da5Sopenharmony_ci OpName %8 "x" 451fd4e5da5Sopenharmony_ci OpName %10 "y" 452fd4e5da5Sopenharmony_ci %2 = OpTypeVoid 453fd4e5da5Sopenharmony_ci %3 = OpTypeFunction %2 454fd4e5da5Sopenharmony_ci %6 = OpTypeInt 32 1 455fd4e5da5Sopenharmony_ci %7 = OpTypePointer Function %6 456fd4e5da5Sopenharmony_ci %9 = OpConstant %6 1 457fd4e5da5Sopenharmony_ci %4 = OpFunction %2 None %3 458fd4e5da5Sopenharmony_ci %5 = OpLabel 459fd4e5da5Sopenharmony_ci %8 = OpVariable %7 Function 460fd4e5da5Sopenharmony_ci %10 = OpVariable %7 Function 461fd4e5da5Sopenharmony_ci OpStore %8 %9 462fd4e5da5Sopenharmony_ci %11 = OpLoad %6 %8 463fd4e5da5Sopenharmony_ci OpBranch %12 464fd4e5da5Sopenharmony_ci %12 = OpLabel 465fd4e5da5Sopenharmony_ci %13 = OpPhi %6 %11 %5 466fd4e5da5Sopenharmony_ci OpStore %10 %13 467fd4e5da5Sopenharmony_ci OpReturn 468fd4e5da5Sopenharmony_ci OpFunctionEnd 469fd4e5da5Sopenharmony_ci )"; 470fd4e5da5Sopenharmony_ci 471fd4e5da5Sopenharmony_ci const auto env = SPV_ENV_UNIVERSAL_1_3; 472fd4e5da5Sopenharmony_ci const auto consumer = nullptr; 473fd4e5da5Sopenharmony_ci const auto context = 474fd4e5da5Sopenharmony_ci BuildModule(env, consumer, shader, kReduceAssembleOption); 475fd4e5da5Sopenharmony_ci const auto ops = 476fd4e5da5Sopenharmony_ci MergeBlocksReductionOpportunityFinder().GetAvailableOpportunities( 477fd4e5da5Sopenharmony_ci context.get(), 0); 478fd4e5da5Sopenharmony_ci ASSERT_EQ(1, ops.size()); 479fd4e5da5Sopenharmony_ci 480fd4e5da5Sopenharmony_ci ASSERT_TRUE(ops[0]->PreconditionHolds()); 481fd4e5da5Sopenharmony_ci ops[0]->TryToApply(); 482fd4e5da5Sopenharmony_ci 483fd4e5da5Sopenharmony_ci std::string after = R"( 484fd4e5da5Sopenharmony_ci OpCapability Shader 485fd4e5da5Sopenharmony_ci %1 = OpExtInstImport "GLSL.std.450" 486fd4e5da5Sopenharmony_ci OpMemoryModel Logical GLSL450 487fd4e5da5Sopenharmony_ci OpEntryPoint Fragment %4 "main" 488fd4e5da5Sopenharmony_ci OpExecutionMode %4 OriginUpperLeft 489fd4e5da5Sopenharmony_ci OpSource ESSL 310 490fd4e5da5Sopenharmony_ci OpName %4 "main" 491fd4e5da5Sopenharmony_ci OpName %8 "x" 492fd4e5da5Sopenharmony_ci OpName %10 "y" 493fd4e5da5Sopenharmony_ci %2 = OpTypeVoid 494fd4e5da5Sopenharmony_ci %3 = OpTypeFunction %2 495fd4e5da5Sopenharmony_ci %6 = OpTypeInt 32 1 496fd4e5da5Sopenharmony_ci %7 = OpTypePointer Function %6 497fd4e5da5Sopenharmony_ci %9 = OpConstant %6 1 498fd4e5da5Sopenharmony_ci %4 = OpFunction %2 None %3 499fd4e5da5Sopenharmony_ci %5 = OpLabel 500fd4e5da5Sopenharmony_ci %8 = OpVariable %7 Function 501fd4e5da5Sopenharmony_ci %10 = OpVariable %7 Function 502fd4e5da5Sopenharmony_ci OpStore %8 %9 503fd4e5da5Sopenharmony_ci %11 = OpLoad %6 %8 504fd4e5da5Sopenharmony_ci OpStore %10 %11 505fd4e5da5Sopenharmony_ci OpReturn 506fd4e5da5Sopenharmony_ci OpFunctionEnd 507fd4e5da5Sopenharmony_ci )"; 508fd4e5da5Sopenharmony_ci 509fd4e5da5Sopenharmony_ci CheckEqual(env, after, context.get()); 510fd4e5da5Sopenharmony_ci} 511fd4e5da5Sopenharmony_ci 512fd4e5da5Sopenharmony_civoid MergeBlocksReductionPassTest_LoopReturn_Helper(bool reverse) { 513fd4e5da5Sopenharmony_ci // A merge block opportunity stores a block that can be merged with its 514fd4e5da5Sopenharmony_ci // predecessor. 515fd4e5da5Sopenharmony_ci // Given blocks A -> B -> C: 516fd4e5da5Sopenharmony_ci // This test demonstrates how merging B->C can invalidate 517fd4e5da5Sopenharmony_ci // the opportunity of merging A->B, and vice-versa. E.g. 518fd4e5da5Sopenharmony_ci // B->C are merged: B is now terminated with OpReturn. 519fd4e5da5Sopenharmony_ci // A->B can now no longer be merged because A is a loop header, which 520fd4e5da5Sopenharmony_ci // cannot be terminated with OpReturn. 521fd4e5da5Sopenharmony_ci 522fd4e5da5Sopenharmony_ci std::string shader = R"( 523fd4e5da5Sopenharmony_ci OpCapability Shader 524fd4e5da5Sopenharmony_ci %1 = OpExtInstImport "GLSL.std.450" 525fd4e5da5Sopenharmony_ci OpMemoryModel Logical GLSL450 526fd4e5da5Sopenharmony_ci OpEntryPoint Fragment %2 "main" 527fd4e5da5Sopenharmony_ci OpExecutionMode %2 OriginUpperLeft 528fd4e5da5Sopenharmony_ci OpSource ESSL 310 529fd4e5da5Sopenharmony_ci OpName %2 "main" 530fd4e5da5Sopenharmony_ci %3 = OpTypeVoid 531fd4e5da5Sopenharmony_ci %4 = OpTypeFunction %3 532fd4e5da5Sopenharmony_ci %5 = OpTypeInt 32 1 533fd4e5da5Sopenharmony_ci %6 = OpTypePointer Function %5 534fd4e5da5Sopenharmony_ci %7 = OpTypeBool 535fd4e5da5Sopenharmony_ci %8 = OpConstantFalse %7 536fd4e5da5Sopenharmony_ci %2 = OpFunction %3 None %4 537fd4e5da5Sopenharmony_ci %9 = OpLabel 538fd4e5da5Sopenharmony_ci OpBranch %10 539fd4e5da5Sopenharmony_ci %10 = OpLabel ; A (loop header) 540fd4e5da5Sopenharmony_ci OpLoopMerge %13 %12 None 541fd4e5da5Sopenharmony_ci OpBranch %11 542fd4e5da5Sopenharmony_ci %12 = OpLabel ; (unreachable continue block) 543fd4e5da5Sopenharmony_ci OpBranch %10 544fd4e5da5Sopenharmony_ci %11 = OpLabel ; B 545fd4e5da5Sopenharmony_ci OpBranch %15 546fd4e5da5Sopenharmony_ci %15 = OpLabel ; C 547fd4e5da5Sopenharmony_ci OpReturn 548fd4e5da5Sopenharmony_ci %13 = OpLabel ; (unreachable merge block) 549fd4e5da5Sopenharmony_ci OpReturn 550fd4e5da5Sopenharmony_ci OpFunctionEnd 551fd4e5da5Sopenharmony_ci )"; 552fd4e5da5Sopenharmony_ci const auto env = SPV_ENV_UNIVERSAL_1_3; 553fd4e5da5Sopenharmony_ci const auto consumer = nullptr; 554fd4e5da5Sopenharmony_ci const auto context = 555fd4e5da5Sopenharmony_ci BuildModule(env, consumer, shader, kReduceAssembleOption); 556fd4e5da5Sopenharmony_ci ASSERT_NE(context.get(), nullptr); 557fd4e5da5Sopenharmony_ci auto opportunities = 558fd4e5da5Sopenharmony_ci MergeBlocksReductionOpportunityFinder().GetAvailableOpportunities( 559fd4e5da5Sopenharmony_ci context.get(), 0); 560fd4e5da5Sopenharmony_ci 561fd4e5da5Sopenharmony_ci // A->B and B->C 562fd4e5da5Sopenharmony_ci ASSERT_EQ(opportunities.size(), 2); 563fd4e5da5Sopenharmony_ci 564fd4e5da5Sopenharmony_ci // Test applying opportunities in both orders. 565fd4e5da5Sopenharmony_ci if (reverse) { 566fd4e5da5Sopenharmony_ci std::reverse(opportunities.begin(), opportunities.end()); 567fd4e5da5Sopenharmony_ci } 568fd4e5da5Sopenharmony_ci 569fd4e5da5Sopenharmony_ci size_t num_applied = 0; 570fd4e5da5Sopenharmony_ci for (auto& ri : opportunities) { 571fd4e5da5Sopenharmony_ci if (ri->PreconditionHolds()) { 572fd4e5da5Sopenharmony_ci ri->TryToApply(); 573fd4e5da5Sopenharmony_ci ++num_applied; 574fd4e5da5Sopenharmony_ci } 575fd4e5da5Sopenharmony_ci } 576fd4e5da5Sopenharmony_ci 577fd4e5da5Sopenharmony_ci // Only 1 opportunity can be applied, as both disable each other. 578fd4e5da5Sopenharmony_ci ASSERT_EQ(num_applied, 1); 579fd4e5da5Sopenharmony_ci 580fd4e5da5Sopenharmony_ci std::string after = R"( 581fd4e5da5Sopenharmony_ci OpCapability Shader 582fd4e5da5Sopenharmony_ci %1 = OpExtInstImport "GLSL.std.450" 583fd4e5da5Sopenharmony_ci OpMemoryModel Logical GLSL450 584fd4e5da5Sopenharmony_ci OpEntryPoint Fragment %2 "main" 585fd4e5da5Sopenharmony_ci OpExecutionMode %2 OriginUpperLeft 586fd4e5da5Sopenharmony_ci OpSource ESSL 310 587fd4e5da5Sopenharmony_ci OpName %2 "main" 588fd4e5da5Sopenharmony_ci %3 = OpTypeVoid 589fd4e5da5Sopenharmony_ci %4 = OpTypeFunction %3 590fd4e5da5Sopenharmony_ci %5 = OpTypeInt 32 1 591fd4e5da5Sopenharmony_ci %6 = OpTypePointer Function %5 592fd4e5da5Sopenharmony_ci %7 = OpTypeBool 593fd4e5da5Sopenharmony_ci %8 = OpConstantFalse %7 594fd4e5da5Sopenharmony_ci %2 = OpFunction %3 None %4 595fd4e5da5Sopenharmony_ci %9 = OpLabel 596fd4e5da5Sopenharmony_ci OpBranch %10 597fd4e5da5Sopenharmony_ci %10 = OpLabel ; A-B (loop header) 598fd4e5da5Sopenharmony_ci OpLoopMerge %13 %12 None 599fd4e5da5Sopenharmony_ci OpBranch %15 600fd4e5da5Sopenharmony_ci %12 = OpLabel ; (unreachable continue block) 601fd4e5da5Sopenharmony_ci OpBranch %10 602fd4e5da5Sopenharmony_ci %15 = OpLabel ; C 603fd4e5da5Sopenharmony_ci OpReturn 604fd4e5da5Sopenharmony_ci %13 = OpLabel ; (unreachable merge block) 605fd4e5da5Sopenharmony_ci OpReturn 606fd4e5da5Sopenharmony_ci OpFunctionEnd 607fd4e5da5Sopenharmony_ci )"; 608fd4e5da5Sopenharmony_ci 609fd4e5da5Sopenharmony_ci // The only difference is the labels. 610fd4e5da5Sopenharmony_ci std::string after_reversed = R"( 611fd4e5da5Sopenharmony_ci OpCapability Shader 612fd4e5da5Sopenharmony_ci %1 = OpExtInstImport "GLSL.std.450" 613fd4e5da5Sopenharmony_ci OpMemoryModel Logical GLSL450 614fd4e5da5Sopenharmony_ci OpEntryPoint Fragment %2 "main" 615fd4e5da5Sopenharmony_ci OpExecutionMode %2 OriginUpperLeft 616fd4e5da5Sopenharmony_ci OpSource ESSL 310 617fd4e5da5Sopenharmony_ci OpName %2 "main" 618fd4e5da5Sopenharmony_ci %3 = OpTypeVoid 619fd4e5da5Sopenharmony_ci %4 = OpTypeFunction %3 620fd4e5da5Sopenharmony_ci %5 = OpTypeInt 32 1 621fd4e5da5Sopenharmony_ci %6 = OpTypePointer Function %5 622fd4e5da5Sopenharmony_ci %7 = OpTypeBool 623fd4e5da5Sopenharmony_ci %8 = OpConstantFalse %7 624fd4e5da5Sopenharmony_ci %2 = OpFunction %3 None %4 625fd4e5da5Sopenharmony_ci %9 = OpLabel 626fd4e5da5Sopenharmony_ci OpBranch %10 627fd4e5da5Sopenharmony_ci %10 = OpLabel ; A (loop header) 628fd4e5da5Sopenharmony_ci OpLoopMerge %13 %12 None 629fd4e5da5Sopenharmony_ci OpBranch %11 630fd4e5da5Sopenharmony_ci %12 = OpLabel ; (unreachable continue block) 631fd4e5da5Sopenharmony_ci OpBranch %10 632fd4e5da5Sopenharmony_ci %11 = OpLabel ; B-C 633fd4e5da5Sopenharmony_ci OpReturn 634fd4e5da5Sopenharmony_ci %13 = OpLabel ; (unreachable merge block) 635fd4e5da5Sopenharmony_ci OpReturn 636fd4e5da5Sopenharmony_ci OpFunctionEnd 637fd4e5da5Sopenharmony_ci )"; 638fd4e5da5Sopenharmony_ci 639fd4e5da5Sopenharmony_ci CheckEqual(env, reverse ? after_reversed : after, context.get()); 640fd4e5da5Sopenharmony_ci} 641fd4e5da5Sopenharmony_ci 642fd4e5da5Sopenharmony_ciTEST(MergeBlocksReductionPassTest, LoopReturn) { 643fd4e5da5Sopenharmony_ci MergeBlocksReductionPassTest_LoopReturn_Helper(false); 644fd4e5da5Sopenharmony_ci} 645fd4e5da5Sopenharmony_ci 646fd4e5da5Sopenharmony_ciTEST(MergeBlocksReductionPassTest, LoopReturnReverse) { 647fd4e5da5Sopenharmony_ci MergeBlocksReductionPassTest_LoopReturn_Helper(true); 648fd4e5da5Sopenharmony_ci} 649fd4e5da5Sopenharmony_ci 650fd4e5da5Sopenharmony_ciTEST(MergeBlocksReductionPassTest, MergeUnreachable) { 651fd4e5da5Sopenharmony_ci std::string shader = R"( 652fd4e5da5Sopenharmony_ci OpCapability Shader 653fd4e5da5Sopenharmony_ci %1 = OpExtInstImport "GLSL.std.450" 654fd4e5da5Sopenharmony_ci OpMemoryModel Logical GLSL450 655fd4e5da5Sopenharmony_ci OpEntryPoint Fragment %4 "main" 656fd4e5da5Sopenharmony_ci OpExecutionMode %4 OriginUpperLeft 657fd4e5da5Sopenharmony_ci OpSource ESSL 320 658fd4e5da5Sopenharmony_ci OpName %4 "main" 659fd4e5da5Sopenharmony_ci %2 = OpTypeVoid 660fd4e5da5Sopenharmony_ci %3 = OpTypeFunction %2 661fd4e5da5Sopenharmony_ci %11 = OpTypeBool 662fd4e5da5Sopenharmony_ci %12 = OpConstantFalse %11 663fd4e5da5Sopenharmony_ci %4 = OpFunction %2 None %3 664fd4e5da5Sopenharmony_ci %5 = OpLabel 665fd4e5da5Sopenharmony_ci OpReturn 666fd4e5da5Sopenharmony_ci %9 = OpLabel 667fd4e5da5Sopenharmony_ci OpBranch %100 668fd4e5da5Sopenharmony_ci %100 = OpLabel 669fd4e5da5Sopenharmony_ci OpReturn 670fd4e5da5Sopenharmony_ci OpFunctionEnd 671fd4e5da5Sopenharmony_ci )"; 672fd4e5da5Sopenharmony_ci 673fd4e5da5Sopenharmony_ci const auto env = SPV_ENV_UNIVERSAL_1_3; 674fd4e5da5Sopenharmony_ci const auto consumer = nullptr; 675fd4e5da5Sopenharmony_ci const auto context = 676fd4e5da5Sopenharmony_ci BuildModule(env, consumer, shader, kReduceAssembleOption); 677fd4e5da5Sopenharmony_ci const auto ops = 678fd4e5da5Sopenharmony_ci MergeBlocksReductionOpportunityFinder().GetAvailableOpportunities( 679fd4e5da5Sopenharmony_ci context.get(), 0); 680fd4e5da5Sopenharmony_ci ASSERT_EQ(1, ops.size()); 681fd4e5da5Sopenharmony_ci 682fd4e5da5Sopenharmony_ci ASSERT_TRUE(ops[0]->PreconditionHolds()); 683fd4e5da5Sopenharmony_ci ops[0]->TryToApply(); 684fd4e5da5Sopenharmony_ci 685fd4e5da5Sopenharmony_ci std::string after = R"( 686fd4e5da5Sopenharmony_ci OpCapability Shader 687fd4e5da5Sopenharmony_ci %1 = OpExtInstImport "GLSL.std.450" 688fd4e5da5Sopenharmony_ci OpMemoryModel Logical GLSL450 689fd4e5da5Sopenharmony_ci OpEntryPoint Fragment %4 "main" 690fd4e5da5Sopenharmony_ci OpExecutionMode %4 OriginUpperLeft 691fd4e5da5Sopenharmony_ci OpSource ESSL 320 692fd4e5da5Sopenharmony_ci OpName %4 "main" 693fd4e5da5Sopenharmony_ci %2 = OpTypeVoid 694fd4e5da5Sopenharmony_ci %3 = OpTypeFunction %2 695fd4e5da5Sopenharmony_ci %11 = OpTypeBool 696fd4e5da5Sopenharmony_ci %12 = OpConstantFalse %11 697fd4e5da5Sopenharmony_ci %4 = OpFunction %2 None %3 698fd4e5da5Sopenharmony_ci %5 = OpLabel 699fd4e5da5Sopenharmony_ci OpReturn 700fd4e5da5Sopenharmony_ci %9 = OpLabel 701fd4e5da5Sopenharmony_ci OpReturn 702fd4e5da5Sopenharmony_ci OpFunctionEnd 703fd4e5da5Sopenharmony_ci )"; 704fd4e5da5Sopenharmony_ci 705fd4e5da5Sopenharmony_ci CheckEqual(env, after, context.get()); 706fd4e5da5Sopenharmony_ci} 707fd4e5da5Sopenharmony_ci 708fd4e5da5Sopenharmony_ci} // namespace 709fd4e5da5Sopenharmony_ci} // namespace reduce 710fd4e5da5Sopenharmony_ci} // namespace spvtools 711