blob: f2d49ac397c59071d0357274813a1b2f65903ece [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"
Calin Juravlecd6dffe2015-01-08 17:35:35 +000022#include "driver/compiler_options.h"
Nicolas Geoffray804d0932014-05-02 08:46:00 +010023#include "nodes.h"
24#include "optimizing_unit_test.h"
Nicolas Geoffray360231a2014-10-08 21:07:48 +010025#include "prepare_for_register_allocation.h"
Nicolas Geoffray804d0932014-05-02 08:46:00 +010026#include "ssa_liveness_analysis.h"
27#include "utils/arena_allocator.h"
28
29#include "gtest/gtest.h"
30
31namespace art {
32
Nicolas Geoffray26066f22014-06-03 10:36:16 +000033static void DumpBitVector(BitVector* vector,
34 std::ostream& buffer,
35 size_t count,
36 const char* prefix) {
37 buffer << prefix;
38 buffer << '(';
39 for (size_t i = 0; i < count; ++i) {
40 buffer << vector->IsBitSet(i);
41 }
42 buffer << ")\n";
43}
44
Nicolas Geoffray804d0932014-05-02 08:46:00 +010045static void TestCode(const uint16_t* data, const char* expected) {
46 ArenaPool pool;
47 ArenaAllocator allocator(&pool);
48 HGraphBuilder builder(&allocator);
49 const DexFile::CodeItem* item = reinterpret_cast<const DexFile::CodeItem*>(data);
50 HGraph* graph = builder.BuildGraph(*item);
51 ASSERT_NE(graph, nullptr);
Nicolas Geoffraye53798a2014-12-01 10:31:54 +000052 graph->TryBuildingSsa();
Nicolas Geoffray360231a2014-10-08 21:07:48 +010053 // `Inline` conditions into ifs.
54 PrepareForRegisterAllocation(graph).Run();
Calin Juravlecd6dffe2015-01-08 17:35:35 +000055 x86::CodeGeneratorX86 codegen(graph, CompilerOptions());
Nicolas Geoffray8a16d972014-09-11 10:30:02 +010056 SsaLivenessAnalysis liveness(*graph, &codegen);
Nicolas Geoffray804d0932014-05-02 08:46:00 +010057 liveness.Analyze();
58
59 std::ostringstream buffer;
60 for (HInsertionOrderIterator it(*graph); !it.Done(); it.Advance()) {
61 HBasicBlock* block = it.Current();
62 buffer << "Block " << block->GetBlockId() << std::endl;
Nicolas Geoffray26066f22014-06-03 10:36:16 +000063 size_t ssa_values = liveness.GetNumberOfSsaValues();
Nicolas Geoffray804d0932014-05-02 08:46:00 +010064 BitVector* live_in = liveness.GetLiveInSet(*block);
Nicolas Geoffray26066f22014-06-03 10:36:16 +000065 DumpBitVector(live_in, buffer, ssa_values, " live in: ");
Nicolas Geoffray804d0932014-05-02 08:46:00 +010066 BitVector* live_out = liveness.GetLiveOutSet(*block);
Nicolas Geoffray26066f22014-06-03 10:36:16 +000067 DumpBitVector(live_out, buffer, ssa_values, " live out: ");
Nicolas Geoffray804d0932014-05-02 08:46:00 +010068 BitVector* kill = liveness.GetKillSet(*block);
Nicolas Geoffray26066f22014-06-03 10:36:16 +000069 DumpBitVector(kill, buffer, ssa_values, " kill: ");
Nicolas Geoffray804d0932014-05-02 08:46:00 +010070 }
71 ASSERT_STREQ(expected, buffer.str().c_str());
72}
73
74TEST(LivenessTest, CFG1) {
75 const char* expected =
76 "Block 0\n"
Nicolas Geoffray31d76b42014-06-09 15:02:22 +010077 " live in: (0)\n"
78 " live out: (0)\n"
79 " kill: (1)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +010080 "Block 1\n"
Nicolas Geoffray31d76b42014-06-09 15:02:22 +010081 " live in: (0)\n"
82 " live out: (0)\n"
83 " kill: (0)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +010084 "Block 2\n"
Nicolas Geoffray31d76b42014-06-09 15:02:22 +010085 " live in: (0)\n"
86 " live out: (0)\n"
87 " kill: (0)\n";
Nicolas Geoffray804d0932014-05-02 08:46:00 +010088
89 // Constant is not used.
90 const uint16_t data[] = ONE_REGISTER_CODE_ITEM(
91 Instruction::CONST_4 | 0 | 0,
92 Instruction::RETURN_VOID);
93
94 TestCode(data, expected);
95}
96
97TEST(LivenessTest, CFG2) {
98 const char* expected =
99 "Block 0\n"
Nicolas Geoffray26066f22014-06-03 10:36:16 +0000100 " live in: (0)\n"
101 " live out: (1)\n"
102 " kill: (1)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100103 "Block 1\n"
Nicolas Geoffray26066f22014-06-03 10:36:16 +0000104 " live in: (1)\n"
105 " live out: (0)\n"
106 " kill: (0)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100107 "Block 2\n"
Nicolas Geoffray26066f22014-06-03 10:36:16 +0000108 " live in: (0)\n"
109 " live out: (0)\n"
110 " kill: (0)\n";
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100111
112 const uint16_t data[] = ONE_REGISTER_CODE_ITEM(
113 Instruction::CONST_4 | 0 | 0,
114 Instruction::RETURN);
115
116 TestCode(data, expected);
117}
118
119TEST(LivenessTest, CFG3) {
120 const char* expected =
121 "Block 0\n" // entry block
Nicolas Geoffray26066f22014-06-03 10:36:16 +0000122 " live in: (000)\n"
123 " live out: (110)\n"
124 " kill: (110)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100125 "Block 1\n" // block with add
Nicolas Geoffray26066f22014-06-03 10:36:16 +0000126 " live in: (110)\n"
127 " live out: (001)\n"
128 " kill: (001)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100129 "Block 2\n" // block with return
Nicolas Geoffray26066f22014-06-03 10:36:16 +0000130 " live in: (001)\n"
131 " live out: (000)\n"
132 " kill: (000)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100133 "Block 3\n" // exit block
Nicolas Geoffray26066f22014-06-03 10:36:16 +0000134 " live in: (000)\n"
135 " live out: (000)\n"
136 " kill: (000)\n";
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100137
138 const uint16_t data[] = TWO_REGISTERS_CODE_ITEM(
139 Instruction::CONST_4 | 3 << 12 | 0,
140 Instruction::CONST_4 | 4 << 12 | 1 << 8,
141 Instruction::ADD_INT_2ADDR | 1 << 12,
142 Instruction::GOTO | 0x100,
143 Instruction::RETURN);
144
145 TestCode(data, expected);
146}
147
148TEST(LivenessTest, CFG4) {
149 // var a;
150 // if (0 == 0) {
151 // a = 5;
152 // } else {
153 // a = 4;
154 // }
155 // return a;
156 //
157 // Bitsets are made of:
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100158 // (constant0, constant4, constant5, phi)
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100159 const char* expected =
160 "Block 0\n" // entry block
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100161 " live in: (0000)\n"
162 " live out: (1110)\n"
163 " kill: (1110)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100164 "Block 1\n" // block with if
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100165 " live in: (1110)\n"
166 " live out: (0110)\n"
167 " kill: (0000)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100168 "Block 2\n" // else block
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100169 " live in: (0100)\n"
170 " live out: (0000)\n"
171 " kill: (0000)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100172 "Block 3\n" // then block
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100173 " live in: (0010)\n"
174 " live out: (0000)\n"
175 " kill: (0000)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100176 "Block 4\n" // return block
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100177 " live in: (0000)\n"
178 " live out: (0000)\n"
179 " kill: (0001)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100180 "Block 5\n" // exit block
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100181 " live in: (0000)\n"
182 " live out: (0000)\n"
183 " kill: (0000)\n";
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100184
185 const uint16_t data[] = ONE_REGISTER_CODE_ITEM(
186 Instruction::CONST_4 | 0 | 0,
187 Instruction::IF_EQ, 4,
188 Instruction::CONST_4 | 4 << 12 | 0,
189 Instruction::GOTO | 0x200,
190 Instruction::CONST_4 | 5 << 12 | 0,
191 Instruction::RETURN | 0 << 8);
192
193 TestCode(data, expected);
194}
195
196TEST(LivenessTest, CFG5) {
197 // var a = 0;
198 // if (0 == 0) {
199 // } else {
200 // a = 4;
201 // }
202 // return a;
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100203 //
204 // Bitsets are made of:
205 // (constant0, constant4, phi)
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100206 const char* expected =
207 "Block 0\n" // entry block
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100208 " live in: (000)\n"
209 " live out: (110)\n"
210 " kill: (110)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100211 "Block 1\n" // block with if
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100212 " live in: (110)\n"
213 " live out: (110)\n"
214 " kill: (000)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100215 "Block 2\n" // else block
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100216 " live in: (010)\n"
217 " live out: (000)\n"
218 " kill: (000)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100219 "Block 3\n" // return block
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100220 " live in: (000)\n"
221 " live out: (000)\n"
222 " kill: (001)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100223 "Block 4\n" // exit block
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100224 " live in: (000)\n"
225 " live out: (000)\n"
226 " kill: (000)\n"
Nicolas Geoffray622d9c32014-05-12 16:11:02 +0100227 "Block 5\n" // block to avoid critical edge. Predecessor is 1, successor is 3.
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100228 " live in: (100)\n"
229 " live out: (000)\n"
230 " kill: (000)\n";
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100231
232 const uint16_t data[] = ONE_REGISTER_CODE_ITEM(
233 Instruction::CONST_4 | 0 | 0,
234 Instruction::IF_EQ, 3,
235 Instruction::CONST_4 | 4 << 12 | 0,
236 Instruction::RETURN | 0 << 8);
237
238 TestCode(data, expected);
239}
240
241TEST(LivenessTest, Loop1) {
242 // Simple loop with one preheader and one back edge.
243 // var a = 0;
244 // while (a == a) {
245 // a = 4;
246 // }
247 // return;
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100248 // Bitsets are made of:
249 // (constant0, constant4, phi)
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100250 const char* expected =
251 "Block 0\n" // entry block
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100252 " live in: (000)\n"
253 " live out: (110)\n"
254 " kill: (110)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100255 "Block 1\n" // pre header
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100256 " live in: (110)\n"
257 " live out: (010)\n"
258 " kill: (000)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100259 "Block 2\n" // loop header
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100260 " live in: (010)\n"
261 " live out: (010)\n"
262 " kill: (001)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100263 "Block 3\n" // back edge
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100264 " live in: (010)\n"
265 " live out: (010)\n"
266 " kill: (000)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100267 "Block 4\n" // return block
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100268 " live in: (000)\n"
269 " live out: (000)\n"
270 " kill: (000)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100271 "Block 5\n" // exit block
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100272 " live in: (000)\n"
273 " live out: (000)\n"
274 " kill: (000)\n";
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100275
276
277 const uint16_t data[] = ONE_REGISTER_CODE_ITEM(
278 Instruction::CONST_4 | 0 | 0,
279 Instruction::IF_EQ, 4,
280 Instruction::CONST_4 | 4 << 12 | 0,
281 Instruction::GOTO | 0xFD00,
282 Instruction::RETURN_VOID);
283
284 TestCode(data, expected);
285}
286
287TEST(LivenessTest, Loop3) {
288 // Test that the returned value stays live in a preceding loop.
289 // var a = 0;
290 // while (a == a) {
291 // a = 4;
292 // }
293 // return 5;
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100294 // Bitsets are made of:
295 // (constant0, constant4, constant5, phi)
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100296 const char* expected =
297 "Block 0\n"
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100298 " live in: (0000)\n"
299 " live out: (1110)\n"
300 " kill: (1110)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100301 "Block 1\n"
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100302 " live in: (1110)\n"
303 " live out: (0110)\n"
304 " kill: (0000)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100305 "Block 2\n" // loop header
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100306 " live in: (0110)\n"
307 " live out: (0110)\n"
308 " kill: (0001)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100309 "Block 3\n" // back edge
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100310 " live in: (0110)\n"
311 " live out: (0110)\n"
312 " kill: (0000)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100313 "Block 4\n" // return block
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100314 " live in: (0010)\n"
315 " live out: (0000)\n"
316 " kill: (0000)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100317 "Block 5\n" // exit block
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100318 " live in: (0000)\n"
319 " live out: (0000)\n"
320 " kill: (0000)\n";
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100321
322 const uint16_t data[] = TWO_REGISTERS_CODE_ITEM(
323 Instruction::CONST_4 | 0 | 0,
324 Instruction::IF_EQ, 4,
325 Instruction::CONST_4 | 4 << 12 | 0,
326 Instruction::GOTO | 0xFD00,
327 Instruction::CONST_4 | 5 << 12 | 1 << 8,
328 Instruction::RETURN | 1 << 8);
329
330 TestCode(data, expected);
331}
332
333
334TEST(LivenessTest, Loop4) {
335 // Make sure we support a preheader of a loop not being the first predecessor
336 // in the predecessor list of the header.
337 // var a = 0;
338 // while (a == a) {
339 // a = 4;
340 // }
341 // return a;
342 // Bitsets are made of:
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100343 // (constant0, constant4, phi)
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100344 const char* expected =
345 "Block 0\n"
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100346 " live in: (000)\n"
347 " live out: (110)\n"
348 " kill: (110)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100349 "Block 1\n"
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100350 " live in: (110)\n"
351 " live out: (110)\n"
352 " kill: (000)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100353 "Block 2\n" // loop header
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100354 " live in: (010)\n"
355 " live out: (011)\n"
356 " kill: (001)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100357 "Block 3\n" // back edge
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100358 " live in: (010)\n"
359 " live out: (010)\n"
360 " kill: (000)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100361 "Block 4\n" // pre loop header
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100362 " live in: (110)\n"
363 " live out: (010)\n"
364 " kill: (000)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100365 "Block 5\n" // return block
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100366 " live in: (001)\n"
367 " live out: (000)\n"
368 " kill: (000)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100369 "Block 6\n" // exit block
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100370 " live in: (000)\n"
371 " live out: (000)\n"
372 " kill: (000)\n";
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100373
374 const uint16_t data[] = ONE_REGISTER_CODE_ITEM(
375 Instruction::CONST_4 | 0 | 0,
376 Instruction::GOTO | 0x500,
377 Instruction::IF_EQ, 5,
378 Instruction::CONST_4 | 4 << 12 | 0,
379 Instruction::GOTO | 0xFD00,
380 Instruction::GOTO | 0xFC00,
381 Instruction::RETURN | 0 << 8);
382
383 TestCode(data, expected);
384}
385
386TEST(LivenessTest, Loop5) {
387 // Make sure we create a preheader of a loop when a header originally has two
388 // incoming blocks and one back edge.
389 // Bitsets are made of:
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100390 // (constant0, constant4, constant5, phi in block 8, phi in block 4)
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100391 const char* expected =
392 "Block 0\n"
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100393 " live in: (00000)\n"
394 " live out: (11100)\n"
395 " kill: (11100)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100396 "Block 1\n"
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100397 " live in: (11100)\n"
398 " live out: (01100)\n"
399 " kill: (00000)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100400 "Block 2\n"
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100401 " live in: (01000)\n"
402 " live out: (00000)\n"
403 " kill: (00000)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100404 "Block 3\n"
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100405 " live in: (00100)\n"
406 " live out: (00000)\n"
407 " kill: (00000)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100408 "Block 4\n" // loop header
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100409 " live in: (00000)\n"
410 " live out: (00001)\n"
411 " kill: (00001)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100412 "Block 5\n" // back edge
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100413 " live in: (00001)\n"
414 " live out: (00000)\n"
415 " kill: (00000)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100416 "Block 6\n" // return block
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100417 " live in: (00001)\n"
418 " live out: (00000)\n"
419 " kill: (00000)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100420 "Block 7\n" // exit block
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100421 " live in: (00000)\n"
422 " live out: (00000)\n"
423 " kill: (00000)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100424 "Block 8\n" // synthesized pre header
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100425 " live in: (00000)\n"
426 " live out: (00000)\n"
427 " kill: (00010)\n";
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100428
429 const uint16_t data[] = ONE_REGISTER_CODE_ITEM(
430 Instruction::CONST_4 | 0 | 0,
431 Instruction::IF_EQ, 4,
432 Instruction::CONST_4 | 4 << 12 | 0,
433 Instruction::GOTO | 0x200,
434 Instruction::CONST_4 | 5 << 12 | 0,
435 Instruction::IF_EQ, 3,
436 Instruction::GOTO | 0xFE00,
437 Instruction::RETURN | 0 << 8);
438
439 TestCode(data, expected);
440}
441
442TEST(LivenessTest, Loop6) {
443 // Bitsets are made of:
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100444 // (constant0, constant4, constant5, phi in block 2, phi in block 8)
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100445 const char* expected =
446 "Block 0\n"
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100447 " live in: (00000)\n"
448 " live out: (11100)\n"
449 " kill: (11100)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100450 "Block 1\n"
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100451 " live in: (11100)\n"
452 " live out: (01100)\n"
453 " kill: (00000)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100454 "Block 2\n" // loop header
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100455 " live in: (01100)\n"
456 " live out: (01110)\n"
457 " kill: (00010)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100458 "Block 3\n"
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100459 " live in: (01100)\n"
460 " live out: (01100)\n"
461 " kill: (00000)\n"
Nicolas Geoffray622d9c32014-05-12 16:11:02 +0100462 "Block 4\n" // original back edge
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100463 " live in: (01100)\n"
464 " live out: (01100)\n"
465 " kill: (00000)\n"
Nicolas Geoffray622d9c32014-05-12 16:11:02 +0100466 "Block 5\n" // original back edge
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100467 " live in: (01100)\n"
468 " live out: (01100)\n"
469 " kill: (00000)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100470 "Block 6\n" // return block
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100471 " live in: (00010)\n"
472 " live out: (00000)\n"
473 " kill: (00000)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100474 "Block 7\n" // exit block
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100475 " live in: (00000)\n"
476 " live out: (00000)\n"
477 " kill: (00000)\n"
Nicolas Geoffray622d9c32014-05-12 16:11:02 +0100478 "Block 8\n" // synthesized back edge
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100479 " live in: (01100)\n"
480 " live out: (01100)\n"
481 " kill: (00001)\n";
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100482
483 const uint16_t data[] = ONE_REGISTER_CODE_ITEM(
484 Instruction::CONST_4 | 0 | 0,
485 Instruction::IF_EQ, 8,
486 Instruction::CONST_4 | 4 << 12 | 0,
487 Instruction::IF_EQ, 4,
488 Instruction::CONST_4 | 5 << 12 | 0,
489 Instruction::GOTO | 0xFA00,
490 Instruction::GOTO | 0xF900,
491 Instruction::RETURN | 0 << 8);
492
493 TestCode(data, expected);
494}
495
496
497TEST(LivenessTest, Loop7) {
498 // Bitsets are made of:
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100499 // (constant0, constant4, constant5, phi in block 2, phi in block 6)
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100500 const char* expected =
501 "Block 0\n"
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100502 " live in: (00000)\n"
503 " live out: (11100)\n"
504 " kill: (11100)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100505 "Block 1\n"
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100506 " live in: (11100)\n"
507 " live out: (01100)\n"
508 " kill: (00000)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100509 "Block 2\n" // loop header
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100510 " live in: (01100)\n"
511 " live out: (01110)\n"
512 " kill: (00010)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100513 "Block 3\n"
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100514 " live in: (01100)\n"
515 " live out: (01100)\n"
516 " kill: (00000)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100517 "Block 4\n" // loop exit
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100518 " live in: (00100)\n"
519 " live out: (00000)\n"
520 " kill: (00000)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100521 "Block 5\n" // back edge
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100522 " live in: (01100)\n"
523 " live out: (01100)\n"
524 " kill: (00000)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100525 "Block 6\n" // return block
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100526 " live in: (00000)\n"
527 " live out: (00000)\n"
528 " kill: (00001)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100529 "Block 7\n" // exit block
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100530 " live in: (00000)\n"
531 " live out: (00000)\n"
532 " kill: (00000)\n"
Nicolas Geoffray622d9c32014-05-12 16:11:02 +0100533 "Block 8\n" // synthesized block to avoid critical edge.
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100534 " live in: (00010)\n"
535 " live out: (00000)\n"
536 " kill: (00000)\n";
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100537
538 const uint16_t data[] = ONE_REGISTER_CODE_ITEM(
539 Instruction::CONST_4 | 0 | 0,
540 Instruction::IF_EQ, 8,
541 Instruction::CONST_4 | 4 << 12 | 0,
542 Instruction::IF_EQ, 4,
543 Instruction::CONST_4 | 5 << 12 | 0,
544 Instruction::GOTO | 0x0200,
545 Instruction::GOTO | 0xF900,
546 Instruction::RETURN | 0 << 8);
547
548 TestCode(data, expected);
549}
550
Nicolas Geoffray8ddb00c2014-09-29 12:00:40 +0100551TEST(LivenessTest, Loop8) {
552 // var a = 0;
553 // while (a == a) {
554 // a = a + a;
555 // }
556 // return a;
557 //
558 // We want to test that the ins of the loop exit
559 // does contain the phi.
560 // Bitsets are made of:
561 // (constant0, phi, add)
562 const char* expected =
563 "Block 0\n"
564 " live in: (000)\n"
565 " live out: (100)\n"
566 " kill: (100)\n"
567 "Block 1\n" // pre loop header
568 " live in: (100)\n"
569 " live out: (000)\n"
570 " kill: (000)\n"
571 "Block 2\n" // loop header
572 " live in: (000)\n"
573 " live out: (010)\n"
574 " kill: (010)\n"
575 "Block 3\n" // back edge
576 " live in: (010)\n"
577 " live out: (000)\n"
578 " kill: (001)\n"
579 "Block 4\n" // return block
580 " live in: (010)\n"
581 " live out: (000)\n"
582 " kill: (000)\n"
583 "Block 5\n" // exit block
584 " live in: (000)\n"
585 " live out: (000)\n"
586 " kill: (000)\n";
587
588 const uint16_t data[] = ONE_REGISTER_CODE_ITEM(
589 Instruction::CONST_4 | 0 | 0,
590 Instruction::IF_EQ, 6,
591 Instruction::ADD_INT, 0, 0,
592 Instruction::GOTO | 0xFB00,
593 Instruction::RETURN | 0 << 8);
594
595 TestCode(data, expected);
596}
597
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100598} // namespace art