blob: 246e7ef3094deaec491e94041904197fa8226add [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 Geoffray8a16d972014-09-11 10:30:02 +010019#include "code_generator_x86.h"
Nicolas Geoffray804d0932014-05-02 08:46:00 +010020#include "dex_file.h"
21#include "dex_instruction.h"
22#include "nodes.h"
23#include "optimizing_unit_test.h"
Nicolas Geoffray360231a2014-10-08 21:07:48 +010024#include "prepare_for_register_allocation.h"
Nicolas Geoffray804d0932014-05-02 08:46:00 +010025#include "ssa_liveness_analysis.h"
26#include "utils/arena_allocator.h"
27
28#include "gtest/gtest.h"
29
30namespace art {
31
Nicolas Geoffray26066f22014-06-03 10:36:16 +000032static void DumpBitVector(BitVector* vector,
33 std::ostream& buffer,
34 size_t count,
35 const char* prefix) {
36 buffer << prefix;
37 buffer << '(';
38 for (size_t i = 0; i < count; ++i) {
39 buffer << vector->IsBitSet(i);
40 }
41 buffer << ")\n";
42}
43
Nicolas Geoffray804d0932014-05-02 08:46:00 +010044static void TestCode(const uint16_t* data, const char* expected) {
45 ArenaPool pool;
46 ArenaAllocator allocator(&pool);
47 HGraphBuilder builder(&allocator);
48 const DexFile::CodeItem* item = reinterpret_cast<const DexFile::CodeItem*>(data);
49 HGraph* graph = builder.BuildGraph(*item);
50 ASSERT_NE(graph, nullptr);
51 graph->BuildDominatorTree();
52 graph->TransformToSSA();
Nicolas Geoffray0d3f5782014-05-14 09:43:38 +010053 graph->FindNaturalLoops();
Nicolas Geoffray360231a2014-10-08 21:07:48 +010054 // `Inline` conditions into ifs.
55 PrepareForRegisterAllocation(graph).Run();
Nicolas Geoffray8a16d972014-09-11 10:30:02 +010056 x86::CodeGeneratorX86 codegen(graph);
57 SsaLivenessAnalysis liveness(*graph, &codegen);
Nicolas Geoffray804d0932014-05-02 08:46:00 +010058 liveness.Analyze();
59
60 std::ostringstream buffer;
61 for (HInsertionOrderIterator it(*graph); !it.Done(); it.Advance()) {
62 HBasicBlock* block = it.Current();
63 buffer << "Block " << block->GetBlockId() << std::endl;
Nicolas Geoffray26066f22014-06-03 10:36:16 +000064 size_t ssa_values = liveness.GetNumberOfSsaValues();
Nicolas Geoffray804d0932014-05-02 08:46:00 +010065 BitVector* live_in = liveness.GetLiveInSet(*block);
Nicolas Geoffray26066f22014-06-03 10:36:16 +000066 DumpBitVector(live_in, buffer, ssa_values, " live in: ");
Nicolas Geoffray804d0932014-05-02 08:46:00 +010067 BitVector* live_out = liveness.GetLiveOutSet(*block);
Nicolas Geoffray26066f22014-06-03 10:36:16 +000068 DumpBitVector(live_out, buffer, ssa_values, " live out: ");
Nicolas Geoffray804d0932014-05-02 08:46:00 +010069 BitVector* kill = liveness.GetKillSet(*block);
Nicolas Geoffray26066f22014-06-03 10:36:16 +000070 DumpBitVector(kill, buffer, ssa_values, " kill: ");
Nicolas Geoffray804d0932014-05-02 08:46:00 +010071 }
72 ASSERT_STREQ(expected, buffer.str().c_str());
73}
74
75TEST(LivenessTest, CFG1) {
76 const char* expected =
77 "Block 0\n"
Nicolas Geoffray31d76b42014-06-09 15:02:22 +010078 " live in: (0)\n"
79 " live out: (0)\n"
80 " kill: (1)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +010081 "Block 1\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 "Block 2\n"
Nicolas Geoffray31d76b42014-06-09 15:02:22 +010086 " live in: (0)\n"
87 " live out: (0)\n"
88 " kill: (0)\n";
Nicolas Geoffray804d0932014-05-02 08:46:00 +010089
90 // Constant is not used.
91 const uint16_t data[] = ONE_REGISTER_CODE_ITEM(
92 Instruction::CONST_4 | 0 | 0,
93 Instruction::RETURN_VOID);
94
95 TestCode(data, expected);
96}
97
98TEST(LivenessTest, CFG2) {
99 const char* expected =
100 "Block 0\n"
Nicolas Geoffray26066f22014-06-03 10:36:16 +0000101 " live in: (0)\n"
102 " live out: (1)\n"
103 " kill: (1)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100104 "Block 1\n"
Nicolas Geoffray26066f22014-06-03 10:36:16 +0000105 " live in: (1)\n"
106 " live out: (0)\n"
107 " kill: (0)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100108 "Block 2\n"
Nicolas Geoffray26066f22014-06-03 10:36:16 +0000109 " live in: (0)\n"
110 " live out: (0)\n"
111 " kill: (0)\n";
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100112
113 const uint16_t data[] = ONE_REGISTER_CODE_ITEM(
114 Instruction::CONST_4 | 0 | 0,
115 Instruction::RETURN);
116
117 TestCode(data, expected);
118}
119
120TEST(LivenessTest, CFG3) {
121 const char* expected =
122 "Block 0\n" // entry block
Nicolas Geoffray26066f22014-06-03 10:36:16 +0000123 " live in: (000)\n"
124 " live out: (110)\n"
125 " kill: (110)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100126 "Block 1\n" // block with add
Nicolas Geoffray26066f22014-06-03 10:36:16 +0000127 " live in: (110)\n"
128 " live out: (001)\n"
129 " kill: (001)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100130 "Block 2\n" // block with return
Nicolas Geoffray26066f22014-06-03 10:36:16 +0000131 " live in: (001)\n"
132 " live out: (000)\n"
133 " kill: (000)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100134 "Block 3\n" // exit block
Nicolas Geoffray26066f22014-06-03 10:36:16 +0000135 " live in: (000)\n"
136 " live out: (000)\n"
137 " kill: (000)\n";
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100138
139 const uint16_t data[] = TWO_REGISTERS_CODE_ITEM(
140 Instruction::CONST_4 | 3 << 12 | 0,
141 Instruction::CONST_4 | 4 << 12 | 1 << 8,
142 Instruction::ADD_INT_2ADDR | 1 << 12,
143 Instruction::GOTO | 0x100,
144 Instruction::RETURN);
145
146 TestCode(data, expected);
147}
148
149TEST(LivenessTest, CFG4) {
150 // var a;
151 // if (0 == 0) {
152 // a = 5;
153 // } else {
154 // a = 4;
155 // }
156 // return a;
157 //
158 // Bitsets are made of:
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100159 // (constant0, constant4, constant5, phi)
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100160 const char* expected =
161 "Block 0\n" // entry block
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100162 " live in: (0000)\n"
163 " live out: (1110)\n"
164 " kill: (1110)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100165 "Block 1\n" // block with if
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100166 " live in: (1110)\n"
167 " live out: (0110)\n"
168 " kill: (0000)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100169 "Block 2\n" // else block
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100170 " live in: (0100)\n"
171 " live out: (0000)\n"
172 " kill: (0000)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100173 "Block 3\n" // then block
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100174 " live in: (0010)\n"
175 " live out: (0000)\n"
176 " kill: (0000)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100177 "Block 4\n" // return block
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100178 " live in: (0000)\n"
179 " live out: (0000)\n"
180 " kill: (0001)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100181 "Block 5\n" // exit block
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100182 " live in: (0000)\n"
183 " live out: (0000)\n"
184 " kill: (0000)\n";
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100185
186 const uint16_t data[] = ONE_REGISTER_CODE_ITEM(
187 Instruction::CONST_4 | 0 | 0,
188 Instruction::IF_EQ, 4,
189 Instruction::CONST_4 | 4 << 12 | 0,
190 Instruction::GOTO | 0x200,
191 Instruction::CONST_4 | 5 << 12 | 0,
192 Instruction::RETURN | 0 << 8);
193
194 TestCode(data, expected);
195}
196
197TEST(LivenessTest, CFG5) {
198 // var a = 0;
199 // if (0 == 0) {
200 // } else {
201 // a = 4;
202 // }
203 // return a;
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100204 //
205 // Bitsets are made of:
206 // (constant0, constant4, phi)
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100207 const char* expected =
208 "Block 0\n" // entry block
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100209 " live in: (000)\n"
210 " live out: (110)\n"
211 " kill: (110)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100212 "Block 1\n" // block with if
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100213 " live in: (110)\n"
214 " live out: (110)\n"
215 " kill: (000)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100216 "Block 2\n" // else block
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100217 " live in: (010)\n"
218 " live out: (000)\n"
219 " kill: (000)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100220 "Block 3\n" // return block
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100221 " live in: (000)\n"
222 " live out: (000)\n"
223 " kill: (001)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100224 "Block 4\n" // exit block
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100225 " live in: (000)\n"
226 " live out: (000)\n"
227 " kill: (000)\n"
Nicolas Geoffray622d9c32014-05-12 16:11:02 +0100228 "Block 5\n" // block to avoid critical edge. Predecessor is 1, successor is 3.
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100229 " live in: (100)\n"
230 " live out: (000)\n"
231 " kill: (000)\n";
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100232
233 const uint16_t data[] = ONE_REGISTER_CODE_ITEM(
234 Instruction::CONST_4 | 0 | 0,
235 Instruction::IF_EQ, 3,
236 Instruction::CONST_4 | 4 << 12 | 0,
237 Instruction::RETURN | 0 << 8);
238
239 TestCode(data, expected);
240}
241
242TEST(LivenessTest, Loop1) {
243 // Simple loop with one preheader and one back edge.
244 // var a = 0;
245 // while (a == a) {
246 // a = 4;
247 // }
248 // return;
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100249 // Bitsets are made of:
250 // (constant0, constant4, phi)
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100251 const char* expected =
252 "Block 0\n" // entry block
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100253 " live in: (000)\n"
254 " live out: (110)\n"
255 " kill: (110)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100256 "Block 1\n" // pre header
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100257 " live in: (110)\n"
258 " live out: (010)\n"
259 " kill: (000)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100260 "Block 2\n" // loop header
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100261 " live in: (010)\n"
262 " live out: (010)\n"
263 " kill: (001)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100264 "Block 3\n" // back edge
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100265 " live in: (010)\n"
266 " live out: (010)\n"
267 " kill: (000)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100268 "Block 4\n" // return block
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100269 " live in: (000)\n"
270 " live out: (000)\n"
271 " kill: (000)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100272 "Block 5\n" // exit block
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100273 " live in: (000)\n"
274 " live out: (000)\n"
275 " kill: (000)\n";
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100276
277
278 const uint16_t data[] = ONE_REGISTER_CODE_ITEM(
279 Instruction::CONST_4 | 0 | 0,
280 Instruction::IF_EQ, 4,
281 Instruction::CONST_4 | 4 << 12 | 0,
282 Instruction::GOTO | 0xFD00,
283 Instruction::RETURN_VOID);
284
285 TestCode(data, expected);
286}
287
288TEST(LivenessTest, Loop3) {
289 // Test that the returned value stays live in a preceding loop.
290 // var a = 0;
291 // while (a == a) {
292 // a = 4;
293 // }
294 // return 5;
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100295 // Bitsets are made of:
296 // (constant0, constant4, constant5, phi)
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100297 const char* expected =
298 "Block 0\n"
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100299 " live in: (0000)\n"
300 " live out: (1110)\n"
301 " kill: (1110)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100302 "Block 1\n"
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100303 " live in: (1110)\n"
304 " live out: (0110)\n"
305 " kill: (0000)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100306 "Block 2\n" // loop header
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100307 " live in: (0110)\n"
308 " live out: (0110)\n"
309 " kill: (0001)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100310 "Block 3\n" // back edge
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100311 " live in: (0110)\n"
312 " live out: (0110)\n"
313 " kill: (0000)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100314 "Block 4\n" // return block
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100315 " live in: (0010)\n"
316 " live out: (0000)\n"
317 " kill: (0000)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100318 "Block 5\n" // exit block
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100319 " live in: (0000)\n"
320 " live out: (0000)\n"
321 " kill: (0000)\n";
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100322
323 const uint16_t data[] = TWO_REGISTERS_CODE_ITEM(
324 Instruction::CONST_4 | 0 | 0,
325 Instruction::IF_EQ, 4,
326 Instruction::CONST_4 | 4 << 12 | 0,
327 Instruction::GOTO | 0xFD00,
328 Instruction::CONST_4 | 5 << 12 | 1 << 8,
329 Instruction::RETURN | 1 << 8);
330
331 TestCode(data, expected);
332}
333
334
335TEST(LivenessTest, Loop4) {
336 // Make sure we support a preheader of a loop not being the first predecessor
337 // in the predecessor list of the header.
338 // var a = 0;
339 // while (a == a) {
340 // a = 4;
341 // }
342 // return a;
343 // Bitsets are made of:
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100344 // (constant0, constant4, phi)
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100345 const char* expected =
346 "Block 0\n"
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100347 " live in: (000)\n"
348 " live out: (110)\n"
349 " kill: (110)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100350 "Block 1\n"
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100351 " live in: (110)\n"
352 " live out: (110)\n"
353 " kill: (000)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100354 "Block 2\n" // loop header
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100355 " live in: (010)\n"
356 " live out: (011)\n"
357 " kill: (001)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100358 "Block 3\n" // back edge
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100359 " live in: (010)\n"
360 " live out: (010)\n"
361 " kill: (000)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100362 "Block 4\n" // pre loop header
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100363 " live in: (110)\n"
364 " live out: (010)\n"
365 " kill: (000)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100366 "Block 5\n" // return block
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100367 " live in: (001)\n"
368 " live out: (000)\n"
369 " kill: (000)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100370 "Block 6\n" // exit block
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100371 " live in: (000)\n"
372 " live out: (000)\n"
373 " kill: (000)\n";
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100374
375 const uint16_t data[] = ONE_REGISTER_CODE_ITEM(
376 Instruction::CONST_4 | 0 | 0,
377 Instruction::GOTO | 0x500,
378 Instruction::IF_EQ, 5,
379 Instruction::CONST_4 | 4 << 12 | 0,
380 Instruction::GOTO | 0xFD00,
381 Instruction::GOTO | 0xFC00,
382 Instruction::RETURN | 0 << 8);
383
384 TestCode(data, expected);
385}
386
387TEST(LivenessTest, Loop5) {
388 // Make sure we create a preheader of a loop when a header originally has two
389 // incoming blocks and one back edge.
390 // Bitsets are made of:
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100391 // (constant0, constant4, constant5, phi in block 8, phi in block 4)
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100392 const char* expected =
393 "Block 0\n"
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100394 " live in: (00000)\n"
395 " live out: (11100)\n"
396 " kill: (11100)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100397 "Block 1\n"
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100398 " live in: (11100)\n"
399 " live out: (01100)\n"
400 " kill: (00000)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100401 "Block 2\n"
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100402 " live in: (01000)\n"
403 " live out: (00000)\n"
404 " kill: (00000)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100405 "Block 3\n"
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100406 " live in: (00100)\n"
407 " live out: (00000)\n"
408 " kill: (00000)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100409 "Block 4\n" // loop header
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100410 " live in: (00000)\n"
411 " live out: (00001)\n"
412 " kill: (00001)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100413 "Block 5\n" // back edge
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100414 " live in: (00001)\n"
415 " live out: (00000)\n"
416 " kill: (00000)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100417 "Block 6\n" // return block
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100418 " live in: (00001)\n"
419 " live out: (00000)\n"
420 " kill: (00000)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100421 "Block 7\n" // exit block
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100422 " live in: (00000)\n"
423 " live out: (00000)\n"
424 " kill: (00000)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100425 "Block 8\n" // synthesized pre header
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100426 " live in: (00000)\n"
427 " live out: (00000)\n"
428 " kill: (00010)\n";
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100429
430 const uint16_t data[] = ONE_REGISTER_CODE_ITEM(
431 Instruction::CONST_4 | 0 | 0,
432 Instruction::IF_EQ, 4,
433 Instruction::CONST_4 | 4 << 12 | 0,
434 Instruction::GOTO | 0x200,
435 Instruction::CONST_4 | 5 << 12 | 0,
436 Instruction::IF_EQ, 3,
437 Instruction::GOTO | 0xFE00,
438 Instruction::RETURN | 0 << 8);
439
440 TestCode(data, expected);
441}
442
443TEST(LivenessTest, Loop6) {
444 // Bitsets are made of:
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100445 // (constant0, constant4, constant5, phi in block 2, phi in block 8)
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100446 const char* expected =
447 "Block 0\n"
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100448 " live in: (00000)\n"
449 " live out: (11100)\n"
450 " kill: (11100)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100451 "Block 1\n"
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100452 " live in: (11100)\n"
453 " live out: (01100)\n"
454 " kill: (00000)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100455 "Block 2\n" // loop header
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100456 " live in: (01100)\n"
457 " live out: (01110)\n"
458 " kill: (00010)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100459 "Block 3\n"
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100460 " live in: (01100)\n"
461 " live out: (01100)\n"
462 " kill: (00000)\n"
Nicolas Geoffray622d9c32014-05-12 16:11:02 +0100463 "Block 4\n" // original back edge
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100464 " live in: (01100)\n"
465 " live out: (01100)\n"
466 " kill: (00000)\n"
Nicolas Geoffray622d9c32014-05-12 16:11:02 +0100467 "Block 5\n" // original back edge
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100468 " live in: (01100)\n"
469 " live out: (01100)\n"
470 " kill: (00000)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100471 "Block 6\n" // return block
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100472 " live in: (00010)\n"
473 " live out: (00000)\n"
474 " kill: (00000)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100475 "Block 7\n" // exit block
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100476 " live in: (00000)\n"
477 " live out: (00000)\n"
478 " kill: (00000)\n"
Nicolas Geoffray622d9c32014-05-12 16:11:02 +0100479 "Block 8\n" // synthesized back edge
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100480 " live in: (01100)\n"
481 " live out: (01100)\n"
482 " kill: (00001)\n";
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100483
484 const uint16_t data[] = ONE_REGISTER_CODE_ITEM(
485 Instruction::CONST_4 | 0 | 0,
486 Instruction::IF_EQ, 8,
487 Instruction::CONST_4 | 4 << 12 | 0,
488 Instruction::IF_EQ, 4,
489 Instruction::CONST_4 | 5 << 12 | 0,
490 Instruction::GOTO | 0xFA00,
491 Instruction::GOTO | 0xF900,
492 Instruction::RETURN | 0 << 8);
493
494 TestCode(data, expected);
495}
496
497
498TEST(LivenessTest, Loop7) {
499 // Bitsets are made of:
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100500 // (constant0, constant4, constant5, phi in block 2, phi in block 6)
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100501 const char* expected =
502 "Block 0\n"
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100503 " live in: (00000)\n"
504 " live out: (11100)\n"
505 " kill: (11100)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100506 "Block 1\n"
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100507 " live in: (11100)\n"
508 " live out: (01100)\n"
509 " kill: (00000)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100510 "Block 2\n" // loop header
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100511 " live in: (01100)\n"
512 " live out: (01110)\n"
513 " kill: (00010)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100514 "Block 3\n"
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100515 " live in: (01100)\n"
516 " live out: (01100)\n"
517 " kill: (00000)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100518 "Block 4\n" // loop exit
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100519 " live in: (00100)\n"
520 " live out: (00000)\n"
521 " kill: (00000)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100522 "Block 5\n" // back edge
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100523 " live in: (01100)\n"
524 " live out: (01100)\n"
525 " kill: (00000)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100526 "Block 6\n" // return block
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100527 " live in: (00000)\n"
528 " live out: (00000)\n"
529 " kill: (00001)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100530 "Block 7\n" // exit block
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100531 " live in: (00000)\n"
532 " live out: (00000)\n"
533 " kill: (00000)\n"
Nicolas Geoffray622d9c32014-05-12 16:11:02 +0100534 "Block 8\n" // synthesized block to avoid critical edge.
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100535 " live in: (00010)\n"
536 " live out: (00000)\n"
537 " kill: (00000)\n";
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100538
539 const uint16_t data[] = ONE_REGISTER_CODE_ITEM(
540 Instruction::CONST_4 | 0 | 0,
541 Instruction::IF_EQ, 8,
542 Instruction::CONST_4 | 4 << 12 | 0,
543 Instruction::IF_EQ, 4,
544 Instruction::CONST_4 | 5 << 12 | 0,
545 Instruction::GOTO | 0x0200,
546 Instruction::GOTO | 0xF900,
547 Instruction::RETURN | 0 << 8);
548
549 TestCode(data, expected);
550}
551
Nicolas Geoffray8ddb00c2014-09-29 12:00:40 +0100552TEST(LivenessTest, Loop8) {
553 // var a = 0;
554 // while (a == a) {
555 // a = a + a;
556 // }
557 // return a;
558 //
559 // We want to test that the ins of the loop exit
560 // does contain the phi.
561 // Bitsets are made of:
562 // (constant0, phi, add)
563 const char* expected =
564 "Block 0\n"
565 " live in: (000)\n"
566 " live out: (100)\n"
567 " kill: (100)\n"
568 "Block 1\n" // pre loop header
569 " live in: (100)\n"
570 " live out: (000)\n"
571 " kill: (000)\n"
572 "Block 2\n" // loop header
573 " live in: (000)\n"
574 " live out: (010)\n"
575 " kill: (010)\n"
576 "Block 3\n" // back edge
577 " live in: (010)\n"
578 " live out: (000)\n"
579 " kill: (001)\n"
580 "Block 4\n" // return block
581 " live in: (010)\n"
582 " live out: (000)\n"
583 " kill: (000)\n"
584 "Block 5\n" // exit block
585 " live in: (000)\n"
586 " live out: (000)\n"
587 " kill: (000)\n";
588
589 const uint16_t data[] = ONE_REGISTER_CODE_ITEM(
590 Instruction::CONST_4 | 0 | 0,
591 Instruction::IF_EQ, 6,
592 Instruction::ADD_INT, 0, 0,
593 Instruction::GOTO | 0xFB00,
594 Instruction::RETURN | 0 << 8);
595
596 TestCode(data, expected);
597}
598
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100599} // namespace art