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