blob: ba3787e9be3f6269b8e68e79504c20490662b324 [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
Vladimir Marko0a516052019-10-14 13:00:44 +000028namespace 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.
Vladimir Markof91fc122020-05-13 09:21:00 +010050 std::unique_ptr<CompilerOptions> compiler_options =
51 CommonCompilerTest::CreateCompilerOptions(kRuntimeISA, "default");
52 PrepareForRegisterAllocation(graph, *compiler_options).Run();
53 std::unique_ptr<CodeGenerator> codegen = CodeGenerator::Create(graph, *compiler_options);
Vladimir Markoa0431112018-06-25 09:32:54 +010054 SsaLivenessAnalysis liveness(graph, codegen.get(), GetScopedAllocator());
Nicolas Geoffray804d0932014-05-02 08:46:00 +010055 liveness.Analyze();
56
57 std::ostringstream buffer;
Vladimir Marko2c45bc92016-10-25 16:54:12 +010058 for (HBasicBlock* block : graph->GetBlocks()) {
Nicolas Geoffray804d0932014-05-02 08:46:00 +010059 buffer << "Block " << block->GetBlockId() << std::endl;
Nicolas Geoffray26066f22014-06-03 10:36:16 +000060 size_t ssa_values = liveness.GetNumberOfSsaValues();
Nicolas Geoffray804d0932014-05-02 08:46:00 +010061 BitVector* live_in = liveness.GetLiveInSet(*block);
Nicolas Geoffray26066f22014-06-03 10:36:16 +000062 DumpBitVector(live_in, buffer, ssa_values, " live in: ");
Nicolas Geoffray804d0932014-05-02 08:46:00 +010063 BitVector* live_out = liveness.GetLiveOutSet(*block);
Nicolas Geoffray26066f22014-06-03 10:36:16 +000064 DumpBitVector(live_out, buffer, ssa_values, " live out: ");
Nicolas Geoffray804d0932014-05-02 08:46:00 +010065 BitVector* kill = liveness.GetKillSet(*block);
Nicolas Geoffray26066f22014-06-03 10:36:16 +000066 DumpBitVector(kill, buffer, ssa_values, " kill: ");
Nicolas Geoffray804d0932014-05-02 08:46:00 +010067 }
68 ASSERT_STREQ(expected, buffer.str().c_str());
69}
70
David Brazdil4833f5a2015-12-16 10:37:39 +000071TEST_F(LivenessTest, CFG1) {
Nicolas Geoffray804d0932014-05-02 08:46:00 +010072 const char* expected =
73 "Block 0\n"
Nicolas Geoffray31d76b42014-06-09 15:02:22 +010074 " live in: (0)\n"
75 " live out: (0)\n"
76 " kill: (1)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +010077 "Block 1\n"
Nicolas Geoffray31d76b42014-06-09 15:02:22 +010078 " live in: (0)\n"
79 " live out: (0)\n"
80 " kill: (0)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +010081 "Block 2\n"
Nicolas Geoffray31d76b42014-06-09 15:02:22 +010082 " live in: (0)\n"
83 " live out: (0)\n"
84 " kill: (0)\n";
Nicolas Geoffray804d0932014-05-02 08:46:00 +010085
86 // Constant is not used.
Mathieu Chartierfa3db3d2018-01-12 14:42:18 -080087 const std::vector<uint16_t> data = ONE_REGISTER_CODE_ITEM(
Nicolas Geoffray804d0932014-05-02 08:46:00 +010088 Instruction::CONST_4 | 0 | 0,
89 Instruction::RETURN_VOID);
90
91 TestCode(data, expected);
92}
93
David Brazdil4833f5a2015-12-16 10:37:39 +000094TEST_F(LivenessTest, CFG2) {
Nicolas Geoffray804d0932014-05-02 08:46:00 +010095 const char* expected =
96 "Block 0\n"
Nicolas Geoffray26066f22014-06-03 10:36:16 +000097 " live in: (0)\n"
98 " live out: (1)\n"
99 " kill: (1)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100100 "Block 1\n"
Nicolas Geoffray26066f22014-06-03 10:36:16 +0000101 " live in: (1)\n"
102 " live out: (0)\n"
103 " kill: (0)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100104 "Block 2\n"
Nicolas Geoffray26066f22014-06-03 10:36:16 +0000105 " live in: (0)\n"
106 " live out: (0)\n"
107 " kill: (0)\n";
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100108
Mathieu Chartierfa3db3d2018-01-12 14:42:18 -0800109 const std::vector<uint16_t> data = ONE_REGISTER_CODE_ITEM(
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100110 Instruction::CONST_4 | 0 | 0,
111 Instruction::RETURN);
112
113 TestCode(data, expected);
114}
115
David Brazdil4833f5a2015-12-16 10:37:39 +0000116TEST_F(LivenessTest, CFG3) {
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100117 const char* expected =
118 "Block 0\n" // entry block
Nicolas Geoffray26066f22014-06-03 10:36:16 +0000119 " live in: (000)\n"
120 " live out: (110)\n"
121 " kill: (110)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100122 "Block 1\n" // block with add
Nicolas Geoffray26066f22014-06-03 10:36:16 +0000123 " live in: (110)\n"
124 " live out: (001)\n"
125 " kill: (001)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100126 "Block 2\n" // block with return
Nicolas Geoffray26066f22014-06-03 10:36:16 +0000127 " live in: (001)\n"
128 " live out: (000)\n"
129 " kill: (000)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100130 "Block 3\n" // exit block
Nicolas Geoffray26066f22014-06-03 10:36:16 +0000131 " live in: (000)\n"
132 " live out: (000)\n"
133 " kill: (000)\n";
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100134
Mathieu Chartierfa3db3d2018-01-12 14:42:18 -0800135 const std::vector<uint16_t> data = TWO_REGISTERS_CODE_ITEM(
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100136 Instruction::CONST_4 | 3 << 12 | 0,
137 Instruction::CONST_4 | 4 << 12 | 1 << 8,
138 Instruction::ADD_INT_2ADDR | 1 << 12,
139 Instruction::GOTO | 0x100,
140 Instruction::RETURN);
141
142 TestCode(data, expected);
143}
144
David Brazdil4833f5a2015-12-16 10:37:39 +0000145TEST_F(LivenessTest, CFG4) {
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100146 // var a;
147 // if (0 == 0) {
148 // a = 5;
149 // } else {
150 // a = 4;
151 // }
152 // return a;
153 //
154 // Bitsets are made of:
David Brazdildee58d62016-04-07 09:54:26 +0000155 // (constant0, constant5, constant4, phi)
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100156 const char* expected =
157 "Block 0\n" // entry block
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100158 " live in: (0000)\n"
159 " live out: (1110)\n"
160 " kill: (1110)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100161 "Block 1\n" // block with if
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100162 " live in: (1110)\n"
163 " live out: (0110)\n"
164 " kill: (0000)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100165 "Block 2\n" // else block
David Brazdildee58d62016-04-07 09:54:26 +0000166 " live in: (0010)\n"
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100167 " live out: (0000)\n"
168 " kill: (0000)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100169 "Block 3\n" // then block
David Brazdildee58d62016-04-07 09:54:26 +0000170 " live in: (0100)\n"
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100171 " live out: (0000)\n"
172 " kill: (0000)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100173 "Block 4\n" // return block
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100174 " live in: (0000)\n"
175 " live out: (0000)\n"
176 " kill: (0001)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100177 "Block 5\n" // exit block
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100178 " live in: (0000)\n"
179 " live out: (0000)\n"
180 " kill: (0000)\n";
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100181
Mathieu Chartierfa3db3d2018-01-12 14:42:18 -0800182 const std::vector<uint16_t> data = ONE_REGISTER_CODE_ITEM(
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100183 Instruction::CONST_4 | 0 | 0,
184 Instruction::IF_EQ, 4,
185 Instruction::CONST_4 | 4 << 12 | 0,
186 Instruction::GOTO | 0x200,
187 Instruction::CONST_4 | 5 << 12 | 0,
188 Instruction::RETURN | 0 << 8);
189
190 TestCode(data, expected);
191}
192
David Brazdil4833f5a2015-12-16 10:37:39 +0000193TEST_F(LivenessTest, CFG5) {
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100194 // var a = 0;
195 // if (0 == 0) {
196 // } else {
197 // a = 4;
198 // }
199 // return a;
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100200 //
201 // Bitsets are made of:
202 // (constant0, constant4, phi)
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100203 const char* expected =
204 "Block 0\n" // entry block
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100205 " live in: (000)\n"
206 " live out: (110)\n"
207 " kill: (110)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100208 "Block 1\n" // block with if
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100209 " live in: (110)\n"
210 " live out: (110)\n"
211 " kill: (000)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100212 "Block 2\n" // else block
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100213 " live in: (010)\n"
214 " live out: (000)\n"
215 " kill: (000)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100216 "Block 3\n" // return block
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100217 " live in: (000)\n"
218 " live out: (000)\n"
219 " kill: (001)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100220 "Block 4\n" // exit block
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100221 " live in: (000)\n"
222 " live out: (000)\n"
223 " kill: (000)\n"
Nicolas Geoffray622d9c32014-05-12 16:11:02 +0100224 "Block 5\n" // block to avoid critical edge. Predecessor is 1, successor is 3.
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100225 " live in: (100)\n"
226 " live out: (000)\n"
227 " kill: (000)\n";
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100228
Mathieu Chartierfa3db3d2018-01-12 14:42:18 -0800229 const std::vector<uint16_t> data = ONE_REGISTER_CODE_ITEM(
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100230 Instruction::CONST_4 | 0 | 0,
231 Instruction::IF_EQ, 3,
232 Instruction::CONST_4 | 4 << 12 | 0,
233 Instruction::RETURN | 0 << 8);
234
235 TestCode(data, expected);
236}
237
David Brazdil4833f5a2015-12-16 10:37:39 +0000238TEST_F(LivenessTest, Loop1) {
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100239 // Simple loop with one preheader and one back edge.
240 // var a = 0;
241 // while (a == a) {
242 // a = 4;
243 // }
244 // return;
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100245 // Bitsets are made of:
246 // (constant0, constant4, phi)
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100247 const char* expected =
248 "Block 0\n" // entry block
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100249 " live in: (000)\n"
250 " live out: (110)\n"
251 " kill: (110)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100252 "Block 1\n" // pre header
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100253 " live in: (110)\n"
254 " live out: (010)\n"
255 " kill: (000)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100256 "Block 2\n" // loop header
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100257 " live in: (010)\n"
258 " live out: (010)\n"
259 " kill: (001)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100260 "Block 3\n" // back edge
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100261 " live in: (010)\n"
262 " live out: (010)\n"
263 " kill: (000)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100264 "Block 4\n" // return block
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100265 " live in: (000)\n"
266 " live out: (000)\n"
267 " kill: (000)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100268 "Block 5\n" // exit block
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100269 " live in: (000)\n"
270 " live out: (000)\n"
271 " kill: (000)\n";
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100272
273
Mathieu Chartierfa3db3d2018-01-12 14:42:18 -0800274 const std::vector<uint16_t> data = ONE_REGISTER_CODE_ITEM(
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100275 Instruction::CONST_4 | 0 | 0,
276 Instruction::IF_EQ, 4,
277 Instruction::CONST_4 | 4 << 12 | 0,
278 Instruction::GOTO | 0xFD00,
279 Instruction::RETURN_VOID);
280
281 TestCode(data, expected);
282}
283
David Brazdil4833f5a2015-12-16 10:37:39 +0000284TEST_F(LivenessTest, Loop3) {
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100285 // Test that the returned value stays live in a preceding loop.
286 // var a = 0;
287 // while (a == a) {
288 // a = 4;
289 // }
290 // return 5;
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100291 // Bitsets are made of:
David Brazdildee58d62016-04-07 09:54:26 +0000292 // (constant0, constant5, constant4, phi)
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100293 const char* expected =
294 "Block 0\n"
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100295 " live in: (0000)\n"
296 " live out: (1110)\n"
297 " kill: (1110)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100298 "Block 1\n"
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100299 " live in: (1110)\n"
300 " live out: (0110)\n"
301 " kill: (0000)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100302 "Block 2\n" // loop header
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100303 " live in: (0110)\n"
304 " live out: (0110)\n"
305 " kill: (0001)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100306 "Block 3\n" // back edge
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100307 " live in: (0110)\n"
308 " live out: (0110)\n"
309 " kill: (0000)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100310 "Block 4\n" // return block
David Brazdildee58d62016-04-07 09:54:26 +0000311 " live in: (0100)\n"
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100312 " live out: (0000)\n"
313 " kill: (0000)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100314 "Block 5\n" // exit block
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100315 " live in: (0000)\n"
316 " live out: (0000)\n"
317 " kill: (0000)\n";
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100318
Mathieu Chartierfa3db3d2018-01-12 14:42:18 -0800319 const std::vector<uint16_t> data = TWO_REGISTERS_CODE_ITEM(
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100320 Instruction::CONST_4 | 0 | 0,
321 Instruction::IF_EQ, 4,
322 Instruction::CONST_4 | 4 << 12 | 0,
323 Instruction::GOTO | 0xFD00,
324 Instruction::CONST_4 | 5 << 12 | 1 << 8,
325 Instruction::RETURN | 1 << 8);
326
327 TestCode(data, expected);
328}
329
330
David Brazdil4833f5a2015-12-16 10:37:39 +0000331TEST_F(LivenessTest, Loop4) {
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100332 // Make sure we support a preheader of a loop not being the first predecessor
333 // in the predecessor list of the header.
334 // var a = 0;
335 // while (a == a) {
336 // a = 4;
337 // }
338 // return a;
339 // Bitsets are made of:
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100340 // (constant0, constant4, phi)
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100341 const char* expected =
342 "Block 0\n"
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100343 " live in: (000)\n"
344 " live out: (110)\n"
345 " kill: (110)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100346 "Block 1\n"
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100347 " live in: (110)\n"
348 " live out: (110)\n"
349 " kill: (000)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100350 "Block 2\n" // loop header
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100351 " live in: (010)\n"
352 " live out: (011)\n"
353 " kill: (001)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100354 "Block 3\n" // back edge
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100355 " live in: (010)\n"
356 " live out: (010)\n"
357 " kill: (000)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100358 "Block 4\n" // pre loop header
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100359 " live in: (110)\n"
360 " live out: (010)\n"
361 " kill: (000)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100362 "Block 5\n" // return block
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100363 " live in: (001)\n"
364 " live out: (000)\n"
365 " kill: (000)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100366 "Block 6\n" // exit block
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100367 " live in: (000)\n"
368 " live out: (000)\n"
369 " kill: (000)\n";
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100370
Mathieu Chartierfa3db3d2018-01-12 14:42:18 -0800371 const std::vector<uint16_t> data = ONE_REGISTER_CODE_ITEM(
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100372 Instruction::CONST_4 | 0 | 0,
373 Instruction::GOTO | 0x500,
374 Instruction::IF_EQ, 5,
375 Instruction::CONST_4 | 4 << 12 | 0,
376 Instruction::GOTO | 0xFD00,
377 Instruction::GOTO | 0xFC00,
378 Instruction::RETURN | 0 << 8);
379
380 TestCode(data, expected);
381}
382
David Brazdil4833f5a2015-12-16 10:37:39 +0000383TEST_F(LivenessTest, Loop5) {
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100384 // Make sure we create a preheader of a loop when a header originally has two
385 // incoming blocks and one back edge.
386 // Bitsets are made of:
David Brazdildee58d62016-04-07 09:54:26 +0000387 // (constant0, constant5, constant4, phi in block 8)
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100388 const char* expected =
389 "Block 0\n"
Nicolas Geoffray3afca782015-03-10 18:59:31 +0000390 " live in: (0000)\n"
391 " live out: (1110)\n"
392 " kill: (1110)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100393 "Block 1\n"
Nicolas Geoffray3afca782015-03-10 18:59:31 +0000394 " live in: (1110)\n"
395 " live out: (0110)\n"
396 " kill: (0000)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100397 "Block 2\n"
David Brazdildee58d62016-04-07 09:54:26 +0000398 " live in: (0010)\n"
Nicolas Geoffray3afca782015-03-10 18:59:31 +0000399 " live out: (0000)\n"
400 " kill: (0000)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100401 "Block 3\n"
David Brazdildee58d62016-04-07 09:54:26 +0000402 " live in: (0100)\n"
Nicolas Geoffray3afca782015-03-10 18:59:31 +0000403 " live out: (0000)\n"
404 " kill: (0000)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100405 "Block 4\n" // loop header
Nicolas Geoffray3afca782015-03-10 18:59:31 +0000406 " live in: (0001)\n"
407 " live out: (0001)\n"
408 " kill: (0000)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100409 "Block 5\n" // back edge
Nicolas Geoffray3afca782015-03-10 18:59:31 +0000410 " live in: (0001)\n"
411 " live out: (0001)\n"
412 " kill: (0000)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100413 "Block 6\n" // return block
Nicolas Geoffray3afca782015-03-10 18:59:31 +0000414 " live in: (0001)\n"
415 " live out: (0000)\n"
416 " kill: (0000)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100417 "Block 7\n" // exit block
Nicolas Geoffray3afca782015-03-10 18:59:31 +0000418 " live in: (0000)\n"
419 " live out: (0000)\n"
420 " kill: (0000)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100421 "Block 8\n" // synthesized pre header
Nicolas Geoffray3afca782015-03-10 18:59:31 +0000422 " live in: (0000)\n"
423 " live out: (0001)\n"
424 " kill: (0001)\n";
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100425
Mathieu Chartierfa3db3d2018-01-12 14:42:18 -0800426 const std::vector<uint16_t> data = ONE_REGISTER_CODE_ITEM(
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100427 Instruction::CONST_4 | 0 | 0,
428 Instruction::IF_EQ, 4,
429 Instruction::CONST_4 | 4 << 12 | 0,
430 Instruction::GOTO | 0x200,
431 Instruction::CONST_4 | 5 << 12 | 0,
432 Instruction::IF_EQ, 3,
433 Instruction::GOTO | 0xFE00,
434 Instruction::RETURN | 0 << 8);
435
436 TestCode(data, expected);
437}
438
David Brazdil4833f5a2015-12-16 10:37:39 +0000439TEST_F(LivenessTest, Loop6) {
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100440 // Bitsets are made of:
Nicolas Geoffraydb216f42015-05-05 17:02:20 +0100441 // (constant0, constant4, constant5, phi in block 2)
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100442 const char* expected =
443 "Block 0\n"
Nicolas Geoffraydb216f42015-05-05 17:02:20 +0100444 " live in: (0000)\n"
445 " live out: (1110)\n"
446 " kill: (1110)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100447 "Block 1\n"
Nicolas Geoffraydb216f42015-05-05 17:02:20 +0100448 " live in: (1110)\n"
449 " live out: (0110)\n"
450 " kill: (0000)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100451 "Block 2\n" // loop header
Nicolas Geoffraydb216f42015-05-05 17:02:20 +0100452 " live in: (0110)\n"
453 " live out: (0111)\n"
454 " kill: (0001)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100455 "Block 3\n"
Nicolas Geoffraydb216f42015-05-05 17:02:20 +0100456 " live in: (0110)\n"
457 " live out: (0110)\n"
458 " kill: (0000)\n"
459 "Block 4\n" // back edge
460 " live in: (0110)\n"
461 " live out: (0110)\n"
462 " kill: (0000)\n"
463 "Block 5\n" // back edge
464 " live in: (0110)\n"
465 " live out: (0110)\n"
466 " kill: (0000)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100467 "Block 6\n" // return block
Nicolas Geoffraydb216f42015-05-05 17:02:20 +0100468 " live in: (0001)\n"
469 " live out: (0000)\n"
470 " kill: (0000)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100471 "Block 7\n" // exit block
Nicolas Geoffraydb216f42015-05-05 17:02:20 +0100472 " live in: (0000)\n"
473 " live out: (0000)\n"
474 " kill: (0000)\n";
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100475
Mathieu Chartierfa3db3d2018-01-12 14:42:18 -0800476 const std::vector<uint16_t> data = ONE_REGISTER_CODE_ITEM(
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100477 Instruction::CONST_4 | 0 | 0,
478 Instruction::IF_EQ, 8,
479 Instruction::CONST_4 | 4 << 12 | 0,
480 Instruction::IF_EQ, 4,
481 Instruction::CONST_4 | 5 << 12 | 0,
482 Instruction::GOTO | 0xFA00,
483 Instruction::GOTO | 0xF900,
484 Instruction::RETURN | 0 << 8);
485
486 TestCode(data, expected);
487}
488
489
David Brazdil4833f5a2015-12-16 10:37:39 +0000490TEST_F(LivenessTest, Loop7) {
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100491 // Bitsets are made of:
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100492 // (constant0, constant4, constant5, phi in block 2, phi in block 6)
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100493 const char* expected =
494 "Block 0\n"
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100495 " live in: (00000)\n"
496 " live out: (11100)\n"
497 " kill: (11100)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100498 "Block 1\n"
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100499 " live in: (11100)\n"
500 " live out: (01100)\n"
501 " kill: (00000)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100502 "Block 2\n" // loop header
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100503 " live in: (01100)\n"
504 " live out: (01110)\n"
505 " kill: (00010)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100506 "Block 3\n"
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100507 " live in: (01100)\n"
508 " live out: (01100)\n"
509 " kill: (00000)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100510 "Block 4\n" // loop exit
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100511 " live in: (00100)\n"
512 " live out: (00000)\n"
513 " kill: (00000)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100514 "Block 5\n" // back edge
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100515 " live in: (01100)\n"
516 " live out: (01100)\n"
517 " kill: (00000)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100518 "Block 6\n" // return block
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100519 " live in: (00000)\n"
520 " live out: (00000)\n"
521 " kill: (00001)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100522 "Block 7\n" // exit block
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100523 " live in: (00000)\n"
524 " live out: (00000)\n"
525 " kill: (00000)\n"
Nicolas Geoffray622d9c32014-05-12 16:11:02 +0100526 "Block 8\n" // synthesized block to avoid critical edge.
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100527 " live in: (00010)\n"
528 " live out: (00000)\n"
529 " kill: (00000)\n";
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100530
Mathieu Chartierfa3db3d2018-01-12 14:42:18 -0800531 const std::vector<uint16_t> data = ONE_REGISTER_CODE_ITEM(
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100532 Instruction::CONST_4 | 0 | 0,
533 Instruction::IF_EQ, 8,
534 Instruction::CONST_4 | 4 << 12 | 0,
535 Instruction::IF_EQ, 4,
536 Instruction::CONST_4 | 5 << 12 | 0,
537 Instruction::GOTO | 0x0200,
538 Instruction::GOTO | 0xF900,
539 Instruction::RETURN | 0 << 8);
540
541 TestCode(data, expected);
542}
543
David Brazdil4833f5a2015-12-16 10:37:39 +0000544TEST_F(LivenessTest, Loop8) {
Nicolas Geoffray8ddb00c2014-09-29 12:00:40 +0100545 // var a = 0;
546 // while (a == a) {
547 // a = a + a;
548 // }
549 // return a;
550 //
551 // We want to test that the ins of the loop exit
552 // does contain the phi.
553 // Bitsets are made of:
554 // (constant0, phi, add)
555 const char* expected =
556 "Block 0\n"
557 " live in: (000)\n"
558 " live out: (100)\n"
559 " kill: (100)\n"
560 "Block 1\n" // pre loop header
561 " live in: (100)\n"
562 " live out: (000)\n"
563 " kill: (000)\n"
564 "Block 2\n" // loop header
565 " live in: (000)\n"
566 " live out: (010)\n"
567 " kill: (010)\n"
568 "Block 3\n" // back edge
569 " live in: (010)\n"
570 " live out: (000)\n"
571 " kill: (001)\n"
572 "Block 4\n" // return block
573 " live in: (010)\n"
574 " live out: (000)\n"
575 " kill: (000)\n"
576 "Block 5\n" // exit block
577 " live in: (000)\n"
578 " live out: (000)\n"
579 " kill: (000)\n";
580
Mathieu Chartierfa3db3d2018-01-12 14:42:18 -0800581 const std::vector<uint16_t> data = ONE_REGISTER_CODE_ITEM(
Nicolas Geoffray8ddb00c2014-09-29 12:00:40 +0100582 Instruction::CONST_4 | 0 | 0,
583 Instruction::IF_EQ, 6,
584 Instruction::ADD_INT, 0, 0,
585 Instruction::GOTO | 0xFB00,
586 Instruction::RETURN | 0 << 8);
587
588 TestCode(data, expected);
589}
590
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100591} // namespace art