blob: 3062e3751d2d59933e545eea10c1aff4d058a03c [file] [log] [blame]
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +00001/*
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"
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +000020#include "optimizing_unit_test.h"
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +000021#include "utils/arena_allocator.h"
22
23#include "gtest/gtest.h"
24
25namespace art {
26
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +000027static void TestCode(const uint16_t* data, const int* blocks, size_t blocks_length) {
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +000028 ArenaPool pool;
29 ArenaAllocator allocator(&pool);
30 HGraphBuilder builder(&allocator);
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +000031 const DexFile::CodeItem* item = reinterpret_cast<const DexFile::CodeItem*>(data);
32 HGraph* graph = builder.BuildGraph(*item);
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +000033 ASSERT_NE(graph, nullptr);
34 graph->BuildDominatorTree();
Nicolas Geoffray804d0932014-05-02 08:46:00 +010035 ASSERT_EQ(graph->GetBlocks().Size(), blocks_length);
36 for (size_t i = 0, e = blocks_length; i < e; ++i) {
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +000037 if (blocks[i] == -1) {
Nicolas Geoffray804d0932014-05-02 08:46:00 +010038 ASSERT_EQ(nullptr, graph->GetBlocks().Get(i)->GetDominator());
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +000039 } else {
Nicolas Geoffray804d0932014-05-02 08:46:00 +010040 ASSERT_NE(nullptr, graph->GetBlocks().Get(i)->GetDominator());
41 ASSERT_EQ(blocks[i], graph->GetBlocks().Get(i)->GetDominator()->GetBlockId());
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +000042 }
43 }
44}
45
46TEST(OptimizerTest, ReturnVoid) {
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +000047 const uint16_t data[] = ZERO_REGISTER_CODE_ITEM(
48 Instruction::RETURN_VOID); // Block number 1
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +000049
50 const int dominators[] = {
51 -1,
52 0,
53 1
54 };
55
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +000056 TestCode(data, dominators, sizeof(dominators) / sizeof(int));
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +000057}
58
59TEST(OptimizerTest, CFG1) {
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +000060 const uint16_t data[] = ZERO_REGISTER_CODE_ITEM(
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +000061 Instruction::GOTO | 0x100, // Block number 1
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +000062 Instruction::RETURN_VOID); // Block number 2
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +000063
64 const int dominators[] = {
65 -1,
66 0,
67 1,
68 2
69 };
70
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +000071 TestCode(data, dominators, sizeof(dominators) / sizeof(int));
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +000072}
73
74TEST(OptimizerTest, CFG2) {
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +000075 const uint16_t data[] = ZERO_REGISTER_CODE_ITEM(
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +000076 Instruction::GOTO | 0x100, // Block number 1
77 Instruction::GOTO | 0x100, // Block number 2
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +000078 Instruction::RETURN_VOID); // Block number 3
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +000079
80 const int dominators[] = {
81 -1,
82 0,
83 1,
84 2,
85 3
86 };
87
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +000088 TestCode(data, dominators, sizeof(dominators) / sizeof(int));
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +000089}
90
91TEST(OptimizerTest, CFG3) {
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +000092 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
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +000097 const int dominators[] = {
98 -1,
99 0,
100 3,
101 1,
102 2
103 };
104
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000105 TestCode(data1, dominators, sizeof(dominators) / sizeof(int));
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000106
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000107 const uint16_t data2[] = ZERO_REGISTER_CODE_ITEM(
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000108 Instruction::GOTO_16, 3,
109 Instruction::RETURN_VOID,
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000110 Instruction::GOTO_16, 0xFFFF);
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000111
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000112 TestCode(data2, dominators, sizeof(dominators) / sizeof(int));
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000113
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000114 const uint16_t data3[] = ZERO_REGISTER_CODE_ITEM(
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000115 Instruction::GOTO_32, 4, 0,
116 Instruction::RETURN_VOID,
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000117 Instruction::GOTO_32, 0xFFFF, 0xFFFF);
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000118
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000119 TestCode(data3, dominators, sizeof(dominators) / sizeof(int));
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000120}
121
122TEST(OptimizerTest, CFG4) {
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000123 const uint16_t data1[] = ZERO_REGISTER_CODE_ITEM(
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000124 Instruction::NOP,
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000125 Instruction::GOTO | 0xFF00);
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000126
127 const int dominators[] = {
128 -1,
129 0,
130 -1
131 };
132
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000133 TestCode(data1, dominators, sizeof(dominators) / sizeof(int));
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000134
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000135 const uint16_t data2[] = ZERO_REGISTER_CODE_ITEM(
136 Instruction::GOTO_32, 0, 0);
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000137
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000138 TestCode(data2, dominators, sizeof(dominators) / sizeof(int));
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000139}
140
141TEST(OptimizerTest, CFG5) {
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000142 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
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000147
148 const int dominators[] = {
149 -1,
150 0,
151 -1,
152 1
153 };
154
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000155 TestCode(data, dominators, sizeof(dominators) / sizeof(int));
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000156}
157
158TEST(OptimizerTest, CFG6) {
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000159 const uint16_t data[] = ONE_REGISTER_CODE_ITEM(
Nicolas Geoffray788aaad2014-03-10 12:00:43 +0000160 Instruction::CONST_4 | 0 | 0,
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000161 Instruction::IF_EQ, 3,
162 Instruction::GOTO | 0x100,
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000163 Instruction::RETURN_VOID);
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000164
165 const int dominators[] = {
166 -1,
167 0,
168 1,
169 1,
Nicolas Geoffray622d9c32014-05-12 16:11:02 +0100170 3,
171 1, // Synthesized block to avoid critical edge.
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000172 };
173
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000174 TestCode(data, dominators, sizeof(dominators) / sizeof(int));
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000175}
176
177TEST(OptimizerTest, CFG7) {
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000178 const uint16_t data[] = ONE_REGISTER_CODE_ITEM(
Nicolas Geoffray788aaad2014-03-10 12:00:43 +0000179 Instruction::CONST_4 | 0 | 0,
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000180 Instruction::IF_EQ, 3, // Block number 1
181 Instruction::GOTO | 0x100, // Block number 2
182 Instruction::GOTO | 0xFF00); // Block number 3
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000183
184 const int dominators[] = {
185 -1,
186 0,
187 1,
188 1,
Nicolas Geoffray622d9c32014-05-12 16:11:02 +0100189 -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.
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000192 };
193
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000194 TestCode(data, dominators, sizeof(dominators) / sizeof(int));
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000195}
196
197TEST(OptimizerTest, CFG8) {
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000198 const uint16_t data[] = ONE_REGISTER_CODE_ITEM(
Nicolas Geoffray788aaad2014-03-10 12:00:43 +0000199 Instruction::CONST_4 | 0 | 0,
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000200 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
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000204
205 const int dominators[] = {
206 -1,
207 0,
208 1,
209 1,
210 1,
Nicolas Geoffray622d9c32014-05-12 16:11:02 +0100211 -1, // exit block is not dominated by any block due to the spin loop.
212 1 // block to avoid critical edge.
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000213 };
214
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000215 TestCode(data, dominators, sizeof(dominators) / sizeof(int));
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000216}
217
218TEST(OptimizerTest, CFG9) {
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000219 const uint16_t data[] = ONE_REGISTER_CODE_ITEM(
Nicolas Geoffray788aaad2014-03-10 12:00:43 +0000220 Instruction::CONST_4 | 0 | 0,
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000221 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
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000225
226 const int dominators[] = {
227 -1,
228 0,
229 1,
230 1,
231 1,
Nicolas Geoffray622d9c32014-05-12 16:11:02 +0100232 -1, // exit block is not dominated by any block due to the spin loop.
233 1 // block to avoid critical edge.
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000234 };
235
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000236 TestCode(data, dominators, sizeof(dominators) / sizeof(int));
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000237}
238
239TEST(OptimizerTest, CFG10) {
Nicolas Geoffray788aaad2014-03-10 12:00:43 +0000240 const uint16_t data[] = ONE_REGISTER_CODE_ITEM(
241 Instruction::CONST_4 | 0 | 0,
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000242 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
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000246 Instruction::RETURN_VOID); // Block number 5
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000247
248 const int dominators[] = {
249 -1,
250 0,
251 1,
252 2,
253 2,
254 1,
Nicolas Geoffray622d9c32014-05-12 16:11:02 +0100255 5, // Block number 5 dominates exit block
256 1, // block to avoid critical edge.
257 2 // block to avoid critical edge.
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000258 };
259
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000260 TestCode(data, dominators, sizeof(dominators) / sizeof(int));
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000261}
262
263} // namespace art