1 /* 2 * Copyright (C) 2014 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 #include "arch/x86/instruction_set_features_x86.h" 18 #include "base/arena_allocator.h" 19 #include "builder.h" 20 #include "code_generator.h" 21 #include "code_generator_x86.h" 22 #include "dex_file.h" 23 #include "dex_instruction.h" 24 #include "driver/compiler_options.h" 25 #include "nodes.h" 26 #include "optimizing_unit_test.h" 27 #include "prepare_for_register_allocation.h" 28 #include "ssa_liveness_analysis.h" 29 30 namespace art { 31 32 class LivenessTest : public CommonCompilerTest {}; 33 34 static void DumpBitVector(BitVector* vector, 35 std::ostream& buffer, 36 size_t count, 37 const char* prefix) { 38 buffer << prefix; 39 buffer << '('; 40 for (size_t i = 0; i < count; ++i) { 41 buffer << vector->IsBitSet(i); 42 } 43 buffer << ")\n"; 44 } 45 46 static void TestCode(const uint16_t* data, const char* expected) { 47 ArenaPool pool; 48 ArenaAllocator allocator(&pool); 49 HGraph* graph = CreateCFG(&allocator, data); 50 // `Inline` conditions into ifs. 51 PrepareForRegisterAllocation(graph).Run(); 52 std::unique_ptr<const X86InstructionSetFeatures> features_x86( 53 X86InstructionSetFeatures::FromCppDefines()); 54 x86::CodeGeneratorX86 codegen(graph, *features_x86.get(), CompilerOptions()); 55 SsaLivenessAnalysis liveness(graph, &codegen); 56 liveness.Analyze(); 57 58 std::ostringstream buffer; 59 for (HBasicBlock* block : graph->GetBlocks()) { 60 buffer << "Block " << block->GetBlockId() << std::endl; 61 size_t ssa_values = liveness.GetNumberOfSsaValues(); 62 BitVector* live_in = liveness.GetLiveInSet(*block); 63 DumpBitVector(live_in, buffer, ssa_values, " live in: "); 64 BitVector* live_out = liveness.GetLiveOutSet(*block); 65 DumpBitVector(live_out, buffer, ssa_values, " live out: "); 66 BitVector* kill = liveness.GetKillSet(*block); 67 DumpBitVector(kill, buffer, ssa_values, " kill: "); 68 } 69 ASSERT_STREQ(expected, buffer.str().c_str()); 70 } 71 72 TEST_F(LivenessTest, CFG1) { 73 const char* expected = 74 "Block 0\n" 75 " live in: (0)\n" 76 " live out: (0)\n" 77 " kill: (1)\n" 78 "Block 1\n" 79 " live in: (0)\n" 80 " live out: (0)\n" 81 " kill: (0)\n" 82 "Block 2\n" 83 " live in: (0)\n" 84 " live out: (0)\n" 85 " kill: (0)\n"; 86 87 // Constant is not used. 88 const uint16_t data[] = ONE_REGISTER_CODE_ITEM( 89 Instruction::CONST_4 | 0 | 0, 90 Instruction::RETURN_VOID); 91 92 TestCode(data, expected); 93 } 94 95 TEST_F(LivenessTest, CFG2) { 96 const char* expected = 97 "Block 0\n" 98 " live in: (0)\n" 99 " live out: (1)\n" 100 " kill: (1)\n" 101 "Block 1\n" 102 " live in: (1)\n" 103 " live out: (0)\n" 104 " kill: (0)\n" 105 "Block 2\n" 106 " live in: (0)\n" 107 " live out: (0)\n" 108 " kill: (0)\n"; 109 110 const uint16_t data[] = ONE_REGISTER_CODE_ITEM( 111 Instruction::CONST_4 | 0 | 0, 112 Instruction::RETURN); 113 114 TestCode(data, expected); 115 } 116 117 TEST_F(LivenessTest, CFG3) { 118 const char* expected = 119 "Block 0\n" // entry block 120 " live in: (000)\n" 121 " live out: (110)\n" 122 " kill: (110)\n" 123 "Block 1\n" // block with add 124 " live in: (110)\n" 125 " live out: (001)\n" 126 " kill: (001)\n" 127 "Block 2\n" // block with return 128 " live in: (001)\n" 129 " live out: (000)\n" 130 " kill: (000)\n" 131 "Block 3\n" // exit block 132 " live in: (000)\n" 133 " live out: (000)\n" 134 " kill: (000)\n"; 135 136 const uint16_t data[] = TWO_REGISTERS_CODE_ITEM( 137 Instruction::CONST_4 | 3 << 12 | 0, 138 Instruction::CONST_4 | 4 << 12 | 1 << 8, 139 Instruction::ADD_INT_2ADDR | 1 << 12, 140 Instruction::GOTO | 0x100, 141 Instruction::RETURN); 142 143 TestCode(data, expected); 144 } 145 146 TEST_F(LivenessTest, CFG4) { 147 // var a; 148 // if (0 == 0) { 149 // a = 5; 150 // } else { 151 // a = 4; 152 // } 153 // return a; 154 // 155 // Bitsets are made of: 156 // (constant0, constant5, constant4, phi) 157 const char* expected = 158 "Block 0\n" // entry block 159 " live in: (0000)\n" 160 " live out: (1110)\n" 161 " kill: (1110)\n" 162 "Block 1\n" // block with if 163 " live in: (1110)\n" 164 " live out: (0110)\n" 165 " kill: (0000)\n" 166 "Block 2\n" // else block 167 " live in: (0010)\n" 168 " live out: (0000)\n" 169 " kill: (0000)\n" 170 "Block 3\n" // then block 171 " live in: (0100)\n" 172 " live out: (0000)\n" 173 " kill: (0000)\n" 174 "Block 4\n" // return block 175 " live in: (0000)\n" 176 " live out: (0000)\n" 177 " kill: (0001)\n" 178 "Block 5\n" // exit block 179 " live in: (0000)\n" 180 " live out: (0000)\n" 181 " kill: (0000)\n"; 182 183 const uint16_t data[] = ONE_REGISTER_CODE_ITEM( 184 Instruction::CONST_4 | 0 | 0, 185 Instruction::IF_EQ, 4, 186 Instruction::CONST_4 | 4 << 12 | 0, 187 Instruction::GOTO | 0x200, 188 Instruction::CONST_4 | 5 << 12 | 0, 189 Instruction::RETURN | 0 << 8); 190 191 TestCode(data, expected); 192 } 193 194 TEST_F(LivenessTest, CFG5) { 195 // var a = 0; 196 // if (0 == 0) { 197 // } else { 198 // a = 4; 199 // } 200 // return a; 201 // 202 // Bitsets are made of: 203 // (constant0, constant4, phi) 204 const char* expected = 205 "Block 0\n" // entry block 206 " live in: (000)\n" 207 " live out: (110)\n" 208 " kill: (110)\n" 209 "Block 1\n" // block with if 210 " live in: (110)\n" 211 " live out: (110)\n" 212 " kill: (000)\n" 213 "Block 2\n" // else block 214 " live in: (010)\n" 215 " live out: (000)\n" 216 " kill: (000)\n" 217 "Block 3\n" // return block 218 " live in: (000)\n" 219 " live out: (000)\n" 220 " kill: (001)\n" 221 "Block 4\n" // exit block 222 " live in: (000)\n" 223 " live out: (000)\n" 224 " kill: (000)\n" 225 "Block 5\n" // block to avoid critical edge. Predecessor is 1, successor is 3. 226 " live in: (100)\n" 227 " live out: (000)\n" 228 " kill: (000)\n"; 229 230 const uint16_t data[] = ONE_REGISTER_CODE_ITEM( 231 Instruction::CONST_4 | 0 | 0, 232 Instruction::IF_EQ, 3, 233 Instruction::CONST_4 | 4 << 12 | 0, 234 Instruction::RETURN | 0 << 8); 235 236 TestCode(data, expected); 237 } 238 239 TEST_F(LivenessTest, Loop1) { 240 // Simple loop with one preheader and one back edge. 241 // var a = 0; 242 // while (a == a) { 243 // a = 4; 244 // } 245 // return; 246 // Bitsets are made of: 247 // (constant0, constant4, phi) 248 const char* expected = 249 "Block 0\n" // entry block 250 " live in: (000)\n" 251 " live out: (110)\n" 252 " kill: (110)\n" 253 "Block 1\n" // pre header 254 " live in: (110)\n" 255 " live out: (010)\n" 256 " kill: (000)\n" 257 "Block 2\n" // loop header 258 " live in: (010)\n" 259 " live out: (010)\n" 260 " kill: (001)\n" 261 "Block 3\n" // back edge 262 " live in: (010)\n" 263 " live out: (010)\n" 264 " kill: (000)\n" 265 "Block 4\n" // return block 266 " live in: (000)\n" 267 " live out: (000)\n" 268 " kill: (000)\n" 269 "Block 5\n" // exit block 270 " live in: (000)\n" 271 " live out: (000)\n" 272 " kill: (000)\n"; 273 274 275 const uint16_t data[] = ONE_REGISTER_CODE_ITEM( 276 Instruction::CONST_4 | 0 | 0, 277 Instruction::IF_EQ, 4, 278 Instruction::CONST_4 | 4 << 12 | 0, 279 Instruction::GOTO | 0xFD00, 280 Instruction::RETURN_VOID); 281 282 TestCode(data, expected); 283 } 284 285 TEST_F(LivenessTest, Loop3) { 286 // Test that the returned value stays live in a preceding loop. 287 // var a = 0; 288 // while (a == a) { 289 // a = 4; 290 // } 291 // return 5; 292 // Bitsets are made of: 293 // (constant0, constant5, constant4, phi) 294 const char* expected = 295 "Block 0\n" 296 " live in: (0000)\n" 297 " live out: (1110)\n" 298 " kill: (1110)\n" 299 "Block 1\n" 300 " live in: (1110)\n" 301 " live out: (0110)\n" 302 " kill: (0000)\n" 303 "Block 2\n" // loop header 304 " live in: (0110)\n" 305 " live out: (0110)\n" 306 " kill: (0001)\n" 307 "Block 3\n" // back edge 308 " live in: (0110)\n" 309 " live out: (0110)\n" 310 " kill: (0000)\n" 311 "Block 4\n" // return block 312 " live in: (0100)\n" 313 " live out: (0000)\n" 314 " kill: (0000)\n" 315 "Block 5\n" // exit block 316 " live in: (0000)\n" 317 " live out: (0000)\n" 318 " kill: (0000)\n"; 319 320 const uint16_t data[] = TWO_REGISTERS_CODE_ITEM( 321 Instruction::CONST_4 | 0 | 0, 322 Instruction::IF_EQ, 4, 323 Instruction::CONST_4 | 4 << 12 | 0, 324 Instruction::GOTO | 0xFD00, 325 Instruction::CONST_4 | 5 << 12 | 1 << 8, 326 Instruction::RETURN | 1 << 8); 327 328 TestCode(data, expected); 329 } 330 331 332 TEST_F(LivenessTest, Loop4) { 333 // Make sure we support a preheader of a loop not being the first predecessor 334 // in the predecessor list of the header. 335 // var a = 0; 336 // while (a == a) { 337 // a = 4; 338 // } 339 // return a; 340 // Bitsets are made of: 341 // (constant0, constant4, phi) 342 const char* expected = 343 "Block 0\n" 344 " live in: (000)\n" 345 " live out: (110)\n" 346 " kill: (110)\n" 347 "Block 1\n" 348 " live in: (110)\n" 349 " live out: (110)\n" 350 " kill: (000)\n" 351 "Block 2\n" // loop header 352 " live in: (010)\n" 353 " live out: (011)\n" 354 " kill: (001)\n" 355 "Block 3\n" // back edge 356 " live in: (010)\n" 357 " live out: (010)\n" 358 " kill: (000)\n" 359 "Block 4\n" // pre loop header 360 " live in: (110)\n" 361 " live out: (010)\n" 362 " kill: (000)\n" 363 "Block 5\n" // return block 364 " live in: (001)\n" 365 " live out: (000)\n" 366 " kill: (000)\n" 367 "Block 6\n" // exit block 368 " live in: (000)\n" 369 " live out: (000)\n" 370 " kill: (000)\n"; 371 372 const uint16_t data[] = ONE_REGISTER_CODE_ITEM( 373 Instruction::CONST_4 | 0 | 0, 374 Instruction::GOTO | 0x500, 375 Instruction::IF_EQ, 5, 376 Instruction::CONST_4 | 4 << 12 | 0, 377 Instruction::GOTO | 0xFD00, 378 Instruction::GOTO | 0xFC00, 379 Instruction::RETURN | 0 << 8); 380 381 TestCode(data, expected); 382 } 383 384 TEST_F(LivenessTest, Loop5) { 385 // Make sure we create a preheader of a loop when a header originally has two 386 // incoming blocks and one back edge. 387 // Bitsets are made of: 388 // (constant0, constant5, constant4, phi in block 8) 389 const char* expected = 390 "Block 0\n" 391 " live in: (0000)\n" 392 " live out: (1110)\n" 393 " kill: (1110)\n" 394 "Block 1\n" 395 " live in: (1110)\n" 396 " live out: (0110)\n" 397 " kill: (0000)\n" 398 "Block 2\n" 399 " live in: (0010)\n" 400 " live out: (0000)\n" 401 " kill: (0000)\n" 402 "Block 3\n" 403 " live in: (0100)\n" 404 " live out: (0000)\n" 405 " kill: (0000)\n" 406 "Block 4\n" // loop header 407 " live in: (0001)\n" 408 " live out: (0001)\n" 409 " kill: (0000)\n" 410 "Block 5\n" // back edge 411 " live in: (0001)\n" 412 " live out: (0001)\n" 413 " kill: (0000)\n" 414 "Block 6\n" // return block 415 " live in: (0001)\n" 416 " live out: (0000)\n" 417 " kill: (0000)\n" 418 "Block 7\n" // exit block 419 " live in: (0000)\n" 420 " live out: (0000)\n" 421 " kill: (0000)\n" 422 "Block 8\n" // synthesized pre header 423 " live in: (0000)\n" 424 " live out: (0001)\n" 425 " kill: (0001)\n"; 426 427 const uint16_t data[] = ONE_REGISTER_CODE_ITEM( 428 Instruction::CONST_4 | 0 | 0, 429 Instruction::IF_EQ, 4, 430 Instruction::CONST_4 | 4 << 12 | 0, 431 Instruction::GOTO | 0x200, 432 Instruction::CONST_4 | 5 << 12 | 0, 433 Instruction::IF_EQ, 3, 434 Instruction::GOTO | 0xFE00, 435 Instruction::RETURN | 0 << 8); 436 437 TestCode(data, expected); 438 } 439 440 TEST_F(LivenessTest, Loop6) { 441 // Bitsets are made of: 442 // (constant0, constant4, constant5, phi in block 2) 443 const char* expected = 444 "Block 0\n" 445 " live in: (0000)\n" 446 " live out: (1110)\n" 447 " kill: (1110)\n" 448 "Block 1\n" 449 " live in: (1110)\n" 450 " live out: (0110)\n" 451 " kill: (0000)\n" 452 "Block 2\n" // loop header 453 " live in: (0110)\n" 454 " live out: (0111)\n" 455 " kill: (0001)\n" 456 "Block 3\n" 457 " live in: (0110)\n" 458 " live out: (0110)\n" 459 " kill: (0000)\n" 460 "Block 4\n" // back edge 461 " live in: (0110)\n" 462 " live out: (0110)\n" 463 " kill: (0000)\n" 464 "Block 5\n" // back edge 465 " live in: (0110)\n" 466 " live out: (0110)\n" 467 " kill: (0000)\n" 468 "Block 6\n" // return block 469 " live in: (0001)\n" 470 " live out: (0000)\n" 471 " kill: (0000)\n" 472 "Block 7\n" // exit block 473 " live in: (0000)\n" 474 " live out: (0000)\n" 475 " kill: (0000)\n"; 476 477 const uint16_t data[] = ONE_REGISTER_CODE_ITEM( 478 Instruction::CONST_4 | 0 | 0, 479 Instruction::IF_EQ, 8, 480 Instruction::CONST_4 | 4 << 12 | 0, 481 Instruction::IF_EQ, 4, 482 Instruction::CONST_4 | 5 << 12 | 0, 483 Instruction::GOTO | 0xFA00, 484 Instruction::GOTO | 0xF900, 485 Instruction::RETURN | 0 << 8); 486 487 TestCode(data, expected); 488 } 489 490 491 TEST_F(LivenessTest, Loop7) { 492 // Bitsets are made of: 493 // (constant0, constant4, constant5, phi in block 2, phi in block 6) 494 const char* expected = 495 "Block 0\n" 496 " live in: (00000)\n" 497 " live out: (11100)\n" 498 " kill: (11100)\n" 499 "Block 1\n" 500 " live in: (11100)\n" 501 " live out: (01100)\n" 502 " kill: (00000)\n" 503 "Block 2\n" // loop header 504 " live in: (01100)\n" 505 " live out: (01110)\n" 506 " kill: (00010)\n" 507 "Block 3\n" 508 " live in: (01100)\n" 509 " live out: (01100)\n" 510 " kill: (00000)\n" 511 "Block 4\n" // loop exit 512 " live in: (00100)\n" 513 " live out: (00000)\n" 514 " kill: (00000)\n" 515 "Block 5\n" // back edge 516 " live in: (01100)\n" 517 " live out: (01100)\n" 518 " kill: (00000)\n" 519 "Block 6\n" // return block 520 " live in: (00000)\n" 521 " live out: (00000)\n" 522 " kill: (00001)\n" 523 "Block 7\n" // exit block 524 " live in: (00000)\n" 525 " live out: (00000)\n" 526 " kill: (00000)\n" 527 "Block 8\n" // synthesized block to avoid critical edge. 528 " live in: (00010)\n" 529 " live out: (00000)\n" 530 " kill: (00000)\n"; 531 532 const uint16_t data[] = ONE_REGISTER_CODE_ITEM( 533 Instruction::CONST_4 | 0 | 0, 534 Instruction::IF_EQ, 8, 535 Instruction::CONST_4 | 4 << 12 | 0, 536 Instruction::IF_EQ, 4, 537 Instruction::CONST_4 | 5 << 12 | 0, 538 Instruction::GOTO | 0x0200, 539 Instruction::GOTO | 0xF900, 540 Instruction::RETURN | 0 << 8); 541 542 TestCode(data, expected); 543 } 544 545 TEST_F(LivenessTest, Loop8) { 546 // var a = 0; 547 // while (a == a) { 548 // a = a + a; 549 // } 550 // return a; 551 // 552 // We want to test that the ins of the loop exit 553 // does contain the phi. 554 // Bitsets are made of: 555 // (constant0, phi, add) 556 const char* expected = 557 "Block 0\n" 558 " live in: (000)\n" 559 " live out: (100)\n" 560 " kill: (100)\n" 561 "Block 1\n" // pre loop header 562 " live in: (100)\n" 563 " live out: (000)\n" 564 " kill: (000)\n" 565 "Block 2\n" // loop header 566 " live in: (000)\n" 567 " live out: (010)\n" 568 " kill: (010)\n" 569 "Block 3\n" // back edge 570 " live in: (010)\n" 571 " live out: (000)\n" 572 " kill: (001)\n" 573 "Block 4\n" // return block 574 " live in: (010)\n" 575 " live out: (000)\n" 576 " kill: (000)\n" 577 "Block 5\n" // exit block 578 " live in: (000)\n" 579 " live out: (000)\n" 580 " kill: (000)\n"; 581 582 const uint16_t data[] = ONE_REGISTER_CODE_ITEM( 583 Instruction::CONST_4 | 0 | 0, 584 Instruction::IF_EQ, 6, 585 Instruction::ADD_INT, 0, 0, 586 Instruction::GOTO | 0xFB00, 587 Instruction::RETURN | 0 << 8); 588 589 TestCode(data, expected); 590 } 591 592 } // namespace art 593