blob: 27aa3e0cdcb0579cfae407851a4ee1bcf6a3833e [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"
Vladimir Markoe2727152019-10-10 10:46:42 +010018#include "base/macros.h"
Nicolas Geoffray804d0932014-05-02 08:46:00 +010019#include "builder.h"
Nicolas Geoffray31d76b42014-06-09 15:02:22 +010020#include "code_generator.h"
David Sehr9e734c72018-01-04 17:56:19 -080021#include "dex/dex_file.h"
22#include "dex/dex_instruction.h"
Calin Juravlecd6dffe2015-01-08 17:35:35 +000023#include "driver/compiler_options.h"
Nicolas Geoffray804d0932014-05-02 08:46:00 +010024#include "nodes.h"
25#include "optimizing_unit_test.h"
Nicolas Geoffray360231a2014-10-08 21:07:48 +010026#include "prepare_for_register_allocation.h"
Nicolas Geoffray804d0932014-05-02 08:46:00 +010027#include "ssa_liveness_analysis.h"
Nicolas Geoffray804d0932014-05-02 08:46:00 +010028
Vladimir Markoe2727152019-10-10 10:46:42 +010029namespace art HIDDEN {
David Brazdild9510df2015-11-04 23:30:22 +000030
Vladimir Markoca6fff82017-10-03 14:49:14 +010031class LivenessTest : public OptimizingUnitTest {
32 protected:
Mathieu Chartierfa3db3d2018-01-12 14:42:18 -080033 void TestCode(const std::vector<uint16_t>& data, const char* expected);
Vladimir Markoca6fff82017-10-03 14:49:14 +010034};
David Brazdil4833f5a2015-12-16 10:37:39 +000035
Nicolas Geoffray26066f22014-06-03 10:36:16 +000036static void DumpBitVector(BitVector* vector,
37 std::ostream& buffer,
38 size_t count,
39 const char* prefix) {
40 buffer << prefix;
41 buffer << '(';
42 for (size_t i = 0; i < count; ++i) {
43 buffer << vector->IsBitSet(i);
44 }
45 buffer << ")\n";
46}
47
Mathieu Chartierfa3db3d2018-01-12 14:42:18 -080048void LivenessTest::TestCode(const std::vector<uint16_t>& data, const char* expected) {
Vladimir Markoca6fff82017-10-03 14:49:14 +010049 HGraph* graph = CreateCFG(data);
Nicolas Geoffray360231a2014-10-08 21:07:48 +010050 // `Inline` conditions into ifs.
Nicolas Geoffray61ba8d22018-08-07 09:55:57 +010051 PrepareForRegisterAllocation(graph, *compiler_options_).Run();
Vladimir Markoa0431112018-06-25 09:32:54 +010052 std::unique_ptr<CodeGenerator> codegen = CodeGenerator::Create(graph, *compiler_options_);
53 SsaLivenessAnalysis liveness(graph, codegen.get(), GetScopedAllocator());
Nicolas Geoffray804d0932014-05-02 08:46:00 +010054 liveness.Analyze();
55
56 std::ostringstream buffer;
Vladimir Marko2c45bc92016-10-25 16:54:12 +010057 for (HBasicBlock* block : graph->GetBlocks()) {
Nicolas Geoffray804d0932014-05-02 08:46:00 +010058 buffer << "Block " << block->GetBlockId() << std::endl;
Nicolas Geoffray26066f22014-06-03 10:36:16 +000059 size_t ssa_values = liveness.GetNumberOfSsaValues();
Nicolas Geoffray804d0932014-05-02 08:46:00 +010060 BitVector* live_in = liveness.GetLiveInSet(*block);
Nicolas Geoffray26066f22014-06-03 10:36:16 +000061 DumpBitVector(live_in, buffer, ssa_values, " live in: ");
Nicolas Geoffray804d0932014-05-02 08:46:00 +010062 BitVector* live_out = liveness.GetLiveOutSet(*block);
Nicolas Geoffray26066f22014-06-03 10:36:16 +000063 DumpBitVector(live_out, buffer, ssa_values, " live out: ");
Nicolas Geoffray804d0932014-05-02 08:46:00 +010064 BitVector* kill = liveness.GetKillSet(*block);
Nicolas Geoffray26066f22014-06-03 10:36:16 +000065 DumpBitVector(kill, buffer, ssa_values, " kill: ");
Nicolas Geoffray804d0932014-05-02 08:46:00 +010066 }
67 ASSERT_STREQ(expected, buffer.str().c_str());
68}
69
David Brazdil4833f5a2015-12-16 10:37:39 +000070TEST_F(LivenessTest, CFG1) {
Nicolas Geoffray804d0932014-05-02 08:46:00 +010071 const char* expected =
72 "Block 0\n"
Nicolas Geoffray31d76b42014-06-09 15:02:22 +010073 " live in: (0)\n"
74 " live out: (0)\n"
75 " kill: (1)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +010076 "Block 1\n"
Nicolas Geoffray31d76b42014-06-09 15:02:22 +010077 " live in: (0)\n"
78 " live out: (0)\n"
79 " kill: (0)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +010080 "Block 2\n"
Nicolas Geoffray31d76b42014-06-09 15:02:22 +010081 " live in: (0)\n"
82 " live out: (0)\n"
83 " kill: (0)\n";
Nicolas Geoffray804d0932014-05-02 08:46:00 +010084
85 // Constant is not used.
Mathieu Chartierfa3db3d2018-01-12 14:42:18 -080086 const std::vector<uint16_t> data = ONE_REGISTER_CODE_ITEM(
Nicolas Geoffray804d0932014-05-02 08:46:00 +010087 Instruction::CONST_4 | 0 | 0,
88 Instruction::RETURN_VOID);
89
90 TestCode(data, expected);
91}
92
David Brazdil4833f5a2015-12-16 10:37:39 +000093TEST_F(LivenessTest, CFG2) {
Nicolas Geoffray804d0932014-05-02 08:46:00 +010094 const char* expected =
95 "Block 0\n"
Nicolas Geoffray26066f22014-06-03 10:36:16 +000096 " live in: (0)\n"
97 " live out: (1)\n"
98 " kill: (1)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +010099 "Block 1\n"
Nicolas Geoffray26066f22014-06-03 10:36:16 +0000100 " live in: (1)\n"
101 " live out: (0)\n"
102 " kill: (0)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100103 "Block 2\n"
Nicolas Geoffray26066f22014-06-03 10:36:16 +0000104 " live in: (0)\n"
105 " live out: (0)\n"
106 " kill: (0)\n";
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100107
Mathieu Chartierfa3db3d2018-01-12 14:42:18 -0800108 const std::vector<uint16_t> data = ONE_REGISTER_CODE_ITEM(
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100109 Instruction::CONST_4 | 0 | 0,
110 Instruction::RETURN);
111
112 TestCode(data, expected);
113}
114
David Brazdil4833f5a2015-12-16 10:37:39 +0000115TEST_F(LivenessTest, CFG3) {
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100116 const char* expected =
117 "Block 0\n" // entry block
Nicolas Geoffray26066f22014-06-03 10:36:16 +0000118 " live in: (000)\n"
119 " live out: (110)\n"
120 " kill: (110)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100121 "Block 1\n" // block with add
Nicolas Geoffray26066f22014-06-03 10:36:16 +0000122 " live in: (110)\n"
123 " live out: (001)\n"
124 " kill: (001)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100125 "Block 2\n" // block with return
Nicolas Geoffray26066f22014-06-03 10:36:16 +0000126 " live in: (001)\n"
127 " live out: (000)\n"
128 " kill: (000)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100129 "Block 3\n" // exit block
Nicolas Geoffray26066f22014-06-03 10:36:16 +0000130 " live in: (000)\n"
131 " live out: (000)\n"
132 " kill: (000)\n";
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100133
Mathieu Chartierfa3db3d2018-01-12 14:42:18 -0800134 const std::vector<uint16_t> data = TWO_REGISTERS_CODE_ITEM(
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100135 Instruction::CONST_4 | 3 << 12 | 0,
136 Instruction::CONST_4 | 4 << 12 | 1 << 8,
137 Instruction::ADD_INT_2ADDR | 1 << 12,
138 Instruction::GOTO | 0x100,
139 Instruction::RETURN);
140
141 TestCode(data, expected);
142}
143
David Brazdil4833f5a2015-12-16 10:37:39 +0000144TEST_F(LivenessTest, CFG4) {
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100145 // var a;
146 // if (0 == 0) {
147 // a = 5;
148 // } else {
149 // a = 4;
150 // }
151 // return a;
152 //
153 // Bitsets are made of:
David Brazdildee58d62016-04-07 09:54:26 +0000154 // (constant0, constant5, constant4, phi)
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100155 const char* expected =
156 "Block 0\n" // entry block
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100157 " live in: (0000)\n"
158 " live out: (1110)\n"
159 " kill: (1110)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100160 "Block 1\n" // block with if
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100161 " live in: (1110)\n"
162 " live out: (0110)\n"
163 " kill: (0000)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100164 "Block 2\n" // else block
David Brazdildee58d62016-04-07 09:54:26 +0000165 " live in: (0010)\n"
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100166 " live out: (0000)\n"
167 " kill: (0000)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100168 "Block 3\n" // then block
David Brazdildee58d62016-04-07 09:54:26 +0000169 " live in: (0100)\n"
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100170 " live out: (0000)\n"
171 " kill: (0000)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100172 "Block 4\n" // return block
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100173 " live in: (0000)\n"
174 " live out: (0000)\n"
175 " kill: (0001)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100176 "Block 5\n" // exit block
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100177 " live in: (0000)\n"
178 " live out: (0000)\n"
179 " kill: (0000)\n";
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100180
Mathieu Chartierfa3db3d2018-01-12 14:42:18 -0800181 const std::vector<uint16_t> data = ONE_REGISTER_CODE_ITEM(
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100182 Instruction::CONST_4 | 0 | 0,
183 Instruction::IF_EQ, 4,
184 Instruction::CONST_4 | 4 << 12 | 0,
185 Instruction::GOTO | 0x200,
186 Instruction::CONST_4 | 5 << 12 | 0,
187 Instruction::RETURN | 0 << 8);
188
189 TestCode(data, expected);
190}
191
David Brazdil4833f5a2015-12-16 10:37:39 +0000192TEST_F(LivenessTest, CFG5) {
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100193 // var a = 0;
194 // if (0 == 0) {
195 // } else {
196 // a = 4;
197 // }
198 // return a;
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100199 //
200 // Bitsets are made of:
201 // (constant0, constant4, phi)
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100202 const char* expected =
203 "Block 0\n" // entry block
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100204 " live in: (000)\n"
205 " live out: (110)\n"
206 " kill: (110)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100207 "Block 1\n" // block with if
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100208 " live in: (110)\n"
209 " live out: (110)\n"
210 " kill: (000)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100211 "Block 2\n" // else block
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100212 " live in: (010)\n"
213 " live out: (000)\n"
214 " kill: (000)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100215 "Block 3\n" // return block
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100216 " live in: (000)\n"
217 " live out: (000)\n"
218 " kill: (001)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100219 "Block 4\n" // exit block
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100220 " live in: (000)\n"
221 " live out: (000)\n"
222 " kill: (000)\n"
Nicolas Geoffray622d9c32014-05-12 16:11:02 +0100223 "Block 5\n" // block to avoid critical edge. Predecessor is 1, successor is 3.
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100224 " live in: (100)\n"
225 " live out: (000)\n"
226 " kill: (000)\n";
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100227
Mathieu Chartierfa3db3d2018-01-12 14:42:18 -0800228 const std::vector<uint16_t> data = ONE_REGISTER_CODE_ITEM(
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100229 Instruction::CONST_4 | 0 | 0,
230 Instruction::IF_EQ, 3,
231 Instruction::CONST_4 | 4 << 12 | 0,
232 Instruction::RETURN | 0 << 8);
233
234 TestCode(data, expected);
235}
236
David Brazdil4833f5a2015-12-16 10:37:39 +0000237TEST_F(LivenessTest, Loop1) {
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100238 // Simple loop with one preheader and one back edge.
239 // var a = 0;
240 // while (a == a) {
241 // a = 4;
242 // }
243 // return;
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100244 // Bitsets are made of:
245 // (constant0, constant4, phi)
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100246 const char* expected =
247 "Block 0\n" // entry block
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100248 " live in: (000)\n"
249 " live out: (110)\n"
250 " kill: (110)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100251 "Block 1\n" // pre header
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100252 " live in: (110)\n"
253 " live out: (010)\n"
254 " kill: (000)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100255 "Block 2\n" // loop header
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100256 " live in: (010)\n"
257 " live out: (010)\n"
258 " kill: (001)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100259 "Block 3\n" // back edge
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100260 " live in: (010)\n"
261 " live out: (010)\n"
262 " kill: (000)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100263 "Block 4\n" // return block
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100264 " live in: (000)\n"
265 " live out: (000)\n"
266 " kill: (000)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100267 "Block 5\n" // exit block
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100268 " live in: (000)\n"
269 " live out: (000)\n"
270 " kill: (000)\n";
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100271
272
Mathieu Chartierfa3db3d2018-01-12 14:42:18 -0800273 const std::vector<uint16_t> data = ONE_REGISTER_CODE_ITEM(
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100274 Instruction::CONST_4 | 0 | 0,
275 Instruction::IF_EQ, 4,
276 Instruction::CONST_4 | 4 << 12 | 0,
277 Instruction::GOTO | 0xFD00,
278 Instruction::RETURN_VOID);
279
280 TestCode(data, expected);
281}
282
David Brazdil4833f5a2015-12-16 10:37:39 +0000283TEST_F(LivenessTest, Loop3) {
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100284 // Test that the returned value stays live in a preceding loop.
285 // var a = 0;
286 // while (a == a) {
287 // a = 4;
288 // }
289 // return 5;
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100290 // Bitsets are made of:
David Brazdildee58d62016-04-07 09:54:26 +0000291 // (constant0, constant5, constant4, phi)
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100292 const char* expected =
293 "Block 0\n"
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100294 " live in: (0000)\n"
295 " live out: (1110)\n"
296 " kill: (1110)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100297 "Block 1\n"
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100298 " live in: (1110)\n"
299 " live out: (0110)\n"
300 " kill: (0000)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100301 "Block 2\n" // loop header
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100302 " live in: (0110)\n"
303 " live out: (0110)\n"
304 " kill: (0001)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100305 "Block 3\n" // back edge
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100306 " live in: (0110)\n"
307 " live out: (0110)\n"
308 " kill: (0000)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100309 "Block 4\n" // return block
David Brazdildee58d62016-04-07 09:54:26 +0000310 " live in: (0100)\n"
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100311 " live out: (0000)\n"
312 " kill: (0000)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100313 "Block 5\n" // exit block
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100314 " live in: (0000)\n"
315 " live out: (0000)\n"
316 " kill: (0000)\n";
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100317
Mathieu Chartierfa3db3d2018-01-12 14:42:18 -0800318 const std::vector<uint16_t> data = TWO_REGISTERS_CODE_ITEM(
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100319 Instruction::CONST_4 | 0 | 0,
320 Instruction::IF_EQ, 4,
321 Instruction::CONST_4 | 4 << 12 | 0,
322 Instruction::GOTO | 0xFD00,
323 Instruction::CONST_4 | 5 << 12 | 1 << 8,
324 Instruction::RETURN | 1 << 8);
325
326 TestCode(data, expected);
327}
328
329
David Brazdil4833f5a2015-12-16 10:37:39 +0000330TEST_F(LivenessTest, Loop4) {
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100331 // Make sure we support a preheader of a loop not being the first predecessor
332 // in the predecessor list of the header.
333 // var a = 0;
334 // while (a == a) {
335 // a = 4;
336 // }
337 // return a;
338 // Bitsets are made of:
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100339 // (constant0, constant4, phi)
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100340 const char* expected =
341 "Block 0\n"
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100342 " live in: (000)\n"
343 " live out: (110)\n"
344 " kill: (110)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100345 "Block 1\n"
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100346 " live in: (110)\n"
347 " live out: (110)\n"
348 " kill: (000)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100349 "Block 2\n" // loop header
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100350 " live in: (010)\n"
351 " live out: (011)\n"
352 " kill: (001)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100353 "Block 3\n" // back edge
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100354 " live in: (010)\n"
355 " live out: (010)\n"
356 " kill: (000)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100357 "Block 4\n" // pre loop header
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100358 " live in: (110)\n"
359 " live out: (010)\n"
360 " kill: (000)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100361 "Block 5\n" // return block
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100362 " live in: (001)\n"
363 " live out: (000)\n"
364 " kill: (000)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100365 "Block 6\n" // exit block
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100366 " live in: (000)\n"
367 " live out: (000)\n"
368 " kill: (000)\n";
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100369
Mathieu Chartierfa3db3d2018-01-12 14:42:18 -0800370 const std::vector<uint16_t> data = ONE_REGISTER_CODE_ITEM(
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100371 Instruction::CONST_4 | 0 | 0,
372 Instruction::GOTO | 0x500,
373 Instruction::IF_EQ, 5,
374 Instruction::CONST_4 | 4 << 12 | 0,
375 Instruction::GOTO | 0xFD00,
376 Instruction::GOTO | 0xFC00,
377 Instruction::RETURN | 0 << 8);
378
379 TestCode(data, expected);
380}
381
David Brazdil4833f5a2015-12-16 10:37:39 +0000382TEST_F(LivenessTest, Loop5) {
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100383 // Make sure we create a preheader of a loop when a header originally has two
384 // incoming blocks and one back edge.
385 // Bitsets are made of:
David Brazdildee58d62016-04-07 09:54:26 +0000386 // (constant0, constant5, constant4, phi in block 8)
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100387 const char* expected =
388 "Block 0\n"
Nicolas Geoffray3afca782015-03-10 18:59:31 +0000389 " live in: (0000)\n"
390 " live out: (1110)\n"
391 " kill: (1110)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100392 "Block 1\n"
Nicolas Geoffray3afca782015-03-10 18:59:31 +0000393 " live in: (1110)\n"
394 " live out: (0110)\n"
395 " kill: (0000)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100396 "Block 2\n"
David Brazdildee58d62016-04-07 09:54:26 +0000397 " live in: (0010)\n"
Nicolas Geoffray3afca782015-03-10 18:59:31 +0000398 " live out: (0000)\n"
399 " kill: (0000)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100400 "Block 3\n"
David Brazdildee58d62016-04-07 09:54:26 +0000401 " live in: (0100)\n"
Nicolas Geoffray3afca782015-03-10 18:59:31 +0000402 " live out: (0000)\n"
403 " kill: (0000)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100404 "Block 4\n" // loop header
Nicolas Geoffray3afca782015-03-10 18:59:31 +0000405 " live in: (0001)\n"
406 " live out: (0001)\n"
407 " kill: (0000)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100408 "Block 5\n" // back edge
Nicolas Geoffray3afca782015-03-10 18:59:31 +0000409 " live in: (0001)\n"
410 " live out: (0001)\n"
411 " kill: (0000)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100412 "Block 6\n" // return block
Nicolas Geoffray3afca782015-03-10 18:59:31 +0000413 " live in: (0001)\n"
414 " live out: (0000)\n"
415 " kill: (0000)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100416 "Block 7\n" // exit block
Nicolas Geoffray3afca782015-03-10 18:59:31 +0000417 " live in: (0000)\n"
418 " live out: (0000)\n"
419 " kill: (0000)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100420 "Block 8\n" // synthesized pre header
Nicolas Geoffray3afca782015-03-10 18:59:31 +0000421 " live in: (0000)\n"
422 " live out: (0001)\n"
423 " kill: (0001)\n";
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100424
Mathieu Chartierfa3db3d2018-01-12 14:42:18 -0800425 const std::vector<uint16_t> data = ONE_REGISTER_CODE_ITEM(
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100426 Instruction::CONST_4 | 0 | 0,
427 Instruction::IF_EQ, 4,
428 Instruction::CONST_4 | 4 << 12 | 0,
429 Instruction::GOTO | 0x200,
430 Instruction::CONST_4 | 5 << 12 | 0,
431 Instruction::IF_EQ, 3,
432 Instruction::GOTO | 0xFE00,
433 Instruction::RETURN | 0 << 8);
434
435 TestCode(data, expected);
436}
437
David Brazdil4833f5a2015-12-16 10:37:39 +0000438TEST_F(LivenessTest, Loop6) {
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100439 // Bitsets are made of:
Nicolas Geoffraydb216f42015-05-05 17:02:20 +0100440 // (constant0, constant4, constant5, phi in block 2)
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100441 const char* expected =
442 "Block 0\n"
Nicolas Geoffraydb216f42015-05-05 17:02:20 +0100443 " live in: (0000)\n"
444 " live out: (1110)\n"
445 " kill: (1110)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100446 "Block 1\n"
Nicolas Geoffraydb216f42015-05-05 17:02:20 +0100447 " live in: (1110)\n"
448 " live out: (0110)\n"
449 " kill: (0000)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100450 "Block 2\n" // loop header
Nicolas Geoffraydb216f42015-05-05 17:02:20 +0100451 " live in: (0110)\n"
452 " live out: (0111)\n"
453 " kill: (0001)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100454 "Block 3\n"
Nicolas Geoffraydb216f42015-05-05 17:02:20 +0100455 " live in: (0110)\n"
456 " live out: (0110)\n"
457 " kill: (0000)\n"
458 "Block 4\n" // back edge
459 " live in: (0110)\n"
460 " live out: (0110)\n"
461 " kill: (0000)\n"
462 "Block 5\n" // back edge
463 " live in: (0110)\n"
464 " live out: (0110)\n"
465 " kill: (0000)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100466 "Block 6\n" // return block
Nicolas Geoffraydb216f42015-05-05 17:02:20 +0100467 " live in: (0001)\n"
468 " live out: (0000)\n"
469 " kill: (0000)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100470 "Block 7\n" // exit block
Nicolas Geoffraydb216f42015-05-05 17:02:20 +0100471 " live in: (0000)\n"
472 " live out: (0000)\n"
473 " kill: (0000)\n";
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100474
Mathieu Chartierfa3db3d2018-01-12 14:42:18 -0800475 const std::vector<uint16_t> data = ONE_REGISTER_CODE_ITEM(
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100476 Instruction::CONST_4 | 0 | 0,
477 Instruction::IF_EQ, 8,
478 Instruction::CONST_4 | 4 << 12 | 0,
479 Instruction::IF_EQ, 4,
480 Instruction::CONST_4 | 5 << 12 | 0,
481 Instruction::GOTO | 0xFA00,
482 Instruction::GOTO | 0xF900,
483 Instruction::RETURN | 0 << 8);
484
485 TestCode(data, expected);
486}
487
488
David Brazdil4833f5a2015-12-16 10:37:39 +0000489TEST_F(LivenessTest, Loop7) {
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100490 // Bitsets are made of:
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100491 // (constant0, constant4, constant5, phi in block 2, phi in block 6)
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100492 const char* expected =
493 "Block 0\n"
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100494 " live in: (00000)\n"
495 " live out: (11100)\n"
496 " kill: (11100)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100497 "Block 1\n"
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100498 " live in: (11100)\n"
499 " live out: (01100)\n"
500 " kill: (00000)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100501 "Block 2\n" // loop header
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100502 " live in: (01100)\n"
503 " live out: (01110)\n"
504 " kill: (00010)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100505 "Block 3\n"
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100506 " live in: (01100)\n"
507 " live out: (01100)\n"
508 " kill: (00000)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100509 "Block 4\n" // loop exit
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100510 " live in: (00100)\n"
511 " live out: (00000)\n"
512 " kill: (00000)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100513 "Block 5\n" // back edge
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100514 " live in: (01100)\n"
515 " live out: (01100)\n"
516 " kill: (00000)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100517 "Block 6\n" // return block
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100518 " live in: (00000)\n"
519 " live out: (00000)\n"
520 " kill: (00001)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100521 "Block 7\n" // exit block
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100522 " live in: (00000)\n"
523 " live out: (00000)\n"
524 " kill: (00000)\n"
Nicolas Geoffray622d9c32014-05-12 16:11:02 +0100525 "Block 8\n" // synthesized block to avoid critical edge.
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100526 " live in: (00010)\n"
527 " live out: (00000)\n"
528 " kill: (00000)\n";
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100529
Mathieu Chartierfa3db3d2018-01-12 14:42:18 -0800530 const std::vector<uint16_t> data = ONE_REGISTER_CODE_ITEM(
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100531 Instruction::CONST_4 | 0 | 0,
532 Instruction::IF_EQ, 8,
533 Instruction::CONST_4 | 4 << 12 | 0,
534 Instruction::IF_EQ, 4,
535 Instruction::CONST_4 | 5 << 12 | 0,
536 Instruction::GOTO | 0x0200,
537 Instruction::GOTO | 0xF900,
538 Instruction::RETURN | 0 << 8);
539
540 TestCode(data, expected);
541}
542
David Brazdil4833f5a2015-12-16 10:37:39 +0000543TEST_F(LivenessTest, Loop8) {
Nicolas Geoffray8ddb00c2014-09-29 12:00:40 +0100544 // var a = 0;
545 // while (a == a) {
546 // a = a + a;
547 // }
548 // return a;
549 //
550 // We want to test that the ins of the loop exit
551 // does contain the phi.
552 // Bitsets are made of:
553 // (constant0, phi, add)
554 const char* expected =
555 "Block 0\n"
556 " live in: (000)\n"
557 " live out: (100)\n"
558 " kill: (100)\n"
559 "Block 1\n" // pre loop header
560 " live in: (100)\n"
561 " live out: (000)\n"
562 " kill: (000)\n"
563 "Block 2\n" // loop header
564 " live in: (000)\n"
565 " live out: (010)\n"
566 " kill: (010)\n"
567 "Block 3\n" // back edge
568 " live in: (010)\n"
569 " live out: (000)\n"
570 " kill: (001)\n"
571 "Block 4\n" // return block
572 " live in: (010)\n"
573 " live out: (000)\n"
574 " kill: (000)\n"
575 "Block 5\n" // exit block
576 " live in: (000)\n"
577 " live out: (000)\n"
578 " kill: (000)\n";
579
Mathieu Chartierfa3db3d2018-01-12 14:42:18 -0800580 const std::vector<uint16_t> data = ONE_REGISTER_CODE_ITEM(
Nicolas Geoffray8ddb00c2014-09-29 12:00:40 +0100581 Instruction::CONST_4 | 0 | 0,
582 Instruction::IF_EQ, 6,
583 Instruction::ADD_INT, 0, 0,
584 Instruction::GOTO | 0xFB00,
585 Instruction::RETURN | 0 << 8);
586
587 TestCode(data, expected);
588}
589
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100590} // namespace art