blob: 37b58ded596131ffc2066ae879e904f8299a6d38 [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
Mark Mendellfb8d2792015-03-31 22:16:59 -040017#include "arch/x86/instruction_set_features_x86.h"
Mathieu Chartierb666f482015-02-18 14:33:14 -080018#include "base/arena_allocator.h"
Nicolas Geoffray804d0932014-05-02 08:46:00 +010019#include "builder.h"
Nicolas Geoffray31d76b42014-06-09 15:02:22 +010020#include "code_generator.h"
Nicolas Geoffray8a16d972014-09-11 10:30:02 +010021#include "code_generator_x86.h"
Nicolas Geoffray804d0932014-05-02 08:46:00 +010022#include "dex_file.h"
23#include "dex_instruction.h"
Calin Juravlecd6dffe2015-01-08 17:35:35 +000024#include "driver/compiler_options.h"
Nicolas Geoffray804d0932014-05-02 08:46:00 +010025#include "nodes.h"
26#include "optimizing_unit_test.h"
Nicolas Geoffray360231a2014-10-08 21:07:48 +010027#include "prepare_for_register_allocation.h"
Nicolas Geoffray804d0932014-05-02 08:46:00 +010028#include "ssa_liveness_analysis.h"
Nicolas Geoffray804d0932014-05-02 08:46:00 +010029
Alex Light68289a52015-12-15 17:30:30 -080030namespace art {
David Brazdild9510df2015-11-04 23:30:22 +000031
David Brazdil4833f5a2015-12-16 10:37:39 +000032class LivenessTest : public CommonCompilerTest {};
33
Nicolas Geoffray26066f22014-06-03 10:36:16 +000034static void DumpBitVector(BitVector* vector,
35 std::ostream& buffer,
36 size_t count,
37 const char* prefix) {
38 buffer << prefix;
39 buffer << '(';
40 for (size_t i = 0; i < count; ++i) {
41 buffer << vector->IsBitSet(i);
42 }
43 buffer << ")\n";
44}
45
Nicolas Geoffray804d0932014-05-02 08:46:00 +010046static void TestCode(const uint16_t* data, const char* expected) {
47 ArenaPool pool;
48 ArenaAllocator allocator(&pool);
David Brazdilbadd8262016-02-02 16:28:56 +000049 HGraph* graph = CreateCFG(&allocator, data);
Nicolas Geoffray360231a2014-10-08 21:07:48 +010050 // `Inline` conditions into ifs.
51 PrepareForRegisterAllocation(graph).Run();
Mark Mendellfb8d2792015-03-31 22:16:59 -040052 std::unique_ptr<const X86InstructionSetFeatures> features_x86(
53 X86InstructionSetFeatures::FromCppDefines());
54 x86::CodeGeneratorX86 codegen(graph, *features_x86.get(), CompilerOptions());
Nicolas Geoffray0d9f17d2015-04-15 14:17:44 +010055 SsaLivenessAnalysis liveness(graph, &codegen);
Nicolas Geoffray804d0932014-05-02 08:46:00 +010056 liveness.Analyze();
57
58 std::ostringstream buffer;
Vladimir Marko2c45bc92016-10-25 16:54:12 +010059 for (HBasicBlock* block : graph->GetBlocks()) {
Nicolas Geoffray804d0932014-05-02 08:46:00 +010060 buffer << "Block " << block->GetBlockId() << std::endl;
Nicolas Geoffray26066f22014-06-03 10:36:16 +000061 size_t ssa_values = liveness.GetNumberOfSsaValues();
Nicolas Geoffray804d0932014-05-02 08:46:00 +010062 BitVector* live_in = liveness.GetLiveInSet(*block);
Nicolas Geoffray26066f22014-06-03 10:36:16 +000063 DumpBitVector(live_in, buffer, ssa_values, " live in: ");
Nicolas Geoffray804d0932014-05-02 08:46:00 +010064 BitVector* live_out = liveness.GetLiveOutSet(*block);
Nicolas Geoffray26066f22014-06-03 10:36:16 +000065 DumpBitVector(live_out, buffer, ssa_values, " live out: ");
Nicolas Geoffray804d0932014-05-02 08:46:00 +010066 BitVector* kill = liveness.GetKillSet(*block);
Nicolas Geoffray26066f22014-06-03 10:36:16 +000067 DumpBitVector(kill, buffer, ssa_values, " kill: ");
Nicolas Geoffray804d0932014-05-02 08:46:00 +010068 }
69 ASSERT_STREQ(expected, buffer.str().c_str());
70}
71
David Brazdil4833f5a2015-12-16 10:37:39 +000072TEST_F(LivenessTest, CFG1) {
Nicolas Geoffray804d0932014-05-02 08:46:00 +010073 const char* expected =
74 "Block 0\n"
Nicolas Geoffray31d76b42014-06-09 15:02:22 +010075 " live in: (0)\n"
76 " live out: (0)\n"
77 " kill: (1)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +010078 "Block 1\n"
Nicolas Geoffray31d76b42014-06-09 15:02:22 +010079 " live in: (0)\n"
80 " live out: (0)\n"
81 " kill: (0)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +010082 "Block 2\n"
Nicolas Geoffray31d76b42014-06-09 15:02:22 +010083 " live in: (0)\n"
84 " live out: (0)\n"
85 " kill: (0)\n";
Nicolas Geoffray804d0932014-05-02 08:46:00 +010086
87 // Constant is not used.
88 const uint16_t data[] = ONE_REGISTER_CODE_ITEM(
89 Instruction::CONST_4 | 0 | 0,
90 Instruction::RETURN_VOID);
91
92 TestCode(data, expected);
93}
94
David Brazdil4833f5a2015-12-16 10:37:39 +000095TEST_F(LivenessTest, CFG2) {
Nicolas Geoffray804d0932014-05-02 08:46:00 +010096 const char* expected =
97 "Block 0\n"
Nicolas Geoffray26066f22014-06-03 10:36:16 +000098 " live in: (0)\n"
99 " live out: (1)\n"
100 " kill: (1)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100101 "Block 1\n"
Nicolas Geoffray26066f22014-06-03 10:36:16 +0000102 " live in: (1)\n"
103 " live out: (0)\n"
104 " kill: (0)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100105 "Block 2\n"
Nicolas Geoffray26066f22014-06-03 10:36:16 +0000106 " live in: (0)\n"
107 " live out: (0)\n"
108 " kill: (0)\n";
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100109
110 const uint16_t data[] = ONE_REGISTER_CODE_ITEM(
111 Instruction::CONST_4 | 0 | 0,
112 Instruction::RETURN);
113
114 TestCode(data, expected);
115}
116
David Brazdil4833f5a2015-12-16 10:37:39 +0000117TEST_F(LivenessTest, CFG3) {
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100118 const char* expected =
119 "Block 0\n" // entry block
Nicolas Geoffray26066f22014-06-03 10:36:16 +0000120 " live in: (000)\n"
121 " live out: (110)\n"
122 " kill: (110)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100123 "Block 1\n" // block with add
Nicolas Geoffray26066f22014-06-03 10:36:16 +0000124 " live in: (110)\n"
125 " live out: (001)\n"
126 " kill: (001)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100127 "Block 2\n" // block with return
Nicolas Geoffray26066f22014-06-03 10:36:16 +0000128 " live in: (001)\n"
129 " live out: (000)\n"
130 " kill: (000)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100131 "Block 3\n" // exit block
Nicolas Geoffray26066f22014-06-03 10:36:16 +0000132 " live in: (000)\n"
133 " live out: (000)\n"
134 " kill: (000)\n";
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100135
136 const uint16_t data[] = TWO_REGISTERS_CODE_ITEM(
137 Instruction::CONST_4 | 3 << 12 | 0,
138 Instruction::CONST_4 | 4 << 12 | 1 << 8,
139 Instruction::ADD_INT_2ADDR | 1 << 12,
140 Instruction::GOTO | 0x100,
141 Instruction::RETURN);
142
143 TestCode(data, expected);
144}
145
David Brazdil4833f5a2015-12-16 10:37:39 +0000146TEST_F(LivenessTest, CFG4) {
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100147 // var a;
148 // if (0 == 0) {
149 // a = 5;
150 // } else {
151 // a = 4;
152 // }
153 // return a;
154 //
155 // Bitsets are made of:
David Brazdildee58d62016-04-07 09:54:26 +0000156 // (constant0, constant5, constant4, phi)
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100157 const char* expected =
158 "Block 0\n" // entry block
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100159 " live in: (0000)\n"
160 " live out: (1110)\n"
161 " kill: (1110)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100162 "Block 1\n" // block with if
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100163 " live in: (1110)\n"
164 " live out: (0110)\n"
165 " kill: (0000)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100166 "Block 2\n" // else block
David Brazdildee58d62016-04-07 09:54:26 +0000167 " live in: (0010)\n"
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100168 " live out: (0000)\n"
169 " kill: (0000)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100170 "Block 3\n" // then block
David Brazdildee58d62016-04-07 09:54:26 +0000171 " live in: (0100)\n"
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100172 " live out: (0000)\n"
173 " kill: (0000)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100174 "Block 4\n" // return block
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100175 " live in: (0000)\n"
176 " live out: (0000)\n"
177 " kill: (0001)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100178 "Block 5\n" // exit block
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100179 " live in: (0000)\n"
180 " live out: (0000)\n"
181 " kill: (0000)\n";
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100182
183 const uint16_t data[] = ONE_REGISTER_CODE_ITEM(
184 Instruction::CONST_4 | 0 | 0,
185 Instruction::IF_EQ, 4,
186 Instruction::CONST_4 | 4 << 12 | 0,
187 Instruction::GOTO | 0x200,
188 Instruction::CONST_4 | 5 << 12 | 0,
189 Instruction::RETURN | 0 << 8);
190
191 TestCode(data, expected);
192}
193
David Brazdil4833f5a2015-12-16 10:37:39 +0000194TEST_F(LivenessTest, CFG5) {
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100195 // var a = 0;
196 // if (0 == 0) {
197 // } else {
198 // a = 4;
199 // }
200 // return a;
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100201 //
202 // Bitsets are made of:
203 // (constant0, constant4, phi)
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100204 const char* expected =
205 "Block 0\n" // entry block
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100206 " live in: (000)\n"
207 " live out: (110)\n"
208 " kill: (110)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100209 "Block 1\n" // block with if
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100210 " live in: (110)\n"
211 " live out: (110)\n"
212 " kill: (000)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100213 "Block 2\n" // else block
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100214 " live in: (010)\n"
215 " live out: (000)\n"
216 " kill: (000)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100217 "Block 3\n" // return block
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100218 " live in: (000)\n"
219 " live out: (000)\n"
220 " kill: (001)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100221 "Block 4\n" // exit block
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100222 " live in: (000)\n"
223 " live out: (000)\n"
224 " kill: (000)\n"
Nicolas Geoffray622d9c32014-05-12 16:11:02 +0100225 "Block 5\n" // block to avoid critical edge. Predecessor is 1, successor is 3.
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100226 " live in: (100)\n"
227 " live out: (000)\n"
228 " kill: (000)\n";
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100229
230 const uint16_t data[] = ONE_REGISTER_CODE_ITEM(
231 Instruction::CONST_4 | 0 | 0,
232 Instruction::IF_EQ, 3,
233 Instruction::CONST_4 | 4 << 12 | 0,
234 Instruction::RETURN | 0 << 8);
235
236 TestCode(data, expected);
237}
238
David Brazdil4833f5a2015-12-16 10:37:39 +0000239TEST_F(LivenessTest, Loop1) {
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100240 // Simple loop with one preheader and one back edge.
241 // var a = 0;
242 // while (a == a) {
243 // a = 4;
244 // }
245 // return;
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100246 // Bitsets are made of:
247 // (constant0, constant4, phi)
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100248 const char* expected =
249 "Block 0\n" // entry block
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100250 " live in: (000)\n"
251 " live out: (110)\n"
252 " kill: (110)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100253 "Block 1\n" // pre header
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100254 " live in: (110)\n"
255 " live out: (010)\n"
256 " kill: (000)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100257 "Block 2\n" // loop header
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100258 " live in: (010)\n"
259 " live out: (010)\n"
260 " kill: (001)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100261 "Block 3\n" // back edge
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100262 " live in: (010)\n"
263 " live out: (010)\n"
264 " kill: (000)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100265 "Block 4\n" // return block
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100266 " live in: (000)\n"
267 " live out: (000)\n"
268 " kill: (000)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100269 "Block 5\n" // exit block
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100270 " live in: (000)\n"
271 " live out: (000)\n"
272 " kill: (000)\n";
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100273
274
275 const uint16_t data[] = ONE_REGISTER_CODE_ITEM(
276 Instruction::CONST_4 | 0 | 0,
277 Instruction::IF_EQ, 4,
278 Instruction::CONST_4 | 4 << 12 | 0,
279 Instruction::GOTO | 0xFD00,
280 Instruction::RETURN_VOID);
281
282 TestCode(data, expected);
283}
284
David Brazdil4833f5a2015-12-16 10:37:39 +0000285TEST_F(LivenessTest, Loop3) {
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100286 // Test that the returned value stays live in a preceding loop.
287 // var a = 0;
288 // while (a == a) {
289 // a = 4;
290 // }
291 // return 5;
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100292 // Bitsets are made of:
David Brazdildee58d62016-04-07 09:54:26 +0000293 // (constant0, constant5, constant4, phi)
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100294 const char* expected =
295 "Block 0\n"
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100296 " live in: (0000)\n"
297 " live out: (1110)\n"
298 " kill: (1110)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100299 "Block 1\n"
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100300 " live in: (1110)\n"
301 " live out: (0110)\n"
302 " kill: (0000)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100303 "Block 2\n" // loop header
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100304 " live in: (0110)\n"
305 " live out: (0110)\n"
306 " kill: (0001)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100307 "Block 3\n" // back edge
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100308 " live in: (0110)\n"
309 " live out: (0110)\n"
310 " kill: (0000)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100311 "Block 4\n" // return block
David Brazdildee58d62016-04-07 09:54:26 +0000312 " live in: (0100)\n"
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100313 " live out: (0000)\n"
314 " kill: (0000)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100315 "Block 5\n" // exit block
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100316 " live in: (0000)\n"
317 " live out: (0000)\n"
318 " kill: (0000)\n";
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100319
320 const uint16_t data[] = TWO_REGISTERS_CODE_ITEM(
321 Instruction::CONST_4 | 0 | 0,
322 Instruction::IF_EQ, 4,
323 Instruction::CONST_4 | 4 << 12 | 0,
324 Instruction::GOTO | 0xFD00,
325 Instruction::CONST_4 | 5 << 12 | 1 << 8,
326 Instruction::RETURN | 1 << 8);
327
328 TestCode(data, expected);
329}
330
331
David Brazdil4833f5a2015-12-16 10:37:39 +0000332TEST_F(LivenessTest, Loop4) {
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100333 // Make sure we support a preheader of a loop not being the first predecessor
334 // in the predecessor list of the header.
335 // var a = 0;
336 // while (a == a) {
337 // a = 4;
338 // }
339 // return a;
340 // Bitsets are made of:
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100341 // (constant0, constant4, phi)
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100342 const char* expected =
343 "Block 0\n"
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100344 " live in: (000)\n"
345 " live out: (110)\n"
346 " kill: (110)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100347 "Block 1\n"
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100348 " live in: (110)\n"
349 " live out: (110)\n"
350 " kill: (000)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100351 "Block 2\n" // loop header
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100352 " live in: (010)\n"
353 " live out: (011)\n"
354 " kill: (001)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100355 "Block 3\n" // back edge
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100356 " live in: (010)\n"
357 " live out: (010)\n"
358 " kill: (000)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100359 "Block 4\n" // pre loop header
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100360 " live in: (110)\n"
361 " live out: (010)\n"
362 " kill: (000)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100363 "Block 5\n" // return block
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100364 " live in: (001)\n"
365 " live out: (000)\n"
366 " kill: (000)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100367 "Block 6\n" // exit block
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100368 " live in: (000)\n"
369 " live out: (000)\n"
370 " kill: (000)\n";
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100371
372 const uint16_t data[] = ONE_REGISTER_CODE_ITEM(
373 Instruction::CONST_4 | 0 | 0,
374 Instruction::GOTO | 0x500,
375 Instruction::IF_EQ, 5,
376 Instruction::CONST_4 | 4 << 12 | 0,
377 Instruction::GOTO | 0xFD00,
378 Instruction::GOTO | 0xFC00,
379 Instruction::RETURN | 0 << 8);
380
381 TestCode(data, expected);
382}
383
David Brazdil4833f5a2015-12-16 10:37:39 +0000384TEST_F(LivenessTest, Loop5) {
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100385 // Make sure we create a preheader of a loop when a header originally has two
386 // incoming blocks and one back edge.
387 // Bitsets are made of:
David Brazdildee58d62016-04-07 09:54:26 +0000388 // (constant0, constant5, constant4, phi in block 8)
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100389 const char* expected =
390 "Block 0\n"
Nicolas Geoffray3afca782015-03-10 18:59:31 +0000391 " live in: (0000)\n"
392 " live out: (1110)\n"
393 " kill: (1110)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100394 "Block 1\n"
Nicolas Geoffray3afca782015-03-10 18:59:31 +0000395 " live in: (1110)\n"
396 " live out: (0110)\n"
397 " kill: (0000)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100398 "Block 2\n"
David Brazdildee58d62016-04-07 09:54:26 +0000399 " live in: (0010)\n"
Nicolas Geoffray3afca782015-03-10 18:59:31 +0000400 " live out: (0000)\n"
401 " kill: (0000)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100402 "Block 3\n"
David Brazdildee58d62016-04-07 09:54:26 +0000403 " live in: (0100)\n"
Nicolas Geoffray3afca782015-03-10 18:59:31 +0000404 " live out: (0000)\n"
405 " kill: (0000)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100406 "Block 4\n" // loop header
Nicolas Geoffray3afca782015-03-10 18:59:31 +0000407 " live in: (0001)\n"
408 " live out: (0001)\n"
409 " kill: (0000)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100410 "Block 5\n" // back edge
Nicolas Geoffray3afca782015-03-10 18:59:31 +0000411 " live in: (0001)\n"
412 " live out: (0001)\n"
413 " kill: (0000)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100414 "Block 6\n" // return block
Nicolas Geoffray3afca782015-03-10 18:59:31 +0000415 " live in: (0001)\n"
416 " live out: (0000)\n"
417 " kill: (0000)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100418 "Block 7\n" // exit block
Nicolas Geoffray3afca782015-03-10 18:59:31 +0000419 " live in: (0000)\n"
420 " live out: (0000)\n"
421 " kill: (0000)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100422 "Block 8\n" // synthesized pre header
Nicolas Geoffray3afca782015-03-10 18:59:31 +0000423 " live in: (0000)\n"
424 " live out: (0001)\n"
425 " kill: (0001)\n";
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100426
427 const uint16_t data[] = ONE_REGISTER_CODE_ITEM(
428 Instruction::CONST_4 | 0 | 0,
429 Instruction::IF_EQ, 4,
430 Instruction::CONST_4 | 4 << 12 | 0,
431 Instruction::GOTO | 0x200,
432 Instruction::CONST_4 | 5 << 12 | 0,
433 Instruction::IF_EQ, 3,
434 Instruction::GOTO | 0xFE00,
435 Instruction::RETURN | 0 << 8);
436
437 TestCode(data, expected);
438}
439
David Brazdil4833f5a2015-12-16 10:37:39 +0000440TEST_F(LivenessTest, Loop6) {
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100441 // Bitsets are made of:
Nicolas Geoffraydb216f42015-05-05 17:02:20 +0100442 // (constant0, constant4, constant5, phi in block 2)
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100443 const char* expected =
444 "Block 0\n"
Nicolas Geoffraydb216f42015-05-05 17:02:20 +0100445 " live in: (0000)\n"
446 " live out: (1110)\n"
447 " kill: (1110)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100448 "Block 1\n"
Nicolas Geoffraydb216f42015-05-05 17:02:20 +0100449 " live in: (1110)\n"
450 " live out: (0110)\n"
451 " kill: (0000)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100452 "Block 2\n" // loop header
Nicolas Geoffraydb216f42015-05-05 17:02:20 +0100453 " live in: (0110)\n"
454 " live out: (0111)\n"
455 " kill: (0001)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100456 "Block 3\n"
Nicolas Geoffraydb216f42015-05-05 17:02:20 +0100457 " live in: (0110)\n"
458 " live out: (0110)\n"
459 " kill: (0000)\n"
460 "Block 4\n" // back edge
461 " live in: (0110)\n"
462 " live out: (0110)\n"
463 " kill: (0000)\n"
464 "Block 5\n" // back edge
465 " live in: (0110)\n"
466 " live out: (0110)\n"
467 " kill: (0000)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100468 "Block 6\n" // return block
Nicolas Geoffraydb216f42015-05-05 17:02:20 +0100469 " live in: (0001)\n"
470 " live out: (0000)\n"
471 " kill: (0000)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100472 "Block 7\n" // exit block
Nicolas Geoffraydb216f42015-05-05 17:02:20 +0100473 " live in: (0000)\n"
474 " live out: (0000)\n"
475 " kill: (0000)\n";
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100476
477 const uint16_t data[] = ONE_REGISTER_CODE_ITEM(
478 Instruction::CONST_4 | 0 | 0,
479 Instruction::IF_EQ, 8,
480 Instruction::CONST_4 | 4 << 12 | 0,
481 Instruction::IF_EQ, 4,
482 Instruction::CONST_4 | 5 << 12 | 0,
483 Instruction::GOTO | 0xFA00,
484 Instruction::GOTO | 0xF900,
485 Instruction::RETURN | 0 << 8);
486
487 TestCode(data, expected);
488}
489
490
David Brazdil4833f5a2015-12-16 10:37:39 +0000491TEST_F(LivenessTest, Loop7) {
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100492 // Bitsets are made of:
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100493 // (constant0, constant4, constant5, phi in block 2, phi in block 6)
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100494 const char* expected =
495 "Block 0\n"
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100496 " live in: (00000)\n"
497 " live out: (11100)\n"
498 " kill: (11100)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100499 "Block 1\n"
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100500 " live in: (11100)\n"
501 " live out: (01100)\n"
502 " kill: (00000)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100503 "Block 2\n" // loop header
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100504 " live in: (01100)\n"
505 " live out: (01110)\n"
506 " kill: (00010)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100507 "Block 3\n"
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100508 " live in: (01100)\n"
509 " live out: (01100)\n"
510 " kill: (00000)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100511 "Block 4\n" // loop exit
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100512 " live in: (00100)\n"
513 " live out: (00000)\n"
514 " kill: (00000)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100515 "Block 5\n" // back edge
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100516 " live in: (01100)\n"
517 " live out: (01100)\n"
518 " kill: (00000)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100519 "Block 6\n" // return block
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100520 " live in: (00000)\n"
521 " live out: (00000)\n"
522 " kill: (00001)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100523 "Block 7\n" // exit block
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100524 " live in: (00000)\n"
525 " live out: (00000)\n"
526 " kill: (00000)\n"
Nicolas Geoffray622d9c32014-05-12 16:11:02 +0100527 "Block 8\n" // synthesized block to avoid critical edge.
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100528 " live in: (00010)\n"
529 " live out: (00000)\n"
530 " kill: (00000)\n";
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100531
532 const uint16_t data[] = ONE_REGISTER_CODE_ITEM(
533 Instruction::CONST_4 | 0 | 0,
534 Instruction::IF_EQ, 8,
535 Instruction::CONST_4 | 4 << 12 | 0,
536 Instruction::IF_EQ, 4,
537 Instruction::CONST_4 | 5 << 12 | 0,
538 Instruction::GOTO | 0x0200,
539 Instruction::GOTO | 0xF900,
540 Instruction::RETURN | 0 << 8);
541
542 TestCode(data, expected);
543}
544
David Brazdil4833f5a2015-12-16 10:37:39 +0000545TEST_F(LivenessTest, Loop8) {
Nicolas Geoffray8ddb00c2014-09-29 12:00:40 +0100546 // var a = 0;
547 // while (a == a) {
548 // a = a + a;
549 // }
550 // return a;
551 //
552 // We want to test that the ins of the loop exit
553 // does contain the phi.
554 // Bitsets are made of:
555 // (constant0, phi, add)
556 const char* expected =
557 "Block 0\n"
558 " live in: (000)\n"
559 " live out: (100)\n"
560 " kill: (100)\n"
561 "Block 1\n" // pre loop header
562 " live in: (100)\n"
563 " live out: (000)\n"
564 " kill: (000)\n"
565 "Block 2\n" // loop header
566 " live in: (000)\n"
567 " live out: (010)\n"
568 " kill: (010)\n"
569 "Block 3\n" // back edge
570 " live in: (010)\n"
571 " live out: (000)\n"
572 " kill: (001)\n"
573 "Block 4\n" // return block
574 " live in: (010)\n"
575 " live out: (000)\n"
576 " kill: (000)\n"
577 "Block 5\n" // exit block
578 " live in: (000)\n"
579 " live out: (000)\n"
580 " kill: (000)\n";
581
582 const uint16_t data[] = ONE_REGISTER_CODE_ITEM(
583 Instruction::CONST_4 | 0 | 0,
584 Instruction::IF_EQ, 6,
585 Instruction::ADD_INT, 0, 0,
586 Instruction::GOTO | 0xFB00,
587 Instruction::RETURN | 0 << 8);
588
589 TestCode(data, expected);
590}
591
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100592} // namespace art