1 // Copyright (c) 2018 Google LLC. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 #include <string> 16 17 #include "effcee/effcee.h" 18 #include "gmock/gmock.h" 19 #include "test/opt/pass_fixture.h" 20 21 namespace spvtools { 22 namespace opt { 23 namespace { 24 25 using FusionPassTest = PassTest<::testing::Test>; 26 27 /* 28 Generated from the following GLSL + --eliminate-local-multi-store 29 30 #version 440 core 31 void main() { 32 int[10] a; 33 int[10] b; 34 for (int i = 0; i < 10; i++) { 35 a[i] = a[i]*2; 36 } 37 for (int i = 0; i < 10; i++) { 38 b[i] = a[i]+2; 39 } 40 } 41 42 */ 43 TEST_F(FusionPassTest, SimpleFusion) { 44 const std::string text = R"( 45 ; CHECK: OpPhi 46 ; CHECK: OpLoad 47 ; CHECK: OpStore 48 ; CHECK-NOT: OpPhi 49 ; CHECK: OpLoad 50 ; CHECK: OpStore 51 52 OpCapability Shader 53 %1 = OpExtInstImport "GLSL.std.450" 54 OpMemoryModel Logical GLSL450 55 OpEntryPoint Fragment %4 "main" 56 OpExecutionMode %4 OriginUpperLeft 57 OpSource GLSL 440 58 OpName %4 "main" 59 OpName %8 "i" 60 OpName %23 "a" 61 OpName %34 "i" 62 OpName %42 "b" 63 %2 = OpTypeVoid 64 %3 = OpTypeFunction %2 65 %6 = OpTypeInt 32 1 66 %7 = OpTypePointer Function %6 67 %9 = OpConstant %6 0 68 %16 = OpConstant %6 10 69 %17 = OpTypeBool 70 %19 = OpTypeInt 32 0 71 %20 = OpConstant %19 10 72 %21 = OpTypeArray %6 %20 73 %22 = OpTypePointer Function %21 74 %28 = OpConstant %6 2 75 %32 = OpConstant %6 1 76 %4 = OpFunction %2 None %3 77 %5 = OpLabel 78 %8 = OpVariable %7 Function 79 %23 = OpVariable %22 Function 80 %34 = OpVariable %7 Function 81 %42 = OpVariable %22 Function 82 OpStore %8 %9 83 OpBranch %10 84 %10 = OpLabel 85 %51 = OpPhi %6 %9 %5 %33 %13 86 OpLoopMerge %12 %13 None 87 OpBranch %14 88 %14 = OpLabel 89 %18 = OpSLessThan %17 %51 %16 90 OpBranchConditional %18 %11 %12 91 %11 = OpLabel 92 %26 = OpAccessChain %7 %23 %51 93 %27 = OpLoad %6 %26 94 %29 = OpIMul %6 %27 %28 95 %30 = OpAccessChain %7 %23 %51 96 OpStore %30 %29 97 OpBranch %13 98 %13 = OpLabel 99 %33 = OpIAdd %6 %51 %32 100 OpStore %8 %33 101 OpBranch %10 102 %12 = OpLabel 103 OpStore %34 %9 104 OpBranch %35 105 %35 = OpLabel 106 %52 = OpPhi %6 %9 %12 %50 %38 107 OpLoopMerge %37 %38 None 108 OpBranch %39 109 %39 = OpLabel 110 %41 = OpSLessThan %17 %52 %16 111 OpBranchConditional %41 %36 %37 112 %36 = OpLabel 113 %45 = OpAccessChain %7 %23 %52 114 %46 = OpLoad %6 %45 115 %47 = OpIAdd %6 %46 %28 116 %48 = OpAccessChain %7 %42 %52 117 OpStore %48 %47 118 OpBranch %38 119 %38 = OpLabel 120 %50 = OpIAdd %6 %52 %32 121 OpStore %34 %50 122 OpBranch %35 123 %37 = OpLabel 124 OpReturn 125 OpFunctionEnd 126 )"; 127 128 SinglePassRunAndMatch<LoopFusionPass>(text, true, 20); 129 } 130 131 /* 132 Generated from the following GLSL + --eliminate-local-multi-store 133 134 #version 440 core 135 void main() { 136 int[10] a; 137 int[10] b; 138 int[10] c; 139 for (int i = 0; i < 10; i++) { 140 a[i] = b[i] + 1; 141 } 142 for (int i = 0; i < 10; i++) { 143 c[i] = a[i] + 2; 144 } 145 for (int i = 0; i < 10; i++) { 146 b[i] = c[i] + 10; 147 } 148 } 149 150 */ 151 TEST_F(FusionPassTest, ThreeLoopsFused) { 152 const std::string text = R"( 153 ; CHECK: OpPhi 154 ; CHECK: OpLoad 155 ; CHECK: OpStore 156 ; CHECK-NOT: OpPhi 157 ; CHECK: OpLoad 158 ; CHECK: OpStore 159 ; CHECK-NOT: OpPhi 160 ; CHECK: OpLoad 161 ; CHECK: OpStore 162 163 OpCapability Shader 164 %1 = OpExtInstImport "GLSL.std.450" 165 OpMemoryModel Logical GLSL450 166 OpEntryPoint Fragment %4 "main" 167 OpExecutionMode %4 OriginUpperLeft 168 OpSource GLSL 440 169 OpName %4 "main" 170 OpName %8 "i" 171 OpName %23 "a" 172 OpName %25 "b" 173 OpName %34 "i" 174 OpName %42 "c" 175 OpName %52 "i" 176 %2 = OpTypeVoid 177 %3 = OpTypeFunction %2 178 %6 = OpTypeInt 32 1 179 %7 = OpTypePointer Function %6 180 %9 = OpConstant %6 0 181 %16 = OpConstant %6 10 182 %17 = OpTypeBool 183 %19 = OpTypeInt 32 0 184 %20 = OpConstant %19 10 185 %21 = OpTypeArray %6 %20 186 %22 = OpTypePointer Function %21 187 %29 = OpConstant %6 1 188 %47 = OpConstant %6 2 189 %4 = OpFunction %2 None %3 190 %5 = OpLabel 191 %8 = OpVariable %7 Function 192 %23 = OpVariable %22 Function 193 %25 = OpVariable %22 Function 194 %34 = OpVariable %7 Function 195 %42 = OpVariable %22 Function 196 %52 = OpVariable %7 Function 197 OpStore %8 %9 198 OpBranch %10 199 %10 = OpLabel 200 %68 = OpPhi %6 %9 %5 %33 %13 201 OpLoopMerge %12 %13 None 202 OpBranch %14 203 %14 = OpLabel 204 %18 = OpSLessThan %17 %68 %16 205 OpBranchConditional %18 %11 %12 206 %11 = OpLabel 207 %27 = OpAccessChain %7 %25 %68 208 %28 = OpLoad %6 %27 209 %30 = OpIAdd %6 %28 %29 210 %31 = OpAccessChain %7 %23 %68 211 OpStore %31 %30 212 OpBranch %13 213 %13 = OpLabel 214 %33 = OpIAdd %6 %68 %29 215 OpStore %8 %33 216 OpBranch %10 217 %12 = OpLabel 218 OpStore %34 %9 219 OpBranch %35 220 %35 = OpLabel 221 %69 = OpPhi %6 %9 %12 %51 %38 222 OpLoopMerge %37 %38 None 223 OpBranch %39 224 %39 = OpLabel 225 %41 = OpSLessThan %17 %69 %16 226 OpBranchConditional %41 %36 %37 227 %36 = OpLabel 228 %45 = OpAccessChain %7 %23 %69 229 %46 = OpLoad %6 %45 230 %48 = OpIAdd %6 %46 %47 231 %49 = OpAccessChain %7 %42 %69 232 OpStore %49 %48 233 OpBranch %38 234 %38 = OpLabel 235 %51 = OpIAdd %6 %69 %29 236 OpStore %34 %51 237 OpBranch %35 238 %37 = OpLabel 239 OpStore %52 %9 240 OpBranch %53 241 %53 = OpLabel 242 %70 = OpPhi %6 %9 %37 %67 %56 243 OpLoopMerge %55 %56 None 244 OpBranch %57 245 %57 = OpLabel 246 %59 = OpSLessThan %17 %70 %16 247 OpBranchConditional %59 %54 %55 248 %54 = OpLabel 249 %62 = OpAccessChain %7 %42 %70 250 %63 = OpLoad %6 %62 251 %64 = OpIAdd %6 %63 %16 252 %65 = OpAccessChain %7 %25 %70 253 OpStore %65 %64 254 OpBranch %56 255 %56 = OpLabel 256 %67 = OpIAdd %6 %70 %29 257 OpStore %52 %67 258 OpBranch %53 259 %55 = OpLabel 260 OpReturn 261 OpFunctionEnd 262 263 )"; 264 265 SinglePassRunAndMatch<LoopFusionPass>(text, true, 20); 266 } 267 268 /* 269 Generated from the following GLSL + --eliminate-local-multi-store 270 271 #version 440 core 272 void main() { 273 int[10][10] a; 274 int[10][10] b; 275 int[10][10] c; 276 // Legal both 277 for (int i = 0; i < 10; i++) { 278 for (int j = 0; j < 10; j++) { 279 c[i][j] = a[i][j] + 2; 280 } 281 } 282 for (int i = 0; i < 10; i++) { 283 for (int j = 0; j < 10; j++) { 284 b[i][j] = c[i][j] + 10; 285 } 286 } 287 } 288 289 */ 290 TEST_F(FusionPassTest, NestedLoopsFused) { 291 const std::string text = R"( 292 ; CHECK: OpPhi 293 ; CHECK: OpPhi 294 ; CHECK: OpLoad 295 ; CHECK: OpStore 296 ; CHECK-NOT: OpPhi 297 ; CHECK: OpLoad 298 ; CHECK: OpStore 299 300 OpCapability Shader 301 %1 = OpExtInstImport "GLSL.std.450" 302 OpMemoryModel Logical GLSL450 303 OpEntryPoint Fragment %4 "main" 304 OpExecutionMode %4 OriginUpperLeft 305 OpSource GLSL 440 306 OpName %4 "main" 307 OpName %8 "i" 308 OpName %19 "j" 309 OpName %32 "c" 310 OpName %35 "a" 311 OpName %48 "i" 312 OpName %56 "j" 313 OpName %64 "b" 314 %2 = OpTypeVoid 315 %3 = OpTypeFunction %2 316 %6 = OpTypeInt 32 1 317 %7 = OpTypePointer Function %6 318 %9 = OpConstant %6 0 319 %16 = OpConstant %6 10 320 %17 = OpTypeBool 321 %27 = OpTypeInt 32 0 322 %28 = OpConstant %27 10 323 %29 = OpTypeArray %6 %28 324 %30 = OpTypeArray %29 %28 325 %31 = OpTypePointer Function %30 326 %40 = OpConstant %6 2 327 %44 = OpConstant %6 1 328 %4 = OpFunction %2 None %3 329 %5 = OpLabel 330 %8 = OpVariable %7 Function 331 %19 = OpVariable %7 Function 332 %32 = OpVariable %31 Function 333 %35 = OpVariable %31 Function 334 %48 = OpVariable %7 Function 335 %56 = OpVariable %7 Function 336 %64 = OpVariable %31 Function 337 OpStore %8 %9 338 OpBranch %10 339 %10 = OpLabel 340 %77 = OpPhi %6 %9 %5 %47 %13 341 OpLoopMerge %12 %13 None 342 OpBranch %14 343 %14 = OpLabel 344 %18 = OpSLessThan %17 %77 %16 345 OpBranchConditional %18 %11 %12 346 %11 = OpLabel 347 OpStore %19 %9 348 OpBranch %20 349 %20 = OpLabel 350 %81 = OpPhi %6 %9 %11 %45 %23 351 OpLoopMerge %22 %23 None 352 OpBranch %24 353 %24 = OpLabel 354 %26 = OpSLessThan %17 %81 %16 355 OpBranchConditional %26 %21 %22 356 %21 = OpLabel 357 %38 = OpAccessChain %7 %35 %77 %81 358 %39 = OpLoad %6 %38 359 %41 = OpIAdd %6 %39 %40 360 %42 = OpAccessChain %7 %32 %77 %81 361 OpStore %42 %41 362 OpBranch %23 363 %23 = OpLabel 364 %45 = OpIAdd %6 %81 %44 365 OpStore %19 %45 366 OpBranch %20 367 %22 = OpLabel 368 OpBranch %13 369 %13 = OpLabel 370 %47 = OpIAdd %6 %77 %44 371 OpStore %8 %47 372 OpBranch %10 373 %12 = OpLabel 374 OpStore %48 %9 375 OpBranch %49 376 %49 = OpLabel 377 %78 = OpPhi %6 %9 %12 %76 %52 378 OpLoopMerge %51 %52 None 379 OpBranch %53 380 %53 = OpLabel 381 %55 = OpSLessThan %17 %78 %16 382 OpBranchConditional %55 %50 %51 383 %50 = OpLabel 384 OpStore %56 %9 385 OpBranch %57 386 %57 = OpLabel 387 %79 = OpPhi %6 %9 %50 %74 %60 388 OpLoopMerge %59 %60 None 389 OpBranch %61 390 %61 = OpLabel 391 %63 = OpSLessThan %17 %79 %16 392 OpBranchConditional %63 %58 %59 393 %58 = OpLabel 394 %69 = OpAccessChain %7 %32 %78 %79 395 %70 = OpLoad %6 %69 396 %71 = OpIAdd %6 %70 %16 397 %72 = OpAccessChain %7 %64 %78 %79 398 OpStore %72 %71 399 OpBranch %60 400 %60 = OpLabel 401 %74 = OpIAdd %6 %79 %44 402 OpStore %56 %74 403 OpBranch %57 404 %59 = OpLabel 405 OpBranch %52 406 %52 = OpLabel 407 %76 = OpIAdd %6 %78 %44 408 OpStore %48 %76 409 OpBranch %49 410 %51 = OpLabel 411 OpReturn 412 OpFunctionEnd 413 )"; 414 415 SinglePassRunAndMatch<LoopFusionPass>(text, true, 20); 416 } 417 418 /* 419 Generated from the following GLSL + --eliminate-local-multi-store 420 421 #version 440 core 422 void main() { 423 // Can't fuse, different step 424 for (int i = 0; i < 10; i++) {} 425 for (int j = 0; j < 10; j=j+2) {} 426 } 427 428 */ 429 TEST_F(FusionPassTest, Incompatible) { 430 const std::string text = R"( 431 ; CHECK: OpPhi 432 ; CHECK-NEXT: OpLoopMerge 433 ; CHECK: OpPhi 434 ; CHECK-NEXT: OpLoopMerge 435 436 OpCapability Shader 437 %1 = OpExtInstImport "GLSL.std.450" 438 OpMemoryModel Logical GLSL450 439 OpEntryPoint Fragment %4 "main" 440 OpExecutionMode %4 OriginUpperLeft 441 OpSource GLSL 440 442 OpName %4 "main" 443 OpName %8 "i" 444 OpName %22 "j" 445 %2 = OpTypeVoid 446 %3 = OpTypeFunction %2 447 %6 = OpTypeInt 32 1 448 %7 = OpTypePointer Function %6 449 %9 = OpConstant %6 0 450 %16 = OpConstant %6 10 451 %17 = OpTypeBool 452 %20 = OpConstant %6 1 453 %31 = OpConstant %6 2 454 %4 = OpFunction %2 None %3 455 %5 = OpLabel 456 %8 = OpVariable %7 Function 457 %22 = OpVariable %7 Function 458 OpStore %8 %9 459 OpBranch %10 460 %10 = OpLabel 461 %33 = OpPhi %6 %9 %5 %21 %13 462 OpLoopMerge %12 %13 None 463 OpBranch %14 464 %14 = OpLabel 465 %18 = OpSLessThan %17 %33 %16 466 OpBranchConditional %18 %11 %12 467 %11 = OpLabel 468 OpBranch %13 469 %13 = OpLabel 470 %21 = OpIAdd %6 %33 %20 471 OpStore %8 %21 472 OpBranch %10 473 %12 = OpLabel 474 OpStore %22 %9 475 OpBranch %23 476 %23 = OpLabel 477 %34 = OpPhi %6 %9 %12 %32 %26 478 OpLoopMerge %25 %26 None 479 OpBranch %27 480 %27 = OpLabel 481 %29 = OpSLessThan %17 %34 %16 482 OpBranchConditional %29 %24 %25 483 %24 = OpLabel 484 OpBranch %26 485 %26 = OpLabel 486 %32 = OpIAdd %6 %34 %31 487 OpStore %22 %32 488 OpBranch %23 489 %25 = OpLabel 490 OpReturn 491 OpFunctionEnd 492 )"; 493 494 SinglePassRunAndMatch<LoopFusionPass>(text, true, 20); 495 } 496 497 /* 498 Generated from the following GLSL + --eliminate-local-multi-store 499 500 #version 440 core 501 void main() { 502 int[10] a; 503 int[10] b; 504 int[10] c; 505 // Illegal, loop-independent dependence will become a 506 // backward loop-carried antidependence 507 for (int i = 0; i < 10; i++) { 508 a[i] = b[i] + 1; 509 } 510 for (int i = 0; i < 10; i++) { 511 c[i] = a[i+1] + 2; 512 } 513 } 514 515 */ 516 TEST_F(FusionPassTest, Illegal) { 517 std::string text = R"( 518 ; CHECK: OpPhi 519 ; CHECK-NEXT: OpLoopMerge 520 ; CHECK: OpLoad 521 ; CHECK: OpStore 522 ; CHECK: OpPhi 523 ; CHECK-NEXT: OpLoopMerge 524 ; CHECK: OpLoad 525 ; CHECK: OpStore 526 527 OpCapability Shader 528 %1 = OpExtInstImport "GLSL.std.450" 529 OpMemoryModel Logical GLSL450 530 OpEntryPoint Fragment %4 "main" 531 OpExecutionMode %4 OriginUpperLeft 532 OpSource GLSL 440 533 OpName %4 "main" 534 OpName %8 "i" 535 OpName %23 "a" 536 OpName %25 "b" 537 OpName %34 "i" 538 OpName %42 "c" 539 %2 = OpTypeVoid 540 %3 = OpTypeFunction %2 541 %6 = OpTypeInt 32 1 542 %7 = OpTypePointer Function %6 543 %9 = OpConstant %6 0 544 %16 = OpConstant %6 10 545 %17 = OpTypeBool 546 %19 = OpTypeInt 32 0 547 %20 = OpConstant %19 10 548 %21 = OpTypeArray %6 %20 549 %22 = OpTypePointer Function %21 550 %29 = OpConstant %6 1 551 %48 = OpConstant %6 2 552 %4 = OpFunction %2 None %3 553 %5 = OpLabel 554 %8 = OpVariable %7 Function 555 %23 = OpVariable %22 Function 556 %25 = OpVariable %22 Function 557 %34 = OpVariable %7 Function 558 %42 = OpVariable %22 Function 559 OpStore %8 %9 560 OpBranch %10 561 %10 = OpLabel 562 %53 = OpPhi %6 %9 %5 %33 %13 563 OpLoopMerge %12 %13 None 564 OpBranch %14 565 %14 = OpLabel 566 %18 = OpSLessThan %17 %53 %16 567 OpBranchConditional %18 %11 %12 568 %11 = OpLabel 569 %27 = OpAccessChain %7 %25 %53 570 %28 = OpLoad %6 %27 571 %30 = OpIAdd %6 %28 %29 572 %31 = OpAccessChain %7 %23 %53 573 OpStore %31 %30 574 OpBranch %13 575 %13 = OpLabel 576 %33 = OpIAdd %6 %53 %29 577 OpStore %8 %33 578 OpBranch %10 579 %12 = OpLabel 580 OpStore %34 %9 581 OpBranch %35 582 %35 = OpLabel 583 %54 = OpPhi %6 %9 %12 %52 %38 584 OpLoopMerge %37 %38 None 585 OpBranch %39 586 %39 = OpLabel 587 %41 = OpSLessThan %17 %54 %16 588 OpBranchConditional %41 %36 %37 589 %36 = OpLabel 590 %45 = OpIAdd %6 %54 %29 591 %46 = OpAccessChain %7 %23 %45 592 %47 = OpLoad %6 %46 593 %49 = OpIAdd %6 %47 %48 594 %50 = OpAccessChain %7 %42 %54 595 OpStore %50 %49 596 OpBranch %38 597 %38 = OpLabel 598 %52 = OpIAdd %6 %54 %29 599 OpStore %34 %52 600 OpBranch %35 601 %37 = OpLabel 602 OpReturn 603 OpFunctionEnd 604 )"; 605 606 SinglePassRunAndMatch<LoopFusionPass>(text, true, 20); 607 } 608 609 /* 610 Generated from the following GLSL + --eliminate-local-multi-store 611 612 #version 440 core 613 void main() { 614 int[10] a; 615 int[10] b; 616 for (int i = 0; i < 10; i++) { 617 a[i] = a[i]*2; 618 } 619 for (int i = 0; i < 10; i++) { 620 b[i] = a[i]+2; 621 } 622 } 623 624 */ 625 TEST_F(FusionPassTest, TooManyRegisters) { 626 const std::string text = R"( 627 ; CHECK: OpPhi 628 ; CHECK-NEXT: OpLoopMerge 629 ; CHECK: OpLoad 630 ; CHECK: OpStore 631 ; CHECK: OpPhi 632 ; CHECK-NEXT: OpLoopMerge 633 ; CHECK: OpLoad 634 ; CHECK: OpStore 635 636 OpCapability Shader 637 %1 = OpExtInstImport "GLSL.std.450" 638 OpMemoryModel Logical GLSL450 639 OpEntryPoint Fragment %4 "main" 640 OpExecutionMode %4 OriginUpperLeft 641 OpSource GLSL 440 642 OpName %4 "main" 643 OpName %8 "i" 644 OpName %23 "a" 645 OpName %34 "i" 646 OpName %42 "b" 647 %2 = OpTypeVoid 648 %3 = OpTypeFunction %2 649 %6 = OpTypeInt 32 1 650 %7 = OpTypePointer Function %6 651 %9 = OpConstant %6 0 652 %16 = OpConstant %6 10 653 %17 = OpTypeBool 654 %19 = OpTypeInt 32 0 655 %20 = OpConstant %19 10 656 %21 = OpTypeArray %6 %20 657 %22 = OpTypePointer Function %21 658 %28 = OpConstant %6 2 659 %32 = OpConstant %6 1 660 %4 = OpFunction %2 None %3 661 %5 = OpLabel 662 %8 = OpVariable %7 Function 663 %23 = OpVariable %22 Function 664 %34 = OpVariable %7 Function 665 %42 = OpVariable %22 Function 666 OpStore %8 %9 667 OpBranch %10 668 %10 = OpLabel 669 %51 = OpPhi %6 %9 %5 %33 %13 670 OpLoopMerge %12 %13 None 671 OpBranch %14 672 %14 = OpLabel 673 %18 = OpSLessThan %17 %51 %16 674 OpBranchConditional %18 %11 %12 675 %11 = OpLabel 676 %26 = OpAccessChain %7 %23 %51 677 %27 = OpLoad %6 %26 678 %29 = OpIMul %6 %27 %28 679 %30 = OpAccessChain %7 %23 %51 680 OpStore %30 %29 681 OpBranch %13 682 %13 = OpLabel 683 %33 = OpIAdd %6 %51 %32 684 OpStore %8 %33 685 OpBranch %10 686 %12 = OpLabel 687 OpStore %34 %9 688 OpBranch %35 689 %35 = OpLabel 690 %52 = OpPhi %6 %9 %12 %50 %38 691 OpLoopMerge %37 %38 None 692 OpBranch %39 693 %39 = OpLabel 694 %41 = OpSLessThan %17 %52 %16 695 OpBranchConditional %41 %36 %37 696 %36 = OpLabel 697 %45 = OpAccessChain %7 %23 %52 698 %46 = OpLoad %6 %45 699 %47 = OpIAdd %6 %46 %28 700 %48 = OpAccessChain %7 %42 %52 701 OpStore %48 %47 702 OpBranch %38 703 %38 = OpLabel 704 %50 = OpIAdd %6 %52 %32 705 OpStore %34 %50 706 OpBranch %35 707 %37 = OpLabel 708 OpReturn 709 OpFunctionEnd 710 )"; 711 712 SinglePassRunAndMatch<LoopFusionPass>(text, true, 5); 713 } 714 715 } // namespace 716 } // namespace opt 717 } // namespace spvtools 718