blob: 7623e421fd6516ca4b7c5c6cb86354bddde13597 [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 Geoffray804d0932014-05-02 08:46:00 +010039 ASSERT_EQ(nullptr, graph->GetBlocks().Get(i)->GetDominator());
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +000040 } else {
Nicolas Geoffray804d0932014-05-02 08:46:00 +010041 ASSERT_NE(nullptr, graph->GetBlocks().Get(i)->GetDominator());
42 ASSERT_EQ(blocks[i], graph->GetBlocks().Get(i)->GetDominator()->GetBlockId());
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +000043 }
44 }
45}
46
47TEST(OptimizerTest, ReturnVoid) {
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +000048 const uint16_t data[] = ZERO_REGISTER_CODE_ITEM(
49 Instruction::RETURN_VOID); // Block number 1
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +000050
51 const int dominators[] = {
52 -1,
53 0,
54 1
55 };
56
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +000057 TestCode(data, dominators, sizeof(dominators) / sizeof(int));
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +000058}
59
60TEST(OptimizerTest, CFG1) {
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +000061 const uint16_t data[] = ZERO_REGISTER_CODE_ITEM(
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +000062 Instruction::GOTO | 0x100, // Block number 1
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +000063 Instruction::RETURN_VOID); // Block number 2
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +000064
65 const int dominators[] = {
66 -1,
67 0,
68 1,
69 2
70 };
71
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +000072 TestCode(data, dominators, sizeof(dominators) / sizeof(int));
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +000073}
74
75TEST(OptimizerTest, CFG2) {
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +000076 const uint16_t data[] = ZERO_REGISTER_CODE_ITEM(
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +000077 Instruction::GOTO | 0x100, // Block number 1
78 Instruction::GOTO | 0x100, // Block number 2
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +000079 Instruction::RETURN_VOID); // Block number 3
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +000080
81 const int dominators[] = {
82 -1,
83 0,
84 1,
85 2,
86 3
87 };
88
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +000089 TestCode(data, dominators, sizeof(dominators) / sizeof(int));
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +000090}
91
92TEST(OptimizerTest, CFG3) {
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +000093 const uint16_t data1[] = ZERO_REGISTER_CODE_ITEM(
94 Instruction::GOTO | 0x200, // Block number 1
95 Instruction::RETURN_VOID, // Block number 2
96 Instruction::GOTO | 0xFF00); // Block number 3
97
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +000098 const int dominators[] = {
99 -1,
100 0,
101 3,
102 1,
103 2
104 };
105
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000106 TestCode(data1, dominators, sizeof(dominators) / sizeof(int));
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000107
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000108 const uint16_t data2[] = ZERO_REGISTER_CODE_ITEM(
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000109 Instruction::GOTO_16, 3,
110 Instruction::RETURN_VOID,
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000111 Instruction::GOTO_16, 0xFFFF);
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000112
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000113 TestCode(data2, dominators, sizeof(dominators) / sizeof(int));
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000114
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000115 const uint16_t data3[] = ZERO_REGISTER_CODE_ITEM(
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000116 Instruction::GOTO_32, 4, 0,
117 Instruction::RETURN_VOID,
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000118 Instruction::GOTO_32, 0xFFFF, 0xFFFF);
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000119
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000120 TestCode(data3, dominators, sizeof(dominators) / sizeof(int));
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000121}
122
123TEST(OptimizerTest, CFG4) {
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000124 const uint16_t data1[] = ZERO_REGISTER_CODE_ITEM(
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000125 Instruction::NOP,
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000126 Instruction::GOTO | 0xFF00);
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000127
128 const int dominators[] = {
129 -1,
130 0,
131 -1
132 };
133
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000134 TestCode(data1, dominators, sizeof(dominators) / sizeof(int));
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000135
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000136 const uint16_t data2[] = ZERO_REGISTER_CODE_ITEM(
137 Instruction::GOTO_32, 0, 0);
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000138
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000139 TestCode(data2, dominators, sizeof(dominators) / sizeof(int));
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000140}
141
142TEST(OptimizerTest, CFG5) {
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000143 const uint16_t data[] = ZERO_REGISTER_CODE_ITEM(
144 Instruction::RETURN_VOID, // Block number 1
145 Instruction::GOTO | 0x100, // Dead block
146 Instruction::GOTO | 0xFE00); // Block number 2
147
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000148
149 const int dominators[] = {
150 -1,
151 0,
152 -1,
153 1
154 };
155
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000156 TestCode(data, dominators, sizeof(dominators) / sizeof(int));
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000157}
158
159TEST(OptimizerTest, CFG6) {
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000160 const uint16_t data[] = ONE_REGISTER_CODE_ITEM(
Nicolas Geoffray788aaad2014-03-10 12:00:43 +0000161 Instruction::CONST_4 | 0 | 0,
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000162 Instruction::IF_EQ, 3,
163 Instruction::GOTO | 0x100,
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000164 Instruction::RETURN_VOID);
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000165
166 const int dominators[] = {
167 -1,
168 0,
169 1,
170 1,
Nicolas Geoffray622d9c32014-05-12 16:11:02 +0100171 3,
172 1, // Synthesized block to avoid critical edge.
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000173 };
174
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000175 TestCode(data, dominators, sizeof(dominators) / sizeof(int));
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000176}
177
178TEST(OptimizerTest, CFG7) {
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000179 const uint16_t data[] = ONE_REGISTER_CODE_ITEM(
Nicolas Geoffray788aaad2014-03-10 12:00:43 +0000180 Instruction::CONST_4 | 0 | 0,
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000181 Instruction::IF_EQ, 3, // Block number 1
182 Instruction::GOTO | 0x100, // Block number 2
183 Instruction::GOTO | 0xFF00); // Block number 3
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000184
185 const int dominators[] = {
186 -1,
187 0,
188 1,
189 1,
Nicolas Geoffray622d9c32014-05-12 16:11:02 +0100190 -1, // exit block is not dominated by any block due to the spin loop.
191 1, // block to avoid critical edge.
192 1 // block to avoid critical edge.
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000193 };
194
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000195 TestCode(data, dominators, sizeof(dominators) / sizeof(int));
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000196}
197
198TEST(OptimizerTest, CFG8) {
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000199 const uint16_t data[] = ONE_REGISTER_CODE_ITEM(
Nicolas Geoffray788aaad2014-03-10 12:00:43 +0000200 Instruction::CONST_4 | 0 | 0,
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000201 Instruction::IF_EQ, 3, // Block number 1
202 Instruction::GOTO | 0x200, // Block number 2
203 Instruction::GOTO | 0x100, // Block number 3
204 Instruction::GOTO | 0xFF00); // Block number 4
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000205
206 const int dominators[] = {
207 -1,
208 0,
209 1,
210 1,
211 1,
Nicolas Geoffray622d9c32014-05-12 16:11:02 +0100212 -1, // exit block is not dominated by any block due to the spin loop.
213 1 // block to avoid critical edge.
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000214 };
215
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000216 TestCode(data, dominators, sizeof(dominators) / sizeof(int));
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000217}
218
219TEST(OptimizerTest, CFG9) {
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000220 const uint16_t data[] = ONE_REGISTER_CODE_ITEM(
Nicolas Geoffray788aaad2014-03-10 12:00:43 +0000221 Instruction::CONST_4 | 0 | 0,
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000222 Instruction::IF_EQ, 3, // Block number 1
223 Instruction::GOTO | 0x200, // Block number 2
224 Instruction::GOTO | 0x100, // Block number 3
225 Instruction::GOTO | 0xFE00); // Block number 4
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000226
227 const int dominators[] = {
228 -1,
229 0,
230 1,
231 1,
232 1,
Nicolas Geoffray622d9c32014-05-12 16:11:02 +0100233 -1, // exit block is not dominated by any block due to the spin loop.
234 1 // block to avoid critical edge.
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000235 };
236
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000237 TestCode(data, dominators, sizeof(dominators) / sizeof(int));
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000238}
239
240TEST(OptimizerTest, CFG10) {
Nicolas Geoffray788aaad2014-03-10 12:00:43 +0000241 const uint16_t data[] = ONE_REGISTER_CODE_ITEM(
242 Instruction::CONST_4 | 0 | 0,
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000243 Instruction::IF_EQ, 6, // Block number 1
244 Instruction::IF_EQ, 3, // Block number 2
245 Instruction::GOTO | 0x100, // Block number 3
246 Instruction::GOTO | 0x100, // Block number 4
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000247 Instruction::RETURN_VOID); // Block number 5
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000248
249 const int dominators[] = {
250 -1,
251 0,
252 1,
253 2,
254 2,
255 1,
Nicolas Geoffray622d9c32014-05-12 16:11:02 +0100256 5, // Block number 5 dominates exit block
257 1, // block to avoid critical edge.
258 2 // block to avoid critical edge.
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000259 };
260
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000261 TestCode(data, dominators, sizeof(dominators) / sizeof(int));
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000262}
263
264} // namespace art