blob: 1d72ba116ea5f0063e51791ff4a772dc29f2b553 [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:
Mathieu Chartierfa3db3d2018-01-12 14:42:18 -080029 void TestCode(const std::vector<uint16_t>& data, const uint32_t* blocks, size_t blocks_length);
Vladimir Markoca6fff82017-10-03 14:49:14 +010030};
David Brazdilbadd8262016-02-02 16:28:56 +000031
Mathieu Chartierfa3db3d2018-01-12 14:42:18 -080032void OptimizerTest::TestCode(const std::vector<uint16_t>& data,
33 const uint32_t* blocks,
34 size_t blocks_length) {
Vladimir Markoca6fff82017-10-03 14:49:14 +010035 HGraph* graph = CreateCFG(data);
Vladimir Markofa6b93c2015-09-15 10:15:55 +010036 ASSERT_EQ(graph->GetBlocks().size(), blocks_length);
Nicolas Geoffray804d0932014-05-02 08:46:00 +010037 for (size_t i = 0, e = blocks_length; i < e; ++i) {
Vladimir Markofa6b93c2015-09-15 10:15:55 +010038 if (blocks[i] == kInvalidBlockId) {
Vladimir Markoec7802a2015-10-01 20:57:57 +010039 if (graph->GetBlocks()[i] == nullptr) {
Nicolas Geoffrayf776b922015-04-15 18:22:45 +010040 // Dead block.
41 } else {
42 // Only the entry block has no dominator.
Vladimir Markoec7802a2015-10-01 20:57:57 +010043 ASSERT_EQ(nullptr, graph->GetBlocks()[i]->GetDominator());
44 ASSERT_TRUE(graph->GetBlocks()[i]->IsEntryBlock());
Nicolas Geoffrayf776b922015-04-15 18:22:45 +010045 }
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +000046 } else {
Vladimir Markoec7802a2015-10-01 20:57:57 +010047 ASSERT_NE(nullptr, graph->GetBlocks()[i]->GetDominator());
48 ASSERT_EQ(blocks[i], graph->GetBlocks()[i]->GetDominator()->GetBlockId());
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +000049 }
50 }
51}
52
David Brazdilbadd8262016-02-02 16:28:56 +000053TEST_F(OptimizerTest, ReturnVoid) {
Mathieu Chartierfa3db3d2018-01-12 14:42:18 -080054 const std::vector<uint16_t> data = ZERO_REGISTER_CODE_ITEM(
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +000055 Instruction::RETURN_VOID); // Block number 1
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +000056
Vladimir Markofa6b93c2015-09-15 10:15:55 +010057 const uint32_t dominators[] = {
58 kInvalidBlockId,
59 0,
60 1
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +000061 };
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
David Brazdilbadd8262016-02-02 16:28:56 +000066TEST_F(OptimizerTest, CFG1) {
Mathieu Chartierfa3db3d2018-01-12 14:42:18 -080067 const std::vector<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
Vladimir Markofa6b93c2015-09-15 10:15:55 +010071 const uint32_t dominators[] = {
72 kInvalidBlockId,
73 0,
74 1,
75 2
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +000076 };
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
David Brazdilbadd8262016-02-02 16:28:56 +000081TEST_F(OptimizerTest, CFG2) {
Mathieu Chartierfa3db3d2018-01-12 14:42:18 -080082 const std::vector<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
Vladimir Markofa6b93c2015-09-15 10:15:55 +010087 const uint32_t dominators[] = {
88 kInvalidBlockId,
89 0,
90 1,
91 2,
92 3
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +000093 };
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
David Brazdilbadd8262016-02-02 16:28:56 +000098TEST_F(OptimizerTest, CFG3) {
Mathieu Chartierfa3db3d2018-01-12 14:42:18 -080099 const std::vector<uint16_t> data1 = ZERO_REGISTER_CODE_ITEM(
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000100 Instruction::GOTO | 0x200, // Block number 1
101 Instruction::RETURN_VOID, // Block number 2
102 Instruction::GOTO | 0xFF00); // Block number 3
103
Vladimir Markofa6b93c2015-09-15 10:15:55 +0100104 const uint32_t dominators[] = {
105 kInvalidBlockId,
106 0,
107 3,
108 1,
109 2
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000110 };
111
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000112 TestCode(data1, dominators, sizeof(dominators) / sizeof(int));
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000113
Mathieu Chartierfa3db3d2018-01-12 14:42:18 -0800114 const std::vector<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
Mathieu Chartierfa3db3d2018-01-12 14:42:18 -0800121 const std::vector<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
David Brazdilbadd8262016-02-02 16:28:56 +0000129TEST_F(OptimizerTest, CFG4) {
Mathieu Chartierfa3db3d2018-01-12 14:42:18 -0800130 const std::vector<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
Vladimir Markofa6b93c2015-09-15 10:15:55 +0100134 const uint32_t dominators[] = {
135 kInvalidBlockId,
Nicolas Geoffray788f2f02016-01-22 12:41:38 +0000136 3,
137 kInvalidBlockId,
138 0
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000139 };
140
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000141 TestCode(data1, dominators, sizeof(dominators) / sizeof(int));
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000142
Mathieu Chartierfa3db3d2018-01-12 14:42:18 -0800143 const std::vector<uint16_t> data2 = ZERO_REGISTER_CODE_ITEM(
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000144 Instruction::GOTO_32, 0, 0);
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000145
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000146 TestCode(data2, dominators, sizeof(dominators) / sizeof(int));
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000147}
148
David Brazdilbadd8262016-02-02 16:28:56 +0000149TEST_F(OptimizerTest, CFG5) {
Mathieu Chartierfa3db3d2018-01-12 14:42:18 -0800150 const std::vector<uint16_t> data = ZERO_REGISTER_CODE_ITEM(
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000151 Instruction::RETURN_VOID, // Block number 1
152 Instruction::GOTO | 0x100, // Dead block
153 Instruction::GOTO | 0xFE00); // Block number 2
154
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000155
Vladimir Markofa6b93c2015-09-15 10:15:55 +0100156 const uint32_t dominators[] = {
157 kInvalidBlockId,
158 0,
159 kInvalidBlockId,
160 1
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000161 };
162
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000163 TestCode(data, dominators, sizeof(dominators) / sizeof(int));
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000164}
165
David Brazdilbadd8262016-02-02 16:28:56 +0000166TEST_F(OptimizerTest, CFG6) {
Mathieu Chartierfa3db3d2018-01-12 14:42:18 -0800167 const std::vector<uint16_t> data = ONE_REGISTER_CODE_ITEM(
Nicolas Geoffray788aaad2014-03-10 12:00:43 +0000168 Instruction::CONST_4 | 0 | 0,
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000169 Instruction::IF_EQ, 3,
170 Instruction::GOTO | 0x100,
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000171 Instruction::RETURN_VOID);
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000172
Vladimir Markofa6b93c2015-09-15 10:15:55 +0100173 const uint32_t dominators[] = {
174 kInvalidBlockId,
175 0,
176 1,
177 1,
178 3,
179 1, // Synthesized block to avoid critical edge.
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000180 };
181
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000182 TestCode(data, dominators, sizeof(dominators) / sizeof(int));
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000183}
184
David Brazdilbadd8262016-02-02 16:28:56 +0000185TEST_F(OptimizerTest, CFG7) {
Mathieu Chartierfa3db3d2018-01-12 14:42:18 -0800186 const std::vector<uint16_t> data = ONE_REGISTER_CODE_ITEM(
Nicolas Geoffray788aaad2014-03-10 12:00:43 +0000187 Instruction::CONST_4 | 0 | 0,
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000188 Instruction::IF_EQ, 3, // Block number 1
189 Instruction::GOTO | 0x100, // Block number 2
190 Instruction::GOTO | 0xFF00); // Block number 3
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000191
Vladimir Markofa6b93c2015-09-15 10:15:55 +0100192 const uint32_t dominators[] = {
193 kInvalidBlockId,
194 0,
195 1,
196 1,
197 kInvalidBlockId, // exit block is not dominated by any block due to the spin loop.
198 1, // block to avoid critical edge.
199 1 // block to avoid critical edge.
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000200 };
201
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000202 TestCode(data, dominators, sizeof(dominators) / sizeof(int));
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000203}
204
David Brazdilbadd8262016-02-02 16:28:56 +0000205TEST_F(OptimizerTest, CFG8) {
Mathieu Chartierfa3db3d2018-01-12 14:42:18 -0800206 const std::vector<uint16_t> data = ONE_REGISTER_CODE_ITEM(
Nicolas Geoffray788aaad2014-03-10 12:00:43 +0000207 Instruction::CONST_4 | 0 | 0,
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000208 Instruction::IF_EQ, 3, // Block number 1
209 Instruction::GOTO | 0x200, // Block number 2
210 Instruction::GOTO | 0x100, // Block number 3
211 Instruction::GOTO | 0xFF00); // Block number 4
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000212
Vladimir Markofa6b93c2015-09-15 10:15:55 +0100213 const uint32_t dominators[] = {
214 kInvalidBlockId,
215 0,
216 1,
217 1,
218 1,
219 kInvalidBlockId, // exit block is not dominated by any block due to the spin loop.
220 1 // block to avoid critical edge.
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000221 };
222
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000223 TestCode(data, dominators, sizeof(dominators) / sizeof(int));
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000224}
225
David Brazdilbadd8262016-02-02 16:28:56 +0000226TEST_F(OptimizerTest, CFG9) {
Mathieu Chartierfa3db3d2018-01-12 14:42:18 -0800227 const std::vector<uint16_t> data = ONE_REGISTER_CODE_ITEM(
Nicolas Geoffray788aaad2014-03-10 12:00:43 +0000228 Instruction::CONST_4 | 0 | 0,
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000229 Instruction::IF_EQ, 3, // Block number 1
230 Instruction::GOTO | 0x200, // Block number 2
231 Instruction::GOTO | 0x100, // Block number 3
232 Instruction::GOTO | 0xFE00); // Block number 4
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000233
Vladimir Markofa6b93c2015-09-15 10:15:55 +0100234 const uint32_t dominators[] = {
235 kInvalidBlockId,
236 0,
237 1,
238 1,
239 1,
240 kInvalidBlockId, // exit block is not dominated by any block due to the spin loop.
241 1 // block to avoid critical edge.
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000242 };
243
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000244 TestCode(data, dominators, sizeof(dominators) / sizeof(int));
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000245}
246
David Brazdilbadd8262016-02-02 16:28:56 +0000247TEST_F(OptimizerTest, CFG10) {
Mathieu Chartierfa3db3d2018-01-12 14:42:18 -0800248 const std::vector<uint16_t> data = ONE_REGISTER_CODE_ITEM(
Nicolas Geoffray788aaad2014-03-10 12:00:43 +0000249 Instruction::CONST_4 | 0 | 0,
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000250 Instruction::IF_EQ, 6, // Block number 1
251 Instruction::IF_EQ, 3, // Block number 2
252 Instruction::GOTO | 0x100, // Block number 3
253 Instruction::GOTO | 0x100, // Block number 4
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000254 Instruction::RETURN_VOID); // Block number 5
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000255
Vladimir Markofa6b93c2015-09-15 10:15:55 +0100256 const uint32_t dominators[] = {
257 kInvalidBlockId,
258 0,
259 1,
260 2,
261 2,
262 1,
263 5, // Block number 5 dominates exit block
264 1, // block to avoid critical edge.
265 2 // block to avoid critical edge.
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000266 };
267
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000268 TestCode(data, dominators, sizeof(dominators) / sizeof(int));
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000269}
270
271} // namespace art