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 "dex/dex_instruction.h"
     20 #include "nodes.h"
     21 #include "optimizing_unit_test.h"
     22 
     23 #include "gtest/gtest.h"
     24 
     25 namespace art {
     26 
     27 class OptimizerTest : public OptimizingUnitTest {
     28  protected:
     29   void TestCode(const std::vector<uint16_t>& data, const uint32_t* blocks, size_t blocks_length);
     30 };
     31 
     32 void OptimizerTest::TestCode(const std::vector<uint16_t>& data,
     33                              const uint32_t* blocks,
     34                              size_t blocks_length) {
     35   HGraph* graph = CreateCFG(data);
     36   ASSERT_EQ(graph->GetBlocks().size(), blocks_length);
     37   for (size_t i = 0, e = blocks_length; i < e; ++i) {
     38     if (blocks[i] == kInvalidBlockId) {
     39       if (graph->GetBlocks()[i] == nullptr) {
     40         // Dead block.
     41       } else {
     42         // Only the entry block has no dominator.
     43         ASSERT_EQ(nullptr, graph->GetBlocks()[i]->GetDominator());
     44         ASSERT_TRUE(graph->GetBlocks()[i]->IsEntryBlock());
     45       }
     46     } else {
     47       ASSERT_NE(nullptr, graph->GetBlocks()[i]->GetDominator());
     48       ASSERT_EQ(blocks[i], graph->GetBlocks()[i]->GetDominator()->GetBlockId());
     49     }
     50   }
     51 }
     52 
     53 TEST_F(OptimizerTest, ReturnVoid) {
     54   const std::vector<uint16_t> data = ZERO_REGISTER_CODE_ITEM(
     55       Instruction::RETURN_VOID);  // Block number 1
     56 
     57   const uint32_t dominators[] = {
     58       kInvalidBlockId,
     59       0,
     60       1
     61   };
     62 
     63   TestCode(data, dominators, sizeof(dominators) / sizeof(int));
     64 }
     65 
     66 TEST_F(OptimizerTest, CFG1) {
     67   const std::vector<uint16_t> data = ZERO_REGISTER_CODE_ITEM(
     68     Instruction::GOTO | 0x100,  // Block number 1
     69     Instruction::RETURN_VOID);  // Block number 2
     70 
     71   const uint32_t dominators[] = {
     72       kInvalidBlockId,
     73       0,
     74       1,
     75       2
     76   };
     77 
     78   TestCode(data, dominators, sizeof(dominators) / sizeof(int));
     79 }
     80 
     81 TEST_F(OptimizerTest, CFG2) {
     82   const std::vector<uint16_t> data = ZERO_REGISTER_CODE_ITEM(
     83     Instruction::GOTO | 0x100,  // Block number 1
     84     Instruction::GOTO | 0x100,  // Block number 2
     85     Instruction::RETURN_VOID);  // Block number 3
     86 
     87   const uint32_t dominators[] = {
     88       kInvalidBlockId,
     89       0,
     90       1,
     91       2,
     92       3
     93   };
     94 
     95   TestCode(data, dominators, sizeof(dominators) / sizeof(int));
     96 }
     97 
     98 TEST_F(OptimizerTest, CFG3) {
     99   const std::vector<uint16_t> data1 = ZERO_REGISTER_CODE_ITEM(
    100     Instruction::GOTO | 0x200,    // Block number 1
    101     Instruction::RETURN_VOID,     // Block number 2
    102     Instruction::GOTO | 0xFF00);  // Block number 3
    103 
    104   const uint32_t dominators[] = {
    105       kInvalidBlockId,
    106       0,
    107       3,
    108       1,
    109       2
    110   };
    111 
    112   TestCode(data1, dominators, sizeof(dominators) / sizeof(int));
    113 
    114   const std::vector<uint16_t> data2 = ZERO_REGISTER_CODE_ITEM(
    115     Instruction::GOTO_16, 3,
    116     Instruction::RETURN_VOID,
    117     Instruction::GOTO_16, 0xFFFF);
    118 
    119   TestCode(data2, dominators, sizeof(dominators) / sizeof(int));
    120 
    121   const std::vector<uint16_t> data3 = ZERO_REGISTER_CODE_ITEM(
    122     Instruction::GOTO_32, 4, 0,
    123     Instruction::RETURN_VOID,
    124     Instruction::GOTO_32, 0xFFFF, 0xFFFF);
    125 
    126   TestCode(data3, dominators, sizeof(dominators) / sizeof(int));
    127 }
    128 
    129 TEST_F(OptimizerTest, CFG4) {
    130   const std::vector<uint16_t> data1 = ZERO_REGISTER_CODE_ITEM(
    131     Instruction::NOP,
    132     Instruction::GOTO | 0xFF00);
    133 
    134   const uint32_t dominators[] = {
    135       kInvalidBlockId,
    136       3,
    137       kInvalidBlockId,
    138       0
    139   };
    140 
    141   TestCode(data1, dominators, sizeof(dominators) / sizeof(int));
    142 
    143   const std::vector<uint16_t> data2 = ZERO_REGISTER_CODE_ITEM(
    144     Instruction::GOTO_32, 0, 0);
    145 
    146   TestCode(data2, dominators, sizeof(dominators) / sizeof(int));
    147 }
    148 
    149 TEST_F(OptimizerTest, CFG5) {
    150   const std::vector<uint16_t> data = ZERO_REGISTER_CODE_ITEM(
    151     Instruction::RETURN_VOID,     // Block number 1
    152     Instruction::GOTO | 0x100,    // Dead block
    153     Instruction::GOTO | 0xFE00);  // Block number 2
    154 
    155 
    156   const uint32_t dominators[] = {
    157       kInvalidBlockId,
    158       0,
    159       kInvalidBlockId,
    160       1
    161   };
    162 
    163   TestCode(data, dominators, sizeof(dominators) / sizeof(int));
    164 }
    165 
    166 TEST_F(OptimizerTest, CFG6) {
    167   const std::vector<uint16_t> data = ONE_REGISTER_CODE_ITEM(
    168     Instruction::CONST_4 | 0 | 0,
    169     Instruction::IF_EQ, 3,
    170     Instruction::GOTO | 0x100,
    171     Instruction::RETURN_VOID);
    172 
    173   const uint32_t dominators[] = {
    174       kInvalidBlockId,
    175       0,
    176       1,
    177       1,
    178       3,
    179       1,  // Synthesized block to avoid critical edge.
    180   };
    181 
    182   TestCode(data, dominators, sizeof(dominators) / sizeof(int));
    183 }
    184 
    185 TEST_F(OptimizerTest, CFG7) {
    186   const std::vector<uint16_t> data = ONE_REGISTER_CODE_ITEM(
    187     Instruction::CONST_4 | 0 | 0,
    188     Instruction::IF_EQ, 3,        // Block number 1
    189     Instruction::GOTO | 0x100,    // Block number 2
    190     Instruction::GOTO | 0xFF00);  // Block number 3
    191 
    192   const uint32_t dominators[] = {
    193       kInvalidBlockId,
    194       0,
    195       1,
    196       1,
    197       kInvalidBlockId,  // exit block is not dominated by any block due to the spin loop.
    198       1,   // block to avoid critical edge.
    199       1    // block to avoid critical edge.
    200   };
    201 
    202   TestCode(data, dominators, sizeof(dominators) / sizeof(int));
    203 }
    204 
    205 TEST_F(OptimizerTest, CFG8) {
    206   const std::vector<uint16_t> data = ONE_REGISTER_CODE_ITEM(
    207     Instruction::CONST_4 | 0 | 0,
    208     Instruction::IF_EQ, 3,        // Block number 1
    209     Instruction::GOTO | 0x200,    // Block number 2
    210     Instruction::GOTO | 0x100,    // Block number 3
    211     Instruction::GOTO | 0xFF00);  // Block number 4
    212 
    213   const uint32_t dominators[] = {
    214       kInvalidBlockId,
    215       0,
    216       1,
    217       1,
    218       1,
    219       kInvalidBlockId,  // exit block is not dominated by any block due to the spin loop.
    220       1    // block to avoid critical edge.
    221   };
    222 
    223   TestCode(data, dominators, sizeof(dominators) / sizeof(int));
    224 }
    225 
    226 TEST_F(OptimizerTest, CFG9) {
    227   const std::vector<uint16_t> data = ONE_REGISTER_CODE_ITEM(
    228     Instruction::CONST_4 | 0 | 0,
    229     Instruction::IF_EQ, 3,        // Block number 1
    230     Instruction::GOTO | 0x200,    // Block number 2
    231     Instruction::GOTO | 0x100,    // Block number 3
    232     Instruction::GOTO | 0xFE00);  // Block number 4
    233 
    234   const uint32_t dominators[] = {
    235       kInvalidBlockId,
    236       0,
    237       1,
    238       1,
    239       1,
    240       kInvalidBlockId,  // exit block is not dominated by any block due to the spin loop.
    241       1    // block to avoid critical edge.
    242   };
    243 
    244   TestCode(data, dominators, sizeof(dominators) / sizeof(int));
    245 }
    246 
    247 TEST_F(OptimizerTest, CFG10) {
    248   const std::vector<uint16_t> data = ONE_REGISTER_CODE_ITEM(
    249     Instruction::CONST_4 | 0 | 0,
    250     Instruction::IF_EQ, 6,  // Block number 1
    251     Instruction::IF_EQ, 3,  // Block number 2
    252     Instruction::GOTO | 0x100,  // Block number 3
    253     Instruction::GOTO | 0x100,  // Block number 4
    254     Instruction::RETURN_VOID);  // Block number 5
    255 
    256   const uint32_t dominators[] = {
    257       kInvalidBlockId,
    258       0,
    259       1,
    260       2,
    261       2,
    262       1,
    263       5,    // Block number 5 dominates exit block
    264       1,    // block to avoid critical edge.
    265       2     // block to avoid critical edge.
    266   };
    267 
    268   TestCode(data, dominators, sizeof(dominators) / sizeof(int));
    269 }
    270 
    271 }  // namespace art
    272