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