blob: 7a336204b68cdd85f5100888e8c0c8fec946c1a9 [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"
18#include "dex_file.h"
19#include "dex_instruction.h"
20#include "nodes.h"
21#include "optimizing_unit_test.h"
22#include "ssa_liveness_analysis.h"
23#include "utils/arena_allocator.h"
24
25#include "gtest/gtest.h"
26
27namespace art {
28
Nicolas Geoffray26066f22014-06-03 10:36:16 +000029static void DumpBitVector(BitVector* vector,
30 std::ostream& buffer,
31 size_t count,
32 const char* prefix) {
33 buffer << prefix;
34 buffer << '(';
35 for (size_t i = 0; i < count; ++i) {
36 buffer << vector->IsBitSet(i);
37 }
38 buffer << ")\n";
39}
40
Nicolas Geoffray804d0932014-05-02 08:46:00 +010041static void TestCode(const uint16_t* data, const char* expected) {
42 ArenaPool pool;
43 ArenaAllocator allocator(&pool);
44 HGraphBuilder builder(&allocator);
45 const DexFile::CodeItem* item = reinterpret_cast<const DexFile::CodeItem*>(data);
46 HGraph* graph = builder.BuildGraph(*item);
47 ASSERT_NE(graph, nullptr);
48 graph->BuildDominatorTree();
49 graph->TransformToSSA();
Nicolas Geoffray0d3f5782014-05-14 09:43:38 +010050 graph->FindNaturalLoops();
Nicolas Geoffray804d0932014-05-02 08:46:00 +010051 SsaLivenessAnalysis liveness(*graph);
52 liveness.Analyze();
53
54 std::ostringstream buffer;
55 for (HInsertionOrderIterator it(*graph); !it.Done(); it.Advance()) {
56 HBasicBlock* block = it.Current();
57 buffer << "Block " << block->GetBlockId() << std::endl;
Nicolas Geoffray26066f22014-06-03 10:36:16 +000058 size_t ssa_values = liveness.GetNumberOfSsaValues();
Nicolas Geoffray804d0932014-05-02 08:46:00 +010059 BitVector* live_in = liveness.GetLiveInSet(*block);
Nicolas Geoffray26066f22014-06-03 10:36:16 +000060 DumpBitVector(live_in, buffer, ssa_values, " live in: ");
Nicolas Geoffray804d0932014-05-02 08:46:00 +010061 BitVector* live_out = liveness.GetLiveOutSet(*block);
Nicolas Geoffray26066f22014-06-03 10:36:16 +000062 DumpBitVector(live_out, buffer, ssa_values, " live out: ");
Nicolas Geoffray804d0932014-05-02 08:46:00 +010063 BitVector* kill = liveness.GetKillSet(*block);
Nicolas Geoffray26066f22014-06-03 10:36:16 +000064 DumpBitVector(kill, buffer, ssa_values, " kill: ");
Nicolas Geoffray804d0932014-05-02 08:46:00 +010065 }
66 ASSERT_STREQ(expected, buffer.str().c_str());
67}
68
69TEST(LivenessTest, CFG1) {
70 const char* expected =
71 "Block 0\n"
72 " live in: ()\n"
73 " live out: ()\n"
74 " kill: ()\n"
75 "Block 1\n"
76 " live in: ()\n"
77 " live out: ()\n"
78 " kill: ()\n"
79 "Block 2\n"
80 " live in: ()\n"
81 " live out: ()\n"
82 " kill: ()\n";
83
84 // Constant is not used.
85 const uint16_t data[] = ONE_REGISTER_CODE_ITEM(
86 Instruction::CONST_4 | 0 | 0,
87 Instruction::RETURN_VOID);
88
89 TestCode(data, expected);
90}
91
92TEST(LivenessTest, CFG2) {
93 const char* expected =
94 "Block 0\n"
Nicolas Geoffray26066f22014-06-03 10:36:16 +000095 " live in: (0)\n"
96 " live out: (1)\n"
97 " kill: (1)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +010098 "Block 1\n"
Nicolas Geoffray26066f22014-06-03 10:36:16 +000099 " live in: (1)\n"
100 " live out: (0)\n"
101 " kill: (0)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100102 "Block 2\n"
Nicolas Geoffray26066f22014-06-03 10:36:16 +0000103 " live in: (0)\n"
104 " live out: (0)\n"
105 " kill: (0)\n";
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100106
107 const uint16_t data[] = ONE_REGISTER_CODE_ITEM(
108 Instruction::CONST_4 | 0 | 0,
109 Instruction::RETURN);
110
111 TestCode(data, expected);
112}
113
114TEST(LivenessTest, CFG3) {
115 const char* expected =
116 "Block 0\n" // entry block
Nicolas Geoffray26066f22014-06-03 10:36:16 +0000117 " live in: (000)\n"
118 " live out: (110)\n"
119 " kill: (110)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100120 "Block 1\n" // block with add
Nicolas Geoffray26066f22014-06-03 10:36:16 +0000121 " live in: (110)\n"
122 " live out: (001)\n"
123 " kill: (001)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100124 "Block 2\n" // block with return
Nicolas Geoffray26066f22014-06-03 10:36:16 +0000125 " live in: (001)\n"
126 " live out: (000)\n"
127 " kill: (000)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100128 "Block 3\n" // exit block
Nicolas Geoffray26066f22014-06-03 10:36:16 +0000129 " live in: (000)\n"
130 " live out: (000)\n"
131 " kill: (000)\n";
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100132
133 const uint16_t data[] = TWO_REGISTERS_CODE_ITEM(
134 Instruction::CONST_4 | 3 << 12 | 0,
135 Instruction::CONST_4 | 4 << 12 | 1 << 8,
136 Instruction::ADD_INT_2ADDR | 1 << 12,
137 Instruction::GOTO | 0x100,
138 Instruction::RETURN);
139
140 TestCode(data, expected);
141}
142
143TEST(LivenessTest, CFG4) {
144 // var a;
145 // if (0 == 0) {
146 // a = 5;
147 // } else {
148 // a = 4;
149 // }
150 // return a;
151 //
152 // Bitsets are made of:
153 // (constant0, constant4, constant5, phi, equal test)
154 const char* expected =
155 "Block 0\n" // entry block
Nicolas Geoffray26066f22014-06-03 10:36:16 +0000156 " live in: (00000)\n"
157 " live out: (11100)\n"
158 " kill: (11100)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100159 "Block 1\n" // block with if
Nicolas Geoffray26066f22014-06-03 10:36:16 +0000160 " live in: (11100)\n"
161 " live out: (01100)\n"
162 " kill: (00010)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100163 "Block 2\n" // else block
Nicolas Geoffray26066f22014-06-03 10:36:16 +0000164 " live in: (01000)\n"
165 " live out: (00000)\n"
166 " kill: (00000)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100167 "Block 3\n" // then block
Nicolas Geoffray26066f22014-06-03 10:36:16 +0000168 " live in: (00100)\n"
169 " live out: (00000)\n"
170 " kill: (00000)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100171 "Block 4\n" // return block
Nicolas Geoffray26066f22014-06-03 10:36:16 +0000172 " live in: (00000)\n"
173 " live out: (00000)\n"
174 " kill: (00001)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100175 "Block 5\n" // exit block
Nicolas Geoffray26066f22014-06-03 10:36:16 +0000176 " live in: (00000)\n"
177 " live out: (00000)\n"
178 " kill: (00000)\n";
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100179
180 const uint16_t data[] = ONE_REGISTER_CODE_ITEM(
181 Instruction::CONST_4 | 0 | 0,
182 Instruction::IF_EQ, 4,
183 Instruction::CONST_4 | 4 << 12 | 0,
184 Instruction::GOTO | 0x200,
185 Instruction::CONST_4 | 5 << 12 | 0,
186 Instruction::RETURN | 0 << 8);
187
188 TestCode(data, expected);
189}
190
191TEST(LivenessTest, CFG5) {
192 // var a = 0;
193 // if (0 == 0) {
194 // } else {
195 // a = 4;
196 // }
197 // return a;
198 const char* expected =
199 "Block 0\n" // entry block
Nicolas Geoffray26066f22014-06-03 10:36:16 +0000200 " live in: (0000)\n"
201 " live out: (1100)\n"
202 " kill: (1100)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100203 "Block 1\n" // block with if
Nicolas Geoffray26066f22014-06-03 10:36:16 +0000204 " live in: (1100)\n"
205 " live out: (1100)\n"
206 " kill: (0010)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100207 "Block 2\n" // else block
Nicolas Geoffray26066f22014-06-03 10:36:16 +0000208 " live in: (0100)\n"
209 " live out: (0000)\n"
210 " kill: (0000)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100211 "Block 3\n" // return block
Nicolas Geoffray26066f22014-06-03 10:36:16 +0000212 " live in: (0000)\n"
213 " live out: (0000)\n"
214 " kill: (0001)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100215 "Block 4\n" // exit block
Nicolas Geoffray26066f22014-06-03 10:36:16 +0000216 " live in: (0000)\n"
217 " live out: (0000)\n"
218 " kill: (0000)\n"
Nicolas Geoffray622d9c32014-05-12 16:11:02 +0100219 "Block 5\n" // block to avoid critical edge. Predecessor is 1, successor is 3.
Nicolas Geoffray26066f22014-06-03 10:36:16 +0000220 " live in: (1000)\n"
221 " live out: (0000)\n"
222 " kill: (0000)\n";
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100223
224 const uint16_t data[] = ONE_REGISTER_CODE_ITEM(
225 Instruction::CONST_4 | 0 | 0,
226 Instruction::IF_EQ, 3,
227 Instruction::CONST_4 | 4 << 12 | 0,
228 Instruction::RETURN | 0 << 8);
229
230 TestCode(data, expected);
231}
232
233TEST(LivenessTest, Loop1) {
234 // Simple loop with one preheader and one back edge.
235 // var a = 0;
236 // while (a == a) {
237 // a = 4;
238 // }
239 // return;
240 const char* expected =
241 "Block 0\n" // entry block
Nicolas Geoffray26066f22014-06-03 10:36:16 +0000242 " live in: (0000)\n"
243 " live out: (1100)\n"
244 " kill: (1100)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100245 "Block 1\n" // pre header
Nicolas Geoffray26066f22014-06-03 10:36:16 +0000246 " live in: (1100)\n"
247 " live out: (0100)\n"
248 " kill: (0000)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100249 "Block 2\n" // loop header
Nicolas Geoffray26066f22014-06-03 10:36:16 +0000250 " live in: (0100)\n"
251 " live out: (0100)\n"
252 " kill: (0011)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100253 "Block 3\n" // back edge
Nicolas Geoffray26066f22014-06-03 10:36:16 +0000254 " live in: (0100)\n"
255 " live out: (0100)\n"
256 " kill: (0000)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100257 "Block 4\n" // return block
Nicolas Geoffray26066f22014-06-03 10:36:16 +0000258 " live in: (0000)\n"
259 " live out: (0000)\n"
260 " kill: (0000)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100261 "Block 5\n" // exit block
Nicolas Geoffray26066f22014-06-03 10:36:16 +0000262 " live in: (0000)\n"
263 " live out: (0000)\n"
264 " kill: (0000)\n";
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100265
266
267 const uint16_t data[] = ONE_REGISTER_CODE_ITEM(
268 Instruction::CONST_4 | 0 | 0,
269 Instruction::IF_EQ, 4,
270 Instruction::CONST_4 | 4 << 12 | 0,
271 Instruction::GOTO | 0xFD00,
272 Instruction::RETURN_VOID);
273
274 TestCode(data, expected);
275}
276
277TEST(LivenessTest, Loop3) {
278 // Test that the returned value stays live in a preceding loop.
279 // var a = 0;
280 // while (a == a) {
281 // a = 4;
282 // }
283 // return 5;
284 const char* expected =
285 "Block 0\n"
Nicolas Geoffray26066f22014-06-03 10:36:16 +0000286 " live in: (00000)\n"
287 " live out: (11100)\n"
288 " kill: (11100)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100289 "Block 1\n"
Nicolas Geoffray26066f22014-06-03 10:36:16 +0000290 " live in: (11100)\n"
291 " live out: (01100)\n"
292 " kill: (00000)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100293 "Block 2\n" // loop header
Nicolas Geoffray26066f22014-06-03 10:36:16 +0000294 " live in: (01100)\n"
295 " live out: (01100)\n"
296 " kill: (00011)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100297 "Block 3\n" // back edge
Nicolas Geoffray26066f22014-06-03 10:36:16 +0000298 " live in: (01100)\n"
299 " live out: (01100)\n"
300 " kill: (00000)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100301 "Block 4\n" // return block
Nicolas Geoffray26066f22014-06-03 10:36:16 +0000302 " live in: (00100)\n"
303 " live out: (00000)\n"
304 " kill: (00000)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100305 "Block 5\n" // exit block
Nicolas Geoffray26066f22014-06-03 10:36:16 +0000306 " live in: (00000)\n"
307 " live out: (00000)\n"
308 " kill: (00000)\n";
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100309
310 const uint16_t data[] = TWO_REGISTERS_CODE_ITEM(
311 Instruction::CONST_4 | 0 | 0,
312 Instruction::IF_EQ, 4,
313 Instruction::CONST_4 | 4 << 12 | 0,
314 Instruction::GOTO | 0xFD00,
315 Instruction::CONST_4 | 5 << 12 | 1 << 8,
316 Instruction::RETURN | 1 << 8);
317
318 TestCode(data, expected);
319}
320
321
322TEST(LivenessTest, Loop4) {
323 // Make sure we support a preheader of a loop not being the first predecessor
324 // in the predecessor list of the header.
325 // var a = 0;
326 // while (a == a) {
327 // a = 4;
328 // }
329 // return a;
330 // Bitsets are made of:
331 // (constant0, constant4, phi, equal test)
332 const char* expected =
333 "Block 0\n"
Nicolas Geoffray26066f22014-06-03 10:36:16 +0000334 " live in: (0000)\n"
335 " live out: (1100)\n"
336 " kill: (1100)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100337 "Block 1\n"
Nicolas Geoffray26066f22014-06-03 10:36:16 +0000338 " live in: (1100)\n"
339 " live out: (1100)\n"
340 " kill: (0000)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100341 "Block 2\n" // loop header
Nicolas Geoffray26066f22014-06-03 10:36:16 +0000342 " live in: (0100)\n"
343 " live out: (0110)\n"
344 " kill: (0011)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100345 "Block 3\n" // back edge
Nicolas Geoffray26066f22014-06-03 10:36:16 +0000346 " live in: (0100)\n"
347 " live out: (0100)\n"
348 " kill: (0000)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100349 "Block 4\n" // pre loop header
Nicolas Geoffray26066f22014-06-03 10:36:16 +0000350 " live in: (1100)\n"
351 " live out: (0100)\n"
352 " kill: (0000)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100353 "Block 5\n" // return block
Nicolas Geoffray26066f22014-06-03 10:36:16 +0000354 " live in: (0010)\n"
355 " live out: (0000)\n"
356 " kill: (0000)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100357 "Block 6\n" // exit block
Nicolas Geoffray26066f22014-06-03 10:36:16 +0000358 " live in: (0000)\n"
359 " live out: (0000)\n"
360 " kill: (0000)\n";
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100361
362 const uint16_t data[] = ONE_REGISTER_CODE_ITEM(
363 Instruction::CONST_4 | 0 | 0,
364 Instruction::GOTO | 0x500,
365 Instruction::IF_EQ, 5,
366 Instruction::CONST_4 | 4 << 12 | 0,
367 Instruction::GOTO | 0xFD00,
368 Instruction::GOTO | 0xFC00,
369 Instruction::RETURN | 0 << 8);
370
371 TestCode(data, expected);
372}
373
374TEST(LivenessTest, Loop5) {
375 // Make sure we create a preheader of a loop when a header originally has two
376 // incoming blocks and one back edge.
377 // Bitsets are made of:
378 // (constant0, constant4, constant5, equal in block 1, phi in block 8, phi in block 4,
379 // equal in block 4)
380 const char* expected =
381 "Block 0\n"
Nicolas Geoffray26066f22014-06-03 10:36:16 +0000382 " live in: (0000000)\n"
383 " live out: (1110000)\n"
384 " kill: (1110000)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100385 "Block 1\n"
Nicolas Geoffray26066f22014-06-03 10:36:16 +0000386 " live in: (1110000)\n"
387 " live out: (0110000)\n"
388 " kill: (0001000)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100389 "Block 2\n"
Nicolas Geoffray26066f22014-06-03 10:36:16 +0000390 " live in: (0100000)\n"
391 " live out: (0000000)\n"
392 " kill: (0000000)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100393 "Block 3\n"
Nicolas Geoffray26066f22014-06-03 10:36:16 +0000394 " live in: (0010000)\n"
395 " live out: (0000000)\n"
396 " kill: (0000000)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100397 "Block 4\n" // loop header
Nicolas Geoffray26066f22014-06-03 10:36:16 +0000398 " live in: (0000000)\n"
399 " live out: (0000010)\n"
400 " kill: (0000011)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100401 "Block 5\n" // back edge
Nicolas Geoffray26066f22014-06-03 10:36:16 +0000402 " live in: (0000010)\n"
403 " live out: (0000000)\n"
404 " kill: (0000000)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100405 "Block 6\n" // return block
Nicolas Geoffray26066f22014-06-03 10:36:16 +0000406 " live in: (0000010)\n"
407 " live out: (0000000)\n"
408 " kill: (0000000)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100409 "Block 7\n" // exit block
Nicolas Geoffray26066f22014-06-03 10:36:16 +0000410 " live in: (0000000)\n"
411 " live out: (0000000)\n"
412 " kill: (0000000)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100413 "Block 8\n" // synthesized pre header
Nicolas Geoffray26066f22014-06-03 10:36:16 +0000414 " live in: (0000000)\n"
415 " live out: (0000000)\n"
416 " kill: (0000100)\n";
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100417
418 const uint16_t data[] = ONE_REGISTER_CODE_ITEM(
419 Instruction::CONST_4 | 0 | 0,
420 Instruction::IF_EQ, 4,
421 Instruction::CONST_4 | 4 << 12 | 0,
422 Instruction::GOTO | 0x200,
423 Instruction::CONST_4 | 5 << 12 | 0,
424 Instruction::IF_EQ, 3,
425 Instruction::GOTO | 0xFE00,
426 Instruction::RETURN | 0 << 8);
427
428 TestCode(data, expected);
429}
430
431TEST(LivenessTest, Loop6) {
432 // Bitsets are made of:
Nicolas Geoffray622d9c32014-05-12 16:11:02 +0100433 // (constant0, constant4, constant5, phi in block 2, equal in block 2, equal in block 3,
434 // phi in block 8)
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100435 const char* expected =
436 "Block 0\n"
Nicolas Geoffray26066f22014-06-03 10:36:16 +0000437 " live in: (0000000)\n"
438 " live out: (1110000)\n"
439 " kill: (1110000)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100440 "Block 1\n"
Nicolas Geoffray26066f22014-06-03 10:36:16 +0000441 " live in: (1110000)\n"
442 " live out: (0110000)\n"
443 " kill: (0000000)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100444 "Block 2\n" // loop header
Nicolas Geoffray26066f22014-06-03 10:36:16 +0000445 " live in: (0110000)\n"
446 " live out: (0111000)\n"
447 " kill: (0001100)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100448 "Block 3\n"
Nicolas Geoffray26066f22014-06-03 10:36:16 +0000449 " live in: (0110000)\n"
450 " live out: (0110000)\n"
451 " kill: (0000010)\n"
Nicolas Geoffray622d9c32014-05-12 16:11:02 +0100452 "Block 4\n" // original back edge
Nicolas Geoffray26066f22014-06-03 10:36:16 +0000453 " live in: (0110000)\n"
454 " live out: (0110000)\n"
455 " kill: (0000000)\n"
Nicolas Geoffray622d9c32014-05-12 16:11:02 +0100456 "Block 5\n" // original back edge
Nicolas Geoffray26066f22014-06-03 10:36:16 +0000457 " live in: (0110000)\n"
458 " live out: (0110000)\n"
459 " kill: (0000000)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100460 "Block 6\n" // return block
Nicolas Geoffray26066f22014-06-03 10:36:16 +0000461 " live in: (0001000)\n"
462 " live out: (0000000)\n"
463 " kill: (0000000)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100464 "Block 7\n" // exit block
Nicolas Geoffray26066f22014-06-03 10:36:16 +0000465 " live in: (0000000)\n"
466 " live out: (0000000)\n"
467 " kill: (0000000)\n"
Nicolas Geoffray622d9c32014-05-12 16:11:02 +0100468 "Block 8\n" // synthesized back edge
Nicolas Geoffray26066f22014-06-03 10:36:16 +0000469 " live in: (0110000)\n"
470 " live out: (0110000)\n"
471 " kill: (0000001)\n";
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100472
473 const uint16_t data[] = ONE_REGISTER_CODE_ITEM(
474 Instruction::CONST_4 | 0 | 0,
475 Instruction::IF_EQ, 8,
476 Instruction::CONST_4 | 4 << 12 | 0,
477 Instruction::IF_EQ, 4,
478 Instruction::CONST_4 | 5 << 12 | 0,
479 Instruction::GOTO | 0xFA00,
480 Instruction::GOTO | 0xF900,
481 Instruction::RETURN | 0 << 8);
482
483 TestCode(data, expected);
484}
485
486
487TEST(LivenessTest, Loop7) {
488 // Bitsets are made of:
489 // (constant0, constant4, constant5, phi in block 2, equal in block 2, equal in block 3,
490 // phi in block 6)
491 const char* expected =
492 "Block 0\n"
Nicolas Geoffray26066f22014-06-03 10:36:16 +0000493 " live in: (0000000)\n"
494 " live out: (1110000)\n"
495 " kill: (1110000)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100496 "Block 1\n"
Nicolas Geoffray26066f22014-06-03 10:36:16 +0000497 " live in: (1110000)\n"
498 " live out: (0110000)\n"
499 " kill: (0000000)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100500 "Block 2\n" // loop header
Nicolas Geoffray26066f22014-06-03 10:36:16 +0000501 " live in: (0110000)\n"
502 " live out: (0111000)\n"
503 " kill: (0001100)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100504 "Block 3\n"
Nicolas Geoffray26066f22014-06-03 10:36:16 +0000505 " live in: (0110000)\n"
506 " live out: (0110000)\n"
507 " kill: (0000010)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100508 "Block 4\n" // loop exit
Nicolas Geoffray26066f22014-06-03 10:36:16 +0000509 " live in: (0010000)\n"
510 " live out: (0000000)\n"
511 " kill: (0000000)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100512 "Block 5\n" // back edge
Nicolas Geoffray26066f22014-06-03 10:36:16 +0000513 " live in: (0110000)\n"
514 " live out: (0110000)\n"
515 " kill: (0000000)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100516 "Block 6\n" // return block
Nicolas Geoffray26066f22014-06-03 10:36:16 +0000517 " live in: (0000000)\n"
518 " live out: (0000000)\n"
519 " kill: (0000001)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100520 "Block 7\n" // exit block
Nicolas Geoffray26066f22014-06-03 10:36:16 +0000521 " live in: (0000000)\n"
522 " live out: (0000000)\n"
523 " kill: (0000000)\n"
Nicolas Geoffray622d9c32014-05-12 16:11:02 +0100524 "Block 8\n" // synthesized block to avoid critical edge.
Nicolas Geoffray26066f22014-06-03 10:36:16 +0000525 " live in: (0001000)\n"
526 " live out: (0000000)\n"
527 " kill: (0000000)\n";
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100528
529 const uint16_t data[] = ONE_REGISTER_CODE_ITEM(
530 Instruction::CONST_4 | 0 | 0,
531 Instruction::IF_EQ, 8,
532 Instruction::CONST_4 | 4 << 12 | 0,
533 Instruction::IF_EQ, 4,
534 Instruction::CONST_4 | 5 << 12 | 0,
535 Instruction::GOTO | 0x0200,
536 Instruction::GOTO | 0xF900,
537 Instruction::RETURN | 0 << 8);
538
539 TestCode(data, expected);
540}
541
542} // namespace art