blob: 50c677adf58de8f404a8450b10e3b2c62adf7302 [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
David Brazdilbadd8262016-02-02 16:28:56 +000027class OptimizerTest : public CommonCompilerTest {};
28
Vladimir Markofa6b93c2015-09-15 10:15:55 +010029static void TestCode(const uint16_t* data, const uint32_t* blocks, size_t blocks_length) {
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +000030 ArenaPool pool;
31 ArenaAllocator allocator(&pool);
David Brazdilbadd8262016-02-02 16:28:56 +000032 HGraph* graph = CreateCFG(&allocator, data);
Vladimir Markofa6b93c2015-09-15 10:15:55 +010033 ASSERT_EQ(graph->GetBlocks().size(), blocks_length);
Nicolas Geoffray804d0932014-05-02 08:46:00 +010034 for (size_t i = 0, e = blocks_length; i < e; ++i) {
Vladimir Markofa6b93c2015-09-15 10:15:55 +010035 if (blocks[i] == kInvalidBlockId) {
Vladimir Markoec7802a2015-10-01 20:57:57 +010036 if (graph->GetBlocks()[i] == nullptr) {
Nicolas Geoffrayf776b922015-04-15 18:22:45 +010037 // Dead block.
38 } else {
39 // Only the entry block has no dominator.
Vladimir Markoec7802a2015-10-01 20:57:57 +010040 ASSERT_EQ(nullptr, graph->GetBlocks()[i]->GetDominator());
41 ASSERT_TRUE(graph->GetBlocks()[i]->IsEntryBlock());
Nicolas Geoffrayf776b922015-04-15 18:22:45 +010042 }
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +000043 } else {
Vladimir Markoec7802a2015-10-01 20:57:57 +010044 ASSERT_NE(nullptr, graph->GetBlocks()[i]->GetDominator());
45 ASSERT_EQ(blocks[i], graph->GetBlocks()[i]->GetDominator()->GetBlockId());
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +000046 }
47 }
48}
49
David Brazdilbadd8262016-02-02 16:28:56 +000050TEST_F(OptimizerTest, ReturnVoid) {
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +000051 const uint16_t data[] = ZERO_REGISTER_CODE_ITEM(
52 Instruction::RETURN_VOID); // Block number 1
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +000053
Vladimir Markofa6b93c2015-09-15 10:15:55 +010054 const uint32_t dominators[] = {
55 kInvalidBlockId,
56 0,
57 1
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +000058 };
59
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +000060 TestCode(data, dominators, sizeof(dominators) / sizeof(int));
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +000061}
62
David Brazdilbadd8262016-02-02 16:28:56 +000063TEST_F(OptimizerTest, CFG1) {
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +000064 const uint16_t data[] = ZERO_REGISTER_CODE_ITEM(
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +000065 Instruction::GOTO | 0x100, // Block number 1
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +000066 Instruction::RETURN_VOID); // Block number 2
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +000067
Vladimir Markofa6b93c2015-09-15 10:15:55 +010068 const uint32_t dominators[] = {
69 kInvalidBlockId,
70 0,
71 1,
72 2
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +000073 };
74
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +000075 TestCode(data, dominators, sizeof(dominators) / sizeof(int));
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +000076}
77
David Brazdilbadd8262016-02-02 16:28:56 +000078TEST_F(OptimizerTest, CFG2) {
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +000079 const uint16_t data[] = ZERO_REGISTER_CODE_ITEM(
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +000080 Instruction::GOTO | 0x100, // Block number 1
81 Instruction::GOTO | 0x100, // Block number 2
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +000082 Instruction::RETURN_VOID); // Block number 3
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +000083
Vladimir Markofa6b93c2015-09-15 10:15:55 +010084 const uint32_t dominators[] = {
85 kInvalidBlockId,
86 0,
87 1,
88 2,
89 3
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +000090 };
91
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +000092 TestCode(data, dominators, sizeof(dominators) / sizeof(int));
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +000093}
94
David Brazdilbadd8262016-02-02 16:28:56 +000095TEST_F(OptimizerTest, CFG3) {
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +000096 const uint16_t data1[] = ZERO_REGISTER_CODE_ITEM(
97 Instruction::GOTO | 0x200, // Block number 1
98 Instruction::RETURN_VOID, // Block number 2
99 Instruction::GOTO | 0xFF00); // Block number 3
100
Vladimir Markofa6b93c2015-09-15 10:15:55 +0100101 const uint32_t dominators[] = {
102 kInvalidBlockId,
103 0,
104 3,
105 1,
106 2
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000107 };
108
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000109 TestCode(data1, dominators, sizeof(dominators) / sizeof(int));
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000110
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000111 const uint16_t data2[] = ZERO_REGISTER_CODE_ITEM(
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000112 Instruction::GOTO_16, 3,
113 Instruction::RETURN_VOID,
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000114 Instruction::GOTO_16, 0xFFFF);
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000115
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000116 TestCode(data2, dominators, sizeof(dominators) / sizeof(int));
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000117
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000118 const uint16_t data3[] = ZERO_REGISTER_CODE_ITEM(
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000119 Instruction::GOTO_32, 4, 0,
120 Instruction::RETURN_VOID,
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000121 Instruction::GOTO_32, 0xFFFF, 0xFFFF);
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000122
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000123 TestCode(data3, dominators, sizeof(dominators) / sizeof(int));
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000124}
125
David Brazdilbadd8262016-02-02 16:28:56 +0000126TEST_F(OptimizerTest, CFG4) {
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000127 const uint16_t data1[] = ZERO_REGISTER_CODE_ITEM(
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000128 Instruction::NOP,
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000129 Instruction::GOTO | 0xFF00);
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000130
Vladimir Markofa6b93c2015-09-15 10:15:55 +0100131 const uint32_t dominators[] = {
132 kInvalidBlockId,
Nicolas Geoffray788f2f02016-01-22 12:41:38 +0000133 3,
134 kInvalidBlockId,
135 0
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000136 };
137
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000138 TestCode(data1, dominators, sizeof(dominators) / sizeof(int));
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000139
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000140 const uint16_t data2[] = ZERO_REGISTER_CODE_ITEM(
141 Instruction::GOTO_32, 0, 0);
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000142
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000143 TestCode(data2, dominators, sizeof(dominators) / sizeof(int));
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000144}
145
David Brazdilbadd8262016-02-02 16:28:56 +0000146TEST_F(OptimizerTest, CFG5) {
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000147 const uint16_t data[] = ZERO_REGISTER_CODE_ITEM(
148 Instruction::RETURN_VOID, // Block number 1
149 Instruction::GOTO | 0x100, // Dead block
150 Instruction::GOTO | 0xFE00); // Block number 2
151
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000152
Vladimir Markofa6b93c2015-09-15 10:15:55 +0100153 const uint32_t dominators[] = {
154 kInvalidBlockId,
155 0,
156 kInvalidBlockId,
157 1
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000158 };
159
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000160 TestCode(data, dominators, sizeof(dominators) / sizeof(int));
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000161}
162
David Brazdilbadd8262016-02-02 16:28:56 +0000163TEST_F(OptimizerTest, CFG6) {
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000164 const uint16_t data[] = ONE_REGISTER_CODE_ITEM(
Nicolas Geoffray788aaad2014-03-10 12:00:43 +0000165 Instruction::CONST_4 | 0 | 0,
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000166 Instruction::IF_EQ, 3,
167 Instruction::GOTO | 0x100,
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000168 Instruction::RETURN_VOID);
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000169
Vladimir Markofa6b93c2015-09-15 10:15:55 +0100170 const uint32_t dominators[] = {
171 kInvalidBlockId,
172 0,
173 1,
174 1,
175 3,
176 1, // Synthesized block to avoid critical edge.
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000177 };
178
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000179 TestCode(data, dominators, sizeof(dominators) / sizeof(int));
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000180}
181
David Brazdilbadd8262016-02-02 16:28:56 +0000182TEST_F(OptimizerTest, CFG7) {
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000183 const uint16_t data[] = ONE_REGISTER_CODE_ITEM(
Nicolas Geoffray788aaad2014-03-10 12:00:43 +0000184 Instruction::CONST_4 | 0 | 0,
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000185 Instruction::IF_EQ, 3, // Block number 1
186 Instruction::GOTO | 0x100, // Block number 2
187 Instruction::GOTO | 0xFF00); // Block number 3
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000188
Vladimir Markofa6b93c2015-09-15 10:15:55 +0100189 const uint32_t dominators[] = {
190 kInvalidBlockId,
191 0,
192 1,
193 1,
194 kInvalidBlockId, // exit block is not dominated by any block due to the spin loop.
195 1, // block to avoid critical edge.
196 1 // block to avoid critical edge.
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000197 };
198
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000199 TestCode(data, dominators, sizeof(dominators) / sizeof(int));
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000200}
201
David Brazdilbadd8262016-02-02 16:28:56 +0000202TEST_F(OptimizerTest, CFG8) {
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000203 const uint16_t data[] = ONE_REGISTER_CODE_ITEM(
Nicolas Geoffray788aaad2014-03-10 12:00:43 +0000204 Instruction::CONST_4 | 0 | 0,
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000205 Instruction::IF_EQ, 3, // Block number 1
206 Instruction::GOTO | 0x200, // Block number 2
207 Instruction::GOTO | 0x100, // Block number 3
208 Instruction::GOTO | 0xFF00); // Block number 4
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000209
Vladimir Markofa6b93c2015-09-15 10:15:55 +0100210 const uint32_t dominators[] = {
211 kInvalidBlockId,
212 0,
213 1,
214 1,
215 1,
216 kInvalidBlockId, // exit block is not dominated by any block due to the spin loop.
217 1 // block to avoid critical edge.
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000218 };
219
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000220 TestCode(data, dominators, sizeof(dominators) / sizeof(int));
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000221}
222
David Brazdilbadd8262016-02-02 16:28:56 +0000223TEST_F(OptimizerTest, CFG9) {
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000224 const uint16_t data[] = ONE_REGISTER_CODE_ITEM(
Nicolas Geoffray788aaad2014-03-10 12:00:43 +0000225 Instruction::CONST_4 | 0 | 0,
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000226 Instruction::IF_EQ, 3, // Block number 1
227 Instruction::GOTO | 0x200, // Block number 2
228 Instruction::GOTO | 0x100, // Block number 3
229 Instruction::GOTO | 0xFE00); // Block number 4
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000230
Vladimir Markofa6b93c2015-09-15 10:15:55 +0100231 const uint32_t dominators[] = {
232 kInvalidBlockId,
233 0,
234 1,
235 1,
236 1,
237 kInvalidBlockId, // exit block is not dominated by any block due to the spin loop.
238 1 // block to avoid critical edge.
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000239 };
240
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000241 TestCode(data, dominators, sizeof(dominators) / sizeof(int));
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000242}
243
David Brazdilbadd8262016-02-02 16:28:56 +0000244TEST_F(OptimizerTest, CFG10) {
Nicolas Geoffray788aaad2014-03-10 12:00:43 +0000245 const uint16_t data[] = ONE_REGISTER_CODE_ITEM(
246 Instruction::CONST_4 | 0 | 0,
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000247 Instruction::IF_EQ, 6, // Block number 1
248 Instruction::IF_EQ, 3, // Block number 2
249 Instruction::GOTO | 0x100, // Block number 3
250 Instruction::GOTO | 0x100, // Block number 4
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000251 Instruction::RETURN_VOID); // Block number 5
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000252
Vladimir Markofa6b93c2015-09-15 10:15:55 +0100253 const uint32_t dominators[] = {
254 kInvalidBlockId,
255 0,
256 1,
257 2,
258 2,
259 1,
260 5, // Block number 5 dominates exit block
261 1, // block to avoid critical edge.
262 2 // block to avoid critical edge.
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000263 };
264
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000265 TestCode(data, dominators, sizeof(dominators) / sizeof(int));
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000266}
267
268} // namespace art