blob: 81250ca1330d9da3139b6f56b3406c8463502c9e [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
30#include "gtest/gtest.h"
31
32namespace art {
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 Brazdil5e8b1372015-01-23 14:39:08 +000049 HGraph* graph = new (&allocator) HGraph(&allocator);
50 HGraphBuilder builder(graph);
Nicolas Geoffray804d0932014-05-02 08:46:00 +010051 const DexFile::CodeItem* item = reinterpret_cast<const DexFile::CodeItem*>(data);
David Brazdil5e8b1372015-01-23 14:39:08 +000052 bool graph_built = builder.BuildGraph(*item);
53 ASSERT_TRUE(graph_built);
Nicolas Geoffraye53798a2014-12-01 10:31:54 +000054 graph->TryBuildingSsa();
Nicolas Geoffray360231a2014-10-08 21:07:48 +010055 // `Inline` conditions into ifs.
56 PrepareForRegisterAllocation(graph).Run();
Mark Mendellfb8d2792015-03-31 22:16:59 -040057 std::unique_ptr<const X86InstructionSetFeatures> features_x86(
58 X86InstructionSetFeatures::FromCppDefines());
59 x86::CodeGeneratorX86 codegen(graph, *features_x86.get(), CompilerOptions());
Nicolas Geoffray8a16d972014-09-11 10:30:02 +010060 SsaLivenessAnalysis liveness(*graph, &codegen);
Nicolas Geoffray804d0932014-05-02 08:46:00 +010061 liveness.Analyze();
62
63 std::ostringstream buffer;
64 for (HInsertionOrderIterator it(*graph); !it.Done(); it.Advance()) {
65 HBasicBlock* block = it.Current();
66 buffer << "Block " << block->GetBlockId() << std::endl;
Nicolas Geoffray26066f22014-06-03 10:36:16 +000067 size_t ssa_values = liveness.GetNumberOfSsaValues();
Nicolas Geoffray804d0932014-05-02 08:46:00 +010068 BitVector* live_in = liveness.GetLiveInSet(*block);
Nicolas Geoffray26066f22014-06-03 10:36:16 +000069 DumpBitVector(live_in, buffer, ssa_values, " live in: ");
Nicolas Geoffray804d0932014-05-02 08:46:00 +010070 BitVector* live_out = liveness.GetLiveOutSet(*block);
Nicolas Geoffray26066f22014-06-03 10:36:16 +000071 DumpBitVector(live_out, buffer, ssa_values, " live out: ");
Nicolas Geoffray804d0932014-05-02 08:46:00 +010072 BitVector* kill = liveness.GetKillSet(*block);
Nicolas Geoffray26066f22014-06-03 10:36:16 +000073 DumpBitVector(kill, buffer, ssa_values, " kill: ");
Nicolas Geoffray804d0932014-05-02 08:46:00 +010074 }
75 ASSERT_STREQ(expected, buffer.str().c_str());
76}
77
78TEST(LivenessTest, CFG1) {
79 const char* expected =
80 "Block 0\n"
Nicolas Geoffray31d76b42014-06-09 15:02:22 +010081 " live in: (0)\n"
82 " live out: (0)\n"
83 " kill: (1)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +010084 "Block 1\n"
Nicolas Geoffray31d76b42014-06-09 15:02:22 +010085 " live in: (0)\n"
86 " live out: (0)\n"
87 " kill: (0)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +010088 "Block 2\n"
Nicolas Geoffray31d76b42014-06-09 15:02:22 +010089 " live in: (0)\n"
90 " live out: (0)\n"
91 " kill: (0)\n";
Nicolas Geoffray804d0932014-05-02 08:46:00 +010092
93 // Constant is not used.
94 const uint16_t data[] = ONE_REGISTER_CODE_ITEM(
95 Instruction::CONST_4 | 0 | 0,
96 Instruction::RETURN_VOID);
97
98 TestCode(data, expected);
99}
100
101TEST(LivenessTest, CFG2) {
102 const char* expected =
103 "Block 0\n"
Nicolas Geoffray26066f22014-06-03 10:36:16 +0000104 " live in: (0)\n"
105 " live out: (1)\n"
106 " kill: (1)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100107 "Block 1\n"
Nicolas Geoffray26066f22014-06-03 10:36:16 +0000108 " live in: (1)\n"
109 " live out: (0)\n"
110 " kill: (0)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100111 "Block 2\n"
Nicolas Geoffray26066f22014-06-03 10:36:16 +0000112 " live in: (0)\n"
113 " live out: (0)\n"
114 " kill: (0)\n";
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100115
116 const uint16_t data[] = ONE_REGISTER_CODE_ITEM(
117 Instruction::CONST_4 | 0 | 0,
118 Instruction::RETURN);
119
120 TestCode(data, expected);
121}
122
123TEST(LivenessTest, CFG3) {
124 const char* expected =
125 "Block 0\n" // entry block
Nicolas Geoffray26066f22014-06-03 10:36:16 +0000126 " live in: (000)\n"
127 " live out: (110)\n"
128 " kill: (110)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100129 "Block 1\n" // block with add
Nicolas Geoffray26066f22014-06-03 10:36:16 +0000130 " live in: (110)\n"
131 " live out: (001)\n"
132 " kill: (001)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100133 "Block 2\n" // block with return
Nicolas Geoffray26066f22014-06-03 10:36:16 +0000134 " live in: (001)\n"
135 " live out: (000)\n"
136 " kill: (000)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100137 "Block 3\n" // exit block
Nicolas Geoffray26066f22014-06-03 10:36:16 +0000138 " live in: (000)\n"
139 " live out: (000)\n"
140 " kill: (000)\n";
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100141
142 const uint16_t data[] = TWO_REGISTERS_CODE_ITEM(
143 Instruction::CONST_4 | 3 << 12 | 0,
144 Instruction::CONST_4 | 4 << 12 | 1 << 8,
145 Instruction::ADD_INT_2ADDR | 1 << 12,
146 Instruction::GOTO | 0x100,
147 Instruction::RETURN);
148
149 TestCode(data, expected);
150}
151
152TEST(LivenessTest, CFG4) {
153 // var a;
154 // if (0 == 0) {
155 // a = 5;
156 // } else {
157 // a = 4;
158 // }
159 // return a;
160 //
161 // Bitsets are made of:
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100162 // (constant0, constant4, constant5, phi)
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100163 const char* expected =
164 "Block 0\n" // entry block
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100165 " live in: (0000)\n"
166 " live out: (1110)\n"
167 " kill: (1110)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100168 "Block 1\n" // block with if
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100169 " live in: (1110)\n"
170 " live out: (0110)\n"
171 " kill: (0000)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100172 "Block 2\n" // else block
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100173 " live in: (0100)\n"
174 " live out: (0000)\n"
175 " kill: (0000)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100176 "Block 3\n" // then block
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100177 " live in: (0010)\n"
178 " live out: (0000)\n"
179 " kill: (0000)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100180 "Block 4\n" // return block
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100181 " live in: (0000)\n"
182 " live out: (0000)\n"
183 " kill: (0001)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100184 "Block 5\n" // exit block
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100185 " live in: (0000)\n"
186 " live out: (0000)\n"
187 " kill: (0000)\n";
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100188
189 const uint16_t data[] = ONE_REGISTER_CODE_ITEM(
190 Instruction::CONST_4 | 0 | 0,
191 Instruction::IF_EQ, 4,
192 Instruction::CONST_4 | 4 << 12 | 0,
193 Instruction::GOTO | 0x200,
194 Instruction::CONST_4 | 5 << 12 | 0,
195 Instruction::RETURN | 0 << 8);
196
197 TestCode(data, expected);
198}
199
200TEST(LivenessTest, CFG5) {
201 // var a = 0;
202 // if (0 == 0) {
203 // } else {
204 // a = 4;
205 // }
206 // return a;
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100207 //
208 // Bitsets are made of:
209 // (constant0, constant4, phi)
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100210 const char* expected =
211 "Block 0\n" // entry block
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100212 " live in: (000)\n"
213 " live out: (110)\n"
214 " kill: (110)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100215 "Block 1\n" // block with if
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100216 " live in: (110)\n"
217 " live out: (110)\n"
218 " kill: (000)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100219 "Block 2\n" // else block
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100220 " live in: (010)\n"
221 " live out: (000)\n"
222 " kill: (000)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100223 "Block 3\n" // return block
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100224 " live in: (000)\n"
225 " live out: (000)\n"
226 " kill: (001)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100227 "Block 4\n" // exit block
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100228 " live in: (000)\n"
229 " live out: (000)\n"
230 " kill: (000)\n"
Nicolas Geoffray622d9c32014-05-12 16:11:02 +0100231 "Block 5\n" // block to avoid critical edge. Predecessor is 1, successor is 3.
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100232 " live in: (100)\n"
233 " live out: (000)\n"
234 " kill: (000)\n";
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100235
236 const uint16_t data[] = ONE_REGISTER_CODE_ITEM(
237 Instruction::CONST_4 | 0 | 0,
238 Instruction::IF_EQ, 3,
239 Instruction::CONST_4 | 4 << 12 | 0,
240 Instruction::RETURN | 0 << 8);
241
242 TestCode(data, expected);
243}
244
245TEST(LivenessTest, Loop1) {
246 // Simple loop with one preheader and one back edge.
247 // var a = 0;
248 // while (a == a) {
249 // a = 4;
250 // }
251 // return;
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100252 // Bitsets are made of:
253 // (constant0, constant4, phi)
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100254 const char* expected =
255 "Block 0\n" // entry block
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100256 " live in: (000)\n"
257 " live out: (110)\n"
258 " kill: (110)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100259 "Block 1\n" // pre header
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100260 " live in: (110)\n"
261 " live out: (010)\n"
262 " kill: (000)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100263 "Block 2\n" // loop header
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100264 " live in: (010)\n"
265 " live out: (010)\n"
266 " kill: (001)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100267 "Block 3\n" // back edge
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100268 " live in: (010)\n"
269 " live out: (010)\n"
270 " kill: (000)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100271 "Block 4\n" // return block
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100272 " live in: (000)\n"
273 " live out: (000)\n"
274 " kill: (000)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100275 "Block 5\n" // exit block
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100276 " live in: (000)\n"
277 " live out: (000)\n"
278 " kill: (000)\n";
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100279
280
281 const uint16_t data[] = ONE_REGISTER_CODE_ITEM(
282 Instruction::CONST_4 | 0 | 0,
283 Instruction::IF_EQ, 4,
284 Instruction::CONST_4 | 4 << 12 | 0,
285 Instruction::GOTO | 0xFD00,
286 Instruction::RETURN_VOID);
287
288 TestCode(data, expected);
289}
290
291TEST(LivenessTest, Loop3) {
292 // Test that the returned value stays live in a preceding loop.
293 // var a = 0;
294 // while (a == a) {
295 // a = 4;
296 // }
297 // return 5;
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100298 // Bitsets are made of:
299 // (constant0, constant4, constant5, phi)
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100300 const char* expected =
301 "Block 0\n"
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100302 " live in: (0000)\n"
303 " live out: (1110)\n"
304 " kill: (1110)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100305 "Block 1\n"
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100306 " live in: (1110)\n"
307 " live out: (0110)\n"
308 " kill: (0000)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100309 "Block 2\n" // loop header
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100310 " live in: (0110)\n"
311 " live out: (0110)\n"
312 " kill: (0001)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100313 "Block 3\n" // back edge
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100314 " live in: (0110)\n"
315 " live out: (0110)\n"
316 " kill: (0000)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100317 "Block 4\n" // return block
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100318 " live in: (0010)\n"
319 " live out: (0000)\n"
320 " kill: (0000)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100321 "Block 5\n" // exit block
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100322 " live in: (0000)\n"
323 " live out: (0000)\n"
324 " kill: (0000)\n";
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100325
326 const uint16_t data[] = TWO_REGISTERS_CODE_ITEM(
327 Instruction::CONST_4 | 0 | 0,
328 Instruction::IF_EQ, 4,
329 Instruction::CONST_4 | 4 << 12 | 0,
330 Instruction::GOTO | 0xFD00,
331 Instruction::CONST_4 | 5 << 12 | 1 << 8,
332 Instruction::RETURN | 1 << 8);
333
334 TestCode(data, expected);
335}
336
337
338TEST(LivenessTest, Loop4) {
339 // Make sure we support a preheader of a loop not being the first predecessor
340 // in the predecessor list of the header.
341 // var a = 0;
342 // while (a == a) {
343 // a = 4;
344 // }
345 // return a;
346 // Bitsets are made of:
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100347 // (constant0, constant4, phi)
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100348 const char* expected =
349 "Block 0\n"
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100350 " live in: (000)\n"
351 " live out: (110)\n"
352 " kill: (110)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100353 "Block 1\n"
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100354 " live in: (110)\n"
355 " live out: (110)\n"
356 " kill: (000)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100357 "Block 2\n" // loop header
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100358 " live in: (010)\n"
359 " live out: (011)\n"
360 " kill: (001)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100361 "Block 3\n" // back edge
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100362 " live in: (010)\n"
363 " live out: (010)\n"
364 " kill: (000)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100365 "Block 4\n" // pre loop header
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100366 " live in: (110)\n"
367 " live out: (010)\n"
368 " kill: (000)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100369 "Block 5\n" // return block
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100370 " live in: (001)\n"
371 " live out: (000)\n"
372 " kill: (000)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100373 "Block 6\n" // exit block
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100374 " live in: (000)\n"
375 " live out: (000)\n"
376 " kill: (000)\n";
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100377
378 const uint16_t data[] = ONE_REGISTER_CODE_ITEM(
379 Instruction::CONST_4 | 0 | 0,
380 Instruction::GOTO | 0x500,
381 Instruction::IF_EQ, 5,
382 Instruction::CONST_4 | 4 << 12 | 0,
383 Instruction::GOTO | 0xFD00,
384 Instruction::GOTO | 0xFC00,
385 Instruction::RETURN | 0 << 8);
386
387 TestCode(data, expected);
388}
389
390TEST(LivenessTest, Loop5) {
391 // Make sure we create a preheader of a loop when a header originally has two
392 // incoming blocks and one back edge.
393 // Bitsets are made of:
Nicolas Geoffray3afca782015-03-10 18:59:31 +0000394 // (constant0, constant4, constant5, phi in block 8)
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100395 const char* expected =
396 "Block 0\n"
Nicolas Geoffray3afca782015-03-10 18:59:31 +0000397 " live in: (0000)\n"
398 " live out: (1110)\n"
399 " kill: (1110)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100400 "Block 1\n"
Nicolas Geoffray3afca782015-03-10 18:59:31 +0000401 " live in: (1110)\n"
402 " live out: (0110)\n"
403 " kill: (0000)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100404 "Block 2\n"
Nicolas Geoffray3afca782015-03-10 18:59:31 +0000405 " live in: (0100)\n"
406 " live out: (0000)\n"
407 " kill: (0000)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100408 "Block 3\n"
Nicolas Geoffray3afca782015-03-10 18:59:31 +0000409 " live in: (0010)\n"
410 " live out: (0000)\n"
411 " kill: (0000)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100412 "Block 4\n" // loop header
Nicolas Geoffray3afca782015-03-10 18:59:31 +0000413 " live in: (0001)\n"
414 " live out: (0001)\n"
415 " kill: (0000)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100416 "Block 5\n" // back edge
Nicolas Geoffray3afca782015-03-10 18:59:31 +0000417 " live in: (0001)\n"
418 " live out: (0001)\n"
419 " kill: (0000)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100420 "Block 6\n" // return block
Nicolas Geoffray3afca782015-03-10 18:59:31 +0000421 " live in: (0001)\n"
422 " live out: (0000)\n"
423 " kill: (0000)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100424 "Block 7\n" // exit block
Nicolas Geoffray3afca782015-03-10 18:59:31 +0000425 " live in: (0000)\n"
426 " live out: (0000)\n"
427 " kill: (0000)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100428 "Block 8\n" // synthesized pre header
Nicolas Geoffray3afca782015-03-10 18:59:31 +0000429 " live in: (0000)\n"
430 " live out: (0001)\n"
431 " kill: (0001)\n";
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100432
433 const uint16_t data[] = ONE_REGISTER_CODE_ITEM(
434 Instruction::CONST_4 | 0 | 0,
435 Instruction::IF_EQ, 4,
436 Instruction::CONST_4 | 4 << 12 | 0,
437 Instruction::GOTO | 0x200,
438 Instruction::CONST_4 | 5 << 12 | 0,
439 Instruction::IF_EQ, 3,
440 Instruction::GOTO | 0xFE00,
441 Instruction::RETURN | 0 << 8);
442
443 TestCode(data, expected);
444}
445
446TEST(LivenessTest, Loop6) {
447 // Bitsets are made of:
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100448 // (constant0, constant4, constant5, phi in block 2, phi in block 8)
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100449 const char* expected =
450 "Block 0\n"
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100451 " live in: (00000)\n"
452 " live out: (11100)\n"
453 " kill: (11100)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100454 "Block 1\n"
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100455 " live in: (11100)\n"
456 " live out: (01100)\n"
457 " kill: (00000)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100458 "Block 2\n" // loop header
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100459 " live in: (01100)\n"
460 " live out: (01110)\n"
461 " kill: (00010)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100462 "Block 3\n"
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100463 " live in: (01100)\n"
464 " live out: (01100)\n"
465 " kill: (00000)\n"
Nicolas Geoffray622d9c32014-05-12 16:11:02 +0100466 "Block 4\n" // original back edge
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100467 " live in: (01100)\n"
468 " live out: (01100)\n"
469 " kill: (00000)\n"
Nicolas Geoffray622d9c32014-05-12 16:11:02 +0100470 "Block 5\n" // original back edge
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100471 " live in: (01100)\n"
472 " live out: (01100)\n"
473 " kill: (00000)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100474 "Block 6\n" // return block
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100475 " live in: (00010)\n"
476 " live out: (00000)\n"
477 " kill: (00000)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100478 "Block 7\n" // exit block
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100479 " live in: (00000)\n"
480 " live out: (00000)\n"
481 " kill: (00000)\n"
Nicolas Geoffray622d9c32014-05-12 16:11:02 +0100482 "Block 8\n" // synthesized back edge
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100483 " live in: (01100)\n"
484 " live out: (01100)\n"
485 " kill: (00001)\n";
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100486
487 const uint16_t data[] = ONE_REGISTER_CODE_ITEM(
488 Instruction::CONST_4 | 0 | 0,
489 Instruction::IF_EQ, 8,
490 Instruction::CONST_4 | 4 << 12 | 0,
491 Instruction::IF_EQ, 4,
492 Instruction::CONST_4 | 5 << 12 | 0,
493 Instruction::GOTO | 0xFA00,
494 Instruction::GOTO | 0xF900,
495 Instruction::RETURN | 0 << 8);
496
497 TestCode(data, expected);
498}
499
500
501TEST(LivenessTest, Loop7) {
502 // Bitsets are made of:
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100503 // (constant0, constant4, constant5, phi in block 2, phi in block 6)
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100504 const char* expected =
505 "Block 0\n"
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100506 " live in: (00000)\n"
507 " live out: (11100)\n"
508 " kill: (11100)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100509 "Block 1\n"
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100510 " live in: (11100)\n"
511 " live out: (01100)\n"
512 " kill: (00000)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100513 "Block 2\n" // loop header
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100514 " live in: (01100)\n"
515 " live out: (01110)\n"
516 " kill: (00010)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100517 "Block 3\n"
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100518 " live in: (01100)\n"
519 " live out: (01100)\n"
520 " kill: (00000)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100521 "Block 4\n" // loop exit
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100522 " live in: (00100)\n"
523 " live out: (00000)\n"
524 " kill: (00000)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100525 "Block 5\n" // back edge
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100526 " live in: (01100)\n"
527 " live out: (01100)\n"
528 " kill: (00000)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100529 "Block 6\n" // return block
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100530 " live in: (00000)\n"
531 " live out: (00000)\n"
532 " kill: (00001)\n"
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100533 "Block 7\n" // exit block
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100534 " live in: (00000)\n"
535 " live out: (00000)\n"
536 " kill: (00000)\n"
Nicolas Geoffray622d9c32014-05-12 16:11:02 +0100537 "Block 8\n" // synthesized block to avoid critical edge.
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100538 " live in: (00010)\n"
539 " live out: (00000)\n"
540 " kill: (00000)\n";
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100541
542 const uint16_t data[] = ONE_REGISTER_CODE_ITEM(
543 Instruction::CONST_4 | 0 | 0,
544 Instruction::IF_EQ, 8,
545 Instruction::CONST_4 | 4 << 12 | 0,
546 Instruction::IF_EQ, 4,
547 Instruction::CONST_4 | 5 << 12 | 0,
548 Instruction::GOTO | 0x0200,
549 Instruction::GOTO | 0xF900,
550 Instruction::RETURN | 0 << 8);
551
552 TestCode(data, expected);
553}
554
Nicolas Geoffray8ddb00c2014-09-29 12:00:40 +0100555TEST(LivenessTest, Loop8) {
556 // var a = 0;
557 // while (a == a) {
558 // a = a + a;
559 // }
560 // return a;
561 //
562 // We want to test that the ins of the loop exit
563 // does contain the phi.
564 // Bitsets are made of:
565 // (constant0, phi, add)
566 const char* expected =
567 "Block 0\n"
568 " live in: (000)\n"
569 " live out: (100)\n"
570 " kill: (100)\n"
571 "Block 1\n" // pre loop header
572 " live in: (100)\n"
573 " live out: (000)\n"
574 " kill: (000)\n"
575 "Block 2\n" // loop header
576 " live in: (000)\n"
577 " live out: (010)\n"
578 " kill: (010)\n"
579 "Block 3\n" // back edge
580 " live in: (010)\n"
581 " live out: (000)\n"
582 " kill: (001)\n"
583 "Block 4\n" // return block
584 " live in: (010)\n"
585 " live out: (000)\n"
586 " kill: (000)\n"
587 "Block 5\n" // exit block
588 " live in: (000)\n"
589 " live out: (000)\n"
590 " kill: (000)\n";
591
592 const uint16_t data[] = ONE_REGISTER_CODE_ITEM(
593 Instruction::CONST_4 | 0 | 0,
594 Instruction::IF_EQ, 6,
595 Instruction::ADD_INT, 0, 0,
596 Instruction::GOTO | 0xFB00,
597 Instruction::RETURN | 0 << 8);
598
599 TestCode(data, expected);
600}
601
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100602} // namespace art