blob: 8857b2a7759f1061dad697daf8e5f60d10b5e4ab [file] [log] [blame]
Nicolas Geoffray622d9c32014-05-12 16:11:02 +01001/*
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"
Vladimír Marko434d9682022-11-04 14:04:17 +000018#include "base/macros.h"
Nicolas Geoffray622d9c32014-05-12 16:11:02 +010019#include "builder.h"
David Sehr9e734c72018-01-04 17:56:19 -080020#include "dex/dex_file.h"
21#include "dex/dex_instruction.h"
Nicolas Geoffray622d9c32014-05-12 16:11:02 +010022#include "nodes.h"
23#include "optimizing_unit_test.h"
Nicolas Geoffray622d9c32014-05-12 16:11:02 +010024#include "pretty_printer.h"
Andreas Gampe8cf9cb32017-07-19 09:28:38 -070025#include "ssa_liveness_analysis.h"
Nicolas Geoffray622d9c32014-05-12 16:11:02 +010026
27#include "gtest/gtest.h"
28
Vladimír Marko434d9682022-11-04 14:04:17 +000029namespace art HIDDEN {
Nicolas Geoffray622d9c32014-05-12 16:11:02 +010030
Santiago Aboy Solanes2c50b3a2023-02-10 10:25:31 +000031class FindLoopsTest : public CommonCompilerTest, public OptimizingUnitTestHelper {};
Nicolas Geoffray622d9c32014-05-12 16:11:02 +010032
David Brazdilbadd8262016-02-02 16:28:56 +000033TEST_F(FindLoopsTest, CFG1) {
Nicolas Geoffray622d9c32014-05-12 16:11:02 +010034 // Constant is not used.
Mathieu Chartierfa3db3d2018-01-12 14:42:18 -080035 const std::vector<uint16_t> data = ONE_REGISTER_CODE_ITEM(
Nicolas Geoffray622d9c32014-05-12 16:11:02 +010036 Instruction::CONST_4 | 0 | 0,
37 Instruction::RETURN_VOID);
38
Vladimir Markoca6fff82017-10-03 14:49:14 +010039 HGraph* graph = CreateCFG(data);
Vladimir Markofa6b93c2015-09-15 10:15:55 +010040 for (HBasicBlock* block : graph->GetBlocks()) {
41 ASSERT_EQ(block->GetLoopInformation(), nullptr);
Nicolas Geoffray622d9c32014-05-12 16:11:02 +010042 }
43}
44
David Brazdilbadd8262016-02-02 16:28:56 +000045TEST_F(FindLoopsTest, CFG2) {
Mathieu Chartierfa3db3d2018-01-12 14:42:18 -080046 const std::vector<uint16_t> data = ONE_REGISTER_CODE_ITEM(
Nicolas Geoffray622d9c32014-05-12 16:11:02 +010047 Instruction::CONST_4 | 0 | 0,
48 Instruction::RETURN);
49
Vladimir Markoca6fff82017-10-03 14:49:14 +010050 HGraph* graph = CreateCFG(data);
Vladimir Markofa6b93c2015-09-15 10:15:55 +010051 for (HBasicBlock* block : graph->GetBlocks()) {
52 ASSERT_EQ(block->GetLoopInformation(), nullptr);
Nicolas Geoffray622d9c32014-05-12 16:11:02 +010053 }
54}
55
David Brazdilbadd8262016-02-02 16:28:56 +000056TEST_F(FindLoopsTest, CFG3) {
Mathieu Chartierfa3db3d2018-01-12 14:42:18 -080057 const std::vector<uint16_t> data = TWO_REGISTERS_CODE_ITEM(
Nicolas Geoffray622d9c32014-05-12 16:11:02 +010058 Instruction::CONST_4 | 3 << 12 | 0,
59 Instruction::CONST_4 | 4 << 12 | 1 << 8,
60 Instruction::ADD_INT_2ADDR | 1 << 12,
61 Instruction::GOTO | 0x100,
62 Instruction::RETURN);
63
Vladimir Markoca6fff82017-10-03 14:49:14 +010064 HGraph* graph = CreateCFG(data);
Vladimir Markofa6b93c2015-09-15 10:15:55 +010065 for (HBasicBlock* block : graph->GetBlocks()) {
66 ASSERT_EQ(block->GetLoopInformation(), nullptr);
Nicolas Geoffray622d9c32014-05-12 16:11:02 +010067 }
68}
69
David Brazdilbadd8262016-02-02 16:28:56 +000070TEST_F(FindLoopsTest, CFG4) {
Mathieu Chartierfa3db3d2018-01-12 14:42:18 -080071 const std::vector<uint16_t> data = ONE_REGISTER_CODE_ITEM(
Nicolas Geoffray622d9c32014-05-12 16:11:02 +010072 Instruction::CONST_4 | 0 | 0,
73 Instruction::IF_EQ, 4,
74 Instruction::CONST_4 | 4 << 12 | 0,
75 Instruction::GOTO | 0x200,
76 Instruction::CONST_4 | 5 << 12 | 0,
77 Instruction::RETURN | 0 << 8);
78
Vladimir Markoca6fff82017-10-03 14:49:14 +010079 HGraph* graph = CreateCFG(data);
Vladimir Markofa6b93c2015-09-15 10:15:55 +010080 for (HBasicBlock* block : graph->GetBlocks()) {
81 ASSERT_EQ(block->GetLoopInformation(), nullptr);
Nicolas Geoffray622d9c32014-05-12 16:11:02 +010082 }
83}
84
David Brazdilbadd8262016-02-02 16:28:56 +000085TEST_F(FindLoopsTest, CFG5) {
Mathieu Chartierfa3db3d2018-01-12 14:42:18 -080086 const std::vector<uint16_t> data = ONE_REGISTER_CODE_ITEM(
Nicolas Geoffray622d9c32014-05-12 16:11:02 +010087 Instruction::CONST_4 | 0 | 0,
88 Instruction::IF_EQ, 3,
89 Instruction::CONST_4 | 4 << 12 | 0,
90 Instruction::RETURN | 0 << 8);
91
Vladimir Markoca6fff82017-10-03 14:49:14 +010092 HGraph* graph = CreateCFG(data);
Vladimir Markofa6b93c2015-09-15 10:15:55 +010093 for (HBasicBlock* block : graph->GetBlocks()) {
94 ASSERT_EQ(block->GetLoopInformation(), nullptr);
Nicolas Geoffray622d9c32014-05-12 16:11:02 +010095 }
96}
97
98static void TestBlock(HGraph* graph,
Vladimir Markofa6b93c2015-09-15 10:15:55 +010099 uint32_t block_id,
Nicolas Geoffray622d9c32014-05-12 16:11:02 +0100100 bool is_loop_header,
Vladimir Markofa6b93c2015-09-15 10:15:55 +0100101 uint32_t parent_loop_header_id,
Nicolas Geoffray622d9c32014-05-12 16:11:02 +0100102 const int* blocks_in_loop = nullptr,
103 size_t number_of_blocks = 0) {
Vladimir Markoec7802a2015-10-01 20:57:57 +0100104 HBasicBlock* block = graph->GetBlocks()[block_id];
Nicolas Geoffray622d9c32014-05-12 16:11:02 +0100105 ASSERT_EQ(block->IsLoopHeader(), is_loop_header);
Vladimir Markofa6b93c2015-09-15 10:15:55 +0100106 if (parent_loop_header_id == kInvalidBlockId) {
Nicolas Geoffray622d9c32014-05-12 16:11:02 +0100107 ASSERT_EQ(block->GetLoopInformation(), nullptr);
108 } else {
109 ASSERT_EQ(block->GetLoopInformation()->GetHeader()->GetBlockId(), parent_loop_header_id);
110 }
111
112 if (blocks_in_loop != nullptr) {
113 HLoopInformation* info = block->GetLoopInformation();
114 const BitVector& blocks = info->GetBlocks();
115 ASSERT_EQ(blocks.NumSetBits(), number_of_blocks);
116 for (size_t i = 0; i < number_of_blocks; ++i) {
117 ASSERT_TRUE(blocks.IsBitSet(blocks_in_loop[i]));
118 }
119 } else {
120 ASSERT_FALSE(block->IsLoopHeader());
121 }
122}
123
David Brazdilbadd8262016-02-02 16:28:56 +0000124TEST_F(FindLoopsTest, Loop1) {
Nicolas Geoffray622d9c32014-05-12 16:11:02 +0100125 // Simple loop with one preheader and one back edge.
126 // var a = 0;
127 // while (a == a) {
128 // }
129 // return;
Mathieu Chartierfa3db3d2018-01-12 14:42:18 -0800130 const std::vector<uint16_t> data = ONE_REGISTER_CODE_ITEM(
Nicolas Geoffray622d9c32014-05-12 16:11:02 +0100131 Instruction::CONST_4 | 0 | 0,
132 Instruction::IF_EQ, 3,
133 Instruction::GOTO | 0xFE00,
134 Instruction::RETURN_VOID);
135
Vladimir Markoca6fff82017-10-03 14:49:14 +0100136 HGraph* graph = CreateCFG(data);
Nicolas Geoffray622d9c32014-05-12 16:11:02 +0100137
Vladimir Markofa6b93c2015-09-15 10:15:55 +0100138 TestBlock(graph, 0, false, kInvalidBlockId); // entry block
139 TestBlock(graph, 1, false, kInvalidBlockId); // pre header
Nicolas Geoffray622d9c32014-05-12 16:11:02 +0100140 const int blocks2[] = {2, 3};
Vladimir Markofa6b93c2015-09-15 10:15:55 +0100141 TestBlock(graph, 2, true, 2, blocks2, 2); // loop header
142 TestBlock(graph, 3, false, 2); // block in loop
143 TestBlock(graph, 4, false, kInvalidBlockId); // return block
144 TestBlock(graph, 5, false, kInvalidBlockId); // exit block
Nicolas Geoffray622d9c32014-05-12 16:11:02 +0100145}
146
David Brazdilbadd8262016-02-02 16:28:56 +0000147TEST_F(FindLoopsTest, Loop2) {
Nicolas Geoffray622d9c32014-05-12 16:11:02 +0100148 // Make sure we support a preheader of a loop not being the first predecessor
149 // in the predecessor list of the header.
150 // var a = 0;
151 // while (a == a) {
152 // }
153 // return a;
Mathieu Chartierfa3db3d2018-01-12 14:42:18 -0800154 const std::vector<uint16_t> data = ONE_REGISTER_CODE_ITEM(
Nicolas Geoffray622d9c32014-05-12 16:11:02 +0100155 Instruction::CONST_4 | 0 | 0,
156 Instruction::GOTO | 0x400,
157 Instruction::IF_EQ, 4,
158 Instruction::GOTO | 0xFE00,
159 Instruction::GOTO | 0xFD00,
160 Instruction::RETURN | 0 << 8);
161
Vladimir Markoca6fff82017-10-03 14:49:14 +0100162 HGraph* graph = CreateCFG(data);
Nicolas Geoffray622d9c32014-05-12 16:11:02 +0100163
Vladimir Markofa6b93c2015-09-15 10:15:55 +0100164 TestBlock(graph, 0, false, kInvalidBlockId); // entry block
165 TestBlock(graph, 1, false, kInvalidBlockId); // goto block
Nicolas Geoffray622d9c32014-05-12 16:11:02 +0100166 const int blocks2[] = {2, 3};
Vladimir Markofa6b93c2015-09-15 10:15:55 +0100167 TestBlock(graph, 2, true, 2, blocks2, 2); // loop header
168 TestBlock(graph, 3, false, 2); // block in loop
169 TestBlock(graph, 4, false, kInvalidBlockId); // pre header
170 TestBlock(graph, 5, false, kInvalidBlockId); // return block
171 TestBlock(graph, 6, false, kInvalidBlockId); // exit block
Nicolas Geoffray622d9c32014-05-12 16:11:02 +0100172}
173
David Brazdilbadd8262016-02-02 16:28:56 +0000174TEST_F(FindLoopsTest, Loop3) {
Nicolas Geoffray622d9c32014-05-12 16:11:02 +0100175 // Make sure we create a preheader of a loop when a header originally has two
176 // incoming blocks and one back edge.
Mathieu Chartierfa3db3d2018-01-12 14:42:18 -0800177 const std::vector<uint16_t> data = ONE_REGISTER_CODE_ITEM(
Nicolas Geoffray622d9c32014-05-12 16:11:02 +0100178 Instruction::CONST_4 | 0 | 0,
179 Instruction::IF_EQ, 3,
180 Instruction::GOTO | 0x100,
181 Instruction::IF_EQ, 3,
182 Instruction::GOTO | 0xFE00,
183 Instruction::RETURN | 0 << 8);
184
Vladimir Markoca6fff82017-10-03 14:49:14 +0100185 HGraph* graph = CreateCFG(data);
Nicolas Geoffray622d9c32014-05-12 16:11:02 +0100186
Vladimir Markofa6b93c2015-09-15 10:15:55 +0100187 TestBlock(graph, 0, false, kInvalidBlockId); // entry block
188 TestBlock(graph, 1, false, kInvalidBlockId); // goto block
189 TestBlock(graph, 2, false, kInvalidBlockId);
Nicolas Geoffray622d9c32014-05-12 16:11:02 +0100190 const int blocks2[] = {3, 4};
Vladimir Markofa6b93c2015-09-15 10:15:55 +0100191 TestBlock(graph, 3, true, 3, blocks2, 2); // loop header
192 TestBlock(graph, 4, false, 3); // block in loop
193 TestBlock(graph, 5, false, kInvalidBlockId); // pre header
194 TestBlock(graph, 6, false, kInvalidBlockId); // return block
195 TestBlock(graph, 7, false, kInvalidBlockId); // exit block
196 TestBlock(graph, 8, false, kInvalidBlockId); // synthesized pre header
Nicolas Geoffray622d9c32014-05-12 16:11:02 +0100197}
198
David Brazdilbadd8262016-02-02 16:28:56 +0000199TEST_F(FindLoopsTest, Loop4) {
Nicolas Geoffray622d9c32014-05-12 16:11:02 +0100200 // Test loop with originally two back edges.
Mathieu Chartierfa3db3d2018-01-12 14:42:18 -0800201 const std::vector<uint16_t> data = ONE_REGISTER_CODE_ITEM(
Nicolas Geoffray622d9c32014-05-12 16:11:02 +0100202 Instruction::CONST_4 | 0 | 0,
203 Instruction::IF_EQ, 6,
204 Instruction::IF_EQ, 3,
205 Instruction::GOTO | 0xFC00,
206 Instruction::GOTO | 0xFB00,
207 Instruction::RETURN | 0 << 8);
208
Vladimir Markoca6fff82017-10-03 14:49:14 +0100209 HGraph* graph = CreateCFG(data);
Nicolas Geoffray622d9c32014-05-12 16:11:02 +0100210
Vladimir Markofa6b93c2015-09-15 10:15:55 +0100211 TestBlock(graph, 0, false, kInvalidBlockId); // entry block
212 TestBlock(graph, 1, false, kInvalidBlockId); // pre header
Nicolas Geoffraydb216f42015-05-05 17:02:20 +0100213 const int blocks2[] = {2, 3, 4, 5};
214 TestBlock(graph, 2, true, 2, blocks2, arraysize(blocks2)); // loop header
Vladimir Markofa6b93c2015-09-15 10:15:55 +0100215 TestBlock(graph, 3, false, 2); // block in loop
216 TestBlock(graph, 4, false, 2); // back edge
217 TestBlock(graph, 5, false, 2); // back edge
218 TestBlock(graph, 6, false, kInvalidBlockId); // return block
219 TestBlock(graph, 7, false, kInvalidBlockId); // exit block
Nicolas Geoffray622d9c32014-05-12 16:11:02 +0100220}
221
222
David Brazdilbadd8262016-02-02 16:28:56 +0000223TEST_F(FindLoopsTest, Loop5) {
Nicolas Geoffray622d9c32014-05-12 16:11:02 +0100224 // Test loop with two exit edges.
Mathieu Chartierfa3db3d2018-01-12 14:42:18 -0800225 const std::vector<uint16_t> data = ONE_REGISTER_CODE_ITEM(
Nicolas Geoffray622d9c32014-05-12 16:11:02 +0100226 Instruction::CONST_4 | 0 | 0,
227 Instruction::IF_EQ, 6,
228 Instruction::IF_EQ, 3,
229 Instruction::GOTO | 0x0200,
230 Instruction::GOTO | 0xFB00,
231 Instruction::RETURN | 0 << 8);
232
Vladimir Markoca6fff82017-10-03 14:49:14 +0100233 HGraph* graph = CreateCFG(data);
Nicolas Geoffray622d9c32014-05-12 16:11:02 +0100234
Vladimir Markofa6b93c2015-09-15 10:15:55 +0100235 TestBlock(graph, 0, false, kInvalidBlockId); // entry block
236 TestBlock(graph, 1, false, kInvalidBlockId); // pre header
Nicolas Geoffray622d9c32014-05-12 16:11:02 +0100237 const int blocks2[] = {2, 3, 5};
Vladimir Markofa6b93c2015-09-15 10:15:55 +0100238 TestBlock(graph, 2, true, 2, blocks2, 3); // loop header
239 TestBlock(graph, 3, false, 2); // block in loop
240 TestBlock(graph, 4, false, kInvalidBlockId); // loop exit
241 TestBlock(graph, 5, false, 2); // back edge
242 TestBlock(graph, 6, false, kInvalidBlockId); // return block
243 TestBlock(graph, 7, false, kInvalidBlockId); // exit block
244 TestBlock(graph, 8, false, kInvalidBlockId); // synthesized block at the loop exit
Nicolas Geoffray622d9c32014-05-12 16:11:02 +0100245}
246
David Brazdilbadd8262016-02-02 16:28:56 +0000247TEST_F(FindLoopsTest, InnerLoop) {
Mathieu Chartierfa3db3d2018-01-12 14:42:18 -0800248 const std::vector<uint16_t> data = ONE_REGISTER_CODE_ITEM(
Nicolas Geoffray622d9c32014-05-12 16:11:02 +0100249 Instruction::CONST_4 | 0 | 0,
250 Instruction::IF_EQ, 6,
251 Instruction::IF_EQ, 3,
252 Instruction::GOTO | 0xFE00, // inner loop
253 Instruction::GOTO | 0xFB00,
254 Instruction::RETURN | 0 << 8);
255
Vladimir Markoca6fff82017-10-03 14:49:14 +0100256 HGraph* graph = CreateCFG(data);
Nicolas Geoffray622d9c32014-05-12 16:11:02 +0100257
Vladimir Markofa6b93c2015-09-15 10:15:55 +0100258 TestBlock(graph, 0, false, kInvalidBlockId); // entry block
259 TestBlock(graph, 1, false, kInvalidBlockId); // pre header of outer loop
Nicolas Geoffray622d9c32014-05-12 16:11:02 +0100260 const int blocks2[] = {2, 3, 4, 5, 8};
Vladimir Markofa6b93c2015-09-15 10:15:55 +0100261 TestBlock(graph, 2, true, 2, blocks2, 5); // outer loop header
Nicolas Geoffray622d9c32014-05-12 16:11:02 +0100262 const int blocks3[] = {3, 4};
Vladimir Markofa6b93c2015-09-15 10:15:55 +0100263 TestBlock(graph, 3, true, 3, blocks3, 2); // inner loop header
264 TestBlock(graph, 4, false, 3); // back edge on inner loop
265 TestBlock(graph, 5, false, 2); // back edge on outer loop
266 TestBlock(graph, 6, false, kInvalidBlockId); // return block
267 TestBlock(graph, 7, false, kInvalidBlockId); // exit block
268 TestBlock(graph, 8, false, 2); // synthesized block as pre header of inner loop
Nicolas Geoffray622d9c32014-05-12 16:11:02 +0100269
Vladimir Markoec7802a2015-10-01 20:57:57 +0100270 ASSERT_TRUE(graph->GetBlocks()[3]->GetLoopInformation()->IsIn(
271 *graph->GetBlocks()[2]->GetLoopInformation()));
272 ASSERT_FALSE(graph->GetBlocks()[2]->GetLoopInformation()->IsIn(
273 *graph->GetBlocks()[3]->GetLoopInformation()));
Nicolas Geoffray622d9c32014-05-12 16:11:02 +0100274}
275
David Brazdilbadd8262016-02-02 16:28:56 +0000276TEST_F(FindLoopsTest, TwoLoops) {
Mathieu Chartierfa3db3d2018-01-12 14:42:18 -0800277 const std::vector<uint16_t> data = ONE_REGISTER_CODE_ITEM(
Nicolas Geoffray622d9c32014-05-12 16:11:02 +0100278 Instruction::CONST_4 | 0 | 0,
279 Instruction::IF_EQ, 3,
280 Instruction::GOTO | 0xFE00, // first loop
281 Instruction::IF_EQ, 3,
282 Instruction::GOTO | 0xFE00, // second loop
283 Instruction::RETURN | 0 << 8);
284
Vladimir Markoca6fff82017-10-03 14:49:14 +0100285 HGraph* graph = CreateCFG(data);
Nicolas Geoffray622d9c32014-05-12 16:11:02 +0100286
Vladimir Markofa6b93c2015-09-15 10:15:55 +0100287 TestBlock(graph, 0, false, kInvalidBlockId); // entry block
288 TestBlock(graph, 1, false, kInvalidBlockId); // pre header of first loop
Nicolas Geoffray622d9c32014-05-12 16:11:02 +0100289 const int blocks2[] = {2, 3};
Vladimir Markofa6b93c2015-09-15 10:15:55 +0100290 TestBlock(graph, 2, true, 2, blocks2, 2); // first loop header
291 TestBlock(graph, 3, false, 2); // back edge of first loop
Nicolas Geoffray622d9c32014-05-12 16:11:02 +0100292 const int blocks4[] = {4, 5};
Vladimir Markofa6b93c2015-09-15 10:15:55 +0100293 TestBlock(graph, 4, true, 4, blocks4, 2); // second loop header
294 TestBlock(graph, 5, false, 4); // back edge of second loop
295 TestBlock(graph, 6, false, kInvalidBlockId); // return block
296 TestBlock(graph, 7, false, kInvalidBlockId); // exit block
Nicolas Geoffray622d9c32014-05-12 16:11:02 +0100297
Vladimir Markoec7802a2015-10-01 20:57:57 +0100298 ASSERT_FALSE(graph->GetBlocks()[4]->GetLoopInformation()->IsIn(
299 *graph->GetBlocks()[2]->GetLoopInformation()));
300 ASSERT_FALSE(graph->GetBlocks()[2]->GetLoopInformation()->IsIn(
301 *graph->GetBlocks()[4]->GetLoopInformation()));
Nicolas Geoffray622d9c32014-05-12 16:11:02 +0100302}
303
David Brazdilbadd8262016-02-02 16:28:56 +0000304TEST_F(FindLoopsTest, NonNaturalLoop) {
Mathieu Chartierfa3db3d2018-01-12 14:42:18 -0800305 const std::vector<uint16_t> data = ONE_REGISTER_CODE_ITEM(
Nicolas Geoffray622d9c32014-05-12 16:11:02 +0100306 Instruction::CONST_4 | 0 | 0,
307 Instruction::IF_EQ, 3,
308 Instruction::GOTO | 0x0100,
309 Instruction::IF_EQ, 3,
310 Instruction::GOTO | 0xFD00,
311 Instruction::RETURN | 0 << 8);
312
Vladimir Markoca6fff82017-10-03 14:49:14 +0100313 HGraph* graph = CreateCFG(data);
Vladimir Markoec7802a2015-10-01 20:57:57 +0100314 ASSERT_TRUE(graph->GetBlocks()[3]->IsLoopHeader());
315 HLoopInformation* info = graph->GetBlocks()[3]->GetLoopInformation();
Vladimir Markofa6b93c2015-09-15 10:15:55 +0100316 ASSERT_EQ(1u, info->NumberOfBackEdges());
317 ASSERT_FALSE(info->GetHeader()->Dominates(info->GetBackEdges()[0]));
Nicolas Geoffray622d9c32014-05-12 16:11:02 +0100318}
319
David Brazdilbadd8262016-02-02 16:28:56 +0000320TEST_F(FindLoopsTest, DoWhileLoop) {
Mathieu Chartierfa3db3d2018-01-12 14:42:18 -0800321 const std::vector<uint16_t> data = ONE_REGISTER_CODE_ITEM(
Nicolas Geoffray622d9c32014-05-12 16:11:02 +0100322 Instruction::CONST_4 | 0 | 0,
323 Instruction::GOTO | 0x0100,
324 Instruction::IF_EQ, 0xFFFF,
325 Instruction::RETURN | 0 << 8);
326
Vladimir Markoca6fff82017-10-03 14:49:14 +0100327 HGraph* graph = CreateCFG(data);
Nicolas Geoffray622d9c32014-05-12 16:11:02 +0100328
Vladimir Markofa6b93c2015-09-15 10:15:55 +0100329 TestBlock(graph, 0, false, kInvalidBlockId); // entry block
330 TestBlock(graph, 1, false, kInvalidBlockId); // pre header of first loop
Nicolas Geoffray622d9c32014-05-12 16:11:02 +0100331 const int blocks2[] = {2, 3, 6};
Vladimir Markofa6b93c2015-09-15 10:15:55 +0100332 TestBlock(graph, 2, true, 2, blocks2, 3); // loop header
333 TestBlock(graph, 3, false, 2); // back edge of first loop
334 TestBlock(graph, 4, false, kInvalidBlockId); // return block
335 TestBlock(graph, 5, false, kInvalidBlockId); // exit block
336 TestBlock(graph, 6, false, 2); // synthesized block to avoid a critical edge
Nicolas Geoffray622d9c32014-05-12 16:11:02 +0100337}
338
339} // namespace art