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 <fstream> 18 19 #include "base/stringprintf.h" 20 #include "builder.h" 21 #include "code_generator.h" 22 #include "dex_file.h" 23 #include "dex_instruction.h" 24 #include "graph_visualizer.h" 25 #include "nodes.h" 26 #include "optimizing_unit_test.h" 27 #include "pretty_printer.h" 28 #include "ssa_builder.h" 29 #include "ssa_liveness_analysis.h" 30 #include "utils/arena_allocator.h" 31 32 #include "gtest/gtest.h" 33 34 namespace art { 35 36 static void TestCode(const uint16_t* data, const int* expected_order, size_t number_of_blocks) { 37 ArenaPool pool; 38 ArenaAllocator allocator(&pool); 39 HGraphBuilder builder(&allocator); 40 const DexFile::CodeItem* item = reinterpret_cast<const DexFile::CodeItem*>(data); 41 HGraph* graph = builder.BuildGraph(*item); 42 ASSERT_NE(graph, nullptr); 43 44 graph->BuildDominatorTree(); 45 graph->TransformToSSA(); 46 graph->FindNaturalLoops(); 47 48 CodeGenerator* codegen = CodeGenerator::Create(&allocator, graph, InstructionSet::kX86); 49 SsaLivenessAnalysis liveness(*graph, codegen); 50 liveness.Analyze(); 51 52 ASSERT_EQ(liveness.GetLinearPostOrder().Size(), number_of_blocks); 53 for (size_t i = 0; i < number_of_blocks; ++i) { 54 ASSERT_EQ(liveness.GetLinearPostOrder().Get(number_of_blocks - i - 1)->GetBlockId(), 55 expected_order[i]); 56 } 57 } 58 59 TEST(LinearizeTest, CFG1) { 60 // Structure of this graph (+ are back edges) 61 // Block0 62 // | 63 // Block1 64 // | 65 // Block2 ++++++ 66 // / \ + 67 // Block5 Block7 + 68 // | | + 69 // Block6 Block3 + 70 // + / \ + 71 // Block4 Block8 72 73 const uint16_t data[] = ONE_REGISTER_CODE_ITEM( 74 Instruction::CONST_4 | 0 | 0, 75 Instruction::IF_EQ, 5, 76 Instruction::IF_EQ, 0xFFFE, 77 Instruction::GOTO | 0xFE00, 78 Instruction::RETURN_VOID); 79 80 const int blocks[] = {0, 1, 2, 7, 3, 4, 8, 5, 6}; 81 TestCode(data, blocks, 9); 82 } 83 84 TEST(LinearizeTest, CFG2) { 85 // Structure of this graph (+ are back edges) 86 // Block0 87 // | 88 // Block1 89 // | 90 // Block2 ++++++ 91 // / \ + 92 // Block3 Block7 + 93 // | | + 94 // Block6 Block4 + 95 // + / \ + 96 // Block5 Block8 97 98 const uint16_t data[] = ONE_REGISTER_CODE_ITEM( 99 Instruction::CONST_4 | 0 | 0, 100 Instruction::IF_EQ, 3, 101 Instruction::RETURN_VOID, 102 Instruction::IF_EQ, 0xFFFD, 103 Instruction::GOTO | 0xFE00); 104 105 const int blocks[] = {0, 1, 2, 7, 4, 5, 8, 3, 6}; 106 TestCode(data, blocks, 9); 107 } 108 109 TEST(LinearizeTest, CFG3) { 110 // Structure of this graph (+ are back edges) 111 // Block0 112 // | 113 // Block1 114 // | 115 // Block2 ++++++ 116 // / \ + 117 // Block3 Block8 + 118 // | | + 119 // Block7 Block5 + 120 // / + \ + 121 // Block6 + Block9 122 // | + 123 // Block4 ++ 124 const uint16_t data[] = ONE_REGISTER_CODE_ITEM( 125 Instruction::CONST_4 | 0 | 0, 126 Instruction::IF_EQ, 4, 127 Instruction::RETURN_VOID, 128 Instruction::GOTO | 0x0100, 129 Instruction::IF_EQ, 0xFFFC, 130 Instruction::GOTO | 0xFD00); 131 132 const int blocks[] = {0, 1, 2, 8, 5, 6, 4, 9, 3, 7}; 133 TestCode(data, blocks, 10); 134 } 135 136 TEST(LinearizeTest, CFG4) { 137 /* Structure of this graph (+ are back edges) 138 // Block0 139 // | 140 // Block1 141 // | 142 // Block2 143 // / + \ 144 // Block6 + Block8 145 // | + | 146 // Block7 + Block3 +++++++ 147 // + / \ + 148 // Block9 Block10 + 149 // | + 150 // Block4 + 151 // + / \ + 152 // Block5 Block11 153 */ 154 const uint16_t data[] = ONE_REGISTER_CODE_ITEM( 155 Instruction::CONST_4 | 0 | 0, 156 Instruction::IF_EQ, 7, 157 Instruction::IF_EQ, 0xFFFE, 158 Instruction::IF_EQ, 0xFFFE, 159 Instruction::GOTO | 0xFE00, 160 Instruction::RETURN_VOID); 161 162 const int blocks[] = {0, 1, 2, 8, 3, 10, 4, 5, 11, 9, 6, 7}; 163 TestCode(data, blocks, 12); 164 } 165 166 TEST(LinearizeTest, CFG5) { 167 /* Structure of this graph (+ are back edges) 168 // Block0 169 // | 170 // Block1 171 // | 172 // Block2 173 // / + \ 174 // Block3 + Block8 175 // | + | 176 // Block7 + Block4 +++++++ 177 // + / \ + 178 // Block9 Block10 + 179 // | + 180 // Block5 + 181 // +/ \ + 182 // Block6 Block11 183 */ 184 const uint16_t data[] = ONE_REGISTER_CODE_ITEM( 185 Instruction::CONST_4 | 0 | 0, 186 Instruction::IF_EQ, 3, 187 Instruction::RETURN_VOID, 188 Instruction::IF_EQ, 0xFFFD, 189 Instruction::IF_EQ, 0xFFFE, 190 Instruction::GOTO | 0xFE00); 191 192 const int blocks[] = {0, 1, 2, 8, 4, 10, 5, 6, 11, 9, 3, 7}; 193 TestCode(data, blocks, 12); 194 } 195 196 } // namespace art 197