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 <memory> 16 #include <string> 17 #include <unordered_set> 18 #include <vector> 19 20 #include "gmock/gmock.h" 21 #include "source/opt/register_pressure.h" 22 #include "test/opt/assembly_builder.h" 23 #include "test/opt/function_utils.h" 24 #include "test/opt/pass_fixture.h" 25 #include "test/opt/pass_utils.h" 26 27 namespace spvtools { 28 namespace opt { 29 namespace { 30 31 using ::testing::UnorderedElementsAre; 32 using PassClassTest = PassTest<::testing::Test>; 33 34 void CompareSets(const std::unordered_set<Instruction*>& computed, 35 const std::unordered_set<uint32_t>& expected) { 36 for (Instruction* insn : computed) { 37 EXPECT_TRUE(expected.count(insn->result_id())) 38 << "Unexpected instruction in live set: " << *insn; 39 } 40 EXPECT_EQ(computed.size(), expected.size()); 41 } 42 43 /* 44 Generated from the following GLSL 45 46 #version 330 47 in vec4 BaseColor; 48 flat in int Count; 49 void main() 50 { 51 vec4 color = BaseColor; 52 vec4 acc; 53 if (Count == 0) { 54 acc = color; 55 } 56 else { 57 acc = color + vec4(0,1,2,0); 58 } 59 gl_FragColor = acc + color; 60 } 61 */ 62 TEST_F(PassClassTest, LivenessWithIf) { 63 const std::string text = R"( 64 OpCapability Shader 65 %1 = OpExtInstImport "GLSL.std.450" 66 OpMemoryModel Logical GLSL450 67 OpEntryPoint Fragment %4 "main" %11 %15 %32 68 OpExecutionMode %4 OriginLowerLeft 69 OpSource GLSL 330 70 OpName %4 "main" 71 OpName %11 "BaseColor" 72 OpName %15 "Count" 73 OpName %32 "gl_FragColor" 74 OpDecorate %11 Location 0 75 OpDecorate %15 Flat 76 OpDecorate %15 Location 0 77 OpDecorate %32 Location 0 78 %2 = OpTypeVoid 79 %3 = OpTypeFunction %2 80 %6 = OpTypeFloat 32 81 %7 = OpTypeVector %6 4 82 %10 = OpTypePointer Input %7 83 %11 = OpVariable %10 Input 84 %13 = OpTypeInt 32 1 85 %14 = OpTypePointer Input %13 86 %15 = OpVariable %14 Input 87 %17 = OpConstant %13 0 88 %18 = OpTypeBool 89 %26 = OpConstant %6 0 90 %27 = OpConstant %6 1 91 %28 = OpConstant %6 2 92 %29 = OpConstantComposite %7 %26 %27 %28 %26 93 %31 = OpTypePointer Output %7 94 %32 = OpVariable %31 Output 95 %4 = OpFunction %2 None %3 96 %5 = OpLabel 97 %12 = OpLoad %7 %11 98 %16 = OpLoad %13 %15 99 %19 = OpIEqual %18 %16 %17 100 OpSelectionMerge %21 None 101 OpBranchConditional %19 %20 %24 102 %20 = OpLabel 103 OpBranch %21 104 %24 = OpLabel 105 %30 = OpFAdd %7 %12 %29 106 OpBranch %21 107 %21 = OpLabel 108 %36 = OpPhi %7 %12 %20 %30 %24 109 %35 = OpFAdd %7 %36 %12 110 OpStore %32 %35 111 OpReturn 112 OpFunctionEnd 113 )"; 114 std::unique_ptr<IRContext> context = 115 BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, text, 116 SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); 117 Module* module = context->module(); 118 EXPECT_NE(nullptr, module) << "Assembling failed for shader:\n" 119 << text << std::endl; 120 Function* f = &*module->begin(); 121 LivenessAnalysis* liveness_analysis = context->GetLivenessAnalysis(); 122 const RegisterLiveness* register_liveness = liveness_analysis->Get(f); 123 { 124 SCOPED_TRACE("Block 5"); 125 auto live_sets = register_liveness->Get(5); 126 std::unordered_set<uint32_t> live_in{ 127 11, // %11 = OpVariable %10 Input 128 15, // %15 = OpVariable %14 Input 129 32, // %32 = OpVariable %31 Output 130 }; 131 CompareSets(live_sets->live_in_, live_in); 132 133 std::unordered_set<uint32_t> live_out{ 134 12, // %12 = OpLoad %7 %11 135 32, // %32 = OpVariable %31 Output 136 }; 137 CompareSets(live_sets->live_out_, live_out); 138 } 139 { 140 SCOPED_TRACE("Block 20"); 141 auto live_sets = register_liveness->Get(20); 142 std::unordered_set<uint32_t> live_inout{ 143 12, // %12 = OpLoad %7 %11 144 32, // %32 = OpVariable %31 Output 145 }; 146 CompareSets(live_sets->live_in_, live_inout); 147 CompareSets(live_sets->live_out_, live_inout); 148 } 149 { 150 SCOPED_TRACE("Block 24"); 151 auto live_sets = register_liveness->Get(24); 152 std::unordered_set<uint32_t> live_in{ 153 12, // %12 = OpLoad %7 %11 154 32, // %32 = OpVariable %31 Output 155 }; 156 CompareSets(live_sets->live_in_, live_in); 157 158 std::unordered_set<uint32_t> live_out{ 159 12, // %12 = OpLoad %7 %11 160 30, // %30 = OpFAdd %7 %12 %29 161 32, // %32 = OpVariable %31 Output 162 }; 163 CompareSets(live_sets->live_out_, live_out); 164 } 165 { 166 SCOPED_TRACE("Block 21"); 167 auto live_sets = register_liveness->Get(21); 168 std::unordered_set<uint32_t> live_in{ 169 12, // %12 = OpLoad %7 %11 170 32, // %32 = OpVariable %31 Output 171 36, // %36 = OpPhi %7 %12 %20 %30 %24 172 }; 173 CompareSets(live_sets->live_in_, live_in); 174 175 std::unordered_set<uint32_t> live_out{}; 176 CompareSets(live_sets->live_out_, live_out); 177 } 178 } 179 180 /* 181 Generated from the following GLSL 182 #version 330 183 in vec4 bigColor; 184 in vec4 BaseColor; 185 in float f; 186 flat in int Count; 187 flat in uvec4 v4; 188 void main() 189 { 190 vec4 color = BaseColor; 191 for (int i = 0; i < Count; ++i) 192 color += bigColor; 193 float sum = 0.0; 194 for (int i = 0; i < 4; ++i) { 195 float acc = 0.0; 196 if (sum == 0.0) { 197 acc = v4[i]; 198 } 199 else { 200 acc = BaseColor[i]; 201 } 202 sum += acc + v4[i]; 203 } 204 vec4 tv4; 205 for (int i = 0; i < 4; ++i) 206 tv4[i] = v4[i] * 4u; 207 color += vec4(sum) + tv4; 208 vec4 r; 209 r.xyz = BaseColor.xyz; 210 for (int i = 0; i < Count; ++i) 211 r.w = f; 212 color.xyz += r.xyz; 213 for (int i = 0; i < 16; i += 4) 214 for (int j = 0; j < 4; j++) 215 color *= f; 216 gl_FragColor = color + tv4; 217 } 218 */ 219 TEST_F(PassClassTest, RegisterLiveness) { 220 const std::string text = R"( 221 OpCapability Shader 222 %1 = OpExtInstImport "GLSL.std.450" 223 OpMemoryModel Logical GLSL450 224 OpEntryPoint Fragment %4 "main" %11 %24 %28 %55 %124 %176 225 OpExecutionMode %4 OriginLowerLeft 226 OpSource GLSL 330 227 OpName %4 "main" 228 OpName %11 "BaseColor" 229 OpName %24 "Count" 230 OpName %28 "bigColor" 231 OpName %55 "v4" 232 OpName %84 "tv4" 233 OpName %124 "f" 234 OpName %176 "gl_FragColor" 235 OpDecorate %11 Location 0 236 OpDecorate %24 Flat 237 OpDecorate %24 Location 0 238 OpDecorate %28 Location 0 239 OpDecorate %55 Flat 240 OpDecorate %55 Location 0 241 OpDecorate %124 Location 0 242 OpDecorate %176 Location 0 243 %2 = OpTypeVoid 244 %3 = OpTypeFunction %2 245 %6 = OpTypeFloat 32 246 %7 = OpTypeVector %6 4 247 %8 = OpTypePointer Function %7 248 %10 = OpTypePointer Input %7 249 %11 = OpVariable %10 Input 250 %13 = OpTypeInt 32 1 251 %16 = OpConstant %13 0 252 %23 = OpTypePointer Input %13 253 %24 = OpVariable %23 Input 254 %26 = OpTypeBool 255 %28 = OpVariable %10 Input 256 %33 = OpConstant %13 1 257 %35 = OpTypePointer Function %6 258 %37 = OpConstant %6 0 259 %45 = OpConstant %13 4 260 %52 = OpTypeInt 32 0 261 %53 = OpTypeVector %52 4 262 %54 = OpTypePointer Input %53 263 %55 = OpVariable %54 Input 264 %57 = OpTypePointer Input %52 265 %63 = OpTypePointer Input %6 266 %89 = OpConstant %52 4 267 %102 = OpTypeVector %6 3 268 %124 = OpVariable %63 Input 269 %158 = OpConstant %13 16 270 %175 = OpTypePointer Output %7 271 %176 = OpVariable %175 Output 272 %195 = OpUndef %7 273 %4 = OpFunction %2 None %3 274 %5 = OpLabel 275 %84 = OpVariable %8 Function 276 %12 = OpLoad %7 %11 277 OpBranch %17 278 %17 = OpLabel 279 %191 = OpPhi %7 %12 %5 %31 %18 280 %184 = OpPhi %13 %16 %5 %34 %18 281 %25 = OpLoad %13 %24 282 %27 = OpSLessThan %26 %184 %25 283 OpLoopMerge %19 %18 None 284 OpBranchConditional %27 %18 %19 285 %18 = OpLabel 286 %29 = OpLoad %7 %28 287 %31 = OpFAdd %7 %191 %29 288 %34 = OpIAdd %13 %184 %33 289 OpBranch %17 290 %19 = OpLabel 291 OpBranch %39 292 %39 = OpLabel 293 %188 = OpPhi %6 %37 %19 %73 %51 294 %185 = OpPhi %13 %16 %19 %75 %51 295 %46 = OpSLessThan %26 %185 %45 296 OpLoopMerge %41 %51 None 297 OpBranchConditional %46 %40 %41 298 %40 = OpLabel 299 %49 = OpFOrdEqual %26 %188 %37 300 OpSelectionMerge %51 None 301 OpBranchConditional %49 %50 %61 302 %50 = OpLabel 303 %58 = OpAccessChain %57 %55 %185 304 %59 = OpLoad %52 %58 305 %60 = OpConvertUToF %6 %59 306 OpBranch %51 307 %61 = OpLabel 308 %64 = OpAccessChain %63 %11 %185 309 %65 = OpLoad %6 %64 310 OpBranch %51 311 %51 = OpLabel 312 %210 = OpPhi %6 %60 %50 %65 %61 313 %68 = OpAccessChain %57 %55 %185 314 %69 = OpLoad %52 %68 315 %70 = OpConvertUToF %6 %69 316 %71 = OpFAdd %6 %210 %70 317 %73 = OpFAdd %6 %188 %71 318 %75 = OpIAdd %13 %185 %33 319 OpBranch %39 320 %41 = OpLabel 321 OpBranch %77 322 %77 = OpLabel 323 %186 = OpPhi %13 %16 %41 %94 %78 324 %83 = OpSLessThan %26 %186 %45 325 OpLoopMerge %79 %78 None 326 OpBranchConditional %83 %78 %79 327 %78 = OpLabel 328 %87 = OpAccessChain %57 %55 %186 329 %88 = OpLoad %52 %87 330 %90 = OpIMul %52 %88 %89 331 %91 = OpConvertUToF %6 %90 332 %92 = OpAccessChain %35 %84 %186 333 OpStore %92 %91 334 %94 = OpIAdd %13 %186 %33 335 OpBranch %77 336 %79 = OpLabel 337 %96 = OpCompositeConstruct %7 %188 %188 %188 %188 338 %97 = OpLoad %7 %84 339 %98 = OpFAdd %7 %96 %97 340 %100 = OpFAdd %7 %191 %98 341 %104 = OpVectorShuffle %102 %12 %12 0 1 2 342 %106 = OpVectorShuffle %7 %195 %104 4 5 6 3 343 OpBranch %108 344 %108 = OpLabel 345 %197 = OpPhi %7 %106 %79 %208 %133 346 %196 = OpPhi %13 %16 %79 %143 %133 347 %115 = OpSLessThan %26 %196 %25 348 OpLoopMerge %110 %133 None 349 OpBranchConditional %115 %109 %110 350 %109 = OpLabel 351 OpBranch %117 352 %117 = OpLabel 353 %209 = OpPhi %7 %197 %109 %181 %118 354 %204 = OpPhi %13 %16 %109 %129 %118 355 %123 = OpSLessThan %26 %204 %45 356 OpLoopMerge %119 %118 None 357 OpBranchConditional %123 %118 %119 358 %118 = OpLabel 359 %125 = OpLoad %6 %124 360 %181 = OpCompositeInsert %7 %125 %209 3 361 %129 = OpIAdd %13 %204 %33 362 OpBranch %117 363 %119 = OpLabel 364 OpBranch %131 365 %131 = OpLabel 366 %208 = OpPhi %7 %209 %119 %183 %132 367 %205 = OpPhi %13 %16 %119 %141 %132 368 %137 = OpSLessThan %26 %205 %45 369 OpLoopMerge %133 %132 None 370 OpBranchConditional %137 %132 %133 371 %132 = OpLabel 372 %138 = OpLoad %6 %124 373 %183 = OpCompositeInsert %7 %138 %208 3 374 %141 = OpIAdd %13 %205 %33 375 OpBranch %131 376 %133 = OpLabel 377 %143 = OpIAdd %13 %196 %33 378 OpBranch %108 379 %110 = OpLabel 380 %145 = OpVectorShuffle %102 %197 %197 0 1 2 381 %147 = OpVectorShuffle %102 %100 %100 0 1 2 382 %148 = OpFAdd %102 %147 %145 383 %150 = OpVectorShuffle %7 %100 %148 4 5 6 3 384 OpBranch %152 385 %152 = OpLabel 386 %200 = OpPhi %7 %150 %110 %203 %163 387 %199 = OpPhi %13 %16 %110 %174 %163 388 %159 = OpSLessThan %26 %199 %158 389 OpLoopMerge %154 %163 None 390 OpBranchConditional %159 %153 %154 391 %153 = OpLabel 392 OpBranch %161 393 %161 = OpLabel 394 %203 = OpPhi %7 %200 %153 %170 %162 395 %201 = OpPhi %13 %16 %153 %172 %162 396 %167 = OpSLessThan %26 %201 %45 397 OpLoopMerge %163 %162 None 398 OpBranchConditional %167 %162 %163 399 %162 = OpLabel 400 %168 = OpLoad %6 %124 401 %170 = OpVectorTimesScalar %7 %203 %168 402 %172 = OpIAdd %13 %201 %33 403 OpBranch %161 404 %163 = OpLabel 405 %174 = OpIAdd %13 %199 %45 406 OpBranch %152 407 %154 = OpLabel 408 %178 = OpLoad %7 %84 409 %179 = OpFAdd %7 %200 %178 410 OpStore %176 %179 411 OpReturn 412 OpFunctionEnd 413 )"; 414 std::unique_ptr<IRContext> context = 415 BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, text, 416 SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); 417 Module* module = context->module(); 418 EXPECT_NE(nullptr, module) << "Assembling failed for shader:\n" 419 << text << std::endl; 420 Function* f = &*module->begin(); 421 LivenessAnalysis* liveness_analysis = context->GetLivenessAnalysis(); 422 const RegisterLiveness* register_liveness = liveness_analysis->Get(f); 423 LoopDescriptor& ld = *context->GetLoopDescriptor(f); 424 425 { 426 SCOPED_TRACE("Block 5"); 427 auto live_sets = register_liveness->Get(5); 428 std::unordered_set<uint32_t> live_in{ 429 11, // %11 = OpVariable %10 Input 430 24, // %24 = OpVariable %23 Input 431 28, // %28 = OpVariable %10 Input 432 55, // %55 = OpVariable %54 Input 433 124, // %124 = OpVariable %63 Input 434 176, // %176 = OpVariable %175 Output 435 }; 436 CompareSets(live_sets->live_in_, live_in); 437 438 std::unordered_set<uint32_t> live_out{ 439 11, // %11 = OpVariable %10 Input 440 12, // %12 = OpLoad %7 %11 441 24, // %24 = OpVariable %23 Input 442 28, // %28 = OpVariable %10 Input 443 55, // %55 = OpVariable %54 Input 444 84, // %84 = OpVariable %8 Function 445 124, // %124 = OpVariable %63 Input 446 176, // %176 = OpVariable %175 Output 447 }; 448 CompareSets(live_sets->live_out_, live_out); 449 450 EXPECT_EQ(live_sets->used_registers_, 8u); 451 } 452 { 453 SCOPED_TRACE("Block 17"); 454 auto live_sets = register_liveness->Get(17); 455 std::unordered_set<uint32_t> live_in{ 456 11, // %11 = OpVariable %10 Input 457 12, // %12 = OpLoad %7 %11 458 24, // %24 = OpVariable %23 Input 459 28, // %28 = OpVariable %10 Input 460 55, // %55 = OpVariable %54 Input 461 84, // %84 = OpVariable %8 Function 462 124, // %124 = OpVariable %63 Input 463 176, // %176 = OpVariable %175 Output 464 184, // %184 = OpPhi %13 %16 %5 %34 %18 465 191, // %191 = OpPhi %7 %12 %5 %31 %18 466 }; 467 CompareSets(live_sets->live_in_, live_in); 468 469 std::unordered_set<uint32_t> live_out{ 470 11, // %11 = OpVariable %10 Input 471 12, // %12 = OpLoad %7 %11 472 25, // %25 = OpLoad %13 %24 473 28, // %28 = OpVariable %10 Input 474 55, // %55 = OpVariable %54 Input 475 84, // %84 = OpVariable %8 Function 476 124, // %124 = OpVariable %63 Input 477 176, // %176 = OpVariable %175 Output 478 184, // %184 = OpPhi %13 %16 %5 %34 %18 479 191, // %191 = OpPhi %7 %12 %5 %31 %18 480 }; 481 CompareSets(live_sets->live_out_, live_out); 482 483 EXPECT_EQ(live_sets->used_registers_, 11u); 484 } 485 { 486 SCOPED_TRACE("Block 18"); 487 auto live_sets = register_liveness->Get(18); 488 std::unordered_set<uint32_t> live_in{ 489 11, // %11 = OpVariable %10 Input 490 12, // %12 = OpLoad %7 %11 491 24, // %24 = OpVariable %23 Input 492 28, // %28 = OpVariable %10 Input 493 55, // %55 = OpVariable %54 Input 494 84, // %84 = OpVariable %8 Function 495 124, // %124 = OpVariable %63 Input 496 176, // %176 = OpVariable %175 Output 497 184, // %184 = OpPhi %13 %16 %5 %34 %18 498 191, // %191 = OpPhi %7 %12 %5 %31 %18 499 }; 500 CompareSets(live_sets->live_in_, live_in); 501 502 std::unordered_set<uint32_t> live_out{ 503 11, // %11 = OpVariable %10 Input 504 12, // %12 = OpLoad %7 %11 505 24, // %24 = OpVariable %23 Input 506 28, // %28 = OpVariable %10 Input 507 31, // %31 = OpFAdd %7 %191 %29 508 34, // %34 = OpIAdd %13 %184 %33 509 55, // %55 = OpVariable %54 Input 510 84, // %84 = OpVariable %8 Function 511 124, // %124 = OpVariable %63 Input 512 176, // %176 = OpVariable %175 Output 513 }; 514 CompareSets(live_sets->live_out_, live_out); 515 516 EXPECT_EQ(live_sets->used_registers_, 12u); 517 } 518 { 519 SCOPED_TRACE("Block 19"); 520 auto live_sets = register_liveness->Get(19); 521 std::unordered_set<uint32_t> live_inout{ 522 11, // %11 = OpVariable %10 Input 523 12, // %12 = OpLoad %7 %11 524 25, // %25 = OpLoad %13 %24 525 55, // %55 = OpVariable %54 Input 526 84, // %84 = OpVariable %8 Function 527 124, // %124 = OpVariable %63 Input 528 176, // %176 = OpVariable %175 Output 529 191, // %191 = OpPhi %7 %12 %5 %31 %18 530 }; 531 CompareSets(live_sets->live_in_, live_inout); 532 CompareSets(live_sets->live_out_, live_inout); 533 534 EXPECT_EQ(live_sets->used_registers_, 8u); 535 } 536 { 537 SCOPED_TRACE("Block 39"); 538 auto live_sets = register_liveness->Get(39); 539 std::unordered_set<uint32_t> live_inout{ 540 11, // %11 = OpVariable %10 Input 541 12, // %12 = OpLoad %7 %11 542 25, // %25 = OpLoad %13 %24 543 55, // %55 = OpVariable %54 Input 544 84, // %84 = OpVariable %8 Function 545 124, // %124 = OpVariable %63 Input 546 176, // %176 = OpVariable %175 Output 547 185, // %185 = OpPhi %13 %16 %19 %75 %51 548 188, // %188 = OpPhi %6 %37 %19 %73 %51 549 191, // %191 = OpPhi %7 %12 %5 %31 %18 550 }; 551 CompareSets(live_sets->live_in_, live_inout); 552 CompareSets(live_sets->live_out_, live_inout); 553 554 EXPECT_EQ(live_sets->used_registers_, 11u); 555 } 556 { 557 SCOPED_TRACE("Block 40"); 558 auto live_sets = register_liveness->Get(40); 559 std::unordered_set<uint32_t> live_inout{ 560 11, // %11 = OpVariable %10 Input 561 12, // %12 = OpLoad %7 %11 562 25, // %25 = OpLoad %13 %24 563 55, // %55 = OpVariable %54 Input 564 84, // %84 = OpVariable %8 Function 565 124, // %124 = OpVariable %63 Input 566 176, // %176 = OpVariable %175 Output 567 185, // %185 = OpPhi %13 %16 %19 %75 %51 568 188, // %188 = OpPhi %6 %37 %19 %73 %51 569 191, // %191 = OpPhi %7 %12 %5 %31 %18 570 }; 571 CompareSets(live_sets->live_in_, live_inout); 572 CompareSets(live_sets->live_out_, live_inout); 573 574 EXPECT_EQ(live_sets->used_registers_, 11u); 575 } 576 { 577 SCOPED_TRACE("Block 50"); 578 auto live_sets = register_liveness->Get(50); 579 std::unordered_set<uint32_t> live_in{ 580 11, // %11 = OpVariable %10 Input 581 12, // %12 = OpLoad %7 %11 582 25, // %25 = OpLoad %13 %24 583 55, // %55 = OpVariable %54 Input 584 84, // %84 = OpVariable %8 Function 585 124, // %124 = OpVariable %63 Input 586 176, // %176 = OpVariable %175 Output 587 185, // %185 = OpPhi %13 %16 %19 %75 %51 588 188, // %188 = OpPhi %6 %37 %19 %73 %51 589 191, // %191 = OpPhi %7 %12 %5 %31 %18 590 }; 591 CompareSets(live_sets->live_in_, live_in); 592 593 std::unordered_set<uint32_t> live_out{ 594 11, // %11 = OpVariable %10 Input 595 12, // %12 = OpLoad %7 %11 596 25, // %25 = OpLoad %13 %24 597 55, // %55 = OpVariable %54 Input 598 60, // %60 = OpConvertUToF %6 %59 599 84, // %84 = OpVariable %8 Function 600 124, // %124 = OpVariable %63 Input 601 176, // %176 = OpVariable %175 Output 602 185, // %185 = OpPhi %13 %16 %19 %75 %51 603 188, // %188 = OpPhi %6 %37 %19 %73 %51 604 191, // %191 = OpPhi %7 %12 %5 %31 %18 605 }; 606 CompareSets(live_sets->live_out_, live_out); 607 608 EXPECT_EQ(live_sets->used_registers_, 12u); 609 } 610 { 611 SCOPED_TRACE("Block 61"); 612 auto live_sets = register_liveness->Get(61); 613 std::unordered_set<uint32_t> live_in{ 614 11, // %11 = OpVariable %10 Input 615 12, // %12 = OpLoad %7 %11 616 25, // %25 = OpLoad %13 %24 617 55, // %55 = OpVariable %54 Input 618 84, // %84 = OpVariable %8 Function 619 124, // %124 = OpVariable %63 Input 620 176, // %176 = OpVariable %175 Output 621 185, // %185 = OpPhi %13 %16 %19 %75 %51 622 188, // %188 = OpPhi %6 %37 %19 %73 %51 623 191, // %191 = OpPhi %7 %12 %5 %31 %18 624 }; 625 CompareSets(live_sets->live_in_, live_in); 626 627 std::unordered_set<uint32_t> live_out{ 628 11, // %11 = OpVariable %10 Input 629 12, // %12 = OpLoad %7 %11 630 25, // %25 = OpLoad %13 %24 631 55, // %55 = OpVariable %54 Input 632 65, // %65 = OpLoad %6 %64 633 84, // %84 = OpVariable %8 Function 634 124, // %124 = OpVariable %63 Input 635 176, // %176 = OpVariable %175 Output 636 185, // %185 = OpPhi %13 %16 %19 %75 %51 637 188, // %188 = OpPhi %6 %37 %19 %73 %51 638 191, // %191 = OpPhi %7 %12 %5 %31 %18 639 }; 640 CompareSets(live_sets->live_out_, live_out); 641 642 EXPECT_EQ(live_sets->used_registers_, 12u); 643 } 644 { 645 SCOPED_TRACE("Block 51"); 646 auto live_sets = register_liveness->Get(51); 647 std::unordered_set<uint32_t> live_in{ 648 11, // %11 = OpVariable %10 Input 649 12, // %12 = OpLoad %7 %11 650 25, // %25 = OpLoad %13 %24 651 55, // %55 = OpVariable %54 Input 652 84, // %84 = OpVariable %8 Function 653 124, // %124 = OpVariable %63 Input 654 176, // %176 = OpVariable %175 Output 655 185, // %185 = OpPhi %13 %16 %19 %75 %51 656 188, // %188 = OpPhi %6 %37 %19 %73 %51 657 191, // %191 = OpPhi %7 %12 %5 %31 %18 658 210, // %210 = OpPhi %6 %60 %50 %65 %61 659 }; 660 CompareSets(live_sets->live_in_, live_in); 661 662 std::unordered_set<uint32_t> live_out{ 663 11, // %11 = OpVariable %10 Input 664 12, // %12 = OpLoad %7 %11 665 25, // %25 = OpLoad %13 %24 666 55, // %55 = OpVariable %54 Input 667 73, // %73 = OpFAdd %6 %188 %71 668 75, // %75 = OpIAdd %13 %185 %33 669 84, // %84 = OpVariable %8 Function 670 124, // %124 = OpVariable %63 Input 671 176, // %176 = OpVariable %175 Output 672 191, // %191 = OpPhi %7 %12 %5 %31 %18 673 }; 674 CompareSets(live_sets->live_out_, live_out); 675 676 EXPECT_EQ(live_sets->used_registers_, 13u); 677 } 678 { 679 SCOPED_TRACE("Block 41"); 680 auto live_sets = register_liveness->Get(41); 681 std::unordered_set<uint32_t> live_inout{ 682 12, // %12 = OpLoad %7 %11 683 25, // %25 = OpLoad %13 %24 684 55, // %55 = OpVariable %54 Input 685 84, // %84 = OpVariable %8 Function 686 124, // %124 = OpVariable %63 Input 687 176, // %176 = OpVariable %175 Output 688 188, // %188 = OpPhi %6 %37 %19 %73 %51 689 191, // %191 = OpPhi %7 %12 %5 %31 %18 690 }; 691 CompareSets(live_sets->live_in_, live_inout); 692 CompareSets(live_sets->live_out_, live_inout); 693 694 EXPECT_EQ(live_sets->used_registers_, 8u); 695 } 696 { 697 SCOPED_TRACE("Block 77"); 698 auto live_sets = register_liveness->Get(77); 699 std::unordered_set<uint32_t> live_inout{ 700 12, // %12 = OpLoad %7 %11 701 25, // %25 = OpLoad %13 %24 702 55, // %55 = OpVariable %54 Input 703 84, // %84 = OpVariable %8 Function 704 124, // %124 = OpVariable %63 Input 705 176, // %176 = OpVariable %175 Output 706 186, // %186 = OpPhi %13 %16 %41 %94 %78 707 188, // %188 = OpPhi %6 %37 %19 %73 %51 708 191, // %191 = OpPhi %7 %12 %5 %31 %18 709 }; 710 CompareSets(live_sets->live_in_, live_inout); 711 CompareSets(live_sets->live_out_, live_inout); 712 713 EXPECT_EQ(live_sets->used_registers_, 10u); 714 } 715 { 716 SCOPED_TRACE("Block 78"); 717 auto live_sets = register_liveness->Get(78); 718 std::unordered_set<uint32_t> live_in{ 719 12, // %12 = OpLoad %7 %11 720 25, // %25 = OpLoad %13 %24 721 55, // %55 = OpVariable %54 Input 722 84, // %84 = OpVariable %8 Function 723 124, // %124 = OpVariable %63 Input 724 176, // %176 = OpVariable %175 Output 725 186, // %186 = OpPhi %13 %16 %41 %94 %78 726 188, // %188 = OpPhi %6 %37 %19 %73 %51 727 191, // %191 = OpPhi %7 %12 %5 %31 %18 728 }; 729 CompareSets(live_sets->live_in_, live_in); 730 731 std::unordered_set<uint32_t> live_out{ 732 12, // %12 = OpLoad %7 %11 733 25, // %25 = OpLoad %13 %24 734 55, // %55 = OpVariable %54 Input 735 84, // %84 = OpVariable %8 Function 736 94, // %94 = OpIAdd %13 %186 %33 737 124, // %124 = OpVariable %63 Input 738 176, // %176 = OpVariable %175 Output 739 188, // %188 = OpPhi %6 %37 %19 %73 %51 740 191, // %191 = OpPhi %7 %12 %5 %31 %18 741 }; 742 CompareSets(live_sets->live_out_, live_out); 743 744 EXPECT_EQ(live_sets->used_registers_, 11u); 745 } 746 { 747 SCOPED_TRACE("Block 79"); 748 auto live_sets = register_liveness->Get(79); 749 std::unordered_set<uint32_t> live_in{ 750 12, // %12 = OpLoad %7 %11 751 25, // %25 = OpLoad %13 %24 752 84, // %84 = OpVariable %8 Function 753 124, // %124 = OpVariable %63 Input 754 176, // %176 = OpVariable %175 Output 755 188, // %188 = OpPhi %6 %37 %19 %73 %51 756 191, // %191 = OpPhi %7 %12 %5 %31 %18 757 }; 758 CompareSets(live_sets->live_in_, live_in); 759 760 std::unordered_set<uint32_t> live_out{ 761 25, // %25 = OpLoad %13 %24 762 84, // %84 = OpVariable %8 Function 763 100, // %100 = OpFAdd %7 %191 %98 764 106, // %106 = OpVectorShuffle %7 %195 %104 4 5 6 3 765 124, // %124 = OpVariable %63 Input 766 176, // %176 = OpVariable %175 Output 767 }; 768 CompareSets(live_sets->live_out_, live_out); 769 770 EXPECT_EQ(live_sets->used_registers_, 9u); 771 } 772 { 773 SCOPED_TRACE("Block 108"); 774 auto live_sets = register_liveness->Get(108); 775 std::unordered_set<uint32_t> live_in{ 776 25, // %25 = OpLoad %13 %24 777 84, // %84 = OpVariable %8 Function 778 100, // %100 = OpFAdd %7 %191 %98 779 124, // %124 = OpVariable %63 Input 780 176, // %176 = OpVariable %175 Output 781 196, // %196 = OpPhi %13 %16 %79 %143 %133 782 197, // %197 = OpPhi %7 %106 %79 %208 %133 783 }; 784 CompareSets(live_sets->live_in_, live_in); 785 786 std::unordered_set<uint32_t> live_out{ 787 84, // %84 = OpVariable %8 Function 788 100, // %100 = OpFAdd %7 %191 %98 789 124, // %124 = OpVariable %63 Input 790 176, // %176 = OpVariable %175 Output 791 196, // %196 = OpPhi %13 %16 %79 %143 %133 792 197, // %197 = OpPhi %7 %106 %79 %208 %133 793 }; 794 CompareSets(live_sets->live_out_, live_out); 795 796 EXPECT_EQ(live_sets->used_registers_, 8u); 797 } 798 { 799 SCOPED_TRACE("Block 109"); 800 auto live_sets = register_liveness->Get(109); 801 std::unordered_set<uint32_t> live_inout{ 802 25, // %25 = OpLoad %13 %24 803 84, // %84 = OpVariable %8 Function 804 100, // %100 = OpFAdd %7 %191 %98 805 124, // %124 = OpVariable %63 Input 806 176, // %176 = OpVariable %175 Output 807 196, // %196 = OpPhi %13 %16 %79 %143 %133 808 197, // %197 = OpPhi %7 %106 %79 %208 %133 809 }; 810 CompareSets(live_sets->live_in_, live_inout); 811 CompareSets(live_sets->live_out_, live_inout); 812 813 EXPECT_EQ(live_sets->used_registers_, 7u); 814 } 815 { 816 SCOPED_TRACE("Block 117"); 817 auto live_sets = register_liveness->Get(117); 818 std::unordered_set<uint32_t> live_inout{ 819 25, // %25 = OpLoad %13 %24 820 84, // %84 = OpVariable %8 Function 821 100, // %100 = OpFAdd %7 %191 %98 822 124, // %124 = OpVariable %63 Input 823 176, // %176 = OpVariable %175 Output 824 196, // %196 = OpPhi %13 %16 %79 %143 %133 825 204, // %204 = OpPhi %13 %16 %109 %129 %118 826 209, // %209 = OpPhi %7 %197 %109 %181 %118 827 }; 828 CompareSets(live_sets->live_in_, live_inout); 829 CompareSets(live_sets->live_out_, live_inout); 830 831 EXPECT_EQ(live_sets->used_registers_, 9u); 832 } 833 { 834 SCOPED_TRACE("Block 118"); 835 auto live_sets = register_liveness->Get(118); 836 std::unordered_set<uint32_t> live_in{ 837 25, // %25 = OpLoad %13 %24 838 84, // %84 = OpVariable %8 Function 839 100, // %100 = OpFAdd %7 %191 %98 840 124, // %124 = OpVariable %63 Input 841 176, // %176 = OpVariable %175 Output 842 196, // %196 = OpPhi %13 %16 %79 %143 %133 843 204, // %204 = OpPhi %13 %16 %109 %129 %118 844 209, // %209 = OpPhi %7 %197 %109 %181 %118 845 }; 846 CompareSets(live_sets->live_in_, live_in); 847 848 std::unordered_set<uint32_t> live_out{ 849 25, // %25 = OpLoad %13 %24 850 84, // %84 = OpVariable %8 Function 851 100, // %100 = OpFAdd %7 %191 %98 852 124, // %124 = OpVariable %63 Input 853 129, // %129 = OpIAdd %13 %204 %33 854 176, // %176 = OpVariable %175 Output 855 181, // %181 = OpCompositeInsert %7 %125 %209 3 856 196, // %196 = OpPhi %13 %16 %79 %143 %133 857 }; 858 CompareSets(live_sets->live_out_, live_out); 859 860 EXPECT_EQ(live_sets->used_registers_, 10u); 861 } 862 { 863 SCOPED_TRACE("Block 119"); 864 auto live_sets = register_liveness->Get(119); 865 std::unordered_set<uint32_t> live_inout{ 866 25, // %25 = OpLoad %13 %24 867 84, // %84 = OpVariable %8 Function 868 100, // %100 = OpFAdd %7 %191 %98 869 124, // %124 = OpVariable %63 Input 870 176, // %176 = OpVariable %175 Output 871 196, // %196 = OpPhi %13 %16 %79 %143 %133 872 209, // %209 = OpPhi %7 %197 %109 %181 %118 873 }; 874 CompareSets(live_sets->live_in_, live_inout); 875 CompareSets(live_sets->live_out_, live_inout); 876 877 EXPECT_EQ(live_sets->used_registers_, 7u); 878 } 879 { 880 SCOPED_TRACE("Block 131"); 881 auto live_sets = register_liveness->Get(131); 882 std::unordered_set<uint32_t> live_inout{ 883 25, // %25 = OpLoad %13 %24 884 84, // %84 = OpVariable %8 Function 885 100, // %100 = OpFAdd %7 %191 %98 886 124, // %124 = OpVariable %63 Input 887 176, // %176 = OpVariable %175 Output 888 196, // %196 = OpPhi %13 %16 %79 %143 %133 889 205, // %205 = OpPhi %13 %16 %119 %141 %132 890 208, // %208 = OpPhi %7 %209 %119 %183 %132 891 }; 892 CompareSets(live_sets->live_in_, live_inout); 893 CompareSets(live_sets->live_out_, live_inout); 894 895 EXPECT_EQ(live_sets->used_registers_, 9u); 896 } 897 { 898 SCOPED_TRACE("Block 132"); 899 auto live_sets = register_liveness->Get(132); 900 std::unordered_set<uint32_t> live_in{ 901 25, // %25 = OpLoad %13 %24 902 84, // %84 = OpVariable %8 Function 903 100, // %100 = OpFAdd %7 %191 %98 904 124, // %124 = OpVariable %63 Input 905 176, // %176 = OpVariable %175 Output 906 196, // %196 = OpPhi %13 %16 %79 %143 %133 907 205, // %205 = OpPhi %13 %16 %119 %141 %132 908 208, // %208 = OpPhi %7 %209 %119 %183 %132 909 }; 910 CompareSets(live_sets->live_in_, live_in); 911 912 std::unordered_set<uint32_t> live_out{ 913 25, // %25 = OpLoad %13 %24 914 84, // %84 = OpVariable %8 Function 915 100, // %100 = OpFAdd %7 %191 %98 916 124, // %124 = OpVariable %63 Input 917 141, // %141 = OpIAdd %13 %205 %33 918 176, // %176 = OpVariable %175 Output 919 183, // %183 = OpCompositeInsert %7 %138 %208 3 920 196, // %196 = OpPhi %13 %16 %79 %143 %133 921 }; 922 CompareSets(live_sets->live_out_, live_out); 923 924 EXPECT_EQ(live_sets->used_registers_, 10u); 925 } 926 { 927 SCOPED_TRACE("Block 133"); 928 auto live_sets = register_liveness->Get(133); 929 std::unordered_set<uint32_t> live_in{ 930 25, // %25 = OpLoad %13 %24 931 84, // %84 = OpVariable %8 Function 932 100, // %100 = OpFAdd %7 %191 %98 933 124, // %124 = OpVariable %63 Input 934 176, // %176 = OpVariable %175 Output 935 196, // %196 = OpPhi %13 %16 %79 %143 %133 936 208, // %208 = OpPhi %7 %209 %119 %183 %132 937 }; 938 CompareSets(live_sets->live_in_, live_in); 939 940 std::unordered_set<uint32_t> live_out{ 941 25, // %25 = OpLoad %13 %24 942 84, // %84 = OpVariable %8 Function 943 100, // %100 = OpFAdd %7 %191 %98 944 124, // %124 = OpVariable %63 Input 945 143, // %143 = OpIAdd %13 %196 %33 946 176, // %176 = OpVariable %175 Output 947 208, // %208 = OpPhi %7 %209 %119 %183 %132 948 }; 949 CompareSets(live_sets->live_out_, live_out); 950 951 EXPECT_EQ(live_sets->used_registers_, 8u); 952 } 953 { 954 SCOPED_TRACE("Block 110"); 955 auto live_sets = register_liveness->Get(110); 956 std::unordered_set<uint32_t> live_in{ 957 84, // %84 = OpVariable %8 Function 958 100, // %100 = OpFAdd %7 %191 %98 959 124, // %124 = OpVariable %63 Input 960 176, // %176 = OpVariable %175 Output 961 197, // %197 = OpPhi %7 %106 %79 %208 %133 962 }; 963 CompareSets(live_sets->live_in_, live_in); 964 965 std::unordered_set<uint32_t> live_out{ 966 84, // %84 = OpVariable %8 Function 967 124, // %124 = OpVariable %63 Input 968 150, // %150 = OpVectorShuffle %7 %100 %148 4 5 6 3 969 176, // %176 = OpVariable %175 Output 970 }; 971 CompareSets(live_sets->live_out_, live_out); 972 973 EXPECT_EQ(live_sets->used_registers_, 7u); 974 } 975 { 976 SCOPED_TRACE("Block 152"); 977 auto live_sets = register_liveness->Get(152); 978 std::unordered_set<uint32_t> live_inout{ 979 84, // %84 = OpVariable %8 Function 980 124, // %124 = OpVariable %63 Input 981 176, // %176 = OpVariable %175 Output 982 199, // %199 = OpPhi %13 %16 %110 %174 %163 983 200, // %200 = OpPhi %7 %150 %110 %203 %163 984 }; 985 CompareSets(live_sets->live_in_, live_inout); 986 CompareSets(live_sets->live_out_, live_inout); 987 988 EXPECT_EQ(live_sets->used_registers_, 6u); 989 } 990 { 991 SCOPED_TRACE("Block 153"); 992 auto live_sets = register_liveness->Get(153); 993 std::unordered_set<uint32_t> live_inout{ 994 84, // %84 = OpVariable %8 Function 995 124, // %124 = OpVariable %63 Input 996 176, // %176 = OpVariable %175 Output 997 199, // %199 = OpPhi %13 %16 %110 %174 %163 998 200, // %200 = OpPhi %7 %150 %110 %203 %163 999 }; 1000 CompareSets(live_sets->live_in_, live_inout); 1001 CompareSets(live_sets->live_out_, live_inout); 1002 1003 EXPECT_EQ(live_sets->used_registers_, 5u); 1004 } 1005 { 1006 SCOPED_TRACE("Block 161"); 1007 auto live_sets = register_liveness->Get(161); 1008 std::unordered_set<uint32_t> live_inout{ 1009 84, // %84 = OpVariable %8 Function 1010 124, // %124 = OpVariable %63 Input 1011 176, // %176 = OpVariable %175 Output 1012 199, // %199 = OpPhi %13 %16 %110 %174 %163 1013 201, // %201 = OpPhi %13 %16 %153 %172 %162 1014 203, // %203 = OpPhi %7 %200 %153 %170 %162 1015 }; 1016 CompareSets(live_sets->live_in_, live_inout); 1017 CompareSets(live_sets->live_out_, live_inout); 1018 1019 EXPECT_EQ(live_sets->used_registers_, 7u); 1020 } 1021 { 1022 SCOPED_TRACE("Block 162"); 1023 auto live_sets = register_liveness->Get(162); 1024 std::unordered_set<uint32_t> live_in{ 1025 84, // %84 = OpVariable %8 Function 1026 124, // %124 = OpVariable %63 Input 1027 176, // %176 = OpVariable %175 Output 1028 199, // %199 = OpPhi %13 %16 %110 %174 %163 1029 201, // %201 = OpPhi %13 %16 %153 %172 %162 1030 203, // %203 = OpPhi %7 %200 %153 %170 %162 1031 }; 1032 CompareSets(live_sets->live_in_, live_in); 1033 1034 std::unordered_set<uint32_t> live_out{ 1035 84, // %84 = OpVariable %8 Function 1036 124, // %124 = OpVariable %63 Input 1037 170, // %170 = OpVectorTimesScalar %7 %203 %168 1038 172, // %172 = OpIAdd %13 %201 %33 1039 176, // %176 = OpVariable %175 Output 1040 199, // %199 = OpPhi %13 %16 %110 %174 %163 1041 }; 1042 CompareSets(live_sets->live_out_, live_out); 1043 1044 EXPECT_EQ(live_sets->used_registers_, 8u); 1045 } 1046 { 1047 SCOPED_TRACE("Block 163"); 1048 auto live_sets = register_liveness->Get(163); 1049 std::unordered_set<uint32_t> live_in{ 1050 84, // %84 = OpVariable %8 Function 1051 124, // %124 = OpVariable %63 Input 1052 176, // %176 = OpVariable %175 Output 1053 199, // %199 = OpPhi %13 %16 %110 %174 %163 1054 203, // %203 = OpPhi %7 %200 %153 %170 %162 1055 }; 1056 CompareSets(live_sets->live_in_, live_in); 1057 1058 std::unordered_set<uint32_t> live_out{ 1059 84, // %84 = OpVariable %8 Function 1060 124, // %124 = OpVariable %63 Input 1061 174, // %174 = OpIAdd %13 %199 %45 1062 176, // %176 = OpVariable %175 Output 1063 203, // %203 = OpPhi %7 %200 %153 %170 %162 1064 }; 1065 CompareSets(live_sets->live_out_, live_out); 1066 1067 EXPECT_EQ(live_sets->used_registers_, 6u); 1068 } 1069 { 1070 SCOPED_TRACE("Block 154"); 1071 auto live_sets = register_liveness->Get(154); 1072 std::unordered_set<uint32_t> live_in{ 1073 84, // %84 = OpVariable %8 Function 1074 176, // %176 = OpVariable %175 Output 1075 200, // %200 = OpPhi %7 %150 %110 %203 %163 1076 }; 1077 CompareSets(live_sets->live_in_, live_in); 1078 1079 std::unordered_set<uint32_t> live_out{}; 1080 CompareSets(live_sets->live_out_, live_out); 1081 1082 EXPECT_EQ(live_sets->used_registers_, 4u); 1083 } 1084 1085 { 1086 SCOPED_TRACE("Compute loop pressure"); 1087 RegisterLiveness::RegionRegisterLiveness loop_reg_pressure; 1088 register_liveness->ComputeLoopRegisterPressure(*ld[39], &loop_reg_pressure); 1089 // Generate(*context->cfg()->block(39), &loop_reg_pressure); 1090 std::unordered_set<uint32_t> live_in{ 1091 11, // %11 = OpVariable %10 Input 1092 12, // %12 = OpLoad %7 %11 1093 25, // %25 = OpLoad %13 %24 1094 55, // %55 = OpVariable %54 Input 1095 84, // %84 = OpVariable %8 Function 1096 124, // %124 = OpVariable %63 Input 1097 176, // %176 = OpVariable %175 Output 1098 185, // %185 = OpPhi %13 %16 %19 %75 %51 1099 188, // %188 = OpPhi %6 %37 %19 %73 %51 1100 191, // %191 = OpPhi %7 %12 %5 %31 %18 1101 }; 1102 CompareSets(loop_reg_pressure.live_in_, live_in); 1103 1104 std::unordered_set<uint32_t> live_out{ 1105 12, // %12 = OpLoad %7 %11 1106 25, // %25 = OpLoad %13 %24 1107 55, // %55 = OpVariable %54 Input 1108 84, // %84 = OpVariable %8 Function 1109 124, // %124 = OpVariable %63 Input 1110 176, // %176 = OpVariable %175 Output 1111 188, // %188 = OpPhi %6 %37 %19 %73 %51 1112 191, // %191 = OpPhi %7 %12 %5 %31 %18 1113 }; 1114 CompareSets(loop_reg_pressure.live_out_, live_out); 1115 1116 EXPECT_EQ(loop_reg_pressure.used_registers_, 13u); 1117 } 1118 1119 { 1120 SCOPED_TRACE("Loop Fusion simulation"); 1121 RegisterLiveness::RegionRegisterLiveness simulation_resut; 1122 register_liveness->SimulateFusion(*ld[17], *ld[39], &simulation_resut); 1123 1124 std::unordered_set<uint32_t> live_in{ 1125 11, // %11 = OpVariable %10 Input 1126 12, // %12 = OpLoad %7 %11 1127 24, // %24 = OpVariable %23 Input 1128 25, // %25 = OpLoad %13 %24 1129 28, // %28 = OpVariable %10 Input 1130 55, // %55 = OpVariable %54 Input 1131 84, // %84 = OpVariable %8 Function 1132 124, // %124 = OpVariable %63 Input 1133 176, // %176 = OpVariable %175 Output 1134 184, // %184 = OpPhi %13 %16 %5 %34 %18 1135 185, // %185 = OpPhi %13 %16 %19 %75 %51 1136 188, // %188 = OpPhi %6 %37 %19 %73 %51 1137 191, // %191 = OpPhi %7 %12 %5 %31 %18 1138 }; 1139 CompareSets(simulation_resut.live_in_, live_in); 1140 1141 std::unordered_set<uint32_t> live_out{ 1142 12, // %12 = OpLoad %7 %11 1143 25, // %25 = OpLoad %13 %24 1144 55, // %55 = OpVariable %54 Input 1145 84, // %84 = OpVariable %8 Function 1146 124, // %124 = OpVariable %63 Input 1147 176, // %176 = OpVariable %175 Output 1148 188, // %188 = OpPhi %6 %37 %19 %73 %51 1149 191, // %191 = OpPhi %7 %12 %5 %31 %18 1150 }; 1151 CompareSets(simulation_resut.live_out_, live_out); 1152 1153 EXPECT_EQ(simulation_resut.used_registers_, 17u); 1154 } 1155 } 1156 1157 TEST_F(PassClassTest, FissionSimulation) { 1158 const std::string source = R"( 1159 OpCapability Shader 1160 %1 = OpExtInstImport "GLSL.std.450" 1161 OpMemoryModel Logical GLSL450 1162 OpEntryPoint Fragment %2 "main" 1163 OpExecutionMode %2 OriginUpperLeft 1164 OpSource GLSL 430 1165 OpName %2 "main" 1166 OpName %3 "i" 1167 OpName %4 "A" 1168 OpName %5 "B" 1169 %6 = OpTypeVoid 1170 %7 = OpTypeFunction %6 1171 %8 = OpTypeInt 32 1 1172 %9 = OpTypePointer Function %8 1173 %10 = OpConstant %8 0 1174 %11 = OpConstant %8 10 1175 %12 = OpTypeBool 1176 %13 = OpTypeFloat 32 1177 %14 = OpTypeInt 32 0 1178 %15 = OpConstant %14 10 1179 %16 = OpTypeArray %13 %15 1180 %17 = OpTypePointer Function %16 1181 %18 = OpTypePointer Function %13 1182 %19 = OpConstant %8 1 1183 %2 = OpFunction %6 None %7 1184 %20 = OpLabel 1185 %3 = OpVariable %9 Function 1186 %4 = OpVariable %17 Function 1187 %5 = OpVariable %17 Function 1188 OpBranch %21 1189 %21 = OpLabel 1190 %22 = OpPhi %8 %10 %20 %23 %24 1191 OpLoopMerge %25 %24 None 1192 OpBranch %26 1193 %26 = OpLabel 1194 %27 = OpSLessThan %12 %22 %11 1195 OpBranchConditional %27 %28 %25 1196 %28 = OpLabel 1197 %29 = OpAccessChain %18 %5 %22 1198 %30 = OpLoad %13 %29 1199 %31 = OpAccessChain %18 %4 %22 1200 OpStore %31 %30 1201 %32 = OpAccessChain %18 %4 %22 1202 %33 = OpLoad %13 %32 1203 %34 = OpAccessChain %18 %5 %22 1204 OpStore %34 %33 1205 OpBranch %24 1206 %24 = OpLabel 1207 %23 = OpIAdd %8 %22 %19 1208 OpBranch %21 1209 %25 = OpLabel 1210 OpStore %3 %22 1211 OpReturn 1212 OpFunctionEnd 1213 )"; 1214 std::unique_ptr<IRContext> context = 1215 BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, source, 1216 SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); 1217 Module* module = context->module(); 1218 EXPECT_NE(nullptr, module) << "Assembling failed for shader:\n" 1219 << source << std::endl; 1220 Function* f = &*module->begin(); 1221 LivenessAnalysis* liveness_analysis = context->GetLivenessAnalysis(); 1222 const RegisterLiveness* register_liveness = liveness_analysis->Get(f); 1223 LoopDescriptor& ld = *context->GetLoopDescriptor(f); 1224 analysis::DefUseManager& def_use_mgr = *context->get_def_use_mgr(); 1225 1226 { 1227 RegisterLiveness::RegionRegisterLiveness l1_sim_resut; 1228 RegisterLiveness::RegionRegisterLiveness l2_sim_resut; 1229 std::unordered_set<Instruction*> moved_instructions{ 1230 def_use_mgr.GetDef(29), def_use_mgr.GetDef(30), def_use_mgr.GetDef(31), 1231 def_use_mgr.GetDef(31)->NextNode()}; 1232 std::unordered_set<Instruction*> copied_instructions{ 1233 def_use_mgr.GetDef(22), def_use_mgr.GetDef(27), 1234 def_use_mgr.GetDef(27)->NextNode(), def_use_mgr.GetDef(23)}; 1235 1236 register_liveness->SimulateFission(*ld[21], moved_instructions, 1237 copied_instructions, &l1_sim_resut, 1238 &l2_sim_resut); 1239 { 1240 SCOPED_TRACE("L1 simulation"); 1241 std::unordered_set<uint32_t> live_in{ 1242 3, // %3 = OpVariable %9 Function 1243 4, // %4 = OpVariable %17 Function 1244 5, // %5 = OpVariable %17 Function 1245 22, // %22 = OpPhi %8 %10 %20 %23 %24 1246 }; 1247 CompareSets(l1_sim_resut.live_in_, live_in); 1248 1249 std::unordered_set<uint32_t> live_out{ 1250 3, // %3 = OpVariable %9 Function 1251 4, // %4 = OpVariable %17 Function 1252 5, // %5 = OpVariable %17 Function 1253 22, // %22 = OpPhi %8 %10 %20 %23 %24 1254 }; 1255 CompareSets(l1_sim_resut.live_out_, live_out); 1256 1257 EXPECT_EQ(l1_sim_resut.used_registers_, 6u); 1258 } 1259 { 1260 SCOPED_TRACE("L2 simulation"); 1261 std::unordered_set<uint32_t> live_in{ 1262 3, // %3 = OpVariable %9 Function 1263 4, // %4 = OpVariable %17 Function 1264 5, // %5 = OpVariable %17 Function 1265 22, // %22 = OpPhi %8 %10 %20 %23 %24 1266 }; 1267 CompareSets(l2_sim_resut.live_in_, live_in); 1268 1269 std::unordered_set<uint32_t> live_out{ 1270 3, // %3 = OpVariable %9 Function 1271 22, // %22 = OpPhi %8 %10 %20 %23 %24 1272 }; 1273 CompareSets(l2_sim_resut.live_out_, live_out); 1274 1275 EXPECT_EQ(l2_sim_resut.used_registers_, 6u); 1276 } 1277 } 1278 } 1279 1280 } // namespace 1281 } // namespace opt 1282 } // namespace spvtools 1283