blob: 2d0bc39cd57be49dd69149a4898906f7c0237c88 [file] [log] [blame]
Nicolas Geoffray804d0932014-05-02 08:46:00 +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
17#include "builder.h"
Nicolas Geoffray31d76b42014-06-09 15:02:22 +010018#include "code_generator.h"
Nicolas Geoffray804d0932014-05-02 08:46:00 +010019#include "dex_file.h"
20#include "dex_instruction.h"
21#include "nodes.h"
22#include "optimizing_unit_test.h"
23#include "ssa_liveness_analysis.h"
24#include "utils/arena_allocator.h"
25
26#include "gtest/gtest.h"
27
28namespace art {
29
Nicolas Geoffray26066f22014-06-03 10:36:16 +000030static void DumpBitVector(BitVector* vector,
31 std::ostream& buffer,
32 size_t count,
33 const char* prefix) {
34 buffer << prefix;
35 buffer << '(';
36 for (size_t i = 0; i < count; ++i) {
37 buffer << vector->IsBitSet(i);
38 }
39 buffer << ")\n";
40}
41
Nicolas Geoffray804d0932014-05-02 08:46:00 +010042static void TestCode(const uint16_t* data, const char* expected) {
43 ArenaPool pool;
44 ArenaAllocator allocator(&pool);
45 HGraphBuilder builder(&allocator);
46 const DexFile::CodeItem* item = reinterpret_cast<const DexFile::CodeItem*>(data);
47 HGraph* graph = builder.BuildGraph(*item);
48 ASSERT_NE(graph, nullptr);
49 graph->BuildDominatorTree();
50 graph->TransformToSSA();
Nicolas Geoffray0d3f5782014-05-14 09:43:38 +010051 graph->FindNaturalLoops();
Nicolas Geoffray31d76b42014-06-09 15:02:22 +010052 CodeGenerator* codegen = CodeGenerator::Create(&allocator, graph, InstructionSet::kX86);
53 SsaLivenessAnalysis liveness(*graph, codegen);
Nicolas Geoffray804d0932014-05-02 08:46:00 +010054 liveness.Analyze();
55
56 std::ostringstream buffer;
57 for (HInsertionOrderIterator it(*graph); !it.Done(); it.Advance()) {
58 HBasicBlock* block = it.Current();
59 buffer << "Block " << block->GetBlockId() << std::endl;
Nicolas Geoffray26066f22014-06-03 10:36:16 +000060 size_t ssa_values = liveness.GetNumberOfSsaValues();
Nicolas Geoffray804d0932014-05-02 08:46:00 +010061 BitVector* live_in = liveness.GetLiveInSet(*block);
Nicolas Geoffray26066f22014-06-03 10:36:16 +000062 DumpBitVector(live_in, buffer, ssa_values, " live in: ");
Nicolas Geoffray804d0932014-05-02 08:46:00 +010063 BitVector* live_out = liveness.GetLiveOutSet(*block);
Nicolas Geoffray26066f22014-06-03 10:36:16 +000064 DumpBitVector(live_out, buffer, ssa_values, " live out: ");
Nicolas Geoffray804d0932014-05-02 08:46:00 +010065 BitVector* kill = liveness.GetKillSet(*block);
Nicolas Geoffray26066f22014-06-03 10:36:16 +000066 DumpBitVector(kill, buffer, ssa_values, " kill: ");
Nicolas Geoffray804d0932014-05-02 08:46:00 +010067 }
68 ASSERT_STREQ(expected, buffer.str().c_str());
69}
70
71TEST(LivenessTest, CFG1) {
72 const char* expected =
73 "Block 0\n"
Nicolas Geoffray31d76b42014-06-09 15:02:22 +010074 " live in: (0)\n"
75 " live out: (0)\n"
76 " kill: (1)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +010077 "Block 1\n"
Nicolas Geoffray31d76b42014-06-09 15:02:22 +010078 " live in: (0)\n"
79 " live out: (0)\n"
80 " kill: (0)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +010081 "Block 2\n"
Nicolas Geoffray31d76b42014-06-09 15:02:22 +010082 " live in: (0)\n"
83 " live out: (0)\n"
84 " kill: (0)\n";
Nicolas Geoffray804d0932014-05-02 08:46:00 +010085
86 // Constant is not used.
87 const uint16_t data[] = ONE_REGISTER_CODE_ITEM(
88 Instruction::CONST_4 | 0 | 0,
89 Instruction::RETURN_VOID);
90
91 TestCode(data, expected);
92}
93
94TEST(LivenessTest, CFG2) {
95 const char* expected =
96 "Block 0\n"
Nicolas Geoffray26066f22014-06-03 10:36:16 +000097 " live in: (0)\n"
98 " live out: (1)\n"
99 " kill: (1)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100100 "Block 1\n"
Nicolas Geoffray26066f22014-06-03 10:36:16 +0000101 " live in: (1)\n"
102 " live out: (0)\n"
103 " kill: (0)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100104 "Block 2\n"
Nicolas Geoffray26066f22014-06-03 10:36:16 +0000105 " live in: (0)\n"
106 " live out: (0)\n"
107 " kill: (0)\n";
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100108
109 const uint16_t data[] = ONE_REGISTER_CODE_ITEM(
110 Instruction::CONST_4 | 0 | 0,
111 Instruction::RETURN);
112
113 TestCode(data, expected);
114}
115
116TEST(LivenessTest, CFG3) {
117 const char* expected =
118 "Block 0\n" // entry block
Nicolas Geoffray26066f22014-06-03 10:36:16 +0000119 " live in: (000)\n"
120 " live out: (110)\n"
121 " kill: (110)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100122 "Block 1\n" // block with add
Nicolas Geoffray26066f22014-06-03 10:36:16 +0000123 " live in: (110)\n"
124 " live out: (001)\n"
125 " kill: (001)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100126 "Block 2\n" // block with return
Nicolas Geoffray26066f22014-06-03 10:36:16 +0000127 " live in: (001)\n"
128 " live out: (000)\n"
129 " kill: (000)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100130 "Block 3\n" // exit block
Nicolas Geoffray26066f22014-06-03 10:36:16 +0000131 " live in: (000)\n"
132 " live out: (000)\n"
133 " kill: (000)\n";
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100134
135 const uint16_t data[] = TWO_REGISTERS_CODE_ITEM(
136 Instruction::CONST_4 | 3 << 12 | 0,
137 Instruction::CONST_4 | 4 << 12 | 1 << 8,
138 Instruction::ADD_INT_2ADDR | 1 << 12,
139 Instruction::GOTO | 0x100,
140 Instruction::RETURN);
141
142 TestCode(data, expected);
143}
144
145TEST(LivenessTest, CFG4) {
146 // var a;
147 // if (0 == 0) {
148 // a = 5;
149 // } else {
150 // a = 4;
151 // }
152 // return a;
153 //
154 // Bitsets are made of:
155 // (constant0, constant4, constant5, phi, equal test)
156 const char* expected =
157 "Block 0\n" // entry block
Nicolas Geoffray26066f22014-06-03 10:36:16 +0000158 " live in: (00000)\n"
159 " live out: (11100)\n"
160 " kill: (11100)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100161 "Block 1\n" // block with if
Nicolas Geoffray26066f22014-06-03 10:36:16 +0000162 " live in: (11100)\n"
163 " live out: (01100)\n"
164 " kill: (00010)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100165 "Block 2\n" // else block
Nicolas Geoffray26066f22014-06-03 10:36:16 +0000166 " live in: (01000)\n"
167 " live out: (00000)\n"
168 " kill: (00000)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100169 "Block 3\n" // then block
Nicolas Geoffray26066f22014-06-03 10:36:16 +0000170 " live in: (00100)\n"
171 " live out: (00000)\n"
172 " kill: (00000)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100173 "Block 4\n" // return block
Nicolas Geoffray26066f22014-06-03 10:36:16 +0000174 " live in: (00000)\n"
175 " live out: (00000)\n"
176 " kill: (00001)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100177 "Block 5\n" // exit block
Nicolas Geoffray26066f22014-06-03 10:36:16 +0000178 " live in: (00000)\n"
179 " live out: (00000)\n"
180 " kill: (00000)\n";
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100181
182 const uint16_t data[] = ONE_REGISTER_CODE_ITEM(
183 Instruction::CONST_4 | 0 | 0,
184 Instruction::IF_EQ, 4,
185 Instruction::CONST_4 | 4 << 12 | 0,
186 Instruction::GOTO | 0x200,
187 Instruction::CONST_4 | 5 << 12 | 0,
188 Instruction::RETURN | 0 << 8);
189
190 TestCode(data, expected);
191}
192
193TEST(LivenessTest, CFG5) {
194 // var a = 0;
195 // if (0 == 0) {
196 // } else {
197 // a = 4;
198 // }
199 // return a;
200 const char* expected =
201 "Block 0\n" // entry block
Nicolas Geoffray26066f22014-06-03 10:36:16 +0000202 " live in: (0000)\n"
203 " live out: (1100)\n"
204 " kill: (1100)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100205 "Block 1\n" // block with if
Nicolas Geoffray26066f22014-06-03 10:36:16 +0000206 " live in: (1100)\n"
207 " live out: (1100)\n"
208 " kill: (0010)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100209 "Block 2\n" // else block
Nicolas Geoffray26066f22014-06-03 10:36:16 +0000210 " live in: (0100)\n"
211 " live out: (0000)\n"
212 " kill: (0000)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100213 "Block 3\n" // return block
Nicolas Geoffray26066f22014-06-03 10:36:16 +0000214 " live in: (0000)\n"
215 " live out: (0000)\n"
216 " kill: (0001)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100217 "Block 4\n" // exit block
Nicolas Geoffray26066f22014-06-03 10:36:16 +0000218 " live in: (0000)\n"
219 " live out: (0000)\n"
220 " kill: (0000)\n"
Nicolas Geoffray622d9c32014-05-12 16:11:02 +0100221 "Block 5\n" // block to avoid critical edge. Predecessor is 1, successor is 3.
Nicolas Geoffray26066f22014-06-03 10:36:16 +0000222 " live in: (1000)\n"
223 " live out: (0000)\n"
224 " kill: (0000)\n";
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100225
226 const uint16_t data[] = ONE_REGISTER_CODE_ITEM(
227 Instruction::CONST_4 | 0 | 0,
228 Instruction::IF_EQ, 3,
229 Instruction::CONST_4 | 4 << 12 | 0,
230 Instruction::RETURN | 0 << 8);
231
232 TestCode(data, expected);
233}
234
235TEST(LivenessTest, Loop1) {
236 // Simple loop with one preheader and one back edge.
237 // var a = 0;
238 // while (a == a) {
239 // a = 4;
240 // }
241 // return;
242 const char* expected =
243 "Block 0\n" // entry block
Nicolas Geoffray26066f22014-06-03 10:36:16 +0000244 " live in: (0000)\n"
245 " live out: (1100)\n"
246 " kill: (1100)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100247 "Block 1\n" // pre header
Nicolas Geoffray26066f22014-06-03 10:36:16 +0000248 " live in: (1100)\n"
249 " live out: (0100)\n"
250 " kill: (0000)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100251 "Block 2\n" // loop header
Nicolas Geoffray26066f22014-06-03 10:36:16 +0000252 " live in: (0100)\n"
253 " live out: (0100)\n"
254 " kill: (0011)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100255 "Block 3\n" // back edge
Nicolas Geoffray26066f22014-06-03 10:36:16 +0000256 " live in: (0100)\n"
257 " live out: (0100)\n"
258 " kill: (0000)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100259 "Block 4\n" // return block
Nicolas Geoffray26066f22014-06-03 10:36:16 +0000260 " live in: (0000)\n"
261 " live out: (0000)\n"
262 " kill: (0000)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100263 "Block 5\n" // exit block
Nicolas Geoffray26066f22014-06-03 10:36:16 +0000264 " live in: (0000)\n"
265 " live out: (0000)\n"
266 " kill: (0000)\n";
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100267
268
269 const uint16_t data[] = ONE_REGISTER_CODE_ITEM(
270 Instruction::CONST_4 | 0 | 0,
271 Instruction::IF_EQ, 4,
272 Instruction::CONST_4 | 4 << 12 | 0,
273 Instruction::GOTO | 0xFD00,
274 Instruction::RETURN_VOID);
275
276 TestCode(data, expected);
277}
278
279TEST(LivenessTest, Loop3) {
280 // Test that the returned value stays live in a preceding loop.
281 // var a = 0;
282 // while (a == a) {
283 // a = 4;
284 // }
285 // return 5;
286 const char* expected =
287 "Block 0\n"
Nicolas Geoffray26066f22014-06-03 10:36:16 +0000288 " live in: (00000)\n"
289 " live out: (11100)\n"
290 " kill: (11100)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100291 "Block 1\n"
Nicolas Geoffray26066f22014-06-03 10:36:16 +0000292 " live in: (11100)\n"
293 " live out: (01100)\n"
294 " kill: (00000)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100295 "Block 2\n" // loop header
Nicolas Geoffray26066f22014-06-03 10:36:16 +0000296 " live in: (01100)\n"
297 " live out: (01100)\n"
298 " kill: (00011)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100299 "Block 3\n" // back edge
Nicolas Geoffray26066f22014-06-03 10:36:16 +0000300 " live in: (01100)\n"
301 " live out: (01100)\n"
302 " kill: (00000)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100303 "Block 4\n" // return block
Nicolas Geoffray26066f22014-06-03 10:36:16 +0000304 " live in: (00100)\n"
305 " live out: (00000)\n"
306 " kill: (00000)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100307 "Block 5\n" // exit block
Nicolas Geoffray26066f22014-06-03 10:36:16 +0000308 " live in: (00000)\n"
309 " live out: (00000)\n"
310 " kill: (00000)\n";
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100311
312 const uint16_t data[] = TWO_REGISTERS_CODE_ITEM(
313 Instruction::CONST_4 | 0 | 0,
314 Instruction::IF_EQ, 4,
315 Instruction::CONST_4 | 4 << 12 | 0,
316 Instruction::GOTO | 0xFD00,
317 Instruction::CONST_4 | 5 << 12 | 1 << 8,
318 Instruction::RETURN | 1 << 8);
319
320 TestCode(data, expected);
321}
322
323
324TEST(LivenessTest, Loop4) {
325 // Make sure we support a preheader of a loop not being the first predecessor
326 // in the predecessor list of the header.
327 // var a = 0;
328 // while (a == a) {
329 // a = 4;
330 // }
331 // return a;
332 // Bitsets are made of:
333 // (constant0, constant4, phi, equal test)
334 const char* expected =
335 "Block 0\n"
Nicolas Geoffray26066f22014-06-03 10:36:16 +0000336 " live in: (0000)\n"
337 " live out: (1100)\n"
338 " kill: (1100)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100339 "Block 1\n"
Nicolas Geoffray26066f22014-06-03 10:36:16 +0000340 " live in: (1100)\n"
341 " live out: (1100)\n"
342 " kill: (0000)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100343 "Block 2\n" // loop header
Nicolas Geoffray26066f22014-06-03 10:36:16 +0000344 " live in: (0100)\n"
345 " live out: (0110)\n"
346 " kill: (0011)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100347 "Block 3\n" // back edge
Nicolas Geoffray26066f22014-06-03 10:36:16 +0000348 " live in: (0100)\n"
349 " live out: (0100)\n"
350 " kill: (0000)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100351 "Block 4\n" // pre loop header
Nicolas Geoffray26066f22014-06-03 10:36:16 +0000352 " live in: (1100)\n"
353 " live out: (0100)\n"
354 " kill: (0000)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100355 "Block 5\n" // return block
Nicolas Geoffray26066f22014-06-03 10:36:16 +0000356 " live in: (0010)\n"
357 " live out: (0000)\n"
358 " kill: (0000)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100359 "Block 6\n" // exit block
Nicolas Geoffray26066f22014-06-03 10:36:16 +0000360 " live in: (0000)\n"
361 " live out: (0000)\n"
362 " kill: (0000)\n";
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100363
364 const uint16_t data[] = ONE_REGISTER_CODE_ITEM(
365 Instruction::CONST_4 | 0 | 0,
366 Instruction::GOTO | 0x500,
367 Instruction::IF_EQ, 5,
368 Instruction::CONST_4 | 4 << 12 | 0,
369 Instruction::GOTO | 0xFD00,
370 Instruction::GOTO | 0xFC00,
371 Instruction::RETURN | 0 << 8);
372
373 TestCode(data, expected);
374}
375
376TEST(LivenessTest, Loop5) {
377 // Make sure we create a preheader of a loop when a header originally has two
378 // incoming blocks and one back edge.
379 // Bitsets are made of:
380 // (constant0, constant4, constant5, equal in block 1, phi in block 8, phi in block 4,
381 // equal in block 4)
382 const char* expected =
383 "Block 0\n"
Nicolas Geoffray26066f22014-06-03 10:36:16 +0000384 " live in: (0000000)\n"
385 " live out: (1110000)\n"
386 " kill: (1110000)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100387 "Block 1\n"
Nicolas Geoffray26066f22014-06-03 10:36:16 +0000388 " live in: (1110000)\n"
389 " live out: (0110000)\n"
390 " kill: (0001000)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100391 "Block 2\n"
Nicolas Geoffray26066f22014-06-03 10:36:16 +0000392 " live in: (0100000)\n"
393 " live out: (0000000)\n"
394 " kill: (0000000)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100395 "Block 3\n"
Nicolas Geoffray26066f22014-06-03 10:36:16 +0000396 " live in: (0010000)\n"
397 " live out: (0000000)\n"
398 " kill: (0000000)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100399 "Block 4\n" // loop header
Nicolas Geoffray26066f22014-06-03 10:36:16 +0000400 " live in: (0000000)\n"
401 " live out: (0000010)\n"
402 " kill: (0000011)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100403 "Block 5\n" // back edge
Nicolas Geoffray26066f22014-06-03 10:36:16 +0000404 " live in: (0000010)\n"
405 " live out: (0000000)\n"
406 " kill: (0000000)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100407 "Block 6\n" // return block
Nicolas Geoffray26066f22014-06-03 10:36:16 +0000408 " live in: (0000010)\n"
409 " live out: (0000000)\n"
410 " kill: (0000000)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100411 "Block 7\n" // exit block
Nicolas Geoffray26066f22014-06-03 10:36:16 +0000412 " live in: (0000000)\n"
413 " live out: (0000000)\n"
414 " kill: (0000000)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100415 "Block 8\n" // synthesized pre header
Nicolas Geoffray26066f22014-06-03 10:36:16 +0000416 " live in: (0000000)\n"
417 " live out: (0000000)\n"
418 " kill: (0000100)\n";
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100419
420 const uint16_t data[] = ONE_REGISTER_CODE_ITEM(
421 Instruction::CONST_4 | 0 | 0,
422 Instruction::IF_EQ, 4,
423 Instruction::CONST_4 | 4 << 12 | 0,
424 Instruction::GOTO | 0x200,
425 Instruction::CONST_4 | 5 << 12 | 0,
426 Instruction::IF_EQ, 3,
427 Instruction::GOTO | 0xFE00,
428 Instruction::RETURN | 0 << 8);
429
430 TestCode(data, expected);
431}
432
433TEST(LivenessTest, Loop6) {
434 // Bitsets are made of:
Nicolas Geoffray622d9c32014-05-12 16:11:02 +0100435 // (constant0, constant4, constant5, phi in block 2, equal in block 2, equal in block 3,
436 // phi in block 8)
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100437 const char* expected =
438 "Block 0\n"
Nicolas Geoffray26066f22014-06-03 10:36:16 +0000439 " live in: (0000000)\n"
440 " live out: (1110000)\n"
441 " kill: (1110000)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100442 "Block 1\n"
Nicolas Geoffray26066f22014-06-03 10:36:16 +0000443 " live in: (1110000)\n"
444 " live out: (0110000)\n"
445 " kill: (0000000)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100446 "Block 2\n" // loop header
Nicolas Geoffray26066f22014-06-03 10:36:16 +0000447 " live in: (0110000)\n"
448 " live out: (0111000)\n"
449 " kill: (0001100)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100450 "Block 3\n"
Nicolas Geoffray26066f22014-06-03 10:36:16 +0000451 " live in: (0110000)\n"
452 " live out: (0110000)\n"
453 " kill: (0000010)\n"
Nicolas Geoffray622d9c32014-05-12 16:11:02 +0100454 "Block 4\n" // original back edge
Nicolas Geoffray26066f22014-06-03 10:36:16 +0000455 " live in: (0110000)\n"
456 " live out: (0110000)\n"
457 " kill: (0000000)\n"
Nicolas Geoffray622d9c32014-05-12 16:11:02 +0100458 "Block 5\n" // original back edge
Nicolas Geoffray26066f22014-06-03 10:36:16 +0000459 " live in: (0110000)\n"
460 " live out: (0110000)\n"
461 " kill: (0000000)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100462 "Block 6\n" // return block
Nicolas Geoffray26066f22014-06-03 10:36:16 +0000463 " live in: (0001000)\n"
464 " live out: (0000000)\n"
465 " kill: (0000000)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100466 "Block 7\n" // exit block
Nicolas Geoffray26066f22014-06-03 10:36:16 +0000467 " live in: (0000000)\n"
468 " live out: (0000000)\n"
469 " kill: (0000000)\n"
Nicolas Geoffray622d9c32014-05-12 16:11:02 +0100470 "Block 8\n" // synthesized back edge
Nicolas Geoffray26066f22014-06-03 10:36:16 +0000471 " live in: (0110000)\n"
472 " live out: (0110000)\n"
473 " kill: (0000001)\n";
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100474
475 const uint16_t data[] = ONE_REGISTER_CODE_ITEM(
476 Instruction::CONST_4 | 0 | 0,
477 Instruction::IF_EQ, 8,
478 Instruction::CONST_4 | 4 << 12 | 0,
479 Instruction::IF_EQ, 4,
480 Instruction::CONST_4 | 5 << 12 | 0,
481 Instruction::GOTO | 0xFA00,
482 Instruction::GOTO | 0xF900,
483 Instruction::RETURN | 0 << 8);
484
485 TestCode(data, expected);
486}
487
488
489TEST(LivenessTest, Loop7) {
490 // Bitsets are made of:
491 // (constant0, constant4, constant5, phi in block 2, equal in block 2, equal in block 3,
492 // phi in block 6)
493 const char* expected =
494 "Block 0\n"
Nicolas Geoffray26066f22014-06-03 10:36:16 +0000495 " live in: (0000000)\n"
496 " live out: (1110000)\n"
497 " kill: (1110000)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100498 "Block 1\n"
Nicolas Geoffray26066f22014-06-03 10:36:16 +0000499 " live in: (1110000)\n"
500 " live out: (0110000)\n"
501 " kill: (0000000)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100502 "Block 2\n" // loop header
Nicolas Geoffray26066f22014-06-03 10:36:16 +0000503 " live in: (0110000)\n"
504 " live out: (0111000)\n"
505 " kill: (0001100)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100506 "Block 3\n"
Nicolas Geoffray26066f22014-06-03 10:36:16 +0000507 " live in: (0110000)\n"
508 " live out: (0110000)\n"
509 " kill: (0000010)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100510 "Block 4\n" // loop exit
Nicolas Geoffray26066f22014-06-03 10:36:16 +0000511 " live in: (0010000)\n"
512 " live out: (0000000)\n"
513 " kill: (0000000)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100514 "Block 5\n" // back edge
Nicolas Geoffray26066f22014-06-03 10:36:16 +0000515 " live in: (0110000)\n"
516 " live out: (0110000)\n"
517 " kill: (0000000)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100518 "Block 6\n" // return block
Nicolas Geoffray26066f22014-06-03 10:36:16 +0000519 " live in: (0000000)\n"
520 " live out: (0000000)\n"
521 " kill: (0000001)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100522 "Block 7\n" // exit block
Nicolas Geoffray26066f22014-06-03 10:36:16 +0000523 " live in: (0000000)\n"
524 " live out: (0000000)\n"
525 " kill: (0000000)\n"
Nicolas Geoffray622d9c32014-05-12 16:11:02 +0100526 "Block 8\n" // synthesized block to avoid critical edge.
Nicolas Geoffray26066f22014-06-03 10:36:16 +0000527 " live in: (0001000)\n"
528 " live out: (0000000)\n"
529 " kill: (0000000)\n";
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100530
531 const uint16_t data[] = ONE_REGISTER_CODE_ITEM(
532 Instruction::CONST_4 | 0 | 0,
533 Instruction::IF_EQ, 8,
534 Instruction::CONST_4 | 4 << 12 | 0,
535 Instruction::IF_EQ, 4,
536 Instruction::CONST_4 | 5 << 12 | 0,
537 Instruction::GOTO | 0x0200,
538 Instruction::GOTO | 0xF900,
539 Instruction::RETURN | 0 << 8);
540
541 TestCode(data, expected);
542}
543
544} // namespace art