blob: 61a769730187c62b92cafd47ec4c41ad671d952a [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
Mathieu Chartierb666f482015-02-18 14:33:14 -080017#include "base/arena_allocator.h"
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +000018#include "builder.h"
19#include "dex_instruction.h"
20#include "nodes.h"
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +000021#include "optimizing_unit_test.h"
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +000022
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);
David Brazdil5e8b1372015-01-23 14:39:08 +000030 HGraph* graph = new (&allocator) HGraph(&allocator);
31 HGraphBuilder builder(graph);
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +000032 const DexFile::CodeItem* item = reinterpret_cast<const DexFile::CodeItem*>(data);
David Brazdil5e8b1372015-01-23 14:39:08 +000033 bool graph_built = builder.BuildGraph(*item);
34 ASSERT_TRUE(graph_built);
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +000035 graph->BuildDominatorTree();
Nicolas Geoffray804d0932014-05-02 08:46:00 +010036 ASSERT_EQ(graph->GetBlocks().Size(), blocks_length);
37 for (size_t i = 0, e = blocks_length; i < e; ++i) {
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +000038 if (blocks[i] == -1) {
Nicolas Geoffrayf776b922015-04-15 18:22:45 +010039 if (graph->GetBlocks().Get(i) == nullptr) {
40 // Dead block.
41 } else {
42 // Only the entry block has no dominator.
43 ASSERT_EQ(nullptr, graph->GetBlocks().Get(i)->GetDominator());
44 ASSERT_TRUE(graph->GetBlocks().Get(i)->IsEntryBlock());
45 }
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +000046 } else {
Nicolas Geoffray804d0932014-05-02 08:46:00 +010047 ASSERT_NE(nullptr, graph->GetBlocks().Get(i)->GetDominator());
48 ASSERT_EQ(blocks[i], graph->GetBlocks().Get(i)->GetDominator()->GetBlockId());
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +000049 }
50 }
51}
52
53TEST(OptimizerTest, ReturnVoid) {
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +000054 const uint16_t data[] = ZERO_REGISTER_CODE_ITEM(
55 Instruction::RETURN_VOID); // Block number 1
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +000056
57 const int dominators[] = {
58 -1,
59 0,
60 1
61 };
62
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +000063 TestCode(data, dominators, sizeof(dominators) / sizeof(int));
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +000064}
65
66TEST(OptimizerTest, CFG1) {
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +000067 const uint16_t data[] = ZERO_REGISTER_CODE_ITEM(
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +000068 Instruction::GOTO | 0x100, // Block number 1
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +000069 Instruction::RETURN_VOID); // Block number 2
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +000070
71 const int dominators[] = {
72 -1,
73 0,
74 1,
75 2
76 };
77
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +000078 TestCode(data, dominators, sizeof(dominators) / sizeof(int));
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +000079}
80
81TEST(OptimizerTest, CFG2) {
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +000082 const uint16_t data[] = ZERO_REGISTER_CODE_ITEM(
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +000083 Instruction::GOTO | 0x100, // Block number 1
84 Instruction::GOTO | 0x100, // Block number 2
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +000085 Instruction::RETURN_VOID); // Block number 3
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +000086
87 const int dominators[] = {
88 -1,
89 0,
90 1,
91 2,
92 3
93 };
94
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +000095 TestCode(data, dominators, sizeof(dominators) / sizeof(int));
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +000096}
97
98TEST(OptimizerTest, CFG3) {
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +000099 const 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
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000104 const int dominators[] = {
105 -1,
106 0,
107 3,
108 1,
109 2
110 };
111
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000112 TestCode(data1, dominators, sizeof(dominators) / sizeof(int));
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000113
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000114 const uint16_t data2[] = ZERO_REGISTER_CODE_ITEM(
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000115 Instruction::GOTO_16, 3,
116 Instruction::RETURN_VOID,
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000117 Instruction::GOTO_16, 0xFFFF);
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000118
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000119 TestCode(data2, dominators, sizeof(dominators) / sizeof(int));
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000120
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000121 const uint16_t data3[] = ZERO_REGISTER_CODE_ITEM(
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000122 Instruction::GOTO_32, 4, 0,
123 Instruction::RETURN_VOID,
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000124 Instruction::GOTO_32, 0xFFFF, 0xFFFF);
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000125
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000126 TestCode(data3, dominators, sizeof(dominators) / sizeof(int));
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000127}
128
129TEST(OptimizerTest, CFG4) {
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000130 const uint16_t data1[] = ZERO_REGISTER_CODE_ITEM(
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000131 Instruction::NOP,
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000132 Instruction::GOTO | 0xFF00);
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000133
134 const int dominators[] = {
135 -1,
136 0,
137 -1
138 };
139
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000140 TestCode(data1, dominators, sizeof(dominators) / sizeof(int));
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000141
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000142 const uint16_t data2[] = ZERO_REGISTER_CODE_ITEM(
143 Instruction::GOTO_32, 0, 0);
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000144
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000145 TestCode(data2, dominators, sizeof(dominators) / sizeof(int));
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000146}
147
148TEST(OptimizerTest, CFG5) {
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000149 const uint16_t data[] = ZERO_REGISTER_CODE_ITEM(
150 Instruction::RETURN_VOID, // Block number 1
151 Instruction::GOTO | 0x100, // Dead block
152 Instruction::GOTO | 0xFE00); // Block number 2
153
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000154
155 const int dominators[] = {
156 -1,
157 0,
158 -1,
159 1
160 };
161
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000162 TestCode(data, dominators, sizeof(dominators) / sizeof(int));
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000163}
164
165TEST(OptimizerTest, CFG6) {
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000166 const uint16_t data[] = ONE_REGISTER_CODE_ITEM(
Nicolas Geoffray788aaad2014-03-10 12:00:43 +0000167 Instruction::CONST_4 | 0 | 0,
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000168 Instruction::IF_EQ, 3,
169 Instruction::GOTO | 0x100,
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000170 Instruction::RETURN_VOID);
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000171
172 const int dominators[] = {
173 -1,
174 0,
175 1,
176 1,
Nicolas Geoffray622d9c32014-05-12 16:11:02 +0100177 3,
178 1, // Synthesized block to avoid critical edge.
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000179 };
180
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000181 TestCode(data, dominators, sizeof(dominators) / sizeof(int));
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000182}
183
184TEST(OptimizerTest, CFG7) {
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000185 const uint16_t data[] = ONE_REGISTER_CODE_ITEM(
Nicolas Geoffray788aaad2014-03-10 12:00:43 +0000186 Instruction::CONST_4 | 0 | 0,
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000187 Instruction::IF_EQ, 3, // Block number 1
188 Instruction::GOTO | 0x100, // Block number 2
189 Instruction::GOTO | 0xFF00); // Block number 3
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000190
191 const int dominators[] = {
192 -1,
193 0,
194 1,
195 1,
Nicolas Geoffray622d9c32014-05-12 16:11:02 +0100196 -1, // exit block is not dominated by any block due to the spin loop.
197 1, // block to avoid critical edge.
198 1 // block to avoid critical edge.
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000199 };
200
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000201 TestCode(data, dominators, sizeof(dominators) / sizeof(int));
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000202}
203
204TEST(OptimizerTest, CFG8) {
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000205 const uint16_t data[] = ONE_REGISTER_CODE_ITEM(
Nicolas Geoffray788aaad2014-03-10 12:00:43 +0000206 Instruction::CONST_4 | 0 | 0,
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000207 Instruction::IF_EQ, 3, // Block number 1
208 Instruction::GOTO | 0x200, // Block number 2
209 Instruction::GOTO | 0x100, // Block number 3
210 Instruction::GOTO | 0xFF00); // Block number 4
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000211
212 const int dominators[] = {
213 -1,
214 0,
215 1,
216 1,
217 1,
Nicolas Geoffray622d9c32014-05-12 16:11:02 +0100218 -1, // exit block is not dominated by any block due to the spin loop.
219 1 // block to avoid critical edge.
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000220 };
221
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000222 TestCode(data, dominators, sizeof(dominators) / sizeof(int));
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000223}
224
225TEST(OptimizerTest, CFG9) {
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000226 const uint16_t data[] = ONE_REGISTER_CODE_ITEM(
Nicolas Geoffray788aaad2014-03-10 12:00:43 +0000227 Instruction::CONST_4 | 0 | 0,
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000228 Instruction::IF_EQ, 3, // Block number 1
229 Instruction::GOTO | 0x200, // Block number 2
230 Instruction::GOTO | 0x100, // Block number 3
231 Instruction::GOTO | 0xFE00); // Block number 4
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000232
233 const int dominators[] = {
234 -1,
235 0,
236 1,
237 1,
238 1,
Nicolas Geoffray622d9c32014-05-12 16:11:02 +0100239 -1, // exit block is not dominated by any block due to the spin loop.
240 1 // block to avoid critical edge.
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000241 };
242
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000243 TestCode(data, dominators, sizeof(dominators) / sizeof(int));
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000244}
245
246TEST(OptimizerTest, CFG10) {
Nicolas Geoffray788aaad2014-03-10 12:00:43 +0000247 const uint16_t data[] = ONE_REGISTER_CODE_ITEM(
248 Instruction::CONST_4 | 0 | 0,
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000249 Instruction::IF_EQ, 6, // Block number 1
250 Instruction::IF_EQ, 3, // Block number 2
251 Instruction::GOTO | 0x100, // Block number 3
252 Instruction::GOTO | 0x100, // Block number 4
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000253 Instruction::RETURN_VOID); // Block number 5
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000254
255 const int dominators[] = {
256 -1,
257 0,
258 1,
259 2,
260 2,
261 1,
Nicolas Geoffray622d9c32014-05-12 16:11:02 +0100262 5, // Block number 5 dominates exit block
263 1, // block to avoid critical edge.
264 2 // block to avoid critical edge.
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000265 };
266
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000267 TestCode(data, dominators, sizeof(dominators) / sizeof(int));
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000268}
269
270} // namespace art