blob: bd74368e176592087e86703072996a25829fa26a [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;
59 for (HInsertionOrderIterator it(*graph); !it.Done(); it.Advance()) {
60 HBasicBlock* block = it.Current();
61 buffer << "Block " << block->GetBlockId() << std::endl;
Nicolas Geoffray26066f22014-06-03 10:36:16 +000062 size_t ssa_values = liveness.GetNumberOfSsaValues();
Nicolas Geoffray804d0932014-05-02 08:46:00 +010063 BitVector* live_in = liveness.GetLiveInSet(*block);
Nicolas Geoffray26066f22014-06-03 10:36:16 +000064 DumpBitVector(live_in, buffer, ssa_values, " live in: ");
Nicolas Geoffray804d0932014-05-02 08:46:00 +010065 BitVector* live_out = liveness.GetLiveOutSet(*block);
Nicolas Geoffray26066f22014-06-03 10:36:16 +000066 DumpBitVector(live_out, buffer, ssa_values, " live out: ");
Nicolas Geoffray804d0932014-05-02 08:46:00 +010067 BitVector* kill = liveness.GetKillSet(*block);
Nicolas Geoffray26066f22014-06-03 10:36:16 +000068 DumpBitVector(kill, buffer, ssa_values, " kill: ");
Nicolas Geoffray804d0932014-05-02 08:46:00 +010069 }
70 ASSERT_STREQ(expected, buffer.str().c_str());
71}
72
David Brazdil4833f5a2015-12-16 10:37:39 +000073TEST_F(LivenessTest, CFG1) {
Nicolas Geoffray804d0932014-05-02 08:46:00 +010074 const char* expected =
75 "Block 0\n"
Nicolas Geoffray31d76b42014-06-09 15:02:22 +010076 " live in: (0)\n"
77 " live out: (0)\n"
78 " kill: (1)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +010079 "Block 1\n"
Nicolas Geoffray31d76b42014-06-09 15:02:22 +010080 " live in: (0)\n"
81 " live out: (0)\n"
82 " kill: (0)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +010083 "Block 2\n"
Nicolas Geoffray31d76b42014-06-09 15:02:22 +010084 " live in: (0)\n"
85 " live out: (0)\n"
86 " kill: (0)\n";
Nicolas Geoffray804d0932014-05-02 08:46:00 +010087
88 // Constant is not used.
89 const uint16_t data[] = ONE_REGISTER_CODE_ITEM(
90 Instruction::CONST_4 | 0 | 0,
91 Instruction::RETURN_VOID);
92
93 TestCode(data, expected);
94}
95
David Brazdil4833f5a2015-12-16 10:37:39 +000096TEST_F(LivenessTest, CFG2) {
Nicolas Geoffray804d0932014-05-02 08:46:00 +010097 const char* expected =
98 "Block 0\n"
Nicolas Geoffray26066f22014-06-03 10:36:16 +000099 " live in: (0)\n"
100 " live out: (1)\n"
101 " kill: (1)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100102 "Block 1\n"
Nicolas Geoffray26066f22014-06-03 10:36:16 +0000103 " live in: (1)\n"
104 " live out: (0)\n"
105 " kill: (0)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100106 "Block 2\n"
Nicolas Geoffray26066f22014-06-03 10:36:16 +0000107 " live in: (0)\n"
108 " live out: (0)\n"
109 " kill: (0)\n";
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100110
111 const uint16_t data[] = ONE_REGISTER_CODE_ITEM(
112 Instruction::CONST_4 | 0 | 0,
113 Instruction::RETURN);
114
115 TestCode(data, expected);
116}
117
David Brazdil4833f5a2015-12-16 10:37:39 +0000118TEST_F(LivenessTest, CFG3) {
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100119 const char* expected =
120 "Block 0\n" // entry block
Nicolas Geoffray26066f22014-06-03 10:36:16 +0000121 " live in: (000)\n"
122 " live out: (110)\n"
123 " kill: (110)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100124 "Block 1\n" // block with add
Nicolas Geoffray26066f22014-06-03 10:36:16 +0000125 " live in: (110)\n"
126 " live out: (001)\n"
127 " kill: (001)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100128 "Block 2\n" // block with return
Nicolas Geoffray26066f22014-06-03 10:36:16 +0000129 " live in: (001)\n"
130 " live out: (000)\n"
131 " kill: (000)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100132 "Block 3\n" // exit block
Nicolas Geoffray26066f22014-06-03 10:36:16 +0000133 " live in: (000)\n"
134 " live out: (000)\n"
135 " kill: (000)\n";
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100136
137 const uint16_t data[] = TWO_REGISTERS_CODE_ITEM(
138 Instruction::CONST_4 | 3 << 12 | 0,
139 Instruction::CONST_4 | 4 << 12 | 1 << 8,
140 Instruction::ADD_INT_2ADDR | 1 << 12,
141 Instruction::GOTO | 0x100,
142 Instruction::RETURN);
143
144 TestCode(data, expected);
145}
146
David Brazdil4833f5a2015-12-16 10:37:39 +0000147TEST_F(LivenessTest, CFG4) {
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100148 // var a;
149 // if (0 == 0) {
150 // a = 5;
151 // } else {
152 // a = 4;
153 // }
154 // return a;
155 //
156 // Bitsets are made of:
David Brazdildee58d62016-04-07 09:54:26 +0000157 // (constant0, constant5, constant4, phi)
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100158 const char* expected =
159 "Block 0\n" // entry block
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100160 " live in: (0000)\n"
161 " live out: (1110)\n"
162 " kill: (1110)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100163 "Block 1\n" // block with if
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100164 " live in: (1110)\n"
165 " live out: (0110)\n"
166 " kill: (0000)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100167 "Block 2\n" // else block
David Brazdildee58d62016-04-07 09:54:26 +0000168 " live in: (0010)\n"
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100169 " live out: (0000)\n"
170 " kill: (0000)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100171 "Block 3\n" // then block
David Brazdildee58d62016-04-07 09:54:26 +0000172 " live in: (0100)\n"
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100173 " live out: (0000)\n"
174 " kill: (0000)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100175 "Block 4\n" // return block
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100176 " live in: (0000)\n"
177 " live out: (0000)\n"
178 " kill: (0001)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100179 "Block 5\n" // exit block
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100180 " live in: (0000)\n"
181 " live out: (0000)\n"
182 " kill: (0000)\n";
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100183
184 const uint16_t data[] = ONE_REGISTER_CODE_ITEM(
185 Instruction::CONST_4 | 0 | 0,
186 Instruction::IF_EQ, 4,
187 Instruction::CONST_4 | 4 << 12 | 0,
188 Instruction::GOTO | 0x200,
189 Instruction::CONST_4 | 5 << 12 | 0,
190 Instruction::RETURN | 0 << 8);
191
192 TestCode(data, expected);
193}
194
David Brazdil4833f5a2015-12-16 10:37:39 +0000195TEST_F(LivenessTest, CFG5) {
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100196 // var a = 0;
197 // if (0 == 0) {
198 // } else {
199 // a = 4;
200 // }
201 // return a;
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100202 //
203 // Bitsets are made of:
204 // (constant0, constant4, phi)
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100205 const char* expected =
206 "Block 0\n" // entry block
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100207 " live in: (000)\n"
208 " live out: (110)\n"
209 " kill: (110)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100210 "Block 1\n" // block with if
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100211 " live in: (110)\n"
212 " live out: (110)\n"
213 " kill: (000)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100214 "Block 2\n" // else block
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100215 " live in: (010)\n"
216 " live out: (000)\n"
217 " kill: (000)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100218 "Block 3\n" // return block
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100219 " live in: (000)\n"
220 " live out: (000)\n"
221 " kill: (001)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100222 "Block 4\n" // exit block
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100223 " live in: (000)\n"
224 " live out: (000)\n"
225 " kill: (000)\n"
Nicolas Geoffray622d9c32014-05-12 16:11:02 +0100226 "Block 5\n" // block to avoid critical edge. Predecessor is 1, successor is 3.
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100227 " live in: (100)\n"
228 " live out: (000)\n"
229 " kill: (000)\n";
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100230
231 const uint16_t data[] = ONE_REGISTER_CODE_ITEM(
232 Instruction::CONST_4 | 0 | 0,
233 Instruction::IF_EQ, 3,
234 Instruction::CONST_4 | 4 << 12 | 0,
235 Instruction::RETURN | 0 << 8);
236
237 TestCode(data, expected);
238}
239
David Brazdil4833f5a2015-12-16 10:37:39 +0000240TEST_F(LivenessTest, Loop1) {
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100241 // Simple loop with one preheader and one back edge.
242 // var a = 0;
243 // while (a == a) {
244 // a = 4;
245 // }
246 // return;
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100247 // Bitsets are made of:
248 // (constant0, constant4, phi)
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100249 const char* expected =
250 "Block 0\n" // entry block
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100251 " live in: (000)\n"
252 " live out: (110)\n"
253 " kill: (110)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100254 "Block 1\n" // pre header
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100255 " live in: (110)\n"
256 " live out: (010)\n"
257 " kill: (000)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100258 "Block 2\n" // loop header
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100259 " live in: (010)\n"
260 " live out: (010)\n"
261 " kill: (001)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100262 "Block 3\n" // back edge
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100263 " live in: (010)\n"
264 " live out: (010)\n"
265 " kill: (000)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100266 "Block 4\n" // return block
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100267 " live in: (000)\n"
268 " live out: (000)\n"
269 " kill: (000)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100270 "Block 5\n" // exit block
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100271 " live in: (000)\n"
272 " live out: (000)\n"
273 " kill: (000)\n";
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100274
275
276 const uint16_t data[] = ONE_REGISTER_CODE_ITEM(
277 Instruction::CONST_4 | 0 | 0,
278 Instruction::IF_EQ, 4,
279 Instruction::CONST_4 | 4 << 12 | 0,
280 Instruction::GOTO | 0xFD00,
281 Instruction::RETURN_VOID);
282
283 TestCode(data, expected);
284}
285
David Brazdil4833f5a2015-12-16 10:37:39 +0000286TEST_F(LivenessTest, Loop3) {
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100287 // Test that the returned value stays live in a preceding loop.
288 // var a = 0;
289 // while (a == a) {
290 // a = 4;
291 // }
292 // return 5;
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100293 // Bitsets are made of:
David Brazdildee58d62016-04-07 09:54:26 +0000294 // (constant0, constant5, constant4, phi)
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100295 const char* expected =
296 "Block 0\n"
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100297 " live in: (0000)\n"
298 " live out: (1110)\n"
299 " kill: (1110)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100300 "Block 1\n"
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100301 " live in: (1110)\n"
302 " live out: (0110)\n"
303 " kill: (0000)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100304 "Block 2\n" // loop header
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100305 " live in: (0110)\n"
306 " live out: (0110)\n"
307 " kill: (0001)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100308 "Block 3\n" // back edge
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100309 " live in: (0110)\n"
310 " live out: (0110)\n"
311 " kill: (0000)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100312 "Block 4\n" // return block
David Brazdildee58d62016-04-07 09:54:26 +0000313 " live in: (0100)\n"
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100314 " live out: (0000)\n"
315 " kill: (0000)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100316 "Block 5\n" // exit block
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100317 " live in: (0000)\n"
318 " live out: (0000)\n"
319 " kill: (0000)\n";
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100320
321 const uint16_t data[] = TWO_REGISTERS_CODE_ITEM(
322 Instruction::CONST_4 | 0 | 0,
323 Instruction::IF_EQ, 4,
324 Instruction::CONST_4 | 4 << 12 | 0,
325 Instruction::GOTO | 0xFD00,
326 Instruction::CONST_4 | 5 << 12 | 1 << 8,
327 Instruction::RETURN | 1 << 8);
328
329 TestCode(data, expected);
330}
331
332
David Brazdil4833f5a2015-12-16 10:37:39 +0000333TEST_F(LivenessTest, Loop4) {
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100334 // Make sure we support a preheader of a loop not being the first predecessor
335 // in the predecessor list of the header.
336 // var a = 0;
337 // while (a == a) {
338 // a = 4;
339 // }
340 // return a;
341 // Bitsets are made of:
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100342 // (constant0, constant4, phi)
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100343 const char* expected =
344 "Block 0\n"
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100345 " live in: (000)\n"
346 " live out: (110)\n"
347 " kill: (110)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100348 "Block 1\n"
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100349 " live in: (110)\n"
350 " live out: (110)\n"
351 " kill: (000)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100352 "Block 2\n" // loop header
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100353 " live in: (010)\n"
354 " live out: (011)\n"
355 " kill: (001)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100356 "Block 3\n" // back edge
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100357 " live in: (010)\n"
358 " live out: (010)\n"
359 " kill: (000)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100360 "Block 4\n" // pre loop header
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100361 " live in: (110)\n"
362 " live out: (010)\n"
363 " kill: (000)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100364 "Block 5\n" // return block
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100365 " live in: (001)\n"
366 " live out: (000)\n"
367 " kill: (000)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100368 "Block 6\n" // exit block
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100369 " live in: (000)\n"
370 " live out: (000)\n"
371 " kill: (000)\n";
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100372
373 const uint16_t data[] = ONE_REGISTER_CODE_ITEM(
374 Instruction::CONST_4 | 0 | 0,
375 Instruction::GOTO | 0x500,
376 Instruction::IF_EQ, 5,
377 Instruction::CONST_4 | 4 << 12 | 0,
378 Instruction::GOTO | 0xFD00,
379 Instruction::GOTO | 0xFC00,
380 Instruction::RETURN | 0 << 8);
381
382 TestCode(data, expected);
383}
384
David Brazdil4833f5a2015-12-16 10:37:39 +0000385TEST_F(LivenessTest, Loop5) {
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100386 // Make sure we create a preheader of a loop when a header originally has two
387 // incoming blocks and one back edge.
388 // Bitsets are made of:
David Brazdildee58d62016-04-07 09:54:26 +0000389 // (constant0, constant5, constant4, phi in block 8)
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100390 const char* expected =
391 "Block 0\n"
Nicolas Geoffray3afca782015-03-10 18:59:31 +0000392 " live in: (0000)\n"
393 " live out: (1110)\n"
394 " kill: (1110)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100395 "Block 1\n"
Nicolas Geoffray3afca782015-03-10 18:59:31 +0000396 " live in: (1110)\n"
397 " live out: (0110)\n"
398 " kill: (0000)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100399 "Block 2\n"
David Brazdildee58d62016-04-07 09:54:26 +0000400 " live in: (0010)\n"
Nicolas Geoffray3afca782015-03-10 18:59:31 +0000401 " live out: (0000)\n"
402 " kill: (0000)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100403 "Block 3\n"
David Brazdildee58d62016-04-07 09:54:26 +0000404 " live in: (0100)\n"
Nicolas Geoffray3afca782015-03-10 18:59:31 +0000405 " live out: (0000)\n"
406 " kill: (0000)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100407 "Block 4\n" // loop header
Nicolas Geoffray3afca782015-03-10 18:59:31 +0000408 " live in: (0001)\n"
409 " live out: (0001)\n"
410 " kill: (0000)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100411 "Block 5\n" // back edge
Nicolas Geoffray3afca782015-03-10 18:59:31 +0000412 " live in: (0001)\n"
413 " live out: (0001)\n"
414 " kill: (0000)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100415 "Block 6\n" // return block
Nicolas Geoffray3afca782015-03-10 18:59:31 +0000416 " live in: (0001)\n"
417 " live out: (0000)\n"
418 " kill: (0000)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100419 "Block 7\n" // exit block
Nicolas Geoffray3afca782015-03-10 18:59:31 +0000420 " live in: (0000)\n"
421 " live out: (0000)\n"
422 " kill: (0000)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100423 "Block 8\n" // synthesized pre header
Nicolas Geoffray3afca782015-03-10 18:59:31 +0000424 " live in: (0000)\n"
425 " live out: (0001)\n"
426 " kill: (0001)\n";
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100427
428 const uint16_t data[] = ONE_REGISTER_CODE_ITEM(
429 Instruction::CONST_4 | 0 | 0,
430 Instruction::IF_EQ, 4,
431 Instruction::CONST_4 | 4 << 12 | 0,
432 Instruction::GOTO | 0x200,
433 Instruction::CONST_4 | 5 << 12 | 0,
434 Instruction::IF_EQ, 3,
435 Instruction::GOTO | 0xFE00,
436 Instruction::RETURN | 0 << 8);
437
438 TestCode(data, expected);
439}
440
David Brazdil4833f5a2015-12-16 10:37:39 +0000441TEST_F(LivenessTest, Loop6) {
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100442 // Bitsets are made of:
Nicolas Geoffraydb216f42015-05-05 17:02:20 +0100443 // (constant0, constant4, constant5, phi in block 2)
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100444 const char* expected =
445 "Block 0\n"
Nicolas Geoffraydb216f42015-05-05 17:02:20 +0100446 " live in: (0000)\n"
447 " live out: (1110)\n"
448 " kill: (1110)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100449 "Block 1\n"
Nicolas Geoffraydb216f42015-05-05 17:02:20 +0100450 " live in: (1110)\n"
451 " live out: (0110)\n"
452 " kill: (0000)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100453 "Block 2\n" // loop header
Nicolas Geoffraydb216f42015-05-05 17:02:20 +0100454 " live in: (0110)\n"
455 " live out: (0111)\n"
456 " kill: (0001)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100457 "Block 3\n"
Nicolas Geoffraydb216f42015-05-05 17:02:20 +0100458 " live in: (0110)\n"
459 " live out: (0110)\n"
460 " kill: (0000)\n"
461 "Block 4\n" // back edge
462 " live in: (0110)\n"
463 " live out: (0110)\n"
464 " kill: (0000)\n"
465 "Block 5\n" // back edge
466 " live in: (0110)\n"
467 " live out: (0110)\n"
468 " kill: (0000)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100469 "Block 6\n" // return block
Nicolas Geoffraydb216f42015-05-05 17:02:20 +0100470 " live in: (0001)\n"
471 " live out: (0000)\n"
472 " kill: (0000)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100473 "Block 7\n" // exit block
Nicolas Geoffraydb216f42015-05-05 17:02:20 +0100474 " live in: (0000)\n"
475 " live out: (0000)\n"
476 " kill: (0000)\n";
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100477
478 const uint16_t data[] = ONE_REGISTER_CODE_ITEM(
479 Instruction::CONST_4 | 0 | 0,
480 Instruction::IF_EQ, 8,
481 Instruction::CONST_4 | 4 << 12 | 0,
482 Instruction::IF_EQ, 4,
483 Instruction::CONST_4 | 5 << 12 | 0,
484 Instruction::GOTO | 0xFA00,
485 Instruction::GOTO | 0xF900,
486 Instruction::RETURN | 0 << 8);
487
488 TestCode(data, expected);
489}
490
491
David Brazdil4833f5a2015-12-16 10:37:39 +0000492TEST_F(LivenessTest, Loop7) {
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100493 // Bitsets are made of:
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100494 // (constant0, constant4, constant5, phi in block 2, phi in block 6)
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100495 const char* expected =
496 "Block 0\n"
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100497 " live in: (00000)\n"
498 " live out: (11100)\n"
499 " kill: (11100)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100500 "Block 1\n"
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100501 " live in: (11100)\n"
502 " live out: (01100)\n"
503 " kill: (00000)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100504 "Block 2\n" // loop header
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100505 " live in: (01100)\n"
506 " live out: (01110)\n"
507 " kill: (00010)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100508 "Block 3\n"
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100509 " live in: (01100)\n"
510 " live out: (01100)\n"
511 " kill: (00000)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100512 "Block 4\n" // loop exit
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100513 " live in: (00100)\n"
514 " live out: (00000)\n"
515 " kill: (00000)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100516 "Block 5\n" // back edge
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100517 " live in: (01100)\n"
518 " live out: (01100)\n"
519 " kill: (00000)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100520 "Block 6\n" // return block
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100521 " live in: (00000)\n"
522 " live out: (00000)\n"
523 " kill: (00001)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100524 "Block 7\n" // exit block
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100525 " live in: (00000)\n"
526 " live out: (00000)\n"
527 " kill: (00000)\n"
Nicolas Geoffray622d9c32014-05-12 16:11:02 +0100528 "Block 8\n" // synthesized block to avoid critical edge.
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100529 " live in: (00010)\n"
530 " live out: (00000)\n"
531 " kill: (00000)\n";
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100532
533 const uint16_t data[] = ONE_REGISTER_CODE_ITEM(
534 Instruction::CONST_4 | 0 | 0,
535 Instruction::IF_EQ, 8,
536 Instruction::CONST_4 | 4 << 12 | 0,
537 Instruction::IF_EQ, 4,
538 Instruction::CONST_4 | 5 << 12 | 0,
539 Instruction::GOTO | 0x0200,
540 Instruction::GOTO | 0xF900,
541 Instruction::RETURN | 0 << 8);
542
543 TestCode(data, expected);
544}
545
David Brazdil4833f5a2015-12-16 10:37:39 +0000546TEST_F(LivenessTest, Loop8) {
Nicolas Geoffray8ddb00c2014-09-29 12:00:40 +0100547 // var a = 0;
548 // while (a == a) {
549 // a = a + a;
550 // }
551 // return a;
552 //
553 // We want to test that the ins of the loop exit
554 // does contain the phi.
555 // Bitsets are made of:
556 // (constant0, phi, add)
557 const char* expected =
558 "Block 0\n"
559 " live in: (000)\n"
560 " live out: (100)\n"
561 " kill: (100)\n"
562 "Block 1\n" // pre loop header
563 " live in: (100)\n"
564 " live out: (000)\n"
565 " kill: (000)\n"
566 "Block 2\n" // loop header
567 " live in: (000)\n"
568 " live out: (010)\n"
569 " kill: (010)\n"
570 "Block 3\n" // back edge
571 " live in: (010)\n"
572 " live out: (000)\n"
573 " kill: (001)\n"
574 "Block 4\n" // return block
575 " live in: (010)\n"
576 " live out: (000)\n"
577 " kill: (000)\n"
578 "Block 5\n" // exit block
579 " live in: (000)\n"
580 " live out: (000)\n"
581 " kill: (000)\n";
582
583 const uint16_t data[] = ONE_REGISTER_CODE_ITEM(
584 Instruction::CONST_4 | 0 | 0,
585 Instruction::IF_EQ, 6,
586 Instruction::ADD_INT, 0, 0,
587 Instruction::GOTO | 0xFB00,
588 Instruction::RETURN | 0 << 8);
589
590 TestCode(data, expected);
591}
592
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100593} // namespace art