1fd4e5da5Sopenharmony_ci// Copyright (c) 2018 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 <memory> 16fd4e5da5Sopenharmony_ci#include <vector> 17fd4e5da5Sopenharmony_ci 18fd4e5da5Sopenharmony_ci#include "gmock/gmock.h" 19fd4e5da5Sopenharmony_ci#include "source/opt/loop_descriptor.h" 20fd4e5da5Sopenharmony_ci#include "source/opt/loop_fusion.h" 21fd4e5da5Sopenharmony_ci#include "test/opt/pass_fixture.h" 22fd4e5da5Sopenharmony_ci 23fd4e5da5Sopenharmony_cinamespace spvtools { 24fd4e5da5Sopenharmony_cinamespace opt { 25fd4e5da5Sopenharmony_cinamespace { 26fd4e5da5Sopenharmony_ci 27fd4e5da5Sopenharmony_ciusing FusionCompatibilityTest = PassTest<::testing::Test>; 28fd4e5da5Sopenharmony_ci 29fd4e5da5Sopenharmony_ci/* 30fd4e5da5Sopenharmony_ciGenerated from the following GLSL + --eliminate-local-multi-store 31fd4e5da5Sopenharmony_ci 32fd4e5da5Sopenharmony_ci#version 440 core 33fd4e5da5Sopenharmony_civoid main() { 34fd4e5da5Sopenharmony_ci int i = 0; // Can't fuse, i=0 in first & i=10 in second 35fd4e5da5Sopenharmony_ci for (; i < 10; i++) {} 36fd4e5da5Sopenharmony_ci for (; i < 10; i++) {} 37fd4e5da5Sopenharmony_ci} 38fd4e5da5Sopenharmony_ci*/ 39fd4e5da5Sopenharmony_ciTEST_F(FusionCompatibilityTest, SameInductionVariableDifferentBounds) { 40fd4e5da5Sopenharmony_ci const std::string text = R"( 41fd4e5da5Sopenharmony_ci OpCapability Shader 42fd4e5da5Sopenharmony_ci %1 = OpExtInstImport "GLSL.std.450" 43fd4e5da5Sopenharmony_ci OpMemoryModel Logical GLSL450 44fd4e5da5Sopenharmony_ci OpEntryPoint Fragment %4 "main" 45fd4e5da5Sopenharmony_ci OpExecutionMode %4 OriginUpperLeft 46fd4e5da5Sopenharmony_ci OpSource GLSL 440 47fd4e5da5Sopenharmony_ci OpName %4 "main" 48fd4e5da5Sopenharmony_ci OpName %8 "i" 49fd4e5da5Sopenharmony_ci %2 = OpTypeVoid 50fd4e5da5Sopenharmony_ci %3 = OpTypeFunction %2 51fd4e5da5Sopenharmony_ci %6 = OpTypeInt 32 1 52fd4e5da5Sopenharmony_ci %7 = OpTypePointer Function %6 53fd4e5da5Sopenharmony_ci %9 = OpConstant %6 0 54fd4e5da5Sopenharmony_ci %16 = OpConstant %6 10 55fd4e5da5Sopenharmony_ci %17 = OpTypeBool 56fd4e5da5Sopenharmony_ci %20 = OpConstant %6 1 57fd4e5da5Sopenharmony_ci %4 = OpFunction %2 None %3 58fd4e5da5Sopenharmony_ci %5 = OpLabel 59fd4e5da5Sopenharmony_ci %8 = OpVariable %7 Function 60fd4e5da5Sopenharmony_ci OpStore %8 %9 61fd4e5da5Sopenharmony_ci OpBranch %10 62fd4e5da5Sopenharmony_ci %10 = OpLabel 63fd4e5da5Sopenharmony_ci %31 = OpPhi %6 %9 %5 %21 %13 64fd4e5da5Sopenharmony_ci OpLoopMerge %12 %13 None 65fd4e5da5Sopenharmony_ci OpBranch %14 66fd4e5da5Sopenharmony_ci %14 = OpLabel 67fd4e5da5Sopenharmony_ci %18 = OpSLessThan %17 %31 %16 68fd4e5da5Sopenharmony_ci OpBranchConditional %18 %11 %12 69fd4e5da5Sopenharmony_ci %11 = OpLabel 70fd4e5da5Sopenharmony_ci OpBranch %13 71fd4e5da5Sopenharmony_ci %13 = OpLabel 72fd4e5da5Sopenharmony_ci %21 = OpIAdd %6 %31 %20 73fd4e5da5Sopenharmony_ci OpStore %8 %21 74fd4e5da5Sopenharmony_ci OpBranch %10 75fd4e5da5Sopenharmony_ci %12 = OpLabel 76fd4e5da5Sopenharmony_ci OpBranch %22 77fd4e5da5Sopenharmony_ci %22 = OpLabel 78fd4e5da5Sopenharmony_ci %32 = OpPhi %6 %31 %12 %30 %25 79fd4e5da5Sopenharmony_ci OpLoopMerge %24 %25 None 80fd4e5da5Sopenharmony_ci OpBranch %26 81fd4e5da5Sopenharmony_ci %26 = OpLabel 82fd4e5da5Sopenharmony_ci %28 = OpSLessThan %17 %32 %16 83fd4e5da5Sopenharmony_ci OpBranchConditional %28 %23 %24 84fd4e5da5Sopenharmony_ci %23 = OpLabel 85fd4e5da5Sopenharmony_ci OpBranch %25 86fd4e5da5Sopenharmony_ci %25 = OpLabel 87fd4e5da5Sopenharmony_ci %30 = OpIAdd %6 %32 %20 88fd4e5da5Sopenharmony_ci OpStore %8 %30 89fd4e5da5Sopenharmony_ci OpBranch %22 90fd4e5da5Sopenharmony_ci %24 = OpLabel 91fd4e5da5Sopenharmony_ci OpReturn 92fd4e5da5Sopenharmony_ci OpFunctionEnd 93fd4e5da5Sopenharmony_ci )"; 94fd4e5da5Sopenharmony_ci 95fd4e5da5Sopenharmony_ci std::unique_ptr<IRContext> context = 96fd4e5da5Sopenharmony_ci BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, text, 97fd4e5da5Sopenharmony_ci SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); 98fd4e5da5Sopenharmony_ci Module* module = context->module(); 99fd4e5da5Sopenharmony_ci EXPECT_NE(nullptr, module) << "Assembling failed for shader:\n" 100fd4e5da5Sopenharmony_ci << text << std::endl; 101fd4e5da5Sopenharmony_ci Function& f = *module->begin(); 102fd4e5da5Sopenharmony_ci LoopDescriptor& ld = *context->GetLoopDescriptor(&f); 103fd4e5da5Sopenharmony_ci EXPECT_EQ(ld.NumLoops(), 2u); 104fd4e5da5Sopenharmony_ci 105fd4e5da5Sopenharmony_ci auto loops = ld.GetLoopsInBinaryLayoutOrder(); 106fd4e5da5Sopenharmony_ci 107fd4e5da5Sopenharmony_ci LoopFusion fusion(context.get(), loops[0], loops[1]); 108fd4e5da5Sopenharmony_ci EXPECT_FALSE(fusion.AreCompatible()); 109fd4e5da5Sopenharmony_ci} 110fd4e5da5Sopenharmony_ci 111fd4e5da5Sopenharmony_ci/* 112fd4e5da5Sopenharmony_ciGenerated from the following GLSL + --eliminate-local-multi-store 113fd4e5da5Sopenharmony_ci 114fd4e5da5Sopenharmony_ci// 1 115fd4e5da5Sopenharmony_ci#version 440 core 116fd4e5da5Sopenharmony_civoid main() { 117fd4e5da5Sopenharmony_ci for (int i = 0; i < 10; i++) {} 118fd4e5da5Sopenharmony_ci for (int i = 0; i < 10; i++) {} 119fd4e5da5Sopenharmony_ci} 120fd4e5da5Sopenharmony_ci*/ 121fd4e5da5Sopenharmony_ciTEST_F(FusionCompatibilityTest, Compatible) { 122fd4e5da5Sopenharmony_ci const std::string text = R"( 123fd4e5da5Sopenharmony_ci OpCapability Shader 124fd4e5da5Sopenharmony_ci %1 = OpExtInstImport "GLSL.std.450" 125fd4e5da5Sopenharmony_ci OpMemoryModel Logical GLSL450 126fd4e5da5Sopenharmony_ci OpEntryPoint Fragment %4 "main" 127fd4e5da5Sopenharmony_ci OpExecutionMode %4 OriginUpperLeft 128fd4e5da5Sopenharmony_ci OpSource GLSL 440 129fd4e5da5Sopenharmony_ci OpName %4 "main" 130fd4e5da5Sopenharmony_ci OpName %8 "i" 131fd4e5da5Sopenharmony_ci OpName %22 "i" 132fd4e5da5Sopenharmony_ci %2 = OpTypeVoid 133fd4e5da5Sopenharmony_ci %3 = OpTypeFunction %2 134fd4e5da5Sopenharmony_ci %6 = OpTypeInt 32 1 135fd4e5da5Sopenharmony_ci %7 = OpTypePointer Function %6 136fd4e5da5Sopenharmony_ci %9 = OpConstant %6 0 137fd4e5da5Sopenharmony_ci %16 = OpConstant %6 10 138fd4e5da5Sopenharmony_ci %17 = OpTypeBool 139fd4e5da5Sopenharmony_ci %20 = OpConstant %6 1 140fd4e5da5Sopenharmony_ci %4 = OpFunction %2 None %3 141fd4e5da5Sopenharmony_ci %5 = OpLabel 142fd4e5da5Sopenharmony_ci %8 = OpVariable %7 Function 143fd4e5da5Sopenharmony_ci %22 = OpVariable %7 Function 144fd4e5da5Sopenharmony_ci OpStore %8 %9 145fd4e5da5Sopenharmony_ci OpBranch %10 146fd4e5da5Sopenharmony_ci %10 = OpLabel 147fd4e5da5Sopenharmony_ci %32 = OpPhi %6 %9 %5 %21 %13 148fd4e5da5Sopenharmony_ci OpLoopMerge %12 %13 None 149fd4e5da5Sopenharmony_ci OpBranch %14 150fd4e5da5Sopenharmony_ci %14 = OpLabel 151fd4e5da5Sopenharmony_ci %18 = OpSLessThan %17 %32 %16 152fd4e5da5Sopenharmony_ci OpBranchConditional %18 %11 %12 153fd4e5da5Sopenharmony_ci %11 = OpLabel 154fd4e5da5Sopenharmony_ci OpBranch %13 155fd4e5da5Sopenharmony_ci %13 = OpLabel 156fd4e5da5Sopenharmony_ci %21 = OpIAdd %6 %32 %20 157fd4e5da5Sopenharmony_ci OpStore %8 %21 158fd4e5da5Sopenharmony_ci OpBranch %10 159fd4e5da5Sopenharmony_ci %12 = OpLabel 160fd4e5da5Sopenharmony_ci OpStore %22 %9 161fd4e5da5Sopenharmony_ci OpBranch %23 162fd4e5da5Sopenharmony_ci %23 = OpLabel 163fd4e5da5Sopenharmony_ci %33 = OpPhi %6 %9 %12 %31 %26 164fd4e5da5Sopenharmony_ci OpLoopMerge %25 %26 None 165fd4e5da5Sopenharmony_ci OpBranch %27 166fd4e5da5Sopenharmony_ci %27 = OpLabel 167fd4e5da5Sopenharmony_ci %29 = OpSLessThan %17 %33 %16 168fd4e5da5Sopenharmony_ci OpBranchConditional %29 %24 %25 169fd4e5da5Sopenharmony_ci %24 = OpLabel 170fd4e5da5Sopenharmony_ci OpBranch %26 171fd4e5da5Sopenharmony_ci %26 = OpLabel 172fd4e5da5Sopenharmony_ci %31 = OpIAdd %6 %33 %20 173fd4e5da5Sopenharmony_ci OpStore %22 %31 174fd4e5da5Sopenharmony_ci OpBranch %23 175fd4e5da5Sopenharmony_ci %25 = OpLabel 176fd4e5da5Sopenharmony_ci OpReturn 177fd4e5da5Sopenharmony_ci OpFunctionEnd 178fd4e5da5Sopenharmony_ci )"; 179fd4e5da5Sopenharmony_ci 180fd4e5da5Sopenharmony_ci std::unique_ptr<IRContext> context = 181fd4e5da5Sopenharmony_ci BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, text, 182fd4e5da5Sopenharmony_ci SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); 183fd4e5da5Sopenharmony_ci Module* module = context->module(); 184fd4e5da5Sopenharmony_ci EXPECT_NE(nullptr, module) << "Assembling failed for shader:\n" 185fd4e5da5Sopenharmony_ci << text << std::endl; 186fd4e5da5Sopenharmony_ci Function& f = *module->begin(); 187fd4e5da5Sopenharmony_ci LoopDescriptor& ld = *context->GetLoopDescriptor(&f); 188fd4e5da5Sopenharmony_ci EXPECT_EQ(ld.NumLoops(), 2u); 189fd4e5da5Sopenharmony_ci 190fd4e5da5Sopenharmony_ci auto loops = ld.GetLoopsInBinaryLayoutOrder(); 191fd4e5da5Sopenharmony_ci 192fd4e5da5Sopenharmony_ci LoopFusion fusion(context.get(), loops[0], loops[1]); 193fd4e5da5Sopenharmony_ci EXPECT_TRUE(fusion.AreCompatible()); 194fd4e5da5Sopenharmony_ci} 195fd4e5da5Sopenharmony_ci 196fd4e5da5Sopenharmony_ci/* 197fd4e5da5Sopenharmony_ciGenerated from the following GLSL + --eliminate-local-multi-store 198fd4e5da5Sopenharmony_ci 199fd4e5da5Sopenharmony_ci// 2 200fd4e5da5Sopenharmony_ci#version 440 core 201fd4e5da5Sopenharmony_civoid main() { 202fd4e5da5Sopenharmony_ci for (int i = 0; i < 10; i++) {} 203fd4e5da5Sopenharmony_ci for (int j = 0; j < 10; j++) {} 204fd4e5da5Sopenharmony_ci} 205fd4e5da5Sopenharmony_ci 206fd4e5da5Sopenharmony_ci*/ 207fd4e5da5Sopenharmony_ciTEST_F(FusionCompatibilityTest, DifferentName) { 208fd4e5da5Sopenharmony_ci const std::string text = R"( 209fd4e5da5Sopenharmony_ci OpCapability Shader 210fd4e5da5Sopenharmony_ci %1 = OpExtInstImport "GLSL.std.450" 211fd4e5da5Sopenharmony_ci OpMemoryModel Logical GLSL450 212fd4e5da5Sopenharmony_ci OpEntryPoint Fragment %4 "main" 213fd4e5da5Sopenharmony_ci OpExecutionMode %4 OriginUpperLeft 214fd4e5da5Sopenharmony_ci OpSource GLSL 440 215fd4e5da5Sopenharmony_ci OpName %4 "main" 216fd4e5da5Sopenharmony_ci OpName %8 "i" 217fd4e5da5Sopenharmony_ci OpName %22 "j" 218fd4e5da5Sopenharmony_ci %2 = OpTypeVoid 219fd4e5da5Sopenharmony_ci %3 = OpTypeFunction %2 220fd4e5da5Sopenharmony_ci %6 = OpTypeInt 32 1 221fd4e5da5Sopenharmony_ci %7 = OpTypePointer Function %6 222fd4e5da5Sopenharmony_ci %9 = OpConstant %6 0 223fd4e5da5Sopenharmony_ci %16 = OpConstant %6 10 224fd4e5da5Sopenharmony_ci %17 = OpTypeBool 225fd4e5da5Sopenharmony_ci %20 = OpConstant %6 1 226fd4e5da5Sopenharmony_ci %4 = OpFunction %2 None %3 227fd4e5da5Sopenharmony_ci %5 = OpLabel 228fd4e5da5Sopenharmony_ci %8 = OpVariable %7 Function 229fd4e5da5Sopenharmony_ci %22 = OpVariable %7 Function 230fd4e5da5Sopenharmony_ci OpStore %8 %9 231fd4e5da5Sopenharmony_ci OpBranch %10 232fd4e5da5Sopenharmony_ci %10 = OpLabel 233fd4e5da5Sopenharmony_ci %32 = OpPhi %6 %9 %5 %21 %13 234fd4e5da5Sopenharmony_ci OpLoopMerge %12 %13 None 235fd4e5da5Sopenharmony_ci OpBranch %14 236fd4e5da5Sopenharmony_ci %14 = OpLabel 237fd4e5da5Sopenharmony_ci %18 = OpSLessThan %17 %32 %16 238fd4e5da5Sopenharmony_ci OpBranchConditional %18 %11 %12 239fd4e5da5Sopenharmony_ci %11 = OpLabel 240fd4e5da5Sopenharmony_ci OpBranch %13 241fd4e5da5Sopenharmony_ci %13 = OpLabel 242fd4e5da5Sopenharmony_ci %21 = OpIAdd %6 %32 %20 243fd4e5da5Sopenharmony_ci OpStore %8 %21 244fd4e5da5Sopenharmony_ci OpBranch %10 245fd4e5da5Sopenharmony_ci %12 = OpLabel 246fd4e5da5Sopenharmony_ci OpStore %22 %9 247fd4e5da5Sopenharmony_ci OpBranch %23 248fd4e5da5Sopenharmony_ci %23 = OpLabel 249fd4e5da5Sopenharmony_ci %33 = OpPhi %6 %9 %12 %31 %26 250fd4e5da5Sopenharmony_ci OpLoopMerge %25 %26 None 251fd4e5da5Sopenharmony_ci OpBranch %27 252fd4e5da5Sopenharmony_ci %27 = OpLabel 253fd4e5da5Sopenharmony_ci %29 = OpSLessThan %17 %33 %16 254fd4e5da5Sopenharmony_ci OpBranchConditional %29 %24 %25 255fd4e5da5Sopenharmony_ci %24 = OpLabel 256fd4e5da5Sopenharmony_ci OpBranch %26 257fd4e5da5Sopenharmony_ci %26 = OpLabel 258fd4e5da5Sopenharmony_ci %31 = OpIAdd %6 %33 %20 259fd4e5da5Sopenharmony_ci OpStore %22 %31 260fd4e5da5Sopenharmony_ci OpBranch %23 261fd4e5da5Sopenharmony_ci %25 = OpLabel 262fd4e5da5Sopenharmony_ci OpReturn 263fd4e5da5Sopenharmony_ci OpFunctionEnd 264fd4e5da5Sopenharmony_ci )"; 265fd4e5da5Sopenharmony_ci 266fd4e5da5Sopenharmony_ci std::unique_ptr<IRContext> context = 267fd4e5da5Sopenharmony_ci BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, text, 268fd4e5da5Sopenharmony_ci SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); 269fd4e5da5Sopenharmony_ci Module* module = context->module(); 270fd4e5da5Sopenharmony_ci EXPECT_NE(nullptr, module) << "Assembling failed for shader:\n" 271fd4e5da5Sopenharmony_ci << text << std::endl; 272fd4e5da5Sopenharmony_ci Function& f = *module->begin(); 273fd4e5da5Sopenharmony_ci LoopDescriptor& ld = *context->GetLoopDescriptor(&f); 274fd4e5da5Sopenharmony_ci EXPECT_EQ(ld.NumLoops(), 2u); 275fd4e5da5Sopenharmony_ci 276fd4e5da5Sopenharmony_ci auto loops = ld.GetLoopsInBinaryLayoutOrder(); 277fd4e5da5Sopenharmony_ci 278fd4e5da5Sopenharmony_ci LoopFusion fusion(context.get(), loops[0], loops[1]); 279fd4e5da5Sopenharmony_ci EXPECT_TRUE(fusion.AreCompatible()); 280fd4e5da5Sopenharmony_ci} 281fd4e5da5Sopenharmony_ci 282fd4e5da5Sopenharmony_ci/* 283fd4e5da5Sopenharmony_ciGenerated from the following GLSL + --eliminate-local-multi-store 284fd4e5da5Sopenharmony_ci 285fd4e5da5Sopenharmony_ci#version 440 core 286fd4e5da5Sopenharmony_civoid main() { 287fd4e5da5Sopenharmony_ci // Can't fuse, different step 288fd4e5da5Sopenharmony_ci for (int i = 0; i < 10; i++) {} 289fd4e5da5Sopenharmony_ci for (int j = 0; j < 10; j=j+2) {} 290fd4e5da5Sopenharmony_ci} 291fd4e5da5Sopenharmony_ci 292fd4e5da5Sopenharmony_ci*/ 293fd4e5da5Sopenharmony_ciTEST_F(FusionCompatibilityTest, SameBoundsDifferentStep) { 294fd4e5da5Sopenharmony_ci const std::string text = R"( 295fd4e5da5Sopenharmony_ci OpCapability Shader 296fd4e5da5Sopenharmony_ci %1 = OpExtInstImport "GLSL.std.450" 297fd4e5da5Sopenharmony_ci OpMemoryModel Logical GLSL450 298fd4e5da5Sopenharmony_ci OpEntryPoint Fragment %4 "main" 299fd4e5da5Sopenharmony_ci OpExecutionMode %4 OriginUpperLeft 300fd4e5da5Sopenharmony_ci OpSource GLSL 440 301fd4e5da5Sopenharmony_ci OpName %4 "main" 302fd4e5da5Sopenharmony_ci OpName %8 "i" 303fd4e5da5Sopenharmony_ci OpName %22 "j" 304fd4e5da5Sopenharmony_ci %2 = OpTypeVoid 305fd4e5da5Sopenharmony_ci %3 = OpTypeFunction %2 306fd4e5da5Sopenharmony_ci %6 = OpTypeInt 32 1 307fd4e5da5Sopenharmony_ci %7 = OpTypePointer Function %6 308fd4e5da5Sopenharmony_ci %9 = OpConstant %6 0 309fd4e5da5Sopenharmony_ci %16 = OpConstant %6 10 310fd4e5da5Sopenharmony_ci %17 = OpTypeBool 311fd4e5da5Sopenharmony_ci %20 = OpConstant %6 1 312fd4e5da5Sopenharmony_ci %31 = OpConstant %6 2 313fd4e5da5Sopenharmony_ci %4 = OpFunction %2 None %3 314fd4e5da5Sopenharmony_ci %5 = OpLabel 315fd4e5da5Sopenharmony_ci %8 = OpVariable %7 Function 316fd4e5da5Sopenharmony_ci %22 = OpVariable %7 Function 317fd4e5da5Sopenharmony_ci OpStore %8 %9 318fd4e5da5Sopenharmony_ci OpBranch %10 319fd4e5da5Sopenharmony_ci %10 = OpLabel 320fd4e5da5Sopenharmony_ci %33 = OpPhi %6 %9 %5 %21 %13 321fd4e5da5Sopenharmony_ci OpLoopMerge %12 %13 None 322fd4e5da5Sopenharmony_ci OpBranch %14 323fd4e5da5Sopenharmony_ci %14 = OpLabel 324fd4e5da5Sopenharmony_ci %18 = OpSLessThan %17 %33 %16 325fd4e5da5Sopenharmony_ci OpBranchConditional %18 %11 %12 326fd4e5da5Sopenharmony_ci %11 = OpLabel 327fd4e5da5Sopenharmony_ci OpBranch %13 328fd4e5da5Sopenharmony_ci %13 = OpLabel 329fd4e5da5Sopenharmony_ci %21 = OpIAdd %6 %33 %20 330fd4e5da5Sopenharmony_ci OpStore %8 %21 331fd4e5da5Sopenharmony_ci OpBranch %10 332fd4e5da5Sopenharmony_ci %12 = OpLabel 333fd4e5da5Sopenharmony_ci OpStore %22 %9 334fd4e5da5Sopenharmony_ci OpBranch %23 335fd4e5da5Sopenharmony_ci %23 = OpLabel 336fd4e5da5Sopenharmony_ci %34 = OpPhi %6 %9 %12 %32 %26 337fd4e5da5Sopenharmony_ci OpLoopMerge %25 %26 None 338fd4e5da5Sopenharmony_ci OpBranch %27 339fd4e5da5Sopenharmony_ci %27 = OpLabel 340fd4e5da5Sopenharmony_ci %29 = OpSLessThan %17 %34 %16 341fd4e5da5Sopenharmony_ci OpBranchConditional %29 %24 %25 342fd4e5da5Sopenharmony_ci %24 = OpLabel 343fd4e5da5Sopenharmony_ci OpBranch %26 344fd4e5da5Sopenharmony_ci %26 = OpLabel 345fd4e5da5Sopenharmony_ci %32 = OpIAdd %6 %34 %31 346fd4e5da5Sopenharmony_ci OpStore %22 %32 347fd4e5da5Sopenharmony_ci OpBranch %23 348fd4e5da5Sopenharmony_ci %25 = OpLabel 349fd4e5da5Sopenharmony_ci OpReturn 350fd4e5da5Sopenharmony_ci OpFunctionEnd 351fd4e5da5Sopenharmony_ci )"; 352fd4e5da5Sopenharmony_ci 353fd4e5da5Sopenharmony_ci std::unique_ptr<IRContext> context = 354fd4e5da5Sopenharmony_ci BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, text, 355fd4e5da5Sopenharmony_ci SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); 356fd4e5da5Sopenharmony_ci Module* module = context->module(); 357fd4e5da5Sopenharmony_ci EXPECT_NE(nullptr, module) << "Assembling failed for shader:\n" 358fd4e5da5Sopenharmony_ci << text << std::endl; 359fd4e5da5Sopenharmony_ci Function& f = *module->begin(); 360fd4e5da5Sopenharmony_ci LoopDescriptor& ld = *context->GetLoopDescriptor(&f); 361fd4e5da5Sopenharmony_ci EXPECT_EQ(ld.NumLoops(), 2u); 362fd4e5da5Sopenharmony_ci 363fd4e5da5Sopenharmony_ci auto loops = ld.GetLoopsInBinaryLayoutOrder(); 364fd4e5da5Sopenharmony_ci 365fd4e5da5Sopenharmony_ci LoopFusion fusion(context.get(), loops[0], loops[1]); 366fd4e5da5Sopenharmony_ci EXPECT_FALSE(fusion.AreCompatible()); 367fd4e5da5Sopenharmony_ci} 368fd4e5da5Sopenharmony_ci 369fd4e5da5Sopenharmony_ci/* 370fd4e5da5Sopenharmony_ciGenerated from the following GLSL + --eliminate-local-multi-store 371fd4e5da5Sopenharmony_ci 372fd4e5da5Sopenharmony_ci// 4 373fd4e5da5Sopenharmony_ci#version 440 core 374fd4e5da5Sopenharmony_civoid main() { 375fd4e5da5Sopenharmony_ci // Can't fuse, different upper bound 376fd4e5da5Sopenharmony_ci for (int i = 0; i < 10; i++) {} 377fd4e5da5Sopenharmony_ci for (int j = 0; j < 20; j++) {} 378fd4e5da5Sopenharmony_ci} 379fd4e5da5Sopenharmony_ci 380fd4e5da5Sopenharmony_ci*/ 381fd4e5da5Sopenharmony_ciTEST_F(FusionCompatibilityTest, DifferentUpperBound) { 382fd4e5da5Sopenharmony_ci const std::string text = R"( 383fd4e5da5Sopenharmony_ci OpCapability Shader 384fd4e5da5Sopenharmony_ci %1 = OpExtInstImport "GLSL.std.450" 385fd4e5da5Sopenharmony_ci OpMemoryModel Logical GLSL450 386fd4e5da5Sopenharmony_ci OpEntryPoint Fragment %4 "main" 387fd4e5da5Sopenharmony_ci OpExecutionMode %4 OriginUpperLeft 388fd4e5da5Sopenharmony_ci OpSource GLSL 440 389fd4e5da5Sopenharmony_ci OpName %4 "main" 390fd4e5da5Sopenharmony_ci OpName %8 "i" 391fd4e5da5Sopenharmony_ci OpName %22 "j" 392fd4e5da5Sopenharmony_ci %2 = OpTypeVoid 393fd4e5da5Sopenharmony_ci %3 = OpTypeFunction %2 394fd4e5da5Sopenharmony_ci %6 = OpTypeInt 32 1 395fd4e5da5Sopenharmony_ci %7 = OpTypePointer Function %6 396fd4e5da5Sopenharmony_ci %9 = OpConstant %6 0 397fd4e5da5Sopenharmony_ci %16 = OpConstant %6 10 398fd4e5da5Sopenharmony_ci %17 = OpTypeBool 399fd4e5da5Sopenharmony_ci %20 = OpConstant %6 1 400fd4e5da5Sopenharmony_ci %29 = OpConstant %6 20 401fd4e5da5Sopenharmony_ci %4 = OpFunction %2 None %3 402fd4e5da5Sopenharmony_ci %5 = OpLabel 403fd4e5da5Sopenharmony_ci %8 = OpVariable %7 Function 404fd4e5da5Sopenharmony_ci %22 = OpVariable %7 Function 405fd4e5da5Sopenharmony_ci OpStore %8 %9 406fd4e5da5Sopenharmony_ci OpBranch %10 407fd4e5da5Sopenharmony_ci %10 = OpLabel 408fd4e5da5Sopenharmony_ci %33 = OpPhi %6 %9 %5 %21 %13 409fd4e5da5Sopenharmony_ci OpLoopMerge %12 %13 None 410fd4e5da5Sopenharmony_ci OpBranch %14 411fd4e5da5Sopenharmony_ci %14 = OpLabel 412fd4e5da5Sopenharmony_ci %18 = OpSLessThan %17 %33 %16 413fd4e5da5Sopenharmony_ci OpBranchConditional %18 %11 %12 414fd4e5da5Sopenharmony_ci %11 = OpLabel 415fd4e5da5Sopenharmony_ci OpBranch %13 416fd4e5da5Sopenharmony_ci %13 = OpLabel 417fd4e5da5Sopenharmony_ci %21 = OpIAdd %6 %33 %20 418fd4e5da5Sopenharmony_ci OpStore %8 %21 419fd4e5da5Sopenharmony_ci OpBranch %10 420fd4e5da5Sopenharmony_ci %12 = OpLabel 421fd4e5da5Sopenharmony_ci OpStore %22 %9 422fd4e5da5Sopenharmony_ci OpBranch %23 423fd4e5da5Sopenharmony_ci %23 = OpLabel 424fd4e5da5Sopenharmony_ci %34 = OpPhi %6 %9 %12 %32 %26 425fd4e5da5Sopenharmony_ci OpLoopMerge %25 %26 None 426fd4e5da5Sopenharmony_ci OpBranch %27 427fd4e5da5Sopenharmony_ci %27 = OpLabel 428fd4e5da5Sopenharmony_ci %30 = OpSLessThan %17 %34 %29 429fd4e5da5Sopenharmony_ci OpBranchConditional %30 %24 %25 430fd4e5da5Sopenharmony_ci %24 = OpLabel 431fd4e5da5Sopenharmony_ci OpBranch %26 432fd4e5da5Sopenharmony_ci %26 = OpLabel 433fd4e5da5Sopenharmony_ci %32 = OpIAdd %6 %34 %20 434fd4e5da5Sopenharmony_ci OpStore %22 %32 435fd4e5da5Sopenharmony_ci OpBranch %23 436fd4e5da5Sopenharmony_ci %25 = OpLabel 437fd4e5da5Sopenharmony_ci OpReturn 438fd4e5da5Sopenharmony_ci OpFunctionEnd 439fd4e5da5Sopenharmony_ci )"; 440fd4e5da5Sopenharmony_ci 441fd4e5da5Sopenharmony_ci std::unique_ptr<IRContext> context = 442fd4e5da5Sopenharmony_ci BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, text, 443fd4e5da5Sopenharmony_ci SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); 444fd4e5da5Sopenharmony_ci Module* module = context->module(); 445fd4e5da5Sopenharmony_ci EXPECT_NE(nullptr, module) << "Assembling failed for shader:\n" 446fd4e5da5Sopenharmony_ci << text << std::endl; 447fd4e5da5Sopenharmony_ci Function& f = *module->begin(); 448fd4e5da5Sopenharmony_ci LoopDescriptor& ld = *context->GetLoopDescriptor(&f); 449fd4e5da5Sopenharmony_ci EXPECT_EQ(ld.NumLoops(), 2u); 450fd4e5da5Sopenharmony_ci 451fd4e5da5Sopenharmony_ci auto loops = ld.GetLoopsInBinaryLayoutOrder(); 452fd4e5da5Sopenharmony_ci 453fd4e5da5Sopenharmony_ci LoopFusion fusion(context.get(), loops[0], loops[1]); 454fd4e5da5Sopenharmony_ci EXPECT_FALSE(fusion.AreCompatible()); 455fd4e5da5Sopenharmony_ci} 456fd4e5da5Sopenharmony_ci 457fd4e5da5Sopenharmony_ci/* 458fd4e5da5Sopenharmony_ciGenerated from the following GLSL + --eliminate-local-multi-store 459fd4e5da5Sopenharmony_ci 460fd4e5da5Sopenharmony_ci// 5 461fd4e5da5Sopenharmony_ci#version 440 core 462fd4e5da5Sopenharmony_civoid main() { 463fd4e5da5Sopenharmony_ci // Can't fuse, different lower bound 464fd4e5da5Sopenharmony_ci for (int i = 5; i < 10; i++) {} 465fd4e5da5Sopenharmony_ci for (int j = 0; j < 10; j++) {} 466fd4e5da5Sopenharmony_ci} 467fd4e5da5Sopenharmony_ci 468fd4e5da5Sopenharmony_ci*/ 469fd4e5da5Sopenharmony_ciTEST_F(FusionCompatibilityTest, DifferentLowerBound) { 470fd4e5da5Sopenharmony_ci const std::string text = R"( 471fd4e5da5Sopenharmony_ci OpCapability Shader 472fd4e5da5Sopenharmony_ci %1 = OpExtInstImport "GLSL.std.450" 473fd4e5da5Sopenharmony_ci OpMemoryModel Logical GLSL450 474fd4e5da5Sopenharmony_ci OpEntryPoint Fragment %4 "main" 475fd4e5da5Sopenharmony_ci OpExecutionMode %4 OriginUpperLeft 476fd4e5da5Sopenharmony_ci OpSource GLSL 440 477fd4e5da5Sopenharmony_ci OpName %4 "main" 478fd4e5da5Sopenharmony_ci OpName %8 "i" 479fd4e5da5Sopenharmony_ci OpName %22 "j" 480fd4e5da5Sopenharmony_ci %2 = OpTypeVoid 481fd4e5da5Sopenharmony_ci %3 = OpTypeFunction %2 482fd4e5da5Sopenharmony_ci %6 = OpTypeInt 32 1 483fd4e5da5Sopenharmony_ci %7 = OpTypePointer Function %6 484fd4e5da5Sopenharmony_ci %9 = OpConstant %6 5 485fd4e5da5Sopenharmony_ci %16 = OpConstant %6 10 486fd4e5da5Sopenharmony_ci %17 = OpTypeBool 487fd4e5da5Sopenharmony_ci %20 = OpConstant %6 1 488fd4e5da5Sopenharmony_ci %23 = OpConstant %6 0 489fd4e5da5Sopenharmony_ci %4 = OpFunction %2 None %3 490fd4e5da5Sopenharmony_ci %5 = OpLabel 491fd4e5da5Sopenharmony_ci %8 = OpVariable %7 Function 492fd4e5da5Sopenharmony_ci %22 = OpVariable %7 Function 493fd4e5da5Sopenharmony_ci OpStore %8 %9 494fd4e5da5Sopenharmony_ci OpBranch %10 495fd4e5da5Sopenharmony_ci %10 = OpLabel 496fd4e5da5Sopenharmony_ci %33 = OpPhi %6 %9 %5 %21 %13 497fd4e5da5Sopenharmony_ci OpLoopMerge %12 %13 None 498fd4e5da5Sopenharmony_ci OpBranch %14 499fd4e5da5Sopenharmony_ci %14 = OpLabel 500fd4e5da5Sopenharmony_ci %18 = OpSLessThan %17 %33 %16 501fd4e5da5Sopenharmony_ci OpBranchConditional %18 %11 %12 502fd4e5da5Sopenharmony_ci %11 = OpLabel 503fd4e5da5Sopenharmony_ci OpBranch %13 504fd4e5da5Sopenharmony_ci %13 = OpLabel 505fd4e5da5Sopenharmony_ci %21 = OpIAdd %6 %33 %20 506fd4e5da5Sopenharmony_ci OpStore %8 %21 507fd4e5da5Sopenharmony_ci OpBranch %10 508fd4e5da5Sopenharmony_ci %12 = OpLabel 509fd4e5da5Sopenharmony_ci OpStore %22 %23 510fd4e5da5Sopenharmony_ci OpBranch %24 511fd4e5da5Sopenharmony_ci %24 = OpLabel 512fd4e5da5Sopenharmony_ci %34 = OpPhi %6 %23 %12 %32 %27 513fd4e5da5Sopenharmony_ci OpLoopMerge %26 %27 None 514fd4e5da5Sopenharmony_ci OpBranch %28 515fd4e5da5Sopenharmony_ci %28 = OpLabel 516fd4e5da5Sopenharmony_ci %30 = OpSLessThan %17 %34 %16 517fd4e5da5Sopenharmony_ci OpBranchConditional %30 %25 %26 518fd4e5da5Sopenharmony_ci %25 = OpLabel 519fd4e5da5Sopenharmony_ci OpBranch %27 520fd4e5da5Sopenharmony_ci %27 = OpLabel 521fd4e5da5Sopenharmony_ci %32 = OpIAdd %6 %34 %20 522fd4e5da5Sopenharmony_ci OpStore %22 %32 523fd4e5da5Sopenharmony_ci OpBranch %24 524fd4e5da5Sopenharmony_ci %26 = OpLabel 525fd4e5da5Sopenharmony_ci OpReturn 526fd4e5da5Sopenharmony_ci OpFunctionEnd 527fd4e5da5Sopenharmony_ci )"; 528fd4e5da5Sopenharmony_ci 529fd4e5da5Sopenharmony_ci std::unique_ptr<IRContext> context = 530fd4e5da5Sopenharmony_ci BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, text, 531fd4e5da5Sopenharmony_ci SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); 532fd4e5da5Sopenharmony_ci Module* module = context->module(); 533fd4e5da5Sopenharmony_ci EXPECT_NE(nullptr, module) << "Assembling failed for shader:\n" 534fd4e5da5Sopenharmony_ci << text << std::endl; 535fd4e5da5Sopenharmony_ci Function& f = *module->begin(); 536fd4e5da5Sopenharmony_ci LoopDescriptor& ld = *context->GetLoopDescriptor(&f); 537fd4e5da5Sopenharmony_ci EXPECT_EQ(ld.NumLoops(), 2u); 538fd4e5da5Sopenharmony_ci 539fd4e5da5Sopenharmony_ci auto loops = ld.GetLoopsInBinaryLayoutOrder(); 540fd4e5da5Sopenharmony_ci 541fd4e5da5Sopenharmony_ci LoopFusion fusion(context.get(), loops[0], loops[1]); 542fd4e5da5Sopenharmony_ci EXPECT_FALSE(fusion.AreCompatible()); 543fd4e5da5Sopenharmony_ci} 544fd4e5da5Sopenharmony_ci 545fd4e5da5Sopenharmony_ci/* 546fd4e5da5Sopenharmony_ciGenerated from the following GLSL + --eliminate-local-multi-store 547fd4e5da5Sopenharmony_ci 548fd4e5da5Sopenharmony_ci// 6 549fd4e5da5Sopenharmony_ci#version 440 core 550fd4e5da5Sopenharmony_civoid main() { 551fd4e5da5Sopenharmony_ci // Can't fuse, break in first loop 552fd4e5da5Sopenharmony_ci for (int i = 0; i < 10; i++) { 553fd4e5da5Sopenharmony_ci if (i == 5) { 554fd4e5da5Sopenharmony_ci break; 555fd4e5da5Sopenharmony_ci } 556fd4e5da5Sopenharmony_ci } 557fd4e5da5Sopenharmony_ci for (int j = 0; j < 10; j++) {} 558fd4e5da5Sopenharmony_ci} 559fd4e5da5Sopenharmony_ci 560fd4e5da5Sopenharmony_ci*/ 561fd4e5da5Sopenharmony_ciTEST_F(FusionCompatibilityTest, Break) { 562fd4e5da5Sopenharmony_ci const std::string text = R"( 563fd4e5da5Sopenharmony_ci OpCapability Shader 564fd4e5da5Sopenharmony_ci %1 = OpExtInstImport "GLSL.std.450" 565fd4e5da5Sopenharmony_ci OpMemoryModel Logical GLSL450 566fd4e5da5Sopenharmony_ci OpEntryPoint Fragment %4 "main" 567fd4e5da5Sopenharmony_ci OpExecutionMode %4 OriginUpperLeft 568fd4e5da5Sopenharmony_ci OpSource GLSL 440 569fd4e5da5Sopenharmony_ci OpName %4 "main" 570fd4e5da5Sopenharmony_ci OpName %8 "i" 571fd4e5da5Sopenharmony_ci OpName %28 "j" 572fd4e5da5Sopenharmony_ci %2 = OpTypeVoid 573fd4e5da5Sopenharmony_ci %3 = OpTypeFunction %2 574fd4e5da5Sopenharmony_ci %6 = OpTypeInt 32 1 575fd4e5da5Sopenharmony_ci %7 = OpTypePointer Function %6 576fd4e5da5Sopenharmony_ci %9 = OpConstant %6 0 577fd4e5da5Sopenharmony_ci %16 = OpConstant %6 10 578fd4e5da5Sopenharmony_ci %17 = OpTypeBool 579fd4e5da5Sopenharmony_ci %20 = OpConstant %6 5 580fd4e5da5Sopenharmony_ci %26 = OpConstant %6 1 581fd4e5da5Sopenharmony_ci %4 = OpFunction %2 None %3 582fd4e5da5Sopenharmony_ci %5 = OpLabel 583fd4e5da5Sopenharmony_ci %8 = OpVariable %7 Function 584fd4e5da5Sopenharmony_ci %28 = OpVariable %7 Function 585fd4e5da5Sopenharmony_ci OpStore %8 %9 586fd4e5da5Sopenharmony_ci OpBranch %10 587fd4e5da5Sopenharmony_ci %10 = OpLabel 588fd4e5da5Sopenharmony_ci %38 = OpPhi %6 %9 %5 %27 %13 589fd4e5da5Sopenharmony_ci OpLoopMerge %12 %13 None 590fd4e5da5Sopenharmony_ci OpBranch %14 591fd4e5da5Sopenharmony_ci %14 = OpLabel 592fd4e5da5Sopenharmony_ci %18 = OpSLessThan %17 %38 %16 593fd4e5da5Sopenharmony_ci OpBranchConditional %18 %11 %12 594fd4e5da5Sopenharmony_ci %11 = OpLabel 595fd4e5da5Sopenharmony_ci %21 = OpIEqual %17 %38 %20 596fd4e5da5Sopenharmony_ci OpSelectionMerge %23 None 597fd4e5da5Sopenharmony_ci OpBranchConditional %21 %22 %23 598fd4e5da5Sopenharmony_ci %22 = OpLabel 599fd4e5da5Sopenharmony_ci OpBranch %12 600fd4e5da5Sopenharmony_ci %23 = OpLabel 601fd4e5da5Sopenharmony_ci OpBranch %13 602fd4e5da5Sopenharmony_ci %13 = OpLabel 603fd4e5da5Sopenharmony_ci %27 = OpIAdd %6 %38 %26 604fd4e5da5Sopenharmony_ci OpStore %8 %27 605fd4e5da5Sopenharmony_ci OpBranch %10 606fd4e5da5Sopenharmony_ci %12 = OpLabel 607fd4e5da5Sopenharmony_ci OpStore %28 %9 608fd4e5da5Sopenharmony_ci OpBranch %29 609fd4e5da5Sopenharmony_ci %29 = OpLabel 610fd4e5da5Sopenharmony_ci %39 = OpPhi %6 %9 %12 %37 %32 611fd4e5da5Sopenharmony_ci OpLoopMerge %31 %32 None 612fd4e5da5Sopenharmony_ci OpBranch %33 613fd4e5da5Sopenharmony_ci %33 = OpLabel 614fd4e5da5Sopenharmony_ci %35 = OpSLessThan %17 %39 %16 615fd4e5da5Sopenharmony_ci OpBranchConditional %35 %30 %31 616fd4e5da5Sopenharmony_ci %30 = OpLabel 617fd4e5da5Sopenharmony_ci OpBranch %32 618fd4e5da5Sopenharmony_ci %32 = OpLabel 619fd4e5da5Sopenharmony_ci %37 = OpIAdd %6 %39 %26 620fd4e5da5Sopenharmony_ci OpStore %28 %37 621fd4e5da5Sopenharmony_ci OpBranch %29 622fd4e5da5Sopenharmony_ci %31 = OpLabel 623fd4e5da5Sopenharmony_ci OpReturn 624fd4e5da5Sopenharmony_ci OpFunctionEnd 625fd4e5da5Sopenharmony_ci )"; 626fd4e5da5Sopenharmony_ci 627fd4e5da5Sopenharmony_ci std::unique_ptr<IRContext> context = 628fd4e5da5Sopenharmony_ci BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, text, 629fd4e5da5Sopenharmony_ci SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); 630fd4e5da5Sopenharmony_ci Module* module = context->module(); 631fd4e5da5Sopenharmony_ci EXPECT_NE(nullptr, module) << "Assembling failed for shader:\n" 632fd4e5da5Sopenharmony_ci << text << std::endl; 633fd4e5da5Sopenharmony_ci Function& f = *module->begin(); 634fd4e5da5Sopenharmony_ci LoopDescriptor& ld = *context->GetLoopDescriptor(&f); 635fd4e5da5Sopenharmony_ci EXPECT_EQ(ld.NumLoops(), 2u); 636fd4e5da5Sopenharmony_ci 637fd4e5da5Sopenharmony_ci auto loops = ld.GetLoopsInBinaryLayoutOrder(); 638fd4e5da5Sopenharmony_ci 639fd4e5da5Sopenharmony_ci LoopFusion fusion(context.get(), loops[0], loops[1]); 640fd4e5da5Sopenharmony_ci EXPECT_FALSE(fusion.AreCompatible()); 641fd4e5da5Sopenharmony_ci} 642fd4e5da5Sopenharmony_ci 643fd4e5da5Sopenharmony_ci/* 644fd4e5da5Sopenharmony_ciGenerated from the following GLSL + --eliminate-local-multi-store 645fd4e5da5Sopenharmony_ci 646fd4e5da5Sopenharmony_ci#version 440 core 647fd4e5da5Sopenharmony_cilayout(location = 0) in vec4 c; 648fd4e5da5Sopenharmony_civoid main() { 649fd4e5da5Sopenharmony_ci int N = int(c.x); 650fd4e5da5Sopenharmony_ci for (int i = 0; i < N; i++) {} 651fd4e5da5Sopenharmony_ci for (int j = 0; j < N; j++) {} 652fd4e5da5Sopenharmony_ci} 653fd4e5da5Sopenharmony_ci 654fd4e5da5Sopenharmony_ci*/ 655fd4e5da5Sopenharmony_ciTEST_F(FusionCompatibilityTest, UnknownButSameUpperBound) { 656fd4e5da5Sopenharmony_ci const std::string text = R"( 657fd4e5da5Sopenharmony_ci OpCapability Shader 658fd4e5da5Sopenharmony_ci %1 = OpExtInstImport "GLSL.std.450" 659fd4e5da5Sopenharmony_ci OpMemoryModel Logical GLSL450 660fd4e5da5Sopenharmony_ci OpEntryPoint Fragment %4 "main" %12 661fd4e5da5Sopenharmony_ci OpExecutionMode %4 OriginUpperLeft 662fd4e5da5Sopenharmony_ci OpSource GLSL 440 663fd4e5da5Sopenharmony_ci OpName %4 "main" 664fd4e5da5Sopenharmony_ci OpName %8 "N" 665fd4e5da5Sopenharmony_ci OpName %12 "c" 666fd4e5da5Sopenharmony_ci OpName %19 "i" 667fd4e5da5Sopenharmony_ci OpName %33 "j" 668fd4e5da5Sopenharmony_ci OpDecorate %12 Location 0 669fd4e5da5Sopenharmony_ci %2 = OpTypeVoid 670fd4e5da5Sopenharmony_ci %3 = OpTypeFunction %2 671fd4e5da5Sopenharmony_ci %6 = OpTypeInt 32 1 672fd4e5da5Sopenharmony_ci %7 = OpTypePointer Function %6 673fd4e5da5Sopenharmony_ci %9 = OpTypeFloat 32 674fd4e5da5Sopenharmony_ci %10 = OpTypeVector %9 4 675fd4e5da5Sopenharmony_ci %11 = OpTypePointer Input %10 676fd4e5da5Sopenharmony_ci %12 = OpVariable %11 Input 677fd4e5da5Sopenharmony_ci %13 = OpTypeInt 32 0 678fd4e5da5Sopenharmony_ci %14 = OpConstant %13 0 679fd4e5da5Sopenharmony_ci %15 = OpTypePointer Input %9 680fd4e5da5Sopenharmony_ci %20 = OpConstant %6 0 681fd4e5da5Sopenharmony_ci %28 = OpTypeBool 682fd4e5da5Sopenharmony_ci %31 = OpConstant %6 1 683fd4e5da5Sopenharmony_ci %4 = OpFunction %2 None %3 684fd4e5da5Sopenharmony_ci %5 = OpLabel 685fd4e5da5Sopenharmony_ci %8 = OpVariable %7 Function 686fd4e5da5Sopenharmony_ci %19 = OpVariable %7 Function 687fd4e5da5Sopenharmony_ci %33 = OpVariable %7 Function 688fd4e5da5Sopenharmony_ci %16 = OpAccessChain %15 %12 %14 689fd4e5da5Sopenharmony_ci %17 = OpLoad %9 %16 690fd4e5da5Sopenharmony_ci %18 = OpConvertFToS %6 %17 691fd4e5da5Sopenharmony_ci OpStore %8 %18 692fd4e5da5Sopenharmony_ci OpStore %19 %20 693fd4e5da5Sopenharmony_ci OpBranch %21 694fd4e5da5Sopenharmony_ci %21 = OpLabel 695fd4e5da5Sopenharmony_ci %44 = OpPhi %6 %20 %5 %32 %24 696fd4e5da5Sopenharmony_ci OpLoopMerge %23 %24 None 697fd4e5da5Sopenharmony_ci OpBranch %25 698fd4e5da5Sopenharmony_ci %25 = OpLabel 699fd4e5da5Sopenharmony_ci %29 = OpSLessThan %28 %44 %18 700fd4e5da5Sopenharmony_ci OpBranchConditional %29 %22 %23 701fd4e5da5Sopenharmony_ci %22 = OpLabel 702fd4e5da5Sopenharmony_ci OpBranch %24 703fd4e5da5Sopenharmony_ci %24 = OpLabel 704fd4e5da5Sopenharmony_ci %32 = OpIAdd %6 %44 %31 705fd4e5da5Sopenharmony_ci OpStore %19 %32 706fd4e5da5Sopenharmony_ci OpBranch %21 707fd4e5da5Sopenharmony_ci %23 = OpLabel 708fd4e5da5Sopenharmony_ci OpStore %33 %20 709fd4e5da5Sopenharmony_ci OpBranch %34 710fd4e5da5Sopenharmony_ci %34 = OpLabel 711fd4e5da5Sopenharmony_ci %46 = OpPhi %6 %20 %23 %43 %37 712fd4e5da5Sopenharmony_ci OpLoopMerge %36 %37 None 713fd4e5da5Sopenharmony_ci OpBranch %38 714fd4e5da5Sopenharmony_ci %38 = OpLabel 715fd4e5da5Sopenharmony_ci %41 = OpSLessThan %28 %46 %18 716fd4e5da5Sopenharmony_ci OpBranchConditional %41 %35 %36 717fd4e5da5Sopenharmony_ci %35 = OpLabel 718fd4e5da5Sopenharmony_ci OpBranch %37 719fd4e5da5Sopenharmony_ci %37 = OpLabel 720fd4e5da5Sopenharmony_ci %43 = OpIAdd %6 %46 %31 721fd4e5da5Sopenharmony_ci OpStore %33 %43 722fd4e5da5Sopenharmony_ci OpBranch %34 723fd4e5da5Sopenharmony_ci %36 = OpLabel 724fd4e5da5Sopenharmony_ci OpReturn 725fd4e5da5Sopenharmony_ci OpFunctionEnd 726fd4e5da5Sopenharmony_ci )"; 727fd4e5da5Sopenharmony_ci 728fd4e5da5Sopenharmony_ci std::unique_ptr<IRContext> context = 729fd4e5da5Sopenharmony_ci BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, text, 730fd4e5da5Sopenharmony_ci SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); 731fd4e5da5Sopenharmony_ci Module* module = context->module(); 732fd4e5da5Sopenharmony_ci EXPECT_NE(nullptr, module) << "Assembling failed for shader:\n" 733fd4e5da5Sopenharmony_ci << text << std::endl; 734fd4e5da5Sopenharmony_ci Function& f = *module->begin(); 735fd4e5da5Sopenharmony_ci LoopDescriptor& ld = *context->GetLoopDescriptor(&f); 736fd4e5da5Sopenharmony_ci EXPECT_EQ(ld.NumLoops(), 2u); 737fd4e5da5Sopenharmony_ci 738fd4e5da5Sopenharmony_ci auto loops = ld.GetLoopsInBinaryLayoutOrder(); 739fd4e5da5Sopenharmony_ci 740fd4e5da5Sopenharmony_ci LoopFusion fusion(context.get(), loops[0], loops[1]); 741fd4e5da5Sopenharmony_ci EXPECT_TRUE(fusion.AreCompatible()); 742fd4e5da5Sopenharmony_ci} 743fd4e5da5Sopenharmony_ci 744fd4e5da5Sopenharmony_ci/* 745fd4e5da5Sopenharmony_ciGenerated from the following GLSL + --eliminate-local-multi-store 746fd4e5da5Sopenharmony_ci 747fd4e5da5Sopenharmony_ci#version 440 core 748fd4e5da5Sopenharmony_cilayout(location = 0) in vec4 c; 749fd4e5da5Sopenharmony_civoid main() { 750fd4e5da5Sopenharmony_ci int N = int(c.x); 751fd4e5da5Sopenharmony_ci for (int i = 0; N > j; i++) {} 752fd4e5da5Sopenharmony_ci for (int j = 0; N > j; j++) {} 753fd4e5da5Sopenharmony_ci} 754fd4e5da5Sopenharmony_ci*/ 755fd4e5da5Sopenharmony_ciTEST_F(FusionCompatibilityTest, UnknownButSameUpperBoundReverseCondition) { 756fd4e5da5Sopenharmony_ci const std::string text = R"( 757fd4e5da5Sopenharmony_ci OpCapability Shader 758fd4e5da5Sopenharmony_ci %1 = OpExtInstImport "GLSL.std.450" 759fd4e5da5Sopenharmony_ci OpMemoryModel Logical GLSL450 760fd4e5da5Sopenharmony_ci OpEntryPoint Fragment %4 "main" %12 761fd4e5da5Sopenharmony_ci OpExecutionMode %4 OriginUpperLeft 762fd4e5da5Sopenharmony_ci OpSource GLSL 440 763fd4e5da5Sopenharmony_ci OpName %4 "main" 764fd4e5da5Sopenharmony_ci OpName %8 "N" 765fd4e5da5Sopenharmony_ci OpName %12 "c" 766fd4e5da5Sopenharmony_ci OpName %19 "i" 767fd4e5da5Sopenharmony_ci OpName %33 "j" 768fd4e5da5Sopenharmony_ci OpDecorate %12 Location 0 769fd4e5da5Sopenharmony_ci %2 = OpTypeVoid 770fd4e5da5Sopenharmony_ci %3 = OpTypeFunction %2 771fd4e5da5Sopenharmony_ci %6 = OpTypeInt 32 1 772fd4e5da5Sopenharmony_ci %7 = OpTypePointer Function %6 773fd4e5da5Sopenharmony_ci %9 = OpTypeFloat 32 774fd4e5da5Sopenharmony_ci %10 = OpTypeVector %9 4 775fd4e5da5Sopenharmony_ci %11 = OpTypePointer Input %10 776fd4e5da5Sopenharmony_ci %12 = OpVariable %11 Input 777fd4e5da5Sopenharmony_ci %13 = OpTypeInt 32 0 778fd4e5da5Sopenharmony_ci %14 = OpConstant %13 0 779fd4e5da5Sopenharmony_ci %15 = OpTypePointer Input %9 780fd4e5da5Sopenharmony_ci %20 = OpConstant %6 0 781fd4e5da5Sopenharmony_ci %28 = OpTypeBool 782fd4e5da5Sopenharmony_ci %31 = OpConstant %6 1 783fd4e5da5Sopenharmony_ci %4 = OpFunction %2 None %3 784fd4e5da5Sopenharmony_ci %5 = OpLabel 785fd4e5da5Sopenharmony_ci %8 = OpVariable %7 Function 786fd4e5da5Sopenharmony_ci %19 = OpVariable %7 Function 787fd4e5da5Sopenharmony_ci %33 = OpVariable %7 Function 788fd4e5da5Sopenharmony_ci %16 = OpAccessChain %15 %12 %14 789fd4e5da5Sopenharmony_ci %17 = OpLoad %9 %16 790fd4e5da5Sopenharmony_ci %18 = OpConvertFToS %6 %17 791fd4e5da5Sopenharmony_ci OpStore %8 %18 792fd4e5da5Sopenharmony_ci OpStore %19 %20 793fd4e5da5Sopenharmony_ci OpBranch %21 794fd4e5da5Sopenharmony_ci %21 = OpLabel 795fd4e5da5Sopenharmony_ci %45 = OpPhi %6 %20 %5 %32 %24 796fd4e5da5Sopenharmony_ci OpLoopMerge %23 %24 None 797fd4e5da5Sopenharmony_ci OpBranch %25 798fd4e5da5Sopenharmony_ci %25 = OpLabel 799fd4e5da5Sopenharmony_ci %29 = OpSGreaterThan %28 %18 %45 800fd4e5da5Sopenharmony_ci OpBranchConditional %29 %22 %23 801fd4e5da5Sopenharmony_ci %22 = OpLabel 802fd4e5da5Sopenharmony_ci OpBranch %24 803fd4e5da5Sopenharmony_ci %24 = OpLabel 804fd4e5da5Sopenharmony_ci %32 = OpIAdd %6 %45 %31 805fd4e5da5Sopenharmony_ci OpStore %19 %32 806fd4e5da5Sopenharmony_ci OpBranch %21 807fd4e5da5Sopenharmony_ci %23 = OpLabel 808fd4e5da5Sopenharmony_ci OpStore %33 %20 809fd4e5da5Sopenharmony_ci OpBranch %34 810fd4e5da5Sopenharmony_ci %34 = OpLabel 811fd4e5da5Sopenharmony_ci %47 = OpPhi %6 %20 %23 %43 %37 812fd4e5da5Sopenharmony_ci OpLoopMerge %36 %37 None 813fd4e5da5Sopenharmony_ci OpBranch %38 814fd4e5da5Sopenharmony_ci %38 = OpLabel 815fd4e5da5Sopenharmony_ci %41 = OpSGreaterThan %28 %18 %47 816fd4e5da5Sopenharmony_ci OpBranchConditional %41 %35 %36 817fd4e5da5Sopenharmony_ci %35 = OpLabel 818fd4e5da5Sopenharmony_ci OpBranch %37 819fd4e5da5Sopenharmony_ci %37 = OpLabel 820fd4e5da5Sopenharmony_ci %43 = OpIAdd %6 %47 %31 821fd4e5da5Sopenharmony_ci OpStore %33 %43 822fd4e5da5Sopenharmony_ci OpBranch %34 823fd4e5da5Sopenharmony_ci %36 = OpLabel 824fd4e5da5Sopenharmony_ci OpReturn 825fd4e5da5Sopenharmony_ci OpFunctionEnd 826fd4e5da5Sopenharmony_ci )"; 827fd4e5da5Sopenharmony_ci 828fd4e5da5Sopenharmony_ci std::unique_ptr<IRContext> context = 829fd4e5da5Sopenharmony_ci BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, text, 830fd4e5da5Sopenharmony_ci SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); 831fd4e5da5Sopenharmony_ci Module* module = context->module(); 832fd4e5da5Sopenharmony_ci EXPECT_NE(nullptr, module) << "Assembling failed for shader:\n" 833fd4e5da5Sopenharmony_ci << text << std::endl; 834fd4e5da5Sopenharmony_ci Function& f = *module->begin(); 835fd4e5da5Sopenharmony_ci LoopDescriptor& ld = *context->GetLoopDescriptor(&f); 836fd4e5da5Sopenharmony_ci EXPECT_EQ(ld.NumLoops(), 2u); 837fd4e5da5Sopenharmony_ci 838fd4e5da5Sopenharmony_ci auto loops = ld.GetLoopsInBinaryLayoutOrder(); 839fd4e5da5Sopenharmony_ci 840fd4e5da5Sopenharmony_ci LoopFusion fusion(context.get(), loops[0], loops[1]); 841fd4e5da5Sopenharmony_ci EXPECT_TRUE(fusion.AreCompatible()); 842fd4e5da5Sopenharmony_ci} 843fd4e5da5Sopenharmony_ci 844fd4e5da5Sopenharmony_ci/* 845fd4e5da5Sopenharmony_ciGenerated from the following GLSL + --eliminate-local-multi-store 846fd4e5da5Sopenharmony_ci 847fd4e5da5Sopenharmony_ci#version 440 core 848fd4e5da5Sopenharmony_cilayout(location = 0) in vec4 c; 849fd4e5da5Sopenharmony_civoid main() { 850fd4e5da5Sopenharmony_ci // Can't fuse different bound 851fd4e5da5Sopenharmony_ci int N = int(c.x); 852fd4e5da5Sopenharmony_ci for (int i = 0; i < N; i++) {} 853fd4e5da5Sopenharmony_ci for (int j = 0; j < N+1; j++) {} 854fd4e5da5Sopenharmony_ci} 855fd4e5da5Sopenharmony_ci 856fd4e5da5Sopenharmony_ci*/ 857fd4e5da5Sopenharmony_ciTEST_F(FusionCompatibilityTest, UnknownUpperBoundAddition) { 858fd4e5da5Sopenharmony_ci const std::string text = R"( 859fd4e5da5Sopenharmony_ci OpCapability Shader 860fd4e5da5Sopenharmony_ci %1 = OpExtInstImport "GLSL.std.450" 861fd4e5da5Sopenharmony_ci OpMemoryModel Logical GLSL450 862fd4e5da5Sopenharmony_ci OpEntryPoint Fragment %4 "main" %12 863fd4e5da5Sopenharmony_ci OpExecutionMode %4 OriginUpperLeft 864fd4e5da5Sopenharmony_ci OpSource GLSL 440 865fd4e5da5Sopenharmony_ci OpName %4 "main" 866fd4e5da5Sopenharmony_ci OpName %8 "N" 867fd4e5da5Sopenharmony_ci OpName %12 "c" 868fd4e5da5Sopenharmony_ci OpName %19 "i" 869fd4e5da5Sopenharmony_ci OpName %33 "j" 870fd4e5da5Sopenharmony_ci OpDecorate %12 Location 0 871fd4e5da5Sopenharmony_ci %2 = OpTypeVoid 872fd4e5da5Sopenharmony_ci %3 = OpTypeFunction %2 873fd4e5da5Sopenharmony_ci %6 = OpTypeInt 32 1 874fd4e5da5Sopenharmony_ci %7 = OpTypePointer Function %6 875fd4e5da5Sopenharmony_ci %9 = OpTypeFloat 32 876fd4e5da5Sopenharmony_ci %10 = OpTypeVector %9 4 877fd4e5da5Sopenharmony_ci %11 = OpTypePointer Input %10 878fd4e5da5Sopenharmony_ci %12 = OpVariable %11 Input 879fd4e5da5Sopenharmony_ci %13 = OpTypeInt 32 0 880fd4e5da5Sopenharmony_ci %14 = OpConstant %13 0 881fd4e5da5Sopenharmony_ci %15 = OpTypePointer Input %9 882fd4e5da5Sopenharmony_ci %20 = OpConstant %6 0 883fd4e5da5Sopenharmony_ci %28 = OpTypeBool 884fd4e5da5Sopenharmony_ci %31 = OpConstant %6 1 885fd4e5da5Sopenharmony_ci %4 = OpFunction %2 None %3 886fd4e5da5Sopenharmony_ci %5 = OpLabel 887fd4e5da5Sopenharmony_ci %8 = OpVariable %7 Function 888fd4e5da5Sopenharmony_ci %19 = OpVariable %7 Function 889fd4e5da5Sopenharmony_ci %33 = OpVariable %7 Function 890fd4e5da5Sopenharmony_ci %16 = OpAccessChain %15 %12 %14 891fd4e5da5Sopenharmony_ci %17 = OpLoad %9 %16 892fd4e5da5Sopenharmony_ci %18 = OpConvertFToS %6 %17 893fd4e5da5Sopenharmony_ci OpStore %8 %18 894fd4e5da5Sopenharmony_ci OpStore %19 %20 895fd4e5da5Sopenharmony_ci OpBranch %21 896fd4e5da5Sopenharmony_ci %21 = OpLabel 897fd4e5da5Sopenharmony_ci %45 = OpPhi %6 %20 %5 %32 %24 898fd4e5da5Sopenharmony_ci OpLoopMerge %23 %24 None 899fd4e5da5Sopenharmony_ci OpBranch %25 900fd4e5da5Sopenharmony_ci %25 = OpLabel 901fd4e5da5Sopenharmony_ci %29 = OpSLessThan %28 %45 %18 902fd4e5da5Sopenharmony_ci OpBranchConditional %29 %22 %23 903fd4e5da5Sopenharmony_ci %22 = OpLabel 904fd4e5da5Sopenharmony_ci OpBranch %24 905fd4e5da5Sopenharmony_ci %24 = OpLabel 906fd4e5da5Sopenharmony_ci %32 = OpIAdd %6 %45 %31 907fd4e5da5Sopenharmony_ci OpStore %19 %32 908fd4e5da5Sopenharmony_ci OpBranch %21 909fd4e5da5Sopenharmony_ci %23 = OpLabel 910fd4e5da5Sopenharmony_ci OpStore %33 %20 911fd4e5da5Sopenharmony_ci OpBranch %34 912fd4e5da5Sopenharmony_ci %34 = OpLabel 913fd4e5da5Sopenharmony_ci %47 = OpPhi %6 %20 %23 %44 %37 914fd4e5da5Sopenharmony_ci OpLoopMerge %36 %37 None 915fd4e5da5Sopenharmony_ci OpBranch %38 916fd4e5da5Sopenharmony_ci %38 = OpLabel 917fd4e5da5Sopenharmony_ci %41 = OpIAdd %6 %18 %31 918fd4e5da5Sopenharmony_ci %42 = OpSLessThan %28 %47 %41 919fd4e5da5Sopenharmony_ci OpBranchConditional %42 %35 %36 920fd4e5da5Sopenharmony_ci %35 = OpLabel 921fd4e5da5Sopenharmony_ci OpBranch %37 922fd4e5da5Sopenharmony_ci %37 = OpLabel 923fd4e5da5Sopenharmony_ci %44 = OpIAdd %6 %47 %31 924fd4e5da5Sopenharmony_ci OpStore %33 %44 925fd4e5da5Sopenharmony_ci OpBranch %34 926fd4e5da5Sopenharmony_ci %36 = OpLabel 927fd4e5da5Sopenharmony_ci OpReturn 928fd4e5da5Sopenharmony_ci OpFunctionEnd 929fd4e5da5Sopenharmony_ci )"; 930fd4e5da5Sopenharmony_ci 931fd4e5da5Sopenharmony_ci std::unique_ptr<IRContext> context = 932fd4e5da5Sopenharmony_ci BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, text, 933fd4e5da5Sopenharmony_ci SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); 934fd4e5da5Sopenharmony_ci Module* module = context->module(); 935fd4e5da5Sopenharmony_ci EXPECT_NE(nullptr, module) << "Assembling failed for shader:\n" 936fd4e5da5Sopenharmony_ci << text << std::endl; 937fd4e5da5Sopenharmony_ci Function& f = *module->begin(); 938fd4e5da5Sopenharmony_ci LoopDescriptor& ld = *context->GetLoopDescriptor(&f); 939fd4e5da5Sopenharmony_ci EXPECT_EQ(ld.NumLoops(), 2u); 940fd4e5da5Sopenharmony_ci 941fd4e5da5Sopenharmony_ci auto loops = ld.GetLoopsInBinaryLayoutOrder(); 942fd4e5da5Sopenharmony_ci 943fd4e5da5Sopenharmony_ci LoopFusion fusion(context.get(), loops[0], loops[1]); 944fd4e5da5Sopenharmony_ci EXPECT_FALSE(fusion.AreCompatible()); 945fd4e5da5Sopenharmony_ci} 946fd4e5da5Sopenharmony_ci 947fd4e5da5Sopenharmony_ci/* 948fd4e5da5Sopenharmony_ciGenerated from the following GLSL + --eliminate-local-multi-store 949fd4e5da5Sopenharmony_ci 950fd4e5da5Sopenharmony_ci// 10 951fd4e5da5Sopenharmony_ci#version 440 core 952fd4e5da5Sopenharmony_civoid main() { 953fd4e5da5Sopenharmony_ci for (int i = 0; i < 10; i++) {} 954fd4e5da5Sopenharmony_ci for (int j = 0; j < 10; j++) {} 955fd4e5da5Sopenharmony_ci for (int k = 0; k < 10; k++) {} 956fd4e5da5Sopenharmony_ci} 957fd4e5da5Sopenharmony_ci 958fd4e5da5Sopenharmony_ci*/ 959fd4e5da5Sopenharmony_ciTEST_F(FusionCompatibilityTest, SeveralAdjacentLoops) { 960fd4e5da5Sopenharmony_ci const std::string text = R"( 961fd4e5da5Sopenharmony_ci OpCapability Shader 962fd4e5da5Sopenharmony_ci %1 = OpExtInstImport "GLSL.std.450" 963fd4e5da5Sopenharmony_ci OpMemoryModel Logical GLSL450 964fd4e5da5Sopenharmony_ci OpEntryPoint Fragment %4 "main" 965fd4e5da5Sopenharmony_ci OpExecutionMode %4 OriginUpperLeft 966fd4e5da5Sopenharmony_ci OpSource GLSL 440 967fd4e5da5Sopenharmony_ci OpName %4 "main" 968fd4e5da5Sopenharmony_ci OpName %8 "i" 969fd4e5da5Sopenharmony_ci OpName %22 "j" 970fd4e5da5Sopenharmony_ci OpName %32 "k" 971fd4e5da5Sopenharmony_ci %2 = OpTypeVoid 972fd4e5da5Sopenharmony_ci %3 = OpTypeFunction %2 973fd4e5da5Sopenharmony_ci %6 = OpTypeInt 32 1 974fd4e5da5Sopenharmony_ci %7 = OpTypePointer Function %6 975fd4e5da5Sopenharmony_ci %9 = OpConstant %6 0 976fd4e5da5Sopenharmony_ci %16 = OpConstant %6 10 977fd4e5da5Sopenharmony_ci %17 = OpTypeBool 978fd4e5da5Sopenharmony_ci %20 = OpConstant %6 1 979fd4e5da5Sopenharmony_ci %4 = OpFunction %2 None %3 980fd4e5da5Sopenharmony_ci %5 = OpLabel 981fd4e5da5Sopenharmony_ci %8 = OpVariable %7 Function 982fd4e5da5Sopenharmony_ci %22 = OpVariable %7 Function 983fd4e5da5Sopenharmony_ci %32 = OpVariable %7 Function 984fd4e5da5Sopenharmony_ci OpStore %8 %9 985fd4e5da5Sopenharmony_ci OpBranch %10 986fd4e5da5Sopenharmony_ci %10 = OpLabel 987fd4e5da5Sopenharmony_ci %42 = OpPhi %6 %9 %5 %21 %13 988fd4e5da5Sopenharmony_ci OpLoopMerge %12 %13 None 989fd4e5da5Sopenharmony_ci OpBranch %14 990fd4e5da5Sopenharmony_ci %14 = OpLabel 991fd4e5da5Sopenharmony_ci %18 = OpSLessThan %17 %42 %16 992fd4e5da5Sopenharmony_ci OpBranchConditional %18 %11 %12 993fd4e5da5Sopenharmony_ci %11 = OpLabel 994fd4e5da5Sopenharmony_ci OpBranch %13 995fd4e5da5Sopenharmony_ci %13 = OpLabel 996fd4e5da5Sopenharmony_ci %21 = OpIAdd %6 %42 %20 997fd4e5da5Sopenharmony_ci OpStore %8 %21 998fd4e5da5Sopenharmony_ci OpBranch %10 999fd4e5da5Sopenharmony_ci %12 = OpLabel 1000fd4e5da5Sopenharmony_ci OpStore %22 %9 1001fd4e5da5Sopenharmony_ci OpBranch %23 1002fd4e5da5Sopenharmony_ci %23 = OpLabel 1003fd4e5da5Sopenharmony_ci %43 = OpPhi %6 %9 %12 %31 %26 1004fd4e5da5Sopenharmony_ci OpLoopMerge %25 %26 None 1005fd4e5da5Sopenharmony_ci OpBranch %27 1006fd4e5da5Sopenharmony_ci %27 = OpLabel 1007fd4e5da5Sopenharmony_ci %29 = OpSLessThan %17 %43 %16 1008fd4e5da5Sopenharmony_ci OpBranchConditional %29 %24 %25 1009fd4e5da5Sopenharmony_ci %24 = OpLabel 1010fd4e5da5Sopenharmony_ci OpBranch %26 1011fd4e5da5Sopenharmony_ci %26 = OpLabel 1012fd4e5da5Sopenharmony_ci %31 = OpIAdd %6 %43 %20 1013fd4e5da5Sopenharmony_ci OpStore %22 %31 1014fd4e5da5Sopenharmony_ci OpBranch %23 1015fd4e5da5Sopenharmony_ci %25 = OpLabel 1016fd4e5da5Sopenharmony_ci OpStore %32 %9 1017fd4e5da5Sopenharmony_ci OpBranch %33 1018fd4e5da5Sopenharmony_ci %33 = OpLabel 1019fd4e5da5Sopenharmony_ci %44 = OpPhi %6 %9 %25 %41 %36 1020fd4e5da5Sopenharmony_ci OpLoopMerge %35 %36 None 1021fd4e5da5Sopenharmony_ci OpBranch %37 1022fd4e5da5Sopenharmony_ci %37 = OpLabel 1023fd4e5da5Sopenharmony_ci %39 = OpSLessThan %17 %44 %16 1024fd4e5da5Sopenharmony_ci OpBranchConditional %39 %34 %35 1025fd4e5da5Sopenharmony_ci %34 = OpLabel 1026fd4e5da5Sopenharmony_ci OpBranch %36 1027fd4e5da5Sopenharmony_ci %36 = OpLabel 1028fd4e5da5Sopenharmony_ci %41 = OpIAdd %6 %44 %20 1029fd4e5da5Sopenharmony_ci OpStore %32 %41 1030fd4e5da5Sopenharmony_ci OpBranch %33 1031fd4e5da5Sopenharmony_ci %35 = OpLabel 1032fd4e5da5Sopenharmony_ci OpReturn 1033fd4e5da5Sopenharmony_ci OpFunctionEnd 1034fd4e5da5Sopenharmony_ci )"; 1035fd4e5da5Sopenharmony_ci 1036fd4e5da5Sopenharmony_ci std::unique_ptr<IRContext> context = 1037fd4e5da5Sopenharmony_ci BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, text, 1038fd4e5da5Sopenharmony_ci SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); 1039fd4e5da5Sopenharmony_ci Module* module = context->module(); 1040fd4e5da5Sopenharmony_ci EXPECT_NE(nullptr, module) << "Assembling failed for shader:\n" 1041fd4e5da5Sopenharmony_ci << text << std::endl; 1042fd4e5da5Sopenharmony_ci Function& f = *module->begin(); 1043fd4e5da5Sopenharmony_ci LoopDescriptor& ld = *context->GetLoopDescriptor(&f); 1044fd4e5da5Sopenharmony_ci EXPECT_EQ(ld.NumLoops(), 3u); 1045fd4e5da5Sopenharmony_ci 1046fd4e5da5Sopenharmony_ci auto loops = ld.GetLoopsInBinaryLayoutOrder(); 1047fd4e5da5Sopenharmony_ci 1048fd4e5da5Sopenharmony_ci auto loop_0 = loops[0]; 1049fd4e5da5Sopenharmony_ci auto loop_1 = loops[1]; 1050fd4e5da5Sopenharmony_ci auto loop_2 = loops[2]; 1051fd4e5da5Sopenharmony_ci 1052fd4e5da5Sopenharmony_ci EXPECT_FALSE(LoopFusion(context.get(), loop_0, loop_0).AreCompatible()); 1053fd4e5da5Sopenharmony_ci EXPECT_FALSE(LoopFusion(context.get(), loop_0, loop_2).AreCompatible()); 1054fd4e5da5Sopenharmony_ci EXPECT_FALSE(LoopFusion(context.get(), loop_1, loop_0).AreCompatible()); 1055fd4e5da5Sopenharmony_ci EXPECT_TRUE(LoopFusion(context.get(), loop_0, loop_1).AreCompatible()); 1056fd4e5da5Sopenharmony_ci EXPECT_TRUE(LoopFusion(context.get(), loop_1, loop_2).AreCompatible()); 1057fd4e5da5Sopenharmony_ci} 1058fd4e5da5Sopenharmony_ci 1059fd4e5da5Sopenharmony_ci/* 1060fd4e5da5Sopenharmony_ciGenerated from the following GLSL + --eliminate-local-multi-store 1061fd4e5da5Sopenharmony_ci 1062fd4e5da5Sopenharmony_ci#version 440 core 1063fd4e5da5Sopenharmony_civoid main() { 1064fd4e5da5Sopenharmony_ci // Can't fuse, not adjacent 1065fd4e5da5Sopenharmony_ci int x = 0; 1066fd4e5da5Sopenharmony_ci for (int i = 0; i < 10; i++) { 1067fd4e5da5Sopenharmony_ci if (i > 10) { 1068fd4e5da5Sopenharmony_ci x++; 1069fd4e5da5Sopenharmony_ci } 1070fd4e5da5Sopenharmony_ci } 1071fd4e5da5Sopenharmony_ci x++; 1072fd4e5da5Sopenharmony_ci for (int j = 0; j < 10; j++) {} 1073fd4e5da5Sopenharmony_ci for (int k = 0; k < 10; k++) {} 1074fd4e5da5Sopenharmony_ci} 1075fd4e5da5Sopenharmony_ci 1076fd4e5da5Sopenharmony_ci*/ 1077fd4e5da5Sopenharmony_ciTEST_F(FusionCompatibilityTest, NonAdjacentLoops) { 1078fd4e5da5Sopenharmony_ci const std::string text = R"( 1079fd4e5da5Sopenharmony_ci OpCapability Shader 1080fd4e5da5Sopenharmony_ci %1 = OpExtInstImport "GLSL.std.450" 1081fd4e5da5Sopenharmony_ci OpMemoryModel Logical GLSL450 1082fd4e5da5Sopenharmony_ci OpEntryPoint Fragment %4 "main" 1083fd4e5da5Sopenharmony_ci OpExecutionMode %4 OriginUpperLeft 1084fd4e5da5Sopenharmony_ci OpSource GLSL 440 1085fd4e5da5Sopenharmony_ci OpName %4 "main" 1086fd4e5da5Sopenharmony_ci OpName %8 "x" 1087fd4e5da5Sopenharmony_ci OpName %10 "i" 1088fd4e5da5Sopenharmony_ci OpName %31 "j" 1089fd4e5da5Sopenharmony_ci OpName %41 "k" 1090fd4e5da5Sopenharmony_ci %2 = OpTypeVoid 1091fd4e5da5Sopenharmony_ci %3 = OpTypeFunction %2 1092fd4e5da5Sopenharmony_ci %6 = OpTypeInt 32 1 1093fd4e5da5Sopenharmony_ci %7 = OpTypePointer Function %6 1094fd4e5da5Sopenharmony_ci %9 = OpConstant %6 0 1095fd4e5da5Sopenharmony_ci %17 = OpConstant %6 10 1096fd4e5da5Sopenharmony_ci %18 = OpTypeBool 1097fd4e5da5Sopenharmony_ci %25 = OpConstant %6 1 1098fd4e5da5Sopenharmony_ci %4 = OpFunction %2 None %3 1099fd4e5da5Sopenharmony_ci %5 = OpLabel 1100fd4e5da5Sopenharmony_ci %8 = OpVariable %7 Function 1101fd4e5da5Sopenharmony_ci %10 = OpVariable %7 Function 1102fd4e5da5Sopenharmony_ci %31 = OpVariable %7 Function 1103fd4e5da5Sopenharmony_ci %41 = OpVariable %7 Function 1104fd4e5da5Sopenharmony_ci OpStore %8 %9 1105fd4e5da5Sopenharmony_ci OpStore %10 %9 1106fd4e5da5Sopenharmony_ci OpBranch %11 1107fd4e5da5Sopenharmony_ci %11 = OpLabel 1108fd4e5da5Sopenharmony_ci %52 = OpPhi %6 %9 %5 %56 %14 1109fd4e5da5Sopenharmony_ci %51 = OpPhi %6 %9 %5 %28 %14 1110fd4e5da5Sopenharmony_ci OpLoopMerge %13 %14 None 1111fd4e5da5Sopenharmony_ci OpBranch %15 1112fd4e5da5Sopenharmony_ci %15 = OpLabel 1113fd4e5da5Sopenharmony_ci %19 = OpSLessThan %18 %51 %17 1114fd4e5da5Sopenharmony_ci OpBranchConditional %19 %12 %13 1115fd4e5da5Sopenharmony_ci %12 = OpLabel 1116fd4e5da5Sopenharmony_ci %21 = OpSGreaterThan %18 %52 %17 1117fd4e5da5Sopenharmony_ci OpSelectionMerge %23 None 1118fd4e5da5Sopenharmony_ci OpBranchConditional %21 %22 %23 1119fd4e5da5Sopenharmony_ci %22 = OpLabel 1120fd4e5da5Sopenharmony_ci %26 = OpIAdd %6 %52 %25 1121fd4e5da5Sopenharmony_ci OpStore %8 %26 1122fd4e5da5Sopenharmony_ci OpBranch %23 1123fd4e5da5Sopenharmony_ci %23 = OpLabel 1124fd4e5da5Sopenharmony_ci %56 = OpPhi %6 %52 %12 %26 %22 1125fd4e5da5Sopenharmony_ci OpBranch %14 1126fd4e5da5Sopenharmony_ci %14 = OpLabel 1127fd4e5da5Sopenharmony_ci %28 = OpIAdd %6 %51 %25 1128fd4e5da5Sopenharmony_ci OpStore %10 %28 1129fd4e5da5Sopenharmony_ci OpBranch %11 1130fd4e5da5Sopenharmony_ci %13 = OpLabel 1131fd4e5da5Sopenharmony_ci %30 = OpIAdd %6 %52 %25 1132fd4e5da5Sopenharmony_ci OpStore %8 %30 1133fd4e5da5Sopenharmony_ci OpStore %31 %9 1134fd4e5da5Sopenharmony_ci OpBranch %32 1135fd4e5da5Sopenharmony_ci %32 = OpLabel 1136fd4e5da5Sopenharmony_ci %53 = OpPhi %6 %9 %13 %40 %35 1137fd4e5da5Sopenharmony_ci OpLoopMerge %34 %35 None 1138fd4e5da5Sopenharmony_ci OpBranch %36 1139fd4e5da5Sopenharmony_ci %36 = OpLabel 1140fd4e5da5Sopenharmony_ci %38 = OpSLessThan %18 %53 %17 1141fd4e5da5Sopenharmony_ci OpBranchConditional %38 %33 %34 1142fd4e5da5Sopenharmony_ci %33 = OpLabel 1143fd4e5da5Sopenharmony_ci OpBranch %35 1144fd4e5da5Sopenharmony_ci %35 = OpLabel 1145fd4e5da5Sopenharmony_ci %40 = OpIAdd %6 %53 %25 1146fd4e5da5Sopenharmony_ci OpStore %31 %40 1147fd4e5da5Sopenharmony_ci OpBranch %32 1148fd4e5da5Sopenharmony_ci %34 = OpLabel 1149fd4e5da5Sopenharmony_ci OpStore %41 %9 1150fd4e5da5Sopenharmony_ci OpBranch %42 1151fd4e5da5Sopenharmony_ci %42 = OpLabel 1152fd4e5da5Sopenharmony_ci %54 = OpPhi %6 %9 %34 %50 %45 1153fd4e5da5Sopenharmony_ci OpLoopMerge %44 %45 None 1154fd4e5da5Sopenharmony_ci OpBranch %46 1155fd4e5da5Sopenharmony_ci %46 = OpLabel 1156fd4e5da5Sopenharmony_ci %48 = OpSLessThan %18 %54 %17 1157fd4e5da5Sopenharmony_ci OpBranchConditional %48 %43 %44 1158fd4e5da5Sopenharmony_ci %43 = OpLabel 1159fd4e5da5Sopenharmony_ci OpBranch %45 1160fd4e5da5Sopenharmony_ci %45 = OpLabel 1161fd4e5da5Sopenharmony_ci %50 = OpIAdd %6 %54 %25 1162fd4e5da5Sopenharmony_ci OpStore %41 %50 1163fd4e5da5Sopenharmony_ci OpBranch %42 1164fd4e5da5Sopenharmony_ci %44 = OpLabel 1165fd4e5da5Sopenharmony_ci OpReturn 1166fd4e5da5Sopenharmony_ci OpFunctionEnd 1167fd4e5da5Sopenharmony_ci )"; 1168fd4e5da5Sopenharmony_ci 1169fd4e5da5Sopenharmony_ci std::unique_ptr<IRContext> context = 1170fd4e5da5Sopenharmony_ci BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, text, 1171fd4e5da5Sopenharmony_ci SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); 1172fd4e5da5Sopenharmony_ci Module* module = context->module(); 1173fd4e5da5Sopenharmony_ci EXPECT_NE(nullptr, module) << "Assembling failed for shader:\n" 1174fd4e5da5Sopenharmony_ci << text << std::endl; 1175fd4e5da5Sopenharmony_ci Function& f = *module->begin(); 1176fd4e5da5Sopenharmony_ci LoopDescriptor& ld = *context->GetLoopDescriptor(&f); 1177fd4e5da5Sopenharmony_ci EXPECT_EQ(ld.NumLoops(), 3u); 1178fd4e5da5Sopenharmony_ci 1179fd4e5da5Sopenharmony_ci auto loops = ld.GetLoopsInBinaryLayoutOrder(); 1180fd4e5da5Sopenharmony_ci 1181fd4e5da5Sopenharmony_ci auto loop_0 = loops[0]; 1182fd4e5da5Sopenharmony_ci auto loop_1 = loops[1]; 1183fd4e5da5Sopenharmony_ci auto loop_2 = loops[2]; 1184fd4e5da5Sopenharmony_ci 1185fd4e5da5Sopenharmony_ci EXPECT_FALSE(LoopFusion(context.get(), loop_0, loop_0).AreCompatible()); 1186fd4e5da5Sopenharmony_ci EXPECT_FALSE(LoopFusion(context.get(), loop_0, loop_2).AreCompatible()); 1187fd4e5da5Sopenharmony_ci EXPECT_FALSE(LoopFusion(context.get(), loop_0, loop_1).AreCompatible()); 1188fd4e5da5Sopenharmony_ci EXPECT_TRUE(LoopFusion(context.get(), loop_1, loop_2).AreCompatible()); 1189fd4e5da5Sopenharmony_ci} 1190fd4e5da5Sopenharmony_ci 1191fd4e5da5Sopenharmony_ci/* 1192fd4e5da5Sopenharmony_ciGenerated from the following GLSL + --eliminate-local-multi-store 1193fd4e5da5Sopenharmony_ci 1194fd4e5da5Sopenharmony_ci// 12 1195fd4e5da5Sopenharmony_ci#version 440 core 1196fd4e5da5Sopenharmony_civoid main() { 1197fd4e5da5Sopenharmony_ci int j = 0; 1198fd4e5da5Sopenharmony_ci int i = 0; 1199fd4e5da5Sopenharmony_ci for (; i < 10; i++) {} 1200fd4e5da5Sopenharmony_ci for (; j < 10; j++) {} 1201fd4e5da5Sopenharmony_ci} 1202fd4e5da5Sopenharmony_ci 1203fd4e5da5Sopenharmony_ci*/ 1204fd4e5da5Sopenharmony_ciTEST_F(FusionCompatibilityTest, CompatibleInitDeclaredBeforeLoops) { 1205fd4e5da5Sopenharmony_ci const std::string text = R"( 1206fd4e5da5Sopenharmony_ci OpCapability Shader 1207fd4e5da5Sopenharmony_ci %1 = OpExtInstImport "GLSL.std.450" 1208fd4e5da5Sopenharmony_ci OpMemoryModel Logical GLSL450 1209fd4e5da5Sopenharmony_ci OpEntryPoint Fragment %4 "main" 1210fd4e5da5Sopenharmony_ci OpExecutionMode %4 OriginUpperLeft 1211fd4e5da5Sopenharmony_ci OpSource GLSL 440 1212fd4e5da5Sopenharmony_ci OpName %4 "main" 1213fd4e5da5Sopenharmony_ci OpName %8 "j" 1214fd4e5da5Sopenharmony_ci OpName %10 "i" 1215fd4e5da5Sopenharmony_ci %2 = OpTypeVoid 1216fd4e5da5Sopenharmony_ci %3 = OpTypeFunction %2 1217fd4e5da5Sopenharmony_ci %6 = OpTypeInt 32 1 1218fd4e5da5Sopenharmony_ci %7 = OpTypePointer Function %6 1219fd4e5da5Sopenharmony_ci %9 = OpConstant %6 0 1220fd4e5da5Sopenharmony_ci %17 = OpConstant %6 10 1221fd4e5da5Sopenharmony_ci %18 = OpTypeBool 1222fd4e5da5Sopenharmony_ci %21 = OpConstant %6 1 1223fd4e5da5Sopenharmony_ci %4 = OpFunction %2 None %3 1224fd4e5da5Sopenharmony_ci %5 = OpLabel 1225fd4e5da5Sopenharmony_ci %8 = OpVariable %7 Function 1226fd4e5da5Sopenharmony_ci %10 = OpVariable %7 Function 1227fd4e5da5Sopenharmony_ci OpStore %8 %9 1228fd4e5da5Sopenharmony_ci OpStore %10 %9 1229fd4e5da5Sopenharmony_ci OpBranch %11 1230fd4e5da5Sopenharmony_ci %11 = OpLabel 1231fd4e5da5Sopenharmony_ci %32 = OpPhi %6 %9 %5 %22 %14 1232fd4e5da5Sopenharmony_ci OpLoopMerge %13 %14 None 1233fd4e5da5Sopenharmony_ci OpBranch %15 1234fd4e5da5Sopenharmony_ci %15 = OpLabel 1235fd4e5da5Sopenharmony_ci %19 = OpSLessThan %18 %32 %17 1236fd4e5da5Sopenharmony_ci OpBranchConditional %19 %12 %13 1237fd4e5da5Sopenharmony_ci %12 = OpLabel 1238fd4e5da5Sopenharmony_ci OpBranch %14 1239fd4e5da5Sopenharmony_ci %14 = OpLabel 1240fd4e5da5Sopenharmony_ci %22 = OpIAdd %6 %32 %21 1241fd4e5da5Sopenharmony_ci OpStore %10 %22 1242fd4e5da5Sopenharmony_ci OpBranch %11 1243fd4e5da5Sopenharmony_ci %13 = OpLabel 1244fd4e5da5Sopenharmony_ci OpBranch %23 1245fd4e5da5Sopenharmony_ci %23 = OpLabel 1246fd4e5da5Sopenharmony_ci %33 = OpPhi %6 %9 %13 %31 %26 1247fd4e5da5Sopenharmony_ci OpLoopMerge %25 %26 None 1248fd4e5da5Sopenharmony_ci OpBranch %27 1249fd4e5da5Sopenharmony_ci %27 = OpLabel 1250fd4e5da5Sopenharmony_ci %29 = OpSLessThan %18 %33 %17 1251fd4e5da5Sopenharmony_ci OpBranchConditional %29 %24 %25 1252fd4e5da5Sopenharmony_ci %24 = OpLabel 1253fd4e5da5Sopenharmony_ci OpBranch %26 1254fd4e5da5Sopenharmony_ci %26 = OpLabel 1255fd4e5da5Sopenharmony_ci %31 = OpIAdd %6 %33 %21 1256fd4e5da5Sopenharmony_ci OpStore %8 %31 1257fd4e5da5Sopenharmony_ci OpBranch %23 1258fd4e5da5Sopenharmony_ci %25 = OpLabel 1259fd4e5da5Sopenharmony_ci OpReturn 1260fd4e5da5Sopenharmony_ci OpFunctionEnd 1261fd4e5da5Sopenharmony_ci )"; 1262fd4e5da5Sopenharmony_ci 1263fd4e5da5Sopenharmony_ci std::unique_ptr<IRContext> context = 1264fd4e5da5Sopenharmony_ci BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, text, 1265fd4e5da5Sopenharmony_ci SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); 1266fd4e5da5Sopenharmony_ci Module* module = context->module(); 1267fd4e5da5Sopenharmony_ci EXPECT_NE(nullptr, module) << "Assembling failed for shader:\n" 1268fd4e5da5Sopenharmony_ci << text << std::endl; 1269fd4e5da5Sopenharmony_ci Function& f = *module->begin(); 1270fd4e5da5Sopenharmony_ci LoopDescriptor& ld = *context->GetLoopDescriptor(&f); 1271fd4e5da5Sopenharmony_ci EXPECT_EQ(ld.NumLoops(), 2u); 1272fd4e5da5Sopenharmony_ci 1273fd4e5da5Sopenharmony_ci auto loops = ld.GetLoopsInBinaryLayoutOrder(); 1274fd4e5da5Sopenharmony_ci 1275fd4e5da5Sopenharmony_ci EXPECT_TRUE(LoopFusion(context.get(), loops[0], loops[1]).AreCompatible()); 1276fd4e5da5Sopenharmony_ci} 1277fd4e5da5Sopenharmony_ci 1278fd4e5da5Sopenharmony_ci/* 1279fd4e5da5Sopenharmony_ciGenerated from the following GLSL + --eliminate-local-multi-store 1280fd4e5da5Sopenharmony_ci 1281fd4e5da5Sopenharmony_ci// 13 regenerate! 1282fd4e5da5Sopenharmony_ci#version 440 core 1283fd4e5da5Sopenharmony_civoid main() { 1284fd4e5da5Sopenharmony_ci int[10] a; 1285fd4e5da5Sopenharmony_ci int[10] b; 1286fd4e5da5Sopenharmony_ci // Can't fuse, several induction variables 1287fd4e5da5Sopenharmony_ci for (int j = 0; j < 10; j++) { 1288fd4e5da5Sopenharmony_ci b[i] = a[i]; 1289fd4e5da5Sopenharmony_ci } 1290fd4e5da5Sopenharmony_ci for (int i = 0, j = 0; i < 10; i++, j = j+2) { 1291fd4e5da5Sopenharmony_ci } 1292fd4e5da5Sopenharmony_ci} 1293fd4e5da5Sopenharmony_ci 1294fd4e5da5Sopenharmony_ci*/ 1295fd4e5da5Sopenharmony_ciTEST_F(FusionCompatibilityTest, SeveralInductionVariables) { 1296fd4e5da5Sopenharmony_ci const std::string text = R"( 1297fd4e5da5Sopenharmony_ci OpCapability Shader 1298fd4e5da5Sopenharmony_ci %1 = OpExtInstImport "GLSL.std.450" 1299fd4e5da5Sopenharmony_ci OpMemoryModel Logical GLSL450 1300fd4e5da5Sopenharmony_ci OpEntryPoint Fragment %4 "main" 1301fd4e5da5Sopenharmony_ci OpExecutionMode %4 OriginUpperLeft 1302fd4e5da5Sopenharmony_ci OpSource GLSL 440 1303fd4e5da5Sopenharmony_ci OpName %4 "main" 1304fd4e5da5Sopenharmony_ci OpName %8 "j" 1305fd4e5da5Sopenharmony_ci OpName %23 "b" 1306fd4e5da5Sopenharmony_ci OpName %25 "a" 1307fd4e5da5Sopenharmony_ci OpName %33 "i" 1308fd4e5da5Sopenharmony_ci OpName %34 "j" 1309fd4e5da5Sopenharmony_ci %2 = OpTypeVoid 1310fd4e5da5Sopenharmony_ci %3 = OpTypeFunction %2 1311fd4e5da5Sopenharmony_ci %6 = OpTypeInt 32 1 1312fd4e5da5Sopenharmony_ci %7 = OpTypePointer Function %6 1313fd4e5da5Sopenharmony_ci %9 = OpConstant %6 0 1314fd4e5da5Sopenharmony_ci %16 = OpConstant %6 10 1315fd4e5da5Sopenharmony_ci %17 = OpTypeBool 1316fd4e5da5Sopenharmony_ci %19 = OpTypeInt 32 0 1317fd4e5da5Sopenharmony_ci %20 = OpConstant %19 10 1318fd4e5da5Sopenharmony_ci %21 = OpTypeArray %6 %20 1319fd4e5da5Sopenharmony_ci %22 = OpTypePointer Function %21 1320fd4e5da5Sopenharmony_ci %31 = OpConstant %6 1 1321fd4e5da5Sopenharmony_ci %48 = OpConstant %6 2 1322fd4e5da5Sopenharmony_ci %4 = OpFunction %2 None %3 1323fd4e5da5Sopenharmony_ci %5 = OpLabel 1324fd4e5da5Sopenharmony_ci %8 = OpVariable %7 Function 1325fd4e5da5Sopenharmony_ci %23 = OpVariable %22 Function 1326fd4e5da5Sopenharmony_ci %25 = OpVariable %22 Function 1327fd4e5da5Sopenharmony_ci %33 = OpVariable %7 Function 1328fd4e5da5Sopenharmony_ci %34 = OpVariable %7 Function 1329fd4e5da5Sopenharmony_ci OpStore %8 %9 1330fd4e5da5Sopenharmony_ci OpBranch %10 1331fd4e5da5Sopenharmony_ci %10 = OpLabel 1332fd4e5da5Sopenharmony_ci %50 = OpPhi %6 %9 %5 %32 %13 1333fd4e5da5Sopenharmony_ci OpLoopMerge %12 %13 None 1334fd4e5da5Sopenharmony_ci OpBranch %14 1335fd4e5da5Sopenharmony_ci %14 = OpLabel 1336fd4e5da5Sopenharmony_ci %18 = OpSLessThan %17 %50 %16 1337fd4e5da5Sopenharmony_ci OpBranchConditional %18 %11 %12 1338fd4e5da5Sopenharmony_ci %11 = OpLabel 1339fd4e5da5Sopenharmony_ci %27 = OpAccessChain %7 %25 %50 1340fd4e5da5Sopenharmony_ci %28 = OpLoad %6 %27 1341fd4e5da5Sopenharmony_ci %29 = OpAccessChain %7 %23 %50 1342fd4e5da5Sopenharmony_ci OpStore %29 %28 1343fd4e5da5Sopenharmony_ci OpBranch %13 1344fd4e5da5Sopenharmony_ci %13 = OpLabel 1345fd4e5da5Sopenharmony_ci %32 = OpIAdd %6 %50 %31 1346fd4e5da5Sopenharmony_ci OpStore %8 %32 1347fd4e5da5Sopenharmony_ci OpBranch %10 1348fd4e5da5Sopenharmony_ci %12 = OpLabel 1349fd4e5da5Sopenharmony_ci OpStore %33 %9 1350fd4e5da5Sopenharmony_ci OpStore %34 %9 1351fd4e5da5Sopenharmony_ci OpBranch %35 1352fd4e5da5Sopenharmony_ci %35 = OpLabel 1353fd4e5da5Sopenharmony_ci %52 = OpPhi %6 %9 %12 %49 %38 1354fd4e5da5Sopenharmony_ci %51 = OpPhi %6 %9 %12 %46 %38 1355fd4e5da5Sopenharmony_ci OpLoopMerge %37 %38 None 1356fd4e5da5Sopenharmony_ci OpBranch %39 1357fd4e5da5Sopenharmony_ci %39 = OpLabel 1358fd4e5da5Sopenharmony_ci %41 = OpSLessThan %17 %51 %16 1359fd4e5da5Sopenharmony_ci OpBranchConditional %41 %36 %37 1360fd4e5da5Sopenharmony_ci %36 = OpLabel 1361fd4e5da5Sopenharmony_ci %44 = OpAccessChain %7 %25 %52 1362fd4e5da5Sopenharmony_ci OpStore %44 %51 1363fd4e5da5Sopenharmony_ci OpBranch %38 1364fd4e5da5Sopenharmony_ci %38 = OpLabel 1365fd4e5da5Sopenharmony_ci %46 = OpIAdd %6 %51 %31 1366fd4e5da5Sopenharmony_ci OpStore %33 %46 1367fd4e5da5Sopenharmony_ci %49 = OpIAdd %6 %52 %48 1368fd4e5da5Sopenharmony_ci OpStore %34 %49 1369fd4e5da5Sopenharmony_ci OpBranch %35 1370fd4e5da5Sopenharmony_ci %37 = OpLabel 1371fd4e5da5Sopenharmony_ci OpReturn 1372fd4e5da5Sopenharmony_ci OpFunctionEnd 1373fd4e5da5Sopenharmony_ci )"; 1374fd4e5da5Sopenharmony_ci 1375fd4e5da5Sopenharmony_ci std::unique_ptr<IRContext> context = 1376fd4e5da5Sopenharmony_ci BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, text, 1377fd4e5da5Sopenharmony_ci SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); 1378fd4e5da5Sopenharmony_ci Module* module = context->module(); 1379fd4e5da5Sopenharmony_ci EXPECT_NE(nullptr, module) << "Assembling failed for shader:\n" 1380fd4e5da5Sopenharmony_ci << text << std::endl; 1381fd4e5da5Sopenharmony_ci Function& f = *module->begin(); 1382fd4e5da5Sopenharmony_ci LoopDescriptor& ld = *context->GetLoopDescriptor(&f); 1383fd4e5da5Sopenharmony_ci EXPECT_EQ(ld.NumLoops(), 2u); 1384fd4e5da5Sopenharmony_ci 1385fd4e5da5Sopenharmony_ci auto loops = ld.GetLoopsInBinaryLayoutOrder(); 1386fd4e5da5Sopenharmony_ci 1387fd4e5da5Sopenharmony_ci EXPECT_FALSE(LoopFusion(context.get(), loops[0], loops[1]).AreCompatible()); 1388fd4e5da5Sopenharmony_ci} 1389fd4e5da5Sopenharmony_ci 1390fd4e5da5Sopenharmony_ci/* 1391fd4e5da5Sopenharmony_ciGenerated from the following GLSL + --eliminate-local-multi-store 1392fd4e5da5Sopenharmony_ci 1393fd4e5da5Sopenharmony_ci// 14 1394fd4e5da5Sopenharmony_ci#version 440 core 1395fd4e5da5Sopenharmony_civoid main() { 1396fd4e5da5Sopenharmony_ci // Fine 1397fd4e5da5Sopenharmony_ci for (int i = 0; i < 10; i = i + 2) {} 1398fd4e5da5Sopenharmony_ci for (int j = 0; j < 10; j = j + 2) {} 1399fd4e5da5Sopenharmony_ci} 1400fd4e5da5Sopenharmony_ci 1401fd4e5da5Sopenharmony_ci*/ 1402fd4e5da5Sopenharmony_ciTEST_F(FusionCompatibilityTest, CompatibleNonIncrementStep) { 1403fd4e5da5Sopenharmony_ci const std::string text = R"( 1404fd4e5da5Sopenharmony_ci OpCapability Shader 1405fd4e5da5Sopenharmony_ci %1 = OpExtInstImport "GLSL.std.450" 1406fd4e5da5Sopenharmony_ci OpMemoryModel Logical GLSL450 1407fd4e5da5Sopenharmony_ci OpEntryPoint Fragment %4 "main" 1408fd4e5da5Sopenharmony_ci OpExecutionMode %4 OriginUpperLeft 1409fd4e5da5Sopenharmony_ci OpSource GLSL 440 1410fd4e5da5Sopenharmony_ci OpName %4 "main" 1411fd4e5da5Sopenharmony_ci OpName %8 "j" 1412fd4e5da5Sopenharmony_ci OpName %10 "i" 1413fd4e5da5Sopenharmony_ci OpName %11 "i" 1414fd4e5da5Sopenharmony_ci OpName %24 "j" 1415fd4e5da5Sopenharmony_ci %2 = OpTypeVoid 1416fd4e5da5Sopenharmony_ci %3 = OpTypeFunction %2 1417fd4e5da5Sopenharmony_ci %6 = OpTypeInt 32 1 1418fd4e5da5Sopenharmony_ci %7 = OpTypePointer Function %6 1419fd4e5da5Sopenharmony_ci %9 = OpConstant %6 0 1420fd4e5da5Sopenharmony_ci %18 = OpConstant %6 10 1421fd4e5da5Sopenharmony_ci %19 = OpTypeBool 1422fd4e5da5Sopenharmony_ci %22 = OpConstant %6 2 1423fd4e5da5Sopenharmony_ci %4 = OpFunction %2 None %3 1424fd4e5da5Sopenharmony_ci %5 = OpLabel 1425fd4e5da5Sopenharmony_ci %8 = OpVariable %7 Function 1426fd4e5da5Sopenharmony_ci %10 = OpVariable %7 Function 1427fd4e5da5Sopenharmony_ci %11 = OpVariable %7 Function 1428fd4e5da5Sopenharmony_ci %24 = OpVariable %7 Function 1429fd4e5da5Sopenharmony_ci OpStore %8 %9 1430fd4e5da5Sopenharmony_ci OpStore %10 %9 1431fd4e5da5Sopenharmony_ci OpStore %11 %9 1432fd4e5da5Sopenharmony_ci OpBranch %12 1433fd4e5da5Sopenharmony_ci %12 = OpLabel 1434fd4e5da5Sopenharmony_ci %34 = OpPhi %6 %9 %5 %23 %15 1435fd4e5da5Sopenharmony_ci OpLoopMerge %14 %15 None 1436fd4e5da5Sopenharmony_ci OpBranch %16 1437fd4e5da5Sopenharmony_ci %16 = OpLabel 1438fd4e5da5Sopenharmony_ci %20 = OpSLessThan %19 %34 %18 1439fd4e5da5Sopenharmony_ci OpBranchConditional %20 %13 %14 1440fd4e5da5Sopenharmony_ci %13 = OpLabel 1441fd4e5da5Sopenharmony_ci OpBranch %15 1442fd4e5da5Sopenharmony_ci %15 = OpLabel 1443fd4e5da5Sopenharmony_ci %23 = OpIAdd %6 %34 %22 1444fd4e5da5Sopenharmony_ci OpStore %11 %23 1445fd4e5da5Sopenharmony_ci OpBranch %12 1446fd4e5da5Sopenharmony_ci %14 = OpLabel 1447fd4e5da5Sopenharmony_ci OpStore %24 %9 1448fd4e5da5Sopenharmony_ci OpBranch %25 1449fd4e5da5Sopenharmony_ci %25 = OpLabel 1450fd4e5da5Sopenharmony_ci %35 = OpPhi %6 %9 %14 %33 %28 1451fd4e5da5Sopenharmony_ci OpLoopMerge %27 %28 None 1452fd4e5da5Sopenharmony_ci OpBranch %29 1453fd4e5da5Sopenharmony_ci %29 = OpLabel 1454fd4e5da5Sopenharmony_ci %31 = OpSLessThan %19 %35 %18 1455fd4e5da5Sopenharmony_ci OpBranchConditional %31 %26 %27 1456fd4e5da5Sopenharmony_ci %26 = OpLabel 1457fd4e5da5Sopenharmony_ci OpBranch %28 1458fd4e5da5Sopenharmony_ci %28 = OpLabel 1459fd4e5da5Sopenharmony_ci %33 = OpIAdd %6 %35 %22 1460fd4e5da5Sopenharmony_ci OpStore %24 %33 1461fd4e5da5Sopenharmony_ci OpBranch %25 1462fd4e5da5Sopenharmony_ci %27 = OpLabel 1463fd4e5da5Sopenharmony_ci OpReturn 1464fd4e5da5Sopenharmony_ci OpFunctionEnd 1465fd4e5da5Sopenharmony_ci )"; 1466fd4e5da5Sopenharmony_ci 1467fd4e5da5Sopenharmony_ci std::unique_ptr<IRContext> context = 1468fd4e5da5Sopenharmony_ci BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, text, 1469fd4e5da5Sopenharmony_ci SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); 1470fd4e5da5Sopenharmony_ci Module* module = context->module(); 1471fd4e5da5Sopenharmony_ci EXPECT_NE(nullptr, module) << "Assembling failed for shader:\n" 1472fd4e5da5Sopenharmony_ci << text << std::endl; 1473fd4e5da5Sopenharmony_ci Function& f = *module->begin(); 1474fd4e5da5Sopenharmony_ci LoopDescriptor& ld = *context->GetLoopDescriptor(&f); 1475fd4e5da5Sopenharmony_ci EXPECT_EQ(ld.NumLoops(), 2u); 1476fd4e5da5Sopenharmony_ci 1477fd4e5da5Sopenharmony_ci auto loops = ld.GetLoopsInBinaryLayoutOrder(); 1478fd4e5da5Sopenharmony_ci 1479fd4e5da5Sopenharmony_ci EXPECT_TRUE(LoopFusion(context.get(), loops[0], loops[1]).AreCompatible()); 1480fd4e5da5Sopenharmony_ci} 1481fd4e5da5Sopenharmony_ci 1482fd4e5da5Sopenharmony_ci/* 1483fd4e5da5Sopenharmony_ciGenerated from the following GLSL + --eliminate-local-multi-store 1484fd4e5da5Sopenharmony_ci 1485fd4e5da5Sopenharmony_ci// 15 1486fd4e5da5Sopenharmony_ci#version 440 core 1487fd4e5da5Sopenharmony_ci 1488fd4e5da5Sopenharmony_ciint j = 0; 1489fd4e5da5Sopenharmony_ci 1490fd4e5da5Sopenharmony_civoid main() { 1491fd4e5da5Sopenharmony_ci // Not compatible, unknown init for second. 1492fd4e5da5Sopenharmony_ci for (int i = 0; i < 10; i = i + 2) {} 1493fd4e5da5Sopenharmony_ci for (; j < 10; j = j + 2) {} 1494fd4e5da5Sopenharmony_ci} 1495fd4e5da5Sopenharmony_ci 1496fd4e5da5Sopenharmony_ci*/ 1497fd4e5da5Sopenharmony_ciTEST_F(FusionCompatibilityTest, UnknonInitForSecondLoop) { 1498fd4e5da5Sopenharmony_ci const std::string text = R"( 1499fd4e5da5Sopenharmony_ci OpCapability Shader 1500fd4e5da5Sopenharmony_ci %1 = OpExtInstImport "GLSL.std.450" 1501fd4e5da5Sopenharmony_ci OpMemoryModel Logical GLSL450 1502fd4e5da5Sopenharmony_ci OpEntryPoint Fragment %4 "main" 1503fd4e5da5Sopenharmony_ci OpExecutionMode %4 OriginUpperLeft 1504fd4e5da5Sopenharmony_ci OpSource GLSL 440 1505fd4e5da5Sopenharmony_ci OpName %4 "main" 1506fd4e5da5Sopenharmony_ci OpName %8 "j" 1507fd4e5da5Sopenharmony_ci OpName %11 "i" 1508fd4e5da5Sopenharmony_ci %2 = OpTypeVoid 1509fd4e5da5Sopenharmony_ci %3 = OpTypeFunction %2 1510fd4e5da5Sopenharmony_ci %6 = OpTypeInt 32 1 1511fd4e5da5Sopenharmony_ci %7 = OpTypePointer Private %6 1512fd4e5da5Sopenharmony_ci %8 = OpVariable %7 Private 1513fd4e5da5Sopenharmony_ci %9 = OpConstant %6 0 1514fd4e5da5Sopenharmony_ci %10 = OpTypePointer Function %6 1515fd4e5da5Sopenharmony_ci %18 = OpConstant %6 10 1516fd4e5da5Sopenharmony_ci %19 = OpTypeBool 1517fd4e5da5Sopenharmony_ci %22 = OpConstant %6 2 1518fd4e5da5Sopenharmony_ci %4 = OpFunction %2 None %3 1519fd4e5da5Sopenharmony_ci %5 = OpLabel 1520fd4e5da5Sopenharmony_ci %11 = OpVariable %10 Function 1521fd4e5da5Sopenharmony_ci OpStore %8 %9 1522fd4e5da5Sopenharmony_ci OpStore %11 %9 1523fd4e5da5Sopenharmony_ci OpBranch %12 1524fd4e5da5Sopenharmony_ci %12 = OpLabel 1525fd4e5da5Sopenharmony_ci %33 = OpPhi %6 %9 %5 %23 %15 1526fd4e5da5Sopenharmony_ci OpLoopMerge %14 %15 None 1527fd4e5da5Sopenharmony_ci OpBranch %16 1528fd4e5da5Sopenharmony_ci %16 = OpLabel 1529fd4e5da5Sopenharmony_ci %20 = OpSLessThan %19 %33 %18 1530fd4e5da5Sopenharmony_ci OpBranchConditional %20 %13 %14 1531fd4e5da5Sopenharmony_ci %13 = OpLabel 1532fd4e5da5Sopenharmony_ci OpBranch %15 1533fd4e5da5Sopenharmony_ci %15 = OpLabel 1534fd4e5da5Sopenharmony_ci %23 = OpIAdd %6 %33 %22 1535fd4e5da5Sopenharmony_ci OpStore %11 %23 1536fd4e5da5Sopenharmony_ci OpBranch %12 1537fd4e5da5Sopenharmony_ci %14 = OpLabel 1538fd4e5da5Sopenharmony_ci OpBranch %24 1539fd4e5da5Sopenharmony_ci %24 = OpLabel 1540fd4e5da5Sopenharmony_ci OpLoopMerge %26 %27 None 1541fd4e5da5Sopenharmony_ci OpBranch %28 1542fd4e5da5Sopenharmony_ci %28 = OpLabel 1543fd4e5da5Sopenharmony_ci %29 = OpLoad %6 %8 1544fd4e5da5Sopenharmony_ci %30 = OpSLessThan %19 %29 %18 1545fd4e5da5Sopenharmony_ci OpBranchConditional %30 %25 %26 1546fd4e5da5Sopenharmony_ci %25 = OpLabel 1547fd4e5da5Sopenharmony_ci OpBranch %27 1548fd4e5da5Sopenharmony_ci %27 = OpLabel 1549fd4e5da5Sopenharmony_ci %31 = OpLoad %6 %8 1550fd4e5da5Sopenharmony_ci %32 = OpIAdd %6 %31 %22 1551fd4e5da5Sopenharmony_ci OpStore %8 %32 1552fd4e5da5Sopenharmony_ci OpBranch %24 1553fd4e5da5Sopenharmony_ci %26 = OpLabel 1554fd4e5da5Sopenharmony_ci OpReturn 1555fd4e5da5Sopenharmony_ci OpFunctionEnd 1556fd4e5da5Sopenharmony_ci )"; 1557fd4e5da5Sopenharmony_ci 1558fd4e5da5Sopenharmony_ci std::unique_ptr<IRContext> context = 1559fd4e5da5Sopenharmony_ci BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, text, 1560fd4e5da5Sopenharmony_ci SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); 1561fd4e5da5Sopenharmony_ci Module* module = context->module(); 1562fd4e5da5Sopenharmony_ci EXPECT_NE(nullptr, module) << "Assembling failed for shader:\n" 1563fd4e5da5Sopenharmony_ci << text << std::endl; 1564fd4e5da5Sopenharmony_ci Function& f = *module->begin(); 1565fd4e5da5Sopenharmony_ci LoopDescriptor& ld = *context->GetLoopDescriptor(&f); 1566fd4e5da5Sopenharmony_ci EXPECT_EQ(ld.NumLoops(), 2u); 1567fd4e5da5Sopenharmony_ci 1568fd4e5da5Sopenharmony_ci auto loops = ld.GetLoopsInBinaryLayoutOrder(); 1569fd4e5da5Sopenharmony_ci 1570fd4e5da5Sopenharmony_ci EXPECT_FALSE(LoopFusion(context.get(), loops[0], loops[1]).AreCompatible()); 1571fd4e5da5Sopenharmony_ci} 1572fd4e5da5Sopenharmony_ci 1573fd4e5da5Sopenharmony_ci/* 1574fd4e5da5Sopenharmony_ciGenerated from the following GLSL + --eliminate-local-multi-store 1575fd4e5da5Sopenharmony_ci 1576fd4e5da5Sopenharmony_ci// 16 1577fd4e5da5Sopenharmony_ci#version 440 core 1578fd4e5da5Sopenharmony_civoid main() { 1579fd4e5da5Sopenharmony_ci // Not compatible, continue in loop 0 1580fd4e5da5Sopenharmony_ci for (int i = 0; i < 10; ++i) { 1581fd4e5da5Sopenharmony_ci if (i % 2 == 1) { 1582fd4e5da5Sopenharmony_ci continue; 1583fd4e5da5Sopenharmony_ci } 1584fd4e5da5Sopenharmony_ci } 1585fd4e5da5Sopenharmony_ci for (int j = 0; j < 10; ++j) {} 1586fd4e5da5Sopenharmony_ci} 1587fd4e5da5Sopenharmony_ci 1588fd4e5da5Sopenharmony_ci*/ 1589fd4e5da5Sopenharmony_ciTEST_F(FusionCompatibilityTest, Continue) { 1590fd4e5da5Sopenharmony_ci const std::string text = R"( 1591fd4e5da5Sopenharmony_ci OpCapability Shader 1592fd4e5da5Sopenharmony_ci %1 = OpExtInstImport "GLSL.std.450" 1593fd4e5da5Sopenharmony_ci OpMemoryModel Logical GLSL450 1594fd4e5da5Sopenharmony_ci OpEntryPoint Fragment %4 "main" 1595fd4e5da5Sopenharmony_ci OpExecutionMode %4 OriginUpperLeft 1596fd4e5da5Sopenharmony_ci OpSource GLSL 440 1597fd4e5da5Sopenharmony_ci OpName %4 "main" 1598fd4e5da5Sopenharmony_ci OpName %8 "i" 1599fd4e5da5Sopenharmony_ci OpName %29 "j" 1600fd4e5da5Sopenharmony_ci %2 = OpTypeVoid 1601fd4e5da5Sopenharmony_ci %3 = OpTypeFunction %2 1602fd4e5da5Sopenharmony_ci %6 = OpTypeInt 32 1 1603fd4e5da5Sopenharmony_ci %7 = OpTypePointer Function %6 1604fd4e5da5Sopenharmony_ci %9 = OpConstant %6 0 1605fd4e5da5Sopenharmony_ci %16 = OpConstant %6 10 1606fd4e5da5Sopenharmony_ci %17 = OpTypeBool 1607fd4e5da5Sopenharmony_ci %20 = OpConstant %6 2 1608fd4e5da5Sopenharmony_ci %22 = OpConstant %6 1 1609fd4e5da5Sopenharmony_ci %4 = OpFunction %2 None %3 1610fd4e5da5Sopenharmony_ci %5 = OpLabel 1611fd4e5da5Sopenharmony_ci %8 = OpVariable %7 Function 1612fd4e5da5Sopenharmony_ci %29 = OpVariable %7 Function 1613fd4e5da5Sopenharmony_ci OpStore %8 %9 1614fd4e5da5Sopenharmony_ci OpBranch %10 1615fd4e5da5Sopenharmony_ci %10 = OpLabel 1616fd4e5da5Sopenharmony_ci %39 = OpPhi %6 %9 %5 %28 %13 1617fd4e5da5Sopenharmony_ci OpLoopMerge %12 %13 None 1618fd4e5da5Sopenharmony_ci OpBranch %14 1619fd4e5da5Sopenharmony_ci %14 = OpLabel 1620fd4e5da5Sopenharmony_ci %18 = OpSLessThan %17 %39 %16 1621fd4e5da5Sopenharmony_ci OpBranchConditional %18 %11 %12 1622fd4e5da5Sopenharmony_ci %11 = OpLabel 1623fd4e5da5Sopenharmony_ci %21 = OpSMod %6 %39 %20 1624fd4e5da5Sopenharmony_ci %23 = OpIEqual %17 %21 %22 1625fd4e5da5Sopenharmony_ci OpSelectionMerge %25 None 1626fd4e5da5Sopenharmony_ci OpBranchConditional %23 %24 %25 1627fd4e5da5Sopenharmony_ci %24 = OpLabel 1628fd4e5da5Sopenharmony_ci OpBranch %13 1629fd4e5da5Sopenharmony_ci %25 = OpLabel 1630fd4e5da5Sopenharmony_ci OpBranch %13 1631fd4e5da5Sopenharmony_ci %13 = OpLabel 1632fd4e5da5Sopenharmony_ci %28 = OpIAdd %6 %39 %22 1633fd4e5da5Sopenharmony_ci OpStore %8 %28 1634fd4e5da5Sopenharmony_ci OpBranch %10 1635fd4e5da5Sopenharmony_ci %12 = OpLabel 1636fd4e5da5Sopenharmony_ci OpStore %29 %9 1637fd4e5da5Sopenharmony_ci OpBranch %30 1638fd4e5da5Sopenharmony_ci %30 = OpLabel 1639fd4e5da5Sopenharmony_ci %40 = OpPhi %6 %9 %12 %38 %33 1640fd4e5da5Sopenharmony_ci OpLoopMerge %32 %33 None 1641fd4e5da5Sopenharmony_ci OpBranch %34 1642fd4e5da5Sopenharmony_ci %34 = OpLabel 1643fd4e5da5Sopenharmony_ci %36 = OpSLessThan %17 %40 %16 1644fd4e5da5Sopenharmony_ci OpBranchConditional %36 %31 %32 1645fd4e5da5Sopenharmony_ci %31 = OpLabel 1646fd4e5da5Sopenharmony_ci OpBranch %33 1647fd4e5da5Sopenharmony_ci %33 = OpLabel 1648fd4e5da5Sopenharmony_ci %38 = OpIAdd %6 %40 %22 1649fd4e5da5Sopenharmony_ci OpStore %29 %38 1650fd4e5da5Sopenharmony_ci OpBranch %30 1651fd4e5da5Sopenharmony_ci %32 = OpLabel 1652fd4e5da5Sopenharmony_ci OpReturn 1653fd4e5da5Sopenharmony_ci OpFunctionEnd 1654fd4e5da5Sopenharmony_ci )"; 1655fd4e5da5Sopenharmony_ci 1656fd4e5da5Sopenharmony_ci std::unique_ptr<IRContext> context = 1657fd4e5da5Sopenharmony_ci BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, text, 1658fd4e5da5Sopenharmony_ci SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); 1659fd4e5da5Sopenharmony_ci Module* module = context->module(); 1660fd4e5da5Sopenharmony_ci EXPECT_NE(nullptr, module) << "Assembling failed for shader:\n" 1661fd4e5da5Sopenharmony_ci << text << std::endl; 1662fd4e5da5Sopenharmony_ci Function& f = *module->begin(); 1663fd4e5da5Sopenharmony_ci LoopDescriptor& ld = *context->GetLoopDescriptor(&f); 1664fd4e5da5Sopenharmony_ci EXPECT_EQ(ld.NumLoops(), 2u); 1665fd4e5da5Sopenharmony_ci 1666fd4e5da5Sopenharmony_ci auto loops = ld.GetLoopsInBinaryLayoutOrder(); 1667fd4e5da5Sopenharmony_ci 1668fd4e5da5Sopenharmony_ci EXPECT_FALSE(LoopFusion(context.get(), loops[0], loops[1]).AreCompatible()); 1669fd4e5da5Sopenharmony_ci} 1670fd4e5da5Sopenharmony_ci 1671fd4e5da5Sopenharmony_ci/* 1672fd4e5da5Sopenharmony_ciGenerated from the following GLSL + --eliminate-local-multi-store 1673fd4e5da5Sopenharmony_ci 1674fd4e5da5Sopenharmony_ci#version 440 core 1675fd4e5da5Sopenharmony_civoid main() { 1676fd4e5da5Sopenharmony_ci int[10] a; 1677fd4e5da5Sopenharmony_ci // Compatible 1678fd4e5da5Sopenharmony_ci for (int i = 0; i < 10; ++i) { 1679fd4e5da5Sopenharmony_ci if (i % 2 == 1) { 1680fd4e5da5Sopenharmony_ci } else { 1681fd4e5da5Sopenharmony_ci a[i] = i; 1682fd4e5da5Sopenharmony_ci } 1683fd4e5da5Sopenharmony_ci } 1684fd4e5da5Sopenharmony_ci for (int j = 0; j < 10; ++j) {} 1685fd4e5da5Sopenharmony_ci} 1686fd4e5da5Sopenharmony_ci 1687fd4e5da5Sopenharmony_ci*/ 1688fd4e5da5Sopenharmony_ciTEST_F(FusionCompatibilityTest, IfElseInLoop) { 1689fd4e5da5Sopenharmony_ci const std::string text = R"( 1690fd4e5da5Sopenharmony_ci OpCapability Shader 1691fd4e5da5Sopenharmony_ci %1 = OpExtInstImport "GLSL.std.450" 1692fd4e5da5Sopenharmony_ci OpMemoryModel Logical GLSL450 1693fd4e5da5Sopenharmony_ci OpEntryPoint Fragment %4 "main" 1694fd4e5da5Sopenharmony_ci OpExecutionMode %4 OriginUpperLeft 1695fd4e5da5Sopenharmony_ci OpSource GLSL 440 1696fd4e5da5Sopenharmony_ci OpName %4 "main" 1697fd4e5da5Sopenharmony_ci OpName %8 "i" 1698fd4e5da5Sopenharmony_ci OpName %31 "a" 1699fd4e5da5Sopenharmony_ci OpName %37 "j" 1700fd4e5da5Sopenharmony_ci %2 = OpTypeVoid 1701fd4e5da5Sopenharmony_ci %3 = OpTypeFunction %2 1702fd4e5da5Sopenharmony_ci %6 = OpTypeInt 32 1 1703fd4e5da5Sopenharmony_ci %7 = OpTypePointer Function %6 1704fd4e5da5Sopenharmony_ci %9 = OpConstant %6 0 1705fd4e5da5Sopenharmony_ci %16 = OpConstant %6 10 1706fd4e5da5Sopenharmony_ci %17 = OpTypeBool 1707fd4e5da5Sopenharmony_ci %20 = OpConstant %6 2 1708fd4e5da5Sopenharmony_ci %22 = OpConstant %6 1 1709fd4e5da5Sopenharmony_ci %27 = OpTypeInt 32 0 1710fd4e5da5Sopenharmony_ci %28 = OpConstant %27 10 1711fd4e5da5Sopenharmony_ci %29 = OpTypeArray %6 %28 1712fd4e5da5Sopenharmony_ci %30 = OpTypePointer Function %29 1713fd4e5da5Sopenharmony_ci %4 = OpFunction %2 None %3 1714fd4e5da5Sopenharmony_ci %5 = OpLabel 1715fd4e5da5Sopenharmony_ci %8 = OpVariable %7 Function 1716fd4e5da5Sopenharmony_ci %31 = OpVariable %30 Function 1717fd4e5da5Sopenharmony_ci %37 = OpVariable %7 Function 1718fd4e5da5Sopenharmony_ci OpStore %8 %9 1719fd4e5da5Sopenharmony_ci OpBranch %10 1720fd4e5da5Sopenharmony_ci %10 = OpLabel 1721fd4e5da5Sopenharmony_ci %47 = OpPhi %6 %9 %5 %36 %13 1722fd4e5da5Sopenharmony_ci OpLoopMerge %12 %13 None 1723fd4e5da5Sopenharmony_ci OpBranch %14 1724fd4e5da5Sopenharmony_ci %14 = OpLabel 1725fd4e5da5Sopenharmony_ci %18 = OpSLessThan %17 %47 %16 1726fd4e5da5Sopenharmony_ci OpBranchConditional %18 %11 %12 1727fd4e5da5Sopenharmony_ci %11 = OpLabel 1728fd4e5da5Sopenharmony_ci %21 = OpSMod %6 %47 %20 1729fd4e5da5Sopenharmony_ci %23 = OpIEqual %17 %21 %22 1730fd4e5da5Sopenharmony_ci OpSelectionMerge %25 None 1731fd4e5da5Sopenharmony_ci OpBranchConditional %23 %24 %26 1732fd4e5da5Sopenharmony_ci %24 = OpLabel 1733fd4e5da5Sopenharmony_ci OpBranch %25 1734fd4e5da5Sopenharmony_ci %26 = OpLabel 1735fd4e5da5Sopenharmony_ci %34 = OpAccessChain %7 %31 %47 1736fd4e5da5Sopenharmony_ci OpStore %34 %47 1737fd4e5da5Sopenharmony_ci OpBranch %25 1738fd4e5da5Sopenharmony_ci %25 = OpLabel 1739fd4e5da5Sopenharmony_ci OpBranch %13 1740fd4e5da5Sopenharmony_ci %13 = OpLabel 1741fd4e5da5Sopenharmony_ci %36 = OpIAdd %6 %47 %22 1742fd4e5da5Sopenharmony_ci OpStore %8 %36 1743fd4e5da5Sopenharmony_ci OpBranch %10 1744fd4e5da5Sopenharmony_ci %12 = OpLabel 1745fd4e5da5Sopenharmony_ci OpStore %37 %9 1746fd4e5da5Sopenharmony_ci OpBranch %38 1747fd4e5da5Sopenharmony_ci %38 = OpLabel 1748fd4e5da5Sopenharmony_ci %48 = OpPhi %6 %9 %12 %46 %41 1749fd4e5da5Sopenharmony_ci OpLoopMerge %40 %41 None 1750fd4e5da5Sopenharmony_ci OpBranch %42 1751fd4e5da5Sopenharmony_ci %42 = OpLabel 1752fd4e5da5Sopenharmony_ci %44 = OpSLessThan %17 %48 %16 1753fd4e5da5Sopenharmony_ci OpBranchConditional %44 %39 %40 1754fd4e5da5Sopenharmony_ci %39 = OpLabel 1755fd4e5da5Sopenharmony_ci OpBranch %41 1756fd4e5da5Sopenharmony_ci %41 = OpLabel 1757fd4e5da5Sopenharmony_ci %46 = OpIAdd %6 %48 %22 1758fd4e5da5Sopenharmony_ci OpStore %37 %46 1759fd4e5da5Sopenharmony_ci OpBranch %38 1760fd4e5da5Sopenharmony_ci %40 = OpLabel 1761fd4e5da5Sopenharmony_ci OpReturn 1762fd4e5da5Sopenharmony_ci OpFunctionEnd 1763fd4e5da5Sopenharmony_ci )"; 1764fd4e5da5Sopenharmony_ci 1765fd4e5da5Sopenharmony_ci std::unique_ptr<IRContext> context = 1766fd4e5da5Sopenharmony_ci BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, text, 1767fd4e5da5Sopenharmony_ci SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); 1768fd4e5da5Sopenharmony_ci Module* module = context->module(); 1769fd4e5da5Sopenharmony_ci EXPECT_NE(nullptr, module) << "Assembling failed for shader:\n" 1770fd4e5da5Sopenharmony_ci << text << std::endl; 1771fd4e5da5Sopenharmony_ci Function& f = *module->begin(); 1772fd4e5da5Sopenharmony_ci LoopDescriptor& ld = *context->GetLoopDescriptor(&f); 1773fd4e5da5Sopenharmony_ci EXPECT_EQ(ld.NumLoops(), 2u); 1774fd4e5da5Sopenharmony_ci 1775fd4e5da5Sopenharmony_ci auto loops = ld.GetLoopsInBinaryLayoutOrder(); 1776fd4e5da5Sopenharmony_ci 1777fd4e5da5Sopenharmony_ci EXPECT_TRUE(LoopFusion(context.get(), loops[0], loops[1]).AreCompatible()); 1778fd4e5da5Sopenharmony_ci} 1779fd4e5da5Sopenharmony_ci 1780fd4e5da5Sopenharmony_ci} // namespace 1781fd4e5da5Sopenharmony_ci} // namespace opt 1782fd4e5da5Sopenharmony_ci} // namespace spvtools 1783