blob: 572466eec835b62922732a60aaa6b91cd9d9f170 [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"
David Sehr9e734c72018-01-04 17:56:19 -080019#include "dex/dex_instruction.h"
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +000020#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
Vladimir Markoca6fff82017-10-03 14:49:14 +010027class OptimizerTest : public OptimizingUnitTest {
28 protected:
29 void TestCode(const uint16_t* data, const uint32_t* blocks, size_t blocks_length);
30};
David Brazdilbadd8262016-02-02 16:28:56 +000031
Vladimir Markoca6fff82017-10-03 14:49:14 +010032void OptimizerTest::TestCode(const uint16_t* data, const uint32_t* blocks, size_t blocks_length) {
33 HGraph* graph = CreateCFG(data);
Vladimir Markofa6b93c2015-09-15 10:15:55 +010034 ASSERT_EQ(graph->GetBlocks().size(), blocks_length);
Nicolas Geoffray804d0932014-05-02 08:46:00 +010035 for (size_t i = 0, e = blocks_length; i < e; ++i) {
Vladimir Markofa6b93c2015-09-15 10:15:55 +010036 if (blocks[i] == kInvalidBlockId) {
Vladimir Markoec7802a2015-10-01 20:57:57 +010037 if (graph->GetBlocks()[i] == nullptr) {
Nicolas Geoffrayf776b922015-04-15 18:22:45 +010038 // Dead block.
39 } else {
40 // Only the entry block has no dominator.
Vladimir Markoec7802a2015-10-01 20:57:57 +010041 ASSERT_EQ(nullptr, graph->GetBlocks()[i]->GetDominator());
42 ASSERT_TRUE(graph->GetBlocks()[i]->IsEntryBlock());
Nicolas Geoffrayf776b922015-04-15 18:22:45 +010043 }
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +000044 } else {
Vladimir Markoec7802a2015-10-01 20:57:57 +010045 ASSERT_NE(nullptr, graph->GetBlocks()[i]->GetDominator());
46 ASSERT_EQ(blocks[i], graph->GetBlocks()[i]->GetDominator()->GetBlockId());
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +000047 }
48 }
49}
50
David Brazdilbadd8262016-02-02 16:28:56 +000051TEST_F(OptimizerTest, ReturnVoid) {
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +000052 const uint16_t data[] = ZERO_REGISTER_CODE_ITEM(
53 Instruction::RETURN_VOID); // Block number 1
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +000054
Vladimir Markofa6b93c2015-09-15 10:15:55 +010055 const uint32_t dominators[] = {
56 kInvalidBlockId,
57 0,
58 1
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +000059 };
60
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +000061 TestCode(data, dominators, sizeof(dominators) / sizeof(int));
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +000062}
63
David Brazdilbadd8262016-02-02 16:28:56 +000064TEST_F(OptimizerTest, CFG1) {
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +000065 const uint16_t data[] = ZERO_REGISTER_CODE_ITEM(
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +000066 Instruction::GOTO | 0x100, // Block number 1
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +000067 Instruction::RETURN_VOID); // Block number 2
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +000068
Vladimir Markofa6b93c2015-09-15 10:15:55 +010069 const uint32_t dominators[] = {
70 kInvalidBlockId,
71 0,
72 1,
73 2
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +000074 };
75
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +000076 TestCode(data, dominators, sizeof(dominators) / sizeof(int));
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +000077}
78
David Brazdilbadd8262016-02-02 16:28:56 +000079TEST_F(OptimizerTest, CFG2) {
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +000080 const uint16_t data[] = ZERO_REGISTER_CODE_ITEM(
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +000081 Instruction::GOTO | 0x100, // Block number 1
82 Instruction::GOTO | 0x100, // Block number 2
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +000083 Instruction::RETURN_VOID); // Block number 3
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +000084
Vladimir Markofa6b93c2015-09-15 10:15:55 +010085 const uint32_t dominators[] = {
86 kInvalidBlockId,
87 0,
88 1,
89 2,
90 3
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +000091 };
92
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +000093 TestCode(data, dominators, sizeof(dominators) / sizeof(int));
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +000094}
95
David Brazdilbadd8262016-02-02 16:28:56 +000096TEST_F(OptimizerTest, CFG3) {
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +000097 const uint16_t data1[] = ZERO_REGISTER_CODE_ITEM(
98 Instruction::GOTO | 0x200, // Block number 1
99 Instruction::RETURN_VOID, // Block number 2
100 Instruction::GOTO | 0xFF00); // Block number 3
101
Vladimir Markofa6b93c2015-09-15 10:15:55 +0100102 const uint32_t dominators[] = {
103 kInvalidBlockId,
104 0,
105 3,
106 1,
107 2
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000108 };
109
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000110 TestCode(data1, dominators, sizeof(dominators) / sizeof(int));
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000111
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000112 const uint16_t data2[] = ZERO_REGISTER_CODE_ITEM(
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000113 Instruction::GOTO_16, 3,
114 Instruction::RETURN_VOID,
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000115 Instruction::GOTO_16, 0xFFFF);
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000116
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000117 TestCode(data2, dominators, sizeof(dominators) / sizeof(int));
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000118
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000119 const uint16_t data3[] = ZERO_REGISTER_CODE_ITEM(
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000120 Instruction::GOTO_32, 4, 0,
121 Instruction::RETURN_VOID,
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000122 Instruction::GOTO_32, 0xFFFF, 0xFFFF);
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000123
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000124 TestCode(data3, dominators, sizeof(dominators) / sizeof(int));
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000125}
126
David Brazdilbadd8262016-02-02 16:28:56 +0000127TEST_F(OptimizerTest, CFG4) {
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000128 const uint16_t data1[] = ZERO_REGISTER_CODE_ITEM(
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000129 Instruction::NOP,
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000130 Instruction::GOTO | 0xFF00);
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000131
Vladimir Markofa6b93c2015-09-15 10:15:55 +0100132 const uint32_t dominators[] = {
133 kInvalidBlockId,
Nicolas Geoffray788f2f02016-01-22 12:41:38 +0000134 3,
135 kInvalidBlockId,
136 0
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000137 };
138
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000139 TestCode(data1, dominators, sizeof(dominators) / sizeof(int));
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000140
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000141 const uint16_t data2[] = ZERO_REGISTER_CODE_ITEM(
142 Instruction::GOTO_32, 0, 0);
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000143
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000144 TestCode(data2, dominators, sizeof(dominators) / sizeof(int));
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000145}
146
David Brazdilbadd8262016-02-02 16:28:56 +0000147TEST_F(OptimizerTest, CFG5) {
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000148 const uint16_t data[] = ZERO_REGISTER_CODE_ITEM(
149 Instruction::RETURN_VOID, // Block number 1
150 Instruction::GOTO | 0x100, // Dead block
151 Instruction::GOTO | 0xFE00); // Block number 2
152
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000153
Vladimir Markofa6b93c2015-09-15 10:15:55 +0100154 const uint32_t dominators[] = {
155 kInvalidBlockId,
156 0,
157 kInvalidBlockId,
158 1
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000159 };
160
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000161 TestCode(data, dominators, sizeof(dominators) / sizeof(int));
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000162}
163
David Brazdilbadd8262016-02-02 16:28:56 +0000164TEST_F(OptimizerTest, CFG6) {
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000165 const uint16_t data[] = ONE_REGISTER_CODE_ITEM(
Nicolas Geoffray788aaad2014-03-10 12:00:43 +0000166 Instruction::CONST_4 | 0 | 0,
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000167 Instruction::IF_EQ, 3,
168 Instruction::GOTO | 0x100,
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000169 Instruction::RETURN_VOID);
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000170
Vladimir Markofa6b93c2015-09-15 10:15:55 +0100171 const uint32_t dominators[] = {
172 kInvalidBlockId,
173 0,
174 1,
175 1,
176 3,
177 1, // Synthesized block to avoid critical edge.
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000178 };
179
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000180 TestCode(data, dominators, sizeof(dominators) / sizeof(int));
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000181}
182
David Brazdilbadd8262016-02-02 16:28:56 +0000183TEST_F(OptimizerTest, CFG7) {
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000184 const uint16_t data[] = ONE_REGISTER_CODE_ITEM(
Nicolas Geoffray788aaad2014-03-10 12:00:43 +0000185 Instruction::CONST_4 | 0 | 0,
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000186 Instruction::IF_EQ, 3, // Block number 1
187 Instruction::GOTO | 0x100, // Block number 2
188 Instruction::GOTO | 0xFF00); // Block number 3
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000189
Vladimir Markofa6b93c2015-09-15 10:15:55 +0100190 const uint32_t dominators[] = {
191 kInvalidBlockId,
192 0,
193 1,
194 1,
195 kInvalidBlockId, // exit block is not dominated by any block due to the spin loop.
196 1, // block to avoid critical edge.
197 1 // block to avoid critical edge.
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000198 };
199
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000200 TestCode(data, dominators, sizeof(dominators) / sizeof(int));
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000201}
202
David Brazdilbadd8262016-02-02 16:28:56 +0000203TEST_F(OptimizerTest, CFG8) {
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000204 const uint16_t data[] = ONE_REGISTER_CODE_ITEM(
Nicolas Geoffray788aaad2014-03-10 12:00:43 +0000205 Instruction::CONST_4 | 0 | 0,
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000206 Instruction::IF_EQ, 3, // Block number 1
207 Instruction::GOTO | 0x200, // Block number 2
208 Instruction::GOTO | 0x100, // Block number 3
209 Instruction::GOTO | 0xFF00); // Block number 4
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000210
Vladimir Markofa6b93c2015-09-15 10:15:55 +0100211 const uint32_t dominators[] = {
212 kInvalidBlockId,
213 0,
214 1,
215 1,
216 1,
217 kInvalidBlockId, // exit block is not dominated by any block due to the spin loop.
218 1 // block to avoid critical edge.
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000219 };
220
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000221 TestCode(data, dominators, sizeof(dominators) / sizeof(int));
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000222}
223
David Brazdilbadd8262016-02-02 16:28:56 +0000224TEST_F(OptimizerTest, CFG9) {
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000225 const uint16_t data[] = ONE_REGISTER_CODE_ITEM(
Nicolas Geoffray788aaad2014-03-10 12:00:43 +0000226 Instruction::CONST_4 | 0 | 0,
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000227 Instruction::IF_EQ, 3, // Block number 1
228 Instruction::GOTO | 0x200, // Block number 2
229 Instruction::GOTO | 0x100, // Block number 3
230 Instruction::GOTO | 0xFE00); // Block number 4
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000231
Vladimir Markofa6b93c2015-09-15 10:15:55 +0100232 const uint32_t dominators[] = {
233 kInvalidBlockId,
234 0,
235 1,
236 1,
237 1,
238 kInvalidBlockId, // exit block is not dominated by any block due to the spin loop.
239 1 // block to avoid critical edge.
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000240 };
241
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000242 TestCode(data, dominators, sizeof(dominators) / sizeof(int));
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000243}
244
David Brazdilbadd8262016-02-02 16:28:56 +0000245TEST_F(OptimizerTest, CFG10) {
Nicolas Geoffray788aaad2014-03-10 12:00:43 +0000246 const uint16_t data[] = ONE_REGISTER_CODE_ITEM(
247 Instruction::CONST_4 | 0 | 0,
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000248 Instruction::IF_EQ, 6, // Block number 1
249 Instruction::IF_EQ, 3, // Block number 2
250 Instruction::GOTO | 0x100, // Block number 3
251 Instruction::GOTO | 0x100, // Block number 4
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000252 Instruction::RETURN_VOID); // Block number 5
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000253
Vladimir Markofa6b93c2015-09-15 10:15:55 +0100254 const uint32_t dominators[] = {
255 kInvalidBlockId,
256 0,
257 1,
258 2,
259 2,
260 1,
261 5, // Block number 5 dominates exit block
262 1, // block to avoid critical edge.
263 2 // block to avoid critical edge.
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000264 };
265
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000266 TestCode(data, dominators, sizeof(dominators) / sizeof(int));
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000267}
268
269} // namespace art