blob: f11f7a977914b148fb9119305620ff69df414853 [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
Mathieu Chartierb666f482015-02-18 14:33:14 -080017#include "base/arena_allocator.h"
Nicolas Geoffray804d0932014-05-02 08:46:00 +010018#include "builder.h"
Nicolas Geoffray31d76b42014-06-09 15:02:22 +010019#include "code_generator.h"
David Sehr9e734c72018-01-04 17:56:19 -080020#include "dex/dex_file.h"
21#include "dex/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"
Nicolas Geoffray804d0932014-05-02 08:46:00 +010027
Alex Light68289a52015-12-15 17:30:30 -080028namespace art {
David Brazdild9510df2015-11-04 23:30:22 +000029
Vladimir Markoca6fff82017-10-03 14:49:14 +010030class LivenessTest : public OptimizingUnitTest {
31 protected:
Mathieu Chartierfa3db3d2018-01-12 14:42:18 -080032 void TestCode(const std::vector<uint16_t>& data, const char* expected);
Vladimir Markoca6fff82017-10-03 14:49:14 +010033};
David Brazdil4833f5a2015-12-16 10:37:39 +000034
Nicolas Geoffray26066f22014-06-03 10:36:16 +000035static void DumpBitVector(BitVector* vector,
36 std::ostream& buffer,
37 size_t count,
38 const char* prefix) {
39 buffer << prefix;
40 buffer << '(';
41 for (size_t i = 0; i < count; ++i) {
42 buffer << vector->IsBitSet(i);
43 }
44 buffer << ")\n";
45}
46
Mathieu Chartierfa3db3d2018-01-12 14:42:18 -080047void LivenessTest::TestCode(const std::vector<uint16_t>& data, const char* expected) {
Vladimir Markoca6fff82017-10-03 14:49:14 +010048 HGraph* graph = CreateCFG(data);
Nicolas Geoffray360231a2014-10-08 21:07:48 +010049 // `Inline` conditions into ifs.
Nicolas Geoffray61ba8d22018-08-07 09:55:57 +010050 PrepareForRegisterAllocation(graph, *compiler_options_).Run();
Vladimir Markoa0431112018-06-25 09:32:54 +010051 std::unique_ptr<CodeGenerator> codegen = CodeGenerator::Create(graph, *compiler_options_);
52 SsaLivenessAnalysis liveness(graph, codegen.get(), GetScopedAllocator());
Nicolas Geoffray804d0932014-05-02 08:46:00 +010053 liveness.Analyze();
54
55 std::ostringstream buffer;
Vladimir Marko2c45bc92016-10-25 16:54:12 +010056 for (HBasicBlock* block : graph->GetBlocks()) {
Nicolas Geoffray804d0932014-05-02 08:46:00 +010057 buffer << "Block " << block->GetBlockId() << std::endl;
Nicolas Geoffray26066f22014-06-03 10:36:16 +000058 size_t ssa_values = liveness.GetNumberOfSsaValues();
Nicolas Geoffray804d0932014-05-02 08:46:00 +010059 BitVector* live_in = liveness.GetLiveInSet(*block);
Nicolas Geoffray26066f22014-06-03 10:36:16 +000060 DumpBitVector(live_in, buffer, ssa_values, " live in: ");
Nicolas Geoffray804d0932014-05-02 08:46:00 +010061 BitVector* live_out = liveness.GetLiveOutSet(*block);
Nicolas Geoffray26066f22014-06-03 10:36:16 +000062 DumpBitVector(live_out, buffer, ssa_values, " live out: ");
Nicolas Geoffray804d0932014-05-02 08:46:00 +010063 BitVector* kill = liveness.GetKillSet(*block);
Nicolas Geoffray26066f22014-06-03 10:36:16 +000064 DumpBitVector(kill, buffer, ssa_values, " kill: ");
Nicolas Geoffray804d0932014-05-02 08:46:00 +010065 }
66 ASSERT_STREQ(expected, buffer.str().c_str());
67}
68
David Brazdil4833f5a2015-12-16 10:37:39 +000069TEST_F(LivenessTest, CFG1) {
Nicolas Geoffray804d0932014-05-02 08:46:00 +010070 const char* expected =
71 "Block 0\n"
Nicolas Geoffray31d76b42014-06-09 15:02:22 +010072 " live in: (0)\n"
73 " live out: (0)\n"
74 " kill: (1)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +010075 "Block 1\n"
Nicolas Geoffray31d76b42014-06-09 15:02:22 +010076 " live in: (0)\n"
77 " live out: (0)\n"
78 " kill: (0)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +010079 "Block 2\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
84 // Constant is not used.
Mathieu Chartierfa3db3d2018-01-12 14:42:18 -080085 const std::vector<uint16_t> data = ONE_REGISTER_CODE_ITEM(
Nicolas Geoffray804d0932014-05-02 08:46:00 +010086 Instruction::CONST_4 | 0 | 0,
87 Instruction::RETURN_VOID);
88
89 TestCode(data, expected);
90}
91
David Brazdil4833f5a2015-12-16 10:37:39 +000092TEST_F(LivenessTest, CFG2) {
Nicolas Geoffray804d0932014-05-02 08:46:00 +010093 const char* expected =
94 "Block 0\n"
Nicolas Geoffray26066f22014-06-03 10:36:16 +000095 " live in: (0)\n"
96 " live out: (1)\n"
97 " kill: (1)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +010098 "Block 1\n"
Nicolas Geoffray26066f22014-06-03 10:36:16 +000099 " live in: (1)\n"
100 " live out: (0)\n"
101 " kill: (0)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100102 "Block 2\n"
Nicolas Geoffray26066f22014-06-03 10:36:16 +0000103 " live in: (0)\n"
104 " live out: (0)\n"
105 " kill: (0)\n";
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100106
Mathieu Chartierfa3db3d2018-01-12 14:42:18 -0800107 const std::vector<uint16_t> data = ONE_REGISTER_CODE_ITEM(
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100108 Instruction::CONST_4 | 0 | 0,
109 Instruction::RETURN);
110
111 TestCode(data, expected);
112}
113
David Brazdil4833f5a2015-12-16 10:37:39 +0000114TEST_F(LivenessTest, CFG3) {
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100115 const char* expected =
116 "Block 0\n" // entry block
Nicolas Geoffray26066f22014-06-03 10:36:16 +0000117 " live in: (000)\n"
118 " live out: (110)\n"
119 " kill: (110)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100120 "Block 1\n" // block with add
Nicolas Geoffray26066f22014-06-03 10:36:16 +0000121 " live in: (110)\n"
122 " live out: (001)\n"
123 " kill: (001)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100124 "Block 2\n" // block with return
Nicolas Geoffray26066f22014-06-03 10:36:16 +0000125 " live in: (001)\n"
126 " live out: (000)\n"
127 " kill: (000)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100128 "Block 3\n" // exit block
Nicolas Geoffray26066f22014-06-03 10:36:16 +0000129 " live in: (000)\n"
130 " live out: (000)\n"
131 " kill: (000)\n";
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100132
Mathieu Chartierfa3db3d2018-01-12 14:42:18 -0800133 const std::vector<uint16_t> data = TWO_REGISTERS_CODE_ITEM(
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100134 Instruction::CONST_4 | 3 << 12 | 0,
135 Instruction::CONST_4 | 4 << 12 | 1 << 8,
136 Instruction::ADD_INT_2ADDR | 1 << 12,
137 Instruction::GOTO | 0x100,
138 Instruction::RETURN);
139
140 TestCode(data, expected);
141}
142
David Brazdil4833f5a2015-12-16 10:37:39 +0000143TEST_F(LivenessTest, CFG4) {
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100144 // var a;
145 // if (0 == 0) {
146 // a = 5;
147 // } else {
148 // a = 4;
149 // }
150 // return a;
151 //
152 // Bitsets are made of:
David Brazdildee58d62016-04-07 09:54:26 +0000153 // (constant0, constant5, constant4, phi)
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100154 const char* expected =
155 "Block 0\n" // entry block
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100156 " live in: (0000)\n"
157 " live out: (1110)\n"
158 " kill: (1110)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100159 "Block 1\n" // block with if
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100160 " live in: (1110)\n"
161 " live out: (0110)\n"
162 " kill: (0000)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100163 "Block 2\n" // else block
David Brazdildee58d62016-04-07 09:54:26 +0000164 " live in: (0010)\n"
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100165 " live out: (0000)\n"
166 " kill: (0000)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100167 "Block 3\n" // then block
David Brazdildee58d62016-04-07 09:54:26 +0000168 " live in: (0100)\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 4\n" // return block
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100172 " live in: (0000)\n"
173 " live out: (0000)\n"
174 " kill: (0001)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100175 "Block 5\n" // exit block
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100176 " live in: (0000)\n"
177 " live out: (0000)\n"
178 " kill: (0000)\n";
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100179
Mathieu Chartierfa3db3d2018-01-12 14:42:18 -0800180 const std::vector<uint16_t> data = ONE_REGISTER_CODE_ITEM(
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100181 Instruction::CONST_4 | 0 | 0,
182 Instruction::IF_EQ, 4,
183 Instruction::CONST_4 | 4 << 12 | 0,
184 Instruction::GOTO | 0x200,
185 Instruction::CONST_4 | 5 << 12 | 0,
186 Instruction::RETURN | 0 << 8);
187
188 TestCode(data, expected);
189}
190
David Brazdil4833f5a2015-12-16 10:37:39 +0000191TEST_F(LivenessTest, CFG5) {
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100192 // var a = 0;
193 // if (0 == 0) {
194 // } else {
195 // a = 4;
196 // }
197 // return a;
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100198 //
199 // Bitsets are made of:
200 // (constant0, constant4, phi)
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100201 const char* expected =
202 "Block 0\n" // entry block
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100203 " live in: (000)\n"
204 " live out: (110)\n"
205 " kill: (110)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100206 "Block 1\n" // block with if
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100207 " live in: (110)\n"
208 " live out: (110)\n"
209 " kill: (000)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100210 "Block 2\n" // else block
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100211 " live in: (010)\n"
212 " live out: (000)\n"
213 " kill: (000)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100214 "Block 3\n" // return block
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100215 " live in: (000)\n"
216 " live out: (000)\n"
217 " kill: (001)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100218 "Block 4\n" // exit block
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100219 " live in: (000)\n"
220 " live out: (000)\n"
221 " kill: (000)\n"
Nicolas Geoffray622d9c32014-05-12 16:11:02 +0100222 "Block 5\n" // block to avoid critical edge. Predecessor is 1, successor is 3.
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100223 " live in: (100)\n"
224 " live out: (000)\n"
225 " kill: (000)\n";
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100226
Mathieu Chartierfa3db3d2018-01-12 14:42:18 -0800227 const std::vector<uint16_t> data = ONE_REGISTER_CODE_ITEM(
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100228 Instruction::CONST_4 | 0 | 0,
229 Instruction::IF_EQ, 3,
230 Instruction::CONST_4 | 4 << 12 | 0,
231 Instruction::RETURN | 0 << 8);
232
233 TestCode(data, expected);
234}
235
David Brazdil4833f5a2015-12-16 10:37:39 +0000236TEST_F(LivenessTest, Loop1) {
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100237 // Simple loop with one preheader and one back edge.
238 // var a = 0;
239 // while (a == a) {
240 // a = 4;
241 // }
242 // return;
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100243 // Bitsets are made of:
244 // (constant0, constant4, phi)
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100245 const char* expected =
246 "Block 0\n" // entry block
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100247 " live in: (000)\n"
248 " live out: (110)\n"
249 " kill: (110)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100250 "Block 1\n" // pre header
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100251 " live in: (110)\n"
252 " live out: (010)\n"
253 " kill: (000)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100254 "Block 2\n" // loop header
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100255 " live in: (010)\n"
256 " live out: (010)\n"
257 " kill: (001)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100258 "Block 3\n" // back edge
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100259 " live in: (010)\n"
260 " live out: (010)\n"
261 " kill: (000)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100262 "Block 4\n" // return block
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100263 " live in: (000)\n"
264 " live out: (000)\n"
265 " kill: (000)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100266 "Block 5\n" // exit 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
271
Mathieu Chartierfa3db3d2018-01-12 14:42:18 -0800272 const std::vector<uint16_t> data = ONE_REGISTER_CODE_ITEM(
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100273 Instruction::CONST_4 | 0 | 0,
274 Instruction::IF_EQ, 4,
275 Instruction::CONST_4 | 4 << 12 | 0,
276 Instruction::GOTO | 0xFD00,
277 Instruction::RETURN_VOID);
278
279 TestCode(data, expected);
280}
281
David Brazdil4833f5a2015-12-16 10:37:39 +0000282TEST_F(LivenessTest, Loop3) {
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100283 // Test that the returned value stays live in a preceding loop.
284 // var a = 0;
285 // while (a == a) {
286 // a = 4;
287 // }
288 // return 5;
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100289 // Bitsets are made of:
David Brazdildee58d62016-04-07 09:54:26 +0000290 // (constant0, constant5, constant4, phi)
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100291 const char* expected =
292 "Block 0\n"
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100293 " live in: (0000)\n"
294 " live out: (1110)\n"
295 " kill: (1110)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100296 "Block 1\n"
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100297 " live in: (1110)\n"
298 " live out: (0110)\n"
299 " kill: (0000)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100300 "Block 2\n" // loop header
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100301 " live in: (0110)\n"
302 " live out: (0110)\n"
303 " kill: (0001)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100304 "Block 3\n" // back edge
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100305 " live in: (0110)\n"
306 " live out: (0110)\n"
307 " kill: (0000)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100308 "Block 4\n" // return block
David Brazdildee58d62016-04-07 09:54:26 +0000309 " live in: (0100)\n"
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100310 " live out: (0000)\n"
311 " kill: (0000)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100312 "Block 5\n" // exit block
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100313 " live in: (0000)\n"
314 " live out: (0000)\n"
315 " kill: (0000)\n";
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100316
Mathieu Chartierfa3db3d2018-01-12 14:42:18 -0800317 const std::vector<uint16_t> data = TWO_REGISTERS_CODE_ITEM(
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100318 Instruction::CONST_4 | 0 | 0,
319 Instruction::IF_EQ, 4,
320 Instruction::CONST_4 | 4 << 12 | 0,
321 Instruction::GOTO | 0xFD00,
322 Instruction::CONST_4 | 5 << 12 | 1 << 8,
323 Instruction::RETURN | 1 << 8);
324
325 TestCode(data, expected);
326}
327
328
David Brazdil4833f5a2015-12-16 10:37:39 +0000329TEST_F(LivenessTest, Loop4) {
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100330 // Make sure we support a preheader of a loop not being the first predecessor
331 // in the predecessor list of the header.
332 // var a = 0;
333 // while (a == a) {
334 // a = 4;
335 // }
336 // return a;
337 // Bitsets are made of:
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100338 // (constant0, constant4, phi)
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100339 const char* expected =
340 "Block 0\n"
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100341 " live in: (000)\n"
342 " live out: (110)\n"
343 " kill: (110)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100344 "Block 1\n"
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100345 " live in: (110)\n"
346 " live out: (110)\n"
347 " kill: (000)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100348 "Block 2\n" // loop header
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100349 " live in: (010)\n"
350 " live out: (011)\n"
351 " kill: (001)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100352 "Block 3\n" // back edge
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100353 " live in: (010)\n"
354 " live out: (010)\n"
355 " kill: (000)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100356 "Block 4\n" // pre loop header
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100357 " live in: (110)\n"
358 " live out: (010)\n"
359 " kill: (000)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100360 "Block 5\n" // return block
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100361 " live in: (001)\n"
362 " live out: (000)\n"
363 " kill: (000)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100364 "Block 6\n" // exit block
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100365 " live in: (000)\n"
366 " live out: (000)\n"
367 " kill: (000)\n";
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100368
Mathieu Chartierfa3db3d2018-01-12 14:42:18 -0800369 const std::vector<uint16_t> data = ONE_REGISTER_CODE_ITEM(
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100370 Instruction::CONST_4 | 0 | 0,
371 Instruction::GOTO | 0x500,
372 Instruction::IF_EQ, 5,
373 Instruction::CONST_4 | 4 << 12 | 0,
374 Instruction::GOTO | 0xFD00,
375 Instruction::GOTO | 0xFC00,
376 Instruction::RETURN | 0 << 8);
377
378 TestCode(data, expected);
379}
380
David Brazdil4833f5a2015-12-16 10:37:39 +0000381TEST_F(LivenessTest, Loop5) {
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100382 // Make sure we create a preheader of a loop when a header originally has two
383 // incoming blocks and one back edge.
384 // Bitsets are made of:
David Brazdildee58d62016-04-07 09:54:26 +0000385 // (constant0, constant5, constant4, phi in block 8)
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100386 const char* expected =
387 "Block 0\n"
Nicolas Geoffray3afca782015-03-10 18:59:31 +0000388 " live in: (0000)\n"
389 " live out: (1110)\n"
390 " kill: (1110)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100391 "Block 1\n"
Nicolas Geoffray3afca782015-03-10 18:59:31 +0000392 " live in: (1110)\n"
393 " live out: (0110)\n"
394 " kill: (0000)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100395 "Block 2\n"
David Brazdildee58d62016-04-07 09:54:26 +0000396 " live in: (0010)\n"
Nicolas Geoffray3afca782015-03-10 18:59:31 +0000397 " live out: (0000)\n"
398 " kill: (0000)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100399 "Block 3\n"
David Brazdildee58d62016-04-07 09:54:26 +0000400 " live in: (0100)\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 4\n" // loop header
Nicolas Geoffray3afca782015-03-10 18:59:31 +0000404 " live in: (0001)\n"
405 " live out: (0001)\n"
406 " kill: (0000)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100407 "Block 5\n" // back edge
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 6\n" // return block
Nicolas Geoffray3afca782015-03-10 18:59:31 +0000412 " live in: (0001)\n"
413 " live out: (0000)\n"
414 " kill: (0000)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100415 "Block 7\n" // exit block
Nicolas Geoffray3afca782015-03-10 18:59:31 +0000416 " live in: (0000)\n"
417 " live out: (0000)\n"
418 " kill: (0000)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100419 "Block 8\n" // synthesized pre header
Nicolas Geoffray3afca782015-03-10 18:59:31 +0000420 " live in: (0000)\n"
421 " live out: (0001)\n"
422 " kill: (0001)\n";
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100423
Mathieu Chartierfa3db3d2018-01-12 14:42:18 -0800424 const std::vector<uint16_t> data = ONE_REGISTER_CODE_ITEM(
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100425 Instruction::CONST_4 | 0 | 0,
426 Instruction::IF_EQ, 4,
427 Instruction::CONST_4 | 4 << 12 | 0,
428 Instruction::GOTO | 0x200,
429 Instruction::CONST_4 | 5 << 12 | 0,
430 Instruction::IF_EQ, 3,
431 Instruction::GOTO | 0xFE00,
432 Instruction::RETURN | 0 << 8);
433
434 TestCode(data, expected);
435}
436
David Brazdil4833f5a2015-12-16 10:37:39 +0000437TEST_F(LivenessTest, Loop6) {
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100438 // Bitsets are made of:
Nicolas Geoffraydb216f42015-05-05 17:02:20 +0100439 // (constant0, constant4, constant5, phi in block 2)
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100440 const char* expected =
441 "Block 0\n"
Nicolas Geoffraydb216f42015-05-05 17:02:20 +0100442 " live in: (0000)\n"
443 " live out: (1110)\n"
444 " kill: (1110)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100445 "Block 1\n"
Nicolas Geoffraydb216f42015-05-05 17:02:20 +0100446 " live in: (1110)\n"
447 " live out: (0110)\n"
448 " kill: (0000)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100449 "Block 2\n" // loop header
Nicolas Geoffraydb216f42015-05-05 17:02:20 +0100450 " live in: (0110)\n"
451 " live out: (0111)\n"
452 " kill: (0001)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100453 "Block 3\n"
Nicolas Geoffraydb216f42015-05-05 17:02:20 +0100454 " live in: (0110)\n"
455 " live out: (0110)\n"
456 " kill: (0000)\n"
457 "Block 4\n" // back edge
458 " live in: (0110)\n"
459 " live out: (0110)\n"
460 " kill: (0000)\n"
461 "Block 5\n" // back edge
462 " live in: (0110)\n"
463 " live out: (0110)\n"
464 " kill: (0000)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100465 "Block 6\n" // return block
Nicolas Geoffraydb216f42015-05-05 17:02:20 +0100466 " live in: (0001)\n"
467 " live out: (0000)\n"
468 " kill: (0000)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100469 "Block 7\n" // exit block
Nicolas Geoffraydb216f42015-05-05 17:02:20 +0100470 " live in: (0000)\n"
471 " live out: (0000)\n"
472 " kill: (0000)\n";
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100473
Mathieu Chartierfa3db3d2018-01-12 14:42:18 -0800474 const std::vector<uint16_t> data = ONE_REGISTER_CODE_ITEM(
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100475 Instruction::CONST_4 | 0 | 0,
476 Instruction::IF_EQ, 8,
477 Instruction::CONST_4 | 4 << 12 | 0,
478 Instruction::IF_EQ, 4,
479 Instruction::CONST_4 | 5 << 12 | 0,
480 Instruction::GOTO | 0xFA00,
481 Instruction::GOTO | 0xF900,
482 Instruction::RETURN | 0 << 8);
483
484 TestCode(data, expected);
485}
486
487
David Brazdil4833f5a2015-12-16 10:37:39 +0000488TEST_F(LivenessTest, Loop7) {
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100489 // Bitsets are made of:
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100490 // (constant0, constant4, constant5, phi in block 2, phi in block 6)
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100491 const char* expected =
492 "Block 0\n"
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100493 " live in: (00000)\n"
494 " live out: (11100)\n"
495 " kill: (11100)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100496 "Block 1\n"
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100497 " live in: (11100)\n"
498 " live out: (01100)\n"
499 " kill: (00000)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100500 "Block 2\n" // loop header
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100501 " live in: (01100)\n"
502 " live out: (01110)\n"
503 " kill: (00010)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100504 "Block 3\n"
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100505 " live in: (01100)\n"
506 " live out: (01100)\n"
507 " kill: (00000)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100508 "Block 4\n" // loop exit
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100509 " live in: (00100)\n"
510 " live out: (00000)\n"
511 " kill: (00000)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100512 "Block 5\n" // back edge
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100513 " live in: (01100)\n"
514 " live out: (01100)\n"
515 " kill: (00000)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100516 "Block 6\n" // return block
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100517 " live in: (00000)\n"
518 " live out: (00000)\n"
519 " kill: (00001)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100520 "Block 7\n" // exit block
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100521 " live in: (00000)\n"
522 " live out: (00000)\n"
523 " kill: (00000)\n"
Nicolas Geoffray622d9c32014-05-12 16:11:02 +0100524 "Block 8\n" // synthesized block to avoid critical edge.
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100525 " live in: (00010)\n"
526 " live out: (00000)\n"
527 " kill: (00000)\n";
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100528
Mathieu Chartierfa3db3d2018-01-12 14:42:18 -0800529 const std::vector<uint16_t> data = ONE_REGISTER_CODE_ITEM(
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100530 Instruction::CONST_4 | 0 | 0,
531 Instruction::IF_EQ, 8,
532 Instruction::CONST_4 | 4 << 12 | 0,
533 Instruction::IF_EQ, 4,
534 Instruction::CONST_4 | 5 << 12 | 0,
535 Instruction::GOTO | 0x0200,
536 Instruction::GOTO | 0xF900,
537 Instruction::RETURN | 0 << 8);
538
539 TestCode(data, expected);
540}
541
David Brazdil4833f5a2015-12-16 10:37:39 +0000542TEST_F(LivenessTest, Loop8) {
Nicolas Geoffray8ddb00c2014-09-29 12:00:40 +0100543 // var a = 0;
544 // while (a == a) {
545 // a = a + a;
546 // }
547 // return a;
548 //
549 // We want to test that the ins of the loop exit
550 // does contain the phi.
551 // Bitsets are made of:
552 // (constant0, phi, add)
553 const char* expected =
554 "Block 0\n"
555 " live in: (000)\n"
556 " live out: (100)\n"
557 " kill: (100)\n"
558 "Block 1\n" // pre loop header
559 " live in: (100)\n"
560 " live out: (000)\n"
561 " kill: (000)\n"
562 "Block 2\n" // loop header
563 " live in: (000)\n"
564 " live out: (010)\n"
565 " kill: (010)\n"
566 "Block 3\n" // back edge
567 " live in: (010)\n"
568 " live out: (000)\n"
569 " kill: (001)\n"
570 "Block 4\n" // return block
571 " live in: (010)\n"
572 " live out: (000)\n"
573 " kill: (000)\n"
574 "Block 5\n" // exit block
575 " live in: (000)\n"
576 " live out: (000)\n"
577 " kill: (000)\n";
578
Mathieu Chartierfa3db3d2018-01-12 14:42:18 -0800579 const std::vector<uint16_t> data = ONE_REGISTER_CODE_ITEM(
Nicolas Geoffray8ddb00c2014-09-29 12:00:40 +0100580 Instruction::CONST_4 | 0 | 0,
581 Instruction::IF_EQ, 6,
582 Instruction::ADD_INT, 0, 0,
583 Instruction::GOTO | 0xFB00,
584 Instruction::RETURN | 0 << 8);
585
586 TestCode(data, expected);
587}
588
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100589} // namespace art