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