blob: 75b8e9609e6be201a5ff359ce90e32f9ada2acd4 [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"
Nicolas Geoffray622d9c32014-05-12 16:11:02 +010018#include "builder.h"
David Sehr9e734c72018-01-04 17:56:19 -080019#include "dex/dex_file.h"
20#include "dex/dex_instruction.h"
Nicolas Geoffray622d9c32014-05-12 16:11:02 +010021#include "nodes.h"
22#include "optimizing_unit_test.h"
Nicolas Geoffray622d9c32014-05-12 16:11:02 +010023#include "pretty_printer.h"
Andreas Gampe8cf9cb32017-07-19 09:28:38 -070024#include "ssa_liveness_analysis.h"
Nicolas Geoffray622d9c32014-05-12 16:11:02 +010025
26#include "gtest/gtest.h"
27
28namespace art {
29
Vladimir Markoca6fff82017-10-03 14:49:14 +010030class FindLoopsTest : public OptimizingUnitTest {};
Nicolas Geoffray622d9c32014-05-12 16:11:02 +010031
David Brazdilbadd8262016-02-02 16:28:56 +000032TEST_F(FindLoopsTest, CFG1) {
Nicolas Geoffray622d9c32014-05-12 16:11:02 +010033 // Constant is not used.
Mathieu Chartierfa3db3d2018-01-12 14:42:18 -080034 const std::vector<uint16_t> data = ONE_REGISTER_CODE_ITEM(
Nicolas Geoffray622d9c32014-05-12 16:11:02 +010035 Instruction::CONST_4 | 0 | 0,
36 Instruction::RETURN_VOID);
37
Vladimir Markoca6fff82017-10-03 14:49:14 +010038 HGraph* graph = CreateCFG(data);
Vladimir Markofa6b93c2015-09-15 10:15:55 +010039 for (HBasicBlock* block : graph->GetBlocks()) {
40 ASSERT_EQ(block->GetLoopInformation(), nullptr);
Nicolas Geoffray622d9c32014-05-12 16:11:02 +010041 }
42}
43
David Brazdilbadd8262016-02-02 16:28:56 +000044TEST_F(FindLoopsTest, CFG2) {
Mathieu Chartierfa3db3d2018-01-12 14:42:18 -080045 const std::vector<uint16_t> data = ONE_REGISTER_CODE_ITEM(
Nicolas Geoffray622d9c32014-05-12 16:11:02 +010046 Instruction::CONST_4 | 0 | 0,
47 Instruction::RETURN);
48
Vladimir Markoca6fff82017-10-03 14:49:14 +010049 HGraph* graph = CreateCFG(data);
Vladimir Markofa6b93c2015-09-15 10:15:55 +010050 for (HBasicBlock* block : graph->GetBlocks()) {
51 ASSERT_EQ(block->GetLoopInformation(), nullptr);
Nicolas Geoffray622d9c32014-05-12 16:11:02 +010052 }
53}
54
David Brazdilbadd8262016-02-02 16:28:56 +000055TEST_F(FindLoopsTest, CFG3) {
Mathieu Chartierfa3db3d2018-01-12 14:42:18 -080056 const std::vector<uint16_t> data = TWO_REGISTERS_CODE_ITEM(
Nicolas Geoffray622d9c32014-05-12 16:11:02 +010057 Instruction::CONST_4 | 3 << 12 | 0,
58 Instruction::CONST_4 | 4 << 12 | 1 << 8,
59 Instruction::ADD_INT_2ADDR | 1 << 12,
60 Instruction::GOTO | 0x100,
61 Instruction::RETURN);
62
Vladimir Markoca6fff82017-10-03 14:49:14 +010063 HGraph* graph = CreateCFG(data);
Vladimir Markofa6b93c2015-09-15 10:15:55 +010064 for (HBasicBlock* block : graph->GetBlocks()) {
65 ASSERT_EQ(block->GetLoopInformation(), nullptr);
Nicolas Geoffray622d9c32014-05-12 16:11:02 +010066 }
67}
68
David Brazdilbadd8262016-02-02 16:28:56 +000069TEST_F(FindLoopsTest, CFG4) {
Mathieu Chartierfa3db3d2018-01-12 14:42:18 -080070 const std::vector<uint16_t> data = ONE_REGISTER_CODE_ITEM(
Nicolas Geoffray622d9c32014-05-12 16:11:02 +010071 Instruction::CONST_4 | 0 | 0,
72 Instruction::IF_EQ, 4,
73 Instruction::CONST_4 | 4 << 12 | 0,
74 Instruction::GOTO | 0x200,
75 Instruction::CONST_4 | 5 << 12 | 0,
76 Instruction::RETURN | 0 << 8);
77
Vladimir Markoca6fff82017-10-03 14:49:14 +010078 HGraph* graph = CreateCFG(data);
Vladimir Markofa6b93c2015-09-15 10:15:55 +010079 for (HBasicBlock* block : graph->GetBlocks()) {
80 ASSERT_EQ(block->GetLoopInformation(), nullptr);
Nicolas Geoffray622d9c32014-05-12 16:11:02 +010081 }
82}
83
David Brazdilbadd8262016-02-02 16:28:56 +000084TEST_F(FindLoopsTest, CFG5) {
Mathieu Chartierfa3db3d2018-01-12 14:42:18 -080085 const std::vector<uint16_t> data = ONE_REGISTER_CODE_ITEM(
Nicolas Geoffray622d9c32014-05-12 16:11:02 +010086 Instruction::CONST_4 | 0 | 0,
87 Instruction::IF_EQ, 3,
88 Instruction::CONST_4 | 4 << 12 | 0,
89 Instruction::RETURN | 0 << 8);
90
Vladimir Markoca6fff82017-10-03 14:49:14 +010091 HGraph* graph = CreateCFG(data);
Vladimir Markofa6b93c2015-09-15 10:15:55 +010092 for (HBasicBlock* block : graph->GetBlocks()) {
93 ASSERT_EQ(block->GetLoopInformation(), nullptr);
Nicolas Geoffray622d9c32014-05-12 16:11:02 +010094 }
95}
96
97static void TestBlock(HGraph* graph,
Vladimir Markofa6b93c2015-09-15 10:15:55 +010098 uint32_t block_id,
Nicolas Geoffray622d9c32014-05-12 16:11:02 +010099 bool is_loop_header,
Vladimir Markofa6b93c2015-09-15 10:15:55 +0100100 uint32_t parent_loop_header_id,
Nicolas Geoffray622d9c32014-05-12 16:11:02 +0100101 const int* blocks_in_loop = nullptr,
102 size_t number_of_blocks = 0) {
Vladimir Markoec7802a2015-10-01 20:57:57 +0100103 HBasicBlock* block = graph->GetBlocks()[block_id];
Nicolas Geoffray622d9c32014-05-12 16:11:02 +0100104 ASSERT_EQ(block->IsLoopHeader(), is_loop_header);
Vladimir Markofa6b93c2015-09-15 10:15:55 +0100105 if (parent_loop_header_id == kInvalidBlockId) {
Nicolas Geoffray622d9c32014-05-12 16:11:02 +0100106 ASSERT_EQ(block->GetLoopInformation(), nullptr);
107 } else {
108 ASSERT_EQ(block->GetLoopInformation()->GetHeader()->GetBlockId(), parent_loop_header_id);
109 }
110
111 if (blocks_in_loop != nullptr) {
112 HLoopInformation* info = block->GetLoopInformation();
113 const BitVector& blocks = info->GetBlocks();
114 ASSERT_EQ(blocks.NumSetBits(), number_of_blocks);
115 for (size_t i = 0; i < number_of_blocks; ++i) {
116 ASSERT_TRUE(blocks.IsBitSet(blocks_in_loop[i]));
117 }
118 } else {
119 ASSERT_FALSE(block->IsLoopHeader());
120 }
121}
122
David Brazdilbadd8262016-02-02 16:28:56 +0000123TEST_F(FindLoopsTest, Loop1) {
Nicolas Geoffray622d9c32014-05-12 16:11:02 +0100124 // Simple loop with one preheader and one back edge.
125 // var a = 0;
126 // while (a == a) {
127 // }
128 // return;
Mathieu Chartierfa3db3d2018-01-12 14:42:18 -0800129 const std::vector<uint16_t> data = ONE_REGISTER_CODE_ITEM(
Nicolas Geoffray622d9c32014-05-12 16:11:02 +0100130 Instruction::CONST_4 | 0 | 0,
131 Instruction::IF_EQ, 3,
132 Instruction::GOTO | 0xFE00,
133 Instruction::RETURN_VOID);
134
Vladimir Markoca6fff82017-10-03 14:49:14 +0100135 HGraph* graph = CreateCFG(data);
Nicolas Geoffray622d9c32014-05-12 16:11:02 +0100136
Vladimir Markofa6b93c2015-09-15 10:15:55 +0100137 TestBlock(graph, 0, false, kInvalidBlockId); // entry block
138 TestBlock(graph, 1, false, kInvalidBlockId); // pre header
Nicolas Geoffray622d9c32014-05-12 16:11:02 +0100139 const int blocks2[] = {2, 3};
Vladimir Markofa6b93c2015-09-15 10:15:55 +0100140 TestBlock(graph, 2, true, 2, blocks2, 2); // loop header
141 TestBlock(graph, 3, false, 2); // block in loop
142 TestBlock(graph, 4, false, kInvalidBlockId); // return block
143 TestBlock(graph, 5, false, kInvalidBlockId); // exit block
Nicolas Geoffray622d9c32014-05-12 16:11:02 +0100144}
145
David Brazdilbadd8262016-02-02 16:28:56 +0000146TEST_F(FindLoopsTest, Loop2) {
Nicolas Geoffray622d9c32014-05-12 16:11:02 +0100147 // Make sure we support a preheader of a loop not being the first predecessor
148 // in the predecessor list of the header.
149 // var a = 0;
150 // while (a == a) {
151 // }
152 // return a;
Mathieu Chartierfa3db3d2018-01-12 14:42:18 -0800153 const std::vector<uint16_t> data = ONE_REGISTER_CODE_ITEM(
Nicolas Geoffray622d9c32014-05-12 16:11:02 +0100154 Instruction::CONST_4 | 0 | 0,
155 Instruction::GOTO | 0x400,
156 Instruction::IF_EQ, 4,
157 Instruction::GOTO | 0xFE00,
158 Instruction::GOTO | 0xFD00,
159 Instruction::RETURN | 0 << 8);
160
Vladimir Markoca6fff82017-10-03 14:49:14 +0100161 HGraph* graph = CreateCFG(data);
Nicolas Geoffray622d9c32014-05-12 16:11:02 +0100162
Vladimir Markofa6b93c2015-09-15 10:15:55 +0100163 TestBlock(graph, 0, false, kInvalidBlockId); // entry block
164 TestBlock(graph, 1, false, kInvalidBlockId); // goto block
Nicolas Geoffray622d9c32014-05-12 16:11:02 +0100165 const int blocks2[] = {2, 3};
Vladimir Markofa6b93c2015-09-15 10:15:55 +0100166 TestBlock(graph, 2, true, 2, blocks2, 2); // loop header
167 TestBlock(graph, 3, false, 2); // block in loop
168 TestBlock(graph, 4, false, kInvalidBlockId); // pre header
169 TestBlock(graph, 5, false, kInvalidBlockId); // return block
170 TestBlock(graph, 6, false, kInvalidBlockId); // exit block
Nicolas Geoffray622d9c32014-05-12 16:11:02 +0100171}
172
David Brazdilbadd8262016-02-02 16:28:56 +0000173TEST_F(FindLoopsTest, Loop3) {
Nicolas Geoffray622d9c32014-05-12 16:11:02 +0100174 // Make sure we create a preheader of a loop when a header originally has two
175 // incoming blocks and one back edge.
Mathieu Chartierfa3db3d2018-01-12 14:42:18 -0800176 const std::vector<uint16_t> data = ONE_REGISTER_CODE_ITEM(
Nicolas Geoffray622d9c32014-05-12 16:11:02 +0100177 Instruction::CONST_4 | 0 | 0,
178 Instruction::IF_EQ, 3,
179 Instruction::GOTO | 0x100,
180 Instruction::IF_EQ, 3,
181 Instruction::GOTO | 0xFE00,
182 Instruction::RETURN | 0 << 8);
183
Vladimir Markoca6fff82017-10-03 14:49:14 +0100184 HGraph* graph = CreateCFG(data);
Nicolas Geoffray622d9c32014-05-12 16:11:02 +0100185
Vladimir Markofa6b93c2015-09-15 10:15:55 +0100186 TestBlock(graph, 0, false, kInvalidBlockId); // entry block
187 TestBlock(graph, 1, false, kInvalidBlockId); // goto block
188 TestBlock(graph, 2, false, kInvalidBlockId);
Nicolas Geoffray622d9c32014-05-12 16:11:02 +0100189 const int blocks2[] = {3, 4};
Vladimir Markofa6b93c2015-09-15 10:15:55 +0100190 TestBlock(graph, 3, true, 3, blocks2, 2); // loop header
191 TestBlock(graph, 4, false, 3); // block in loop
192 TestBlock(graph, 5, false, kInvalidBlockId); // pre header
193 TestBlock(graph, 6, false, kInvalidBlockId); // return block
194 TestBlock(graph, 7, false, kInvalidBlockId); // exit block
195 TestBlock(graph, 8, false, kInvalidBlockId); // synthesized pre header
Nicolas Geoffray622d9c32014-05-12 16:11:02 +0100196}
197
David Brazdilbadd8262016-02-02 16:28:56 +0000198TEST_F(FindLoopsTest, Loop4) {
Nicolas Geoffray622d9c32014-05-12 16:11:02 +0100199 // Test loop with originally two back edges.
Mathieu Chartierfa3db3d2018-01-12 14:42:18 -0800200 const std::vector<uint16_t> data = ONE_REGISTER_CODE_ITEM(
Nicolas Geoffray622d9c32014-05-12 16:11:02 +0100201 Instruction::CONST_4 | 0 | 0,
202 Instruction::IF_EQ, 6,
203 Instruction::IF_EQ, 3,
204 Instruction::GOTO | 0xFC00,
205 Instruction::GOTO | 0xFB00,
206 Instruction::RETURN | 0 << 8);
207
Vladimir Markoca6fff82017-10-03 14:49:14 +0100208 HGraph* graph = CreateCFG(data);
Nicolas Geoffray622d9c32014-05-12 16:11:02 +0100209
Vladimir Markofa6b93c2015-09-15 10:15:55 +0100210 TestBlock(graph, 0, false, kInvalidBlockId); // entry block
211 TestBlock(graph, 1, false, kInvalidBlockId); // pre header
Nicolas Geoffraydb216f42015-05-05 17:02:20 +0100212 const int blocks2[] = {2, 3, 4, 5};
213 TestBlock(graph, 2, true, 2, blocks2, arraysize(blocks2)); // loop header
Vladimir Markofa6b93c2015-09-15 10:15:55 +0100214 TestBlock(graph, 3, false, 2); // block in loop
215 TestBlock(graph, 4, false, 2); // back edge
216 TestBlock(graph, 5, false, 2); // back edge
217 TestBlock(graph, 6, false, kInvalidBlockId); // return block
218 TestBlock(graph, 7, false, kInvalidBlockId); // exit block
Nicolas Geoffray622d9c32014-05-12 16:11:02 +0100219}
220
221
David Brazdilbadd8262016-02-02 16:28:56 +0000222TEST_F(FindLoopsTest, Loop5) {
Nicolas Geoffray622d9c32014-05-12 16:11:02 +0100223 // Test loop with two exit edges.
Mathieu Chartierfa3db3d2018-01-12 14:42:18 -0800224 const std::vector<uint16_t> data = ONE_REGISTER_CODE_ITEM(
Nicolas Geoffray622d9c32014-05-12 16:11:02 +0100225 Instruction::CONST_4 | 0 | 0,
226 Instruction::IF_EQ, 6,
227 Instruction::IF_EQ, 3,
228 Instruction::GOTO | 0x0200,
229 Instruction::GOTO | 0xFB00,
230 Instruction::RETURN | 0 << 8);
231
Vladimir Markoca6fff82017-10-03 14:49:14 +0100232 HGraph* graph = CreateCFG(data);
Nicolas Geoffray622d9c32014-05-12 16:11:02 +0100233
Vladimir Markofa6b93c2015-09-15 10:15:55 +0100234 TestBlock(graph, 0, false, kInvalidBlockId); // entry block
235 TestBlock(graph, 1, false, kInvalidBlockId); // pre header
Nicolas Geoffray622d9c32014-05-12 16:11:02 +0100236 const int blocks2[] = {2, 3, 5};
Vladimir Markofa6b93c2015-09-15 10:15:55 +0100237 TestBlock(graph, 2, true, 2, blocks2, 3); // loop header
238 TestBlock(graph, 3, false, 2); // block in loop
239 TestBlock(graph, 4, false, kInvalidBlockId); // loop exit
240 TestBlock(graph, 5, false, 2); // back edge
241 TestBlock(graph, 6, false, kInvalidBlockId); // return block
242 TestBlock(graph, 7, false, kInvalidBlockId); // exit block
243 TestBlock(graph, 8, false, kInvalidBlockId); // synthesized block at the loop exit
Nicolas Geoffray622d9c32014-05-12 16:11:02 +0100244}
245
David Brazdilbadd8262016-02-02 16:28:56 +0000246TEST_F(FindLoopsTest, InnerLoop) {
Mathieu Chartierfa3db3d2018-01-12 14:42:18 -0800247 const std::vector<uint16_t> data = ONE_REGISTER_CODE_ITEM(
Nicolas Geoffray622d9c32014-05-12 16:11:02 +0100248 Instruction::CONST_4 | 0 | 0,
249 Instruction::IF_EQ, 6,
250 Instruction::IF_EQ, 3,
251 Instruction::GOTO | 0xFE00, // inner loop
252 Instruction::GOTO | 0xFB00,
253 Instruction::RETURN | 0 << 8);
254
Vladimir Markoca6fff82017-10-03 14:49:14 +0100255 HGraph* graph = CreateCFG(data);
Nicolas Geoffray622d9c32014-05-12 16:11:02 +0100256
Vladimir Markofa6b93c2015-09-15 10:15:55 +0100257 TestBlock(graph, 0, false, kInvalidBlockId); // entry block
258 TestBlock(graph, 1, false, kInvalidBlockId); // pre header of outer loop
Nicolas Geoffray622d9c32014-05-12 16:11:02 +0100259 const int blocks2[] = {2, 3, 4, 5, 8};
Vladimir Markofa6b93c2015-09-15 10:15:55 +0100260 TestBlock(graph, 2, true, 2, blocks2, 5); // outer loop header
Nicolas Geoffray622d9c32014-05-12 16:11:02 +0100261 const int blocks3[] = {3, 4};
Vladimir Markofa6b93c2015-09-15 10:15:55 +0100262 TestBlock(graph, 3, true, 3, blocks3, 2); // inner loop header
263 TestBlock(graph, 4, false, 3); // back edge on inner loop
264 TestBlock(graph, 5, false, 2); // back edge on outer loop
265 TestBlock(graph, 6, false, kInvalidBlockId); // return block
266 TestBlock(graph, 7, false, kInvalidBlockId); // exit block
267 TestBlock(graph, 8, false, 2); // synthesized block as pre header of inner loop
Nicolas Geoffray622d9c32014-05-12 16:11:02 +0100268
Vladimir Markoec7802a2015-10-01 20:57:57 +0100269 ASSERT_TRUE(graph->GetBlocks()[3]->GetLoopInformation()->IsIn(
270 *graph->GetBlocks()[2]->GetLoopInformation()));
271 ASSERT_FALSE(graph->GetBlocks()[2]->GetLoopInformation()->IsIn(
272 *graph->GetBlocks()[3]->GetLoopInformation()));
Nicolas Geoffray622d9c32014-05-12 16:11:02 +0100273}
274
David Brazdilbadd8262016-02-02 16:28:56 +0000275TEST_F(FindLoopsTest, TwoLoops) {
Mathieu Chartierfa3db3d2018-01-12 14:42:18 -0800276 const std::vector<uint16_t> data = ONE_REGISTER_CODE_ITEM(
Nicolas Geoffray622d9c32014-05-12 16:11:02 +0100277 Instruction::CONST_4 | 0 | 0,
278 Instruction::IF_EQ, 3,
279 Instruction::GOTO | 0xFE00, // first loop
280 Instruction::IF_EQ, 3,
281 Instruction::GOTO | 0xFE00, // second loop
282 Instruction::RETURN | 0 << 8);
283
Vladimir Markoca6fff82017-10-03 14:49:14 +0100284 HGraph* graph = CreateCFG(data);
Nicolas Geoffray622d9c32014-05-12 16:11:02 +0100285
Vladimir Markofa6b93c2015-09-15 10:15:55 +0100286 TestBlock(graph, 0, false, kInvalidBlockId); // entry block
287 TestBlock(graph, 1, false, kInvalidBlockId); // pre header of first loop
Nicolas Geoffray622d9c32014-05-12 16:11:02 +0100288 const int blocks2[] = {2, 3};
Vladimir Markofa6b93c2015-09-15 10:15:55 +0100289 TestBlock(graph, 2, true, 2, blocks2, 2); // first loop header
290 TestBlock(graph, 3, false, 2); // back edge of first loop
Nicolas Geoffray622d9c32014-05-12 16:11:02 +0100291 const int blocks4[] = {4, 5};
Vladimir Markofa6b93c2015-09-15 10:15:55 +0100292 TestBlock(graph, 4, true, 4, blocks4, 2); // second loop header
293 TestBlock(graph, 5, false, 4); // back edge of second loop
294 TestBlock(graph, 6, false, kInvalidBlockId); // return block
295 TestBlock(graph, 7, false, kInvalidBlockId); // exit block
Nicolas Geoffray622d9c32014-05-12 16:11:02 +0100296
Vladimir Markoec7802a2015-10-01 20:57:57 +0100297 ASSERT_FALSE(graph->GetBlocks()[4]->GetLoopInformation()->IsIn(
298 *graph->GetBlocks()[2]->GetLoopInformation()));
299 ASSERT_FALSE(graph->GetBlocks()[2]->GetLoopInformation()->IsIn(
300 *graph->GetBlocks()[4]->GetLoopInformation()));
Nicolas Geoffray622d9c32014-05-12 16:11:02 +0100301}
302
David Brazdilbadd8262016-02-02 16:28:56 +0000303TEST_F(FindLoopsTest, NonNaturalLoop) {
Mathieu Chartierfa3db3d2018-01-12 14:42:18 -0800304 const std::vector<uint16_t> data = ONE_REGISTER_CODE_ITEM(
Nicolas Geoffray622d9c32014-05-12 16:11:02 +0100305 Instruction::CONST_4 | 0 | 0,
306 Instruction::IF_EQ, 3,
307 Instruction::GOTO | 0x0100,
308 Instruction::IF_EQ, 3,
309 Instruction::GOTO | 0xFD00,
310 Instruction::RETURN | 0 << 8);
311
Vladimir Markoca6fff82017-10-03 14:49:14 +0100312 HGraph* graph = CreateCFG(data);
Vladimir Markoec7802a2015-10-01 20:57:57 +0100313 ASSERT_TRUE(graph->GetBlocks()[3]->IsLoopHeader());
314 HLoopInformation* info = graph->GetBlocks()[3]->GetLoopInformation();
Vladimir Markofa6b93c2015-09-15 10:15:55 +0100315 ASSERT_EQ(1u, info->NumberOfBackEdges());
316 ASSERT_FALSE(info->GetHeader()->Dominates(info->GetBackEdges()[0]));
Nicolas Geoffray622d9c32014-05-12 16:11:02 +0100317}
318
David Brazdilbadd8262016-02-02 16:28:56 +0000319TEST_F(FindLoopsTest, DoWhileLoop) {
Mathieu Chartierfa3db3d2018-01-12 14:42:18 -0800320 const std::vector<uint16_t> data = ONE_REGISTER_CODE_ITEM(
Nicolas Geoffray622d9c32014-05-12 16:11:02 +0100321 Instruction::CONST_4 | 0 | 0,
322 Instruction::GOTO | 0x0100,
323 Instruction::IF_EQ, 0xFFFF,
324 Instruction::RETURN | 0 << 8);
325
Vladimir Markoca6fff82017-10-03 14:49:14 +0100326 HGraph* graph = CreateCFG(data);
Nicolas Geoffray622d9c32014-05-12 16:11:02 +0100327
Vladimir Markofa6b93c2015-09-15 10:15:55 +0100328 TestBlock(graph, 0, false, kInvalidBlockId); // entry block
329 TestBlock(graph, 1, false, kInvalidBlockId); // pre header of first loop
Nicolas Geoffray622d9c32014-05-12 16:11:02 +0100330 const int blocks2[] = {2, 3, 6};
Vladimir Markofa6b93c2015-09-15 10:15:55 +0100331 TestBlock(graph, 2, true, 2, blocks2, 3); // loop header
332 TestBlock(graph, 3, false, 2); // back edge of first loop
333 TestBlock(graph, 4, false, kInvalidBlockId); // return block
334 TestBlock(graph, 5, false, kInvalidBlockId); // exit block
335 TestBlock(graph, 6, false, 2); // synthesized block to avoid a critical edge
Nicolas Geoffray622d9c32014-05-12 16:11:02 +0100336}
337
338} // namespace art