blob: 007c43e218d68c0abf7c398d87c2d684d4cd52a7 [file] [log] [blame]
Nicolas Geoffrayddb311f2014-05-16 09:28:54 +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
17#include "builder.h"
Nicolas Geoffray31d76b42014-06-09 15:02:22 +010018#include "code_generator.h"
Nicolas Geoffray8a16d972014-09-11 10:30:02 +010019#include "code_generator_x86.h"
Nicolas Geoffrayddb311f2014-05-16 09:28:54 +010020#include "dex_file.h"
21#include "dex_instruction.h"
22#include "nodes.h"
23#include "optimizing_unit_test.h"
Nicolas Geoffray360231a2014-10-08 21:07:48 +010024#include "prepare_for_register_allocation.h"
Nicolas Geoffrayddb311f2014-05-16 09:28:54 +010025#include "ssa_liveness_analysis.h"
26#include "utils/arena_allocator.h"
27
28#include "gtest/gtest.h"
29
30namespace art {
31
32static HGraph* BuildGraph(const uint16_t* data, ArenaAllocator* allocator) {
33 HGraphBuilder builder(allocator);
34 const DexFile::CodeItem* item = reinterpret_cast<const DexFile::CodeItem*>(data);
35 HGraph* graph = builder.BuildGraph(*item);
Nicolas Geoffrayfbc695f2014-09-15 15:33:30 +000036 // Suspend checks implementation may change in the future, and this test relies
37 // on how instructions are ordered.
38 RemoveSuspendChecks(graph);
Nicolas Geoffraye53798a2014-12-01 10:31:54 +000039 graph->TryBuildingSsa();
Nicolas Geoffray360231a2014-10-08 21:07:48 +010040 // `Inline` conditions into ifs.
41 PrepareForRegisterAllocation(graph).Run();
Nicolas Geoffrayddb311f2014-05-16 09:28:54 +010042 return graph;
43}
44
45TEST(LiveRangesTest, CFG1) {
46 /*
47 * Test the following snippet:
48 * return 0;
49 *
50 * Which becomes the following graph (numbered by lifetime position):
51 * 2: constant0
Nicolas Geoffraya7062e02014-05-22 12:50:17 +010052 * 4: goto
Nicolas Geoffrayddb311f2014-05-16 09:28:54 +010053 * |
Nicolas Geoffraya7062e02014-05-22 12:50:17 +010054 * 8: return
Nicolas Geoffrayddb311f2014-05-16 09:28:54 +010055 * |
Nicolas Geoffraya7062e02014-05-22 12:50:17 +010056 * 12: exit
Nicolas Geoffrayddb311f2014-05-16 09:28:54 +010057 */
58 const uint16_t data[] = ONE_REGISTER_CODE_ITEM(
59 Instruction::CONST_4 | 0 | 0,
60 Instruction::RETURN);
61
62 ArenaPool pool;
63 ArenaAllocator allocator(&pool);
64 HGraph* graph = BuildGraph(data, &allocator);
Nicolas Geoffray31d76b42014-06-09 15:02:22 +010065
Nicolas Geoffray8a16d972014-09-11 10:30:02 +010066 x86::CodeGeneratorX86 codegen(graph);
67 SsaLivenessAnalysis liveness(*graph, &codegen);
Nicolas Geoffrayddb311f2014-05-16 09:28:54 +010068 liveness.Analyze();
69
70 LiveInterval* interval = liveness.GetInstructionFromSsaIndex(0)->GetLiveInterval();
Nicolas Geoffraya7062e02014-05-22 12:50:17 +010071 LiveRange* range = interval->GetFirstRange();
72 ASSERT_EQ(2u, range->GetStart());
Nicolas Geoffrayddb311f2014-05-16 09:28:54 +010073 // Last use is the return instruction.
Nicolas Geoffray8e3964b2014-10-17 11:06:38 +010074 ASSERT_EQ(8u, range->GetEnd());
Nicolas Geoffrayddb311f2014-05-16 09:28:54 +010075 HBasicBlock* block = graph->GetBlocks().Get(1);
Roland Levillain476df552014-10-09 17:51:36 +010076 ASSERT_TRUE(block->GetLastInstruction()->IsReturn());
Nicolas Geoffraya7062e02014-05-22 12:50:17 +010077 ASSERT_EQ(8u, block->GetLastInstruction()->GetLifetimePosition());
78 ASSERT_TRUE(range->GetNext() == nullptr);
Nicolas Geoffrayddb311f2014-05-16 09:28:54 +010079}
80
81TEST(LiveRangesTest, CFG2) {
82 /*
83 * Test the following snippet:
84 * var a = 0;
85 * if (0 == 0) {
86 * } else {
87 * }
88 * return a;
89 *
90 * Which becomes the following graph (numbered by lifetime position):
91 * 2: constant0
Nicolas Geoffraya7062e02014-05-22 12:50:17 +010092 * 4: goto
Nicolas Geoffrayddb311f2014-05-16 09:28:54 +010093 * |
Nicolas Geoffraya7062e02014-05-22 12:50:17 +010094 * 8: equal
95 * 10: if
Nicolas Geoffrayddb311f2014-05-16 09:28:54 +010096 * / \
Nicolas Geoffraya7062e02014-05-22 12:50:17 +010097 * 14: goto 18: goto
Nicolas Geoffrayddb311f2014-05-16 09:28:54 +010098 * \ /
Nicolas Geoffraya7062e02014-05-22 12:50:17 +010099 * 22: return
Nicolas Geoffrayddb311f2014-05-16 09:28:54 +0100100 * |
Nicolas Geoffraya7062e02014-05-22 12:50:17 +0100101 * 26: exit
Nicolas Geoffrayddb311f2014-05-16 09:28:54 +0100102 */
103 const uint16_t data[] = ONE_REGISTER_CODE_ITEM(
104 Instruction::CONST_4 | 0 | 0,
105 Instruction::IF_EQ, 3,
106 Instruction::GOTO | 0x100,
107 Instruction::RETURN | 0 << 8);
108
109 ArenaPool pool;
110 ArenaAllocator allocator(&pool);
111 HGraph* graph = BuildGraph(data, &allocator);
Nicolas Geoffray8a16d972014-09-11 10:30:02 +0100112 x86::CodeGeneratorX86 codegen(graph);
113 SsaLivenessAnalysis liveness(*graph, &codegen);
Nicolas Geoffrayddb311f2014-05-16 09:28:54 +0100114 liveness.Analyze();
115
116 LiveInterval* interval = liveness.GetInstructionFromSsaIndex(0)->GetLiveInterval();
Nicolas Geoffraya7062e02014-05-22 12:50:17 +0100117 LiveRange* range = interval->GetFirstRange();
118 ASSERT_EQ(2u, range->GetStart());
Nicolas Geoffrayddb311f2014-05-16 09:28:54 +0100119 // Last use is the return instruction.
Nicolas Geoffray8e3964b2014-10-17 11:06:38 +0100120 ASSERT_EQ(22u, range->GetEnd());
Nicolas Geoffrayddb311f2014-05-16 09:28:54 +0100121 HBasicBlock* block = graph->GetBlocks().Get(3);
Roland Levillain476df552014-10-09 17:51:36 +0100122 ASSERT_TRUE(block->GetLastInstruction()->IsReturn());
Nicolas Geoffraya7062e02014-05-22 12:50:17 +0100123 ASSERT_EQ(22u, block->GetLastInstruction()->GetLifetimePosition());
124 ASSERT_TRUE(range->GetNext() == nullptr);
Nicolas Geoffrayddb311f2014-05-16 09:28:54 +0100125}
126
127TEST(LiveRangesTest, CFG3) {
128 /*
129 * Test the following snippet:
130 * var a = 0;
131 * if (0 == 0) {
132 * } else {
133 * a = 4;
134 * }
135 * return a;
136 *
137 * Which becomes the following graph (numbered by lifetime position):
138 * 2: constant0
Nicolas Geoffraya7062e02014-05-22 12:50:17 +0100139 * 4: constant4
140 * 6: goto
Nicolas Geoffrayddb311f2014-05-16 09:28:54 +0100141 * |
Nicolas Geoffraya7062e02014-05-22 12:50:17 +0100142 * 10: equal
143 * 12: if
Nicolas Geoffrayddb311f2014-05-16 09:28:54 +0100144 * / \
Nicolas Geoffraya7062e02014-05-22 12:50:17 +0100145 * 16: goto 20: goto
Nicolas Geoffrayddb311f2014-05-16 09:28:54 +0100146 * \ /
Nicolas Geoffraya7062e02014-05-22 12:50:17 +0100147 * 22: phi
148 * 24: return
Nicolas Geoffrayddb311f2014-05-16 09:28:54 +0100149 * |
Nicolas Geoffray8ddb00c2014-09-29 12:00:40 +0100150 * 28: exit
Nicolas Geoffrayddb311f2014-05-16 09:28:54 +0100151 */
152 const uint16_t data[] = ONE_REGISTER_CODE_ITEM(
153 Instruction::CONST_4 | 0 | 0,
154 Instruction::IF_EQ, 3,
155 Instruction::CONST_4 | 4 << 12 | 0,
156 Instruction::RETURN | 0 << 8);
157
158 ArenaPool pool;
159 ArenaAllocator allocator(&pool);
160 HGraph* graph = BuildGraph(data, &allocator);
Nicolas Geoffray8a16d972014-09-11 10:30:02 +0100161 x86::CodeGeneratorX86 codegen(graph);
162 SsaLivenessAnalysis liveness(*graph, &codegen);
Nicolas Geoffrayddb311f2014-05-16 09:28:54 +0100163 liveness.Analyze();
164
Nicolas Geoffrayec7e4722014-06-06 11:24:33 +0100165 // Test for the 4 constant.
166 LiveInterval* interval = liveness.GetInstructionFromSsaIndex(1)->GetLiveInterval();
Nicolas Geoffraya7062e02014-05-22 12:50:17 +0100167 LiveRange* range = interval->GetFirstRange();
Nicolas Geoffrayec7e4722014-06-06 11:24:33 +0100168 ASSERT_EQ(4u, range->GetStart());
Nicolas Geoffrayddb311f2014-05-16 09:28:54 +0100169 // Last use is the phi at the return block so instruction is live until
170 // the end of the then block.
Nicolas Geoffraya7062e02014-05-22 12:50:17 +0100171 ASSERT_EQ(18u, range->GetEnd());
172 ASSERT_TRUE(range->GetNext() == nullptr);
Nicolas Geoffrayddb311f2014-05-16 09:28:54 +0100173
Nicolas Geoffrayec7e4722014-06-06 11:24:33 +0100174 // Test for the 0 constant.
175 interval = liveness.GetInstructionFromSsaIndex(0)->GetLiveInterval();
Nicolas Geoffrayddb311f2014-05-16 09:28:54 +0100176 // The then branch is a hole for this constant, therefore its interval has 2 ranges.
Nicolas Geoffraya7062e02014-05-22 12:50:17 +0100177 // First range starts from the definition and ends at the if block.
178 range = interval->GetFirstRange();
Nicolas Geoffrayec7e4722014-06-06 11:24:33 +0100179 ASSERT_EQ(2u, range->GetStart());
180 // 14 is the end of the if block.
Nicolas Geoffraya7062e02014-05-22 12:50:17 +0100181 ASSERT_EQ(14u, range->GetEnd());
182 // Second range is the else block.
183 range = range->GetNext();
184 ASSERT_EQ(18u, range->GetStart());
185 // Last use is the phi at the return block.
186 ASSERT_EQ(22u, range->GetEnd());
187 ASSERT_TRUE(range->GetNext() == nullptr);
Nicolas Geoffrayddb311f2014-05-16 09:28:54 +0100188
189 // Test for the phi.
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100190 interval = liveness.GetInstructionFromSsaIndex(2)->GetLiveInterval();
Nicolas Geoffraya7062e02014-05-22 12:50:17 +0100191 range = interval->GetFirstRange();
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100192 ASSERT_EQ(22u, liveness.GetInstructionFromSsaIndex(2)->GetLifetimePosition());
Nicolas Geoffraya7062e02014-05-22 12:50:17 +0100193 ASSERT_EQ(22u, range->GetStart());
Nicolas Geoffray8e3964b2014-10-17 11:06:38 +0100194 ASSERT_EQ(24u, range->GetEnd());
Nicolas Geoffraya7062e02014-05-22 12:50:17 +0100195 ASSERT_TRUE(range->GetNext() == nullptr);
Nicolas Geoffrayddb311f2014-05-16 09:28:54 +0100196}
197
Nicolas Geoffray8ddb00c2014-09-29 12:00:40 +0100198TEST(LiveRangesTest, Loop1) {
Nicolas Geoffrayddb311f2014-05-16 09:28:54 +0100199 /*
200 * Test the following snippet:
201 * var a = 0;
202 * while (a == a) {
203 * a = 4;
204 * }
205 * return 5;
206 *
207 * Which becomes the following graph (numbered by lifetime position):
208 * 2: constant0
Nicolas Geoffraya7062e02014-05-22 12:50:17 +0100209 * 4: constant4
210 * 6: constant5
Nicolas Geoffrayddb311f2014-05-16 09:28:54 +0100211 * 8: goto
212 * |
Nicolas Geoffraya7062e02014-05-22 12:50:17 +0100213 * 12: goto
214 * |
215 * 14: phi
216 * 16: equal
217 * 18: if +++++
Nicolas Geoffrayddb311f2014-05-16 09:28:54 +0100218 * | \ +
Nicolas Geoffraya7062e02014-05-22 12:50:17 +0100219 * | 22: goto
Nicolas Geoffrayddb311f2014-05-16 09:28:54 +0100220 * |
Nicolas Geoffraya7062e02014-05-22 12:50:17 +0100221 * 26: return
Nicolas Geoffrayddb311f2014-05-16 09:28:54 +0100222 * |
Nicolas Geoffraya7062e02014-05-22 12:50:17 +0100223 * 30: exit
Nicolas Geoffrayddb311f2014-05-16 09:28:54 +0100224 */
225
226 const uint16_t data[] = TWO_REGISTERS_CODE_ITEM(
227 Instruction::CONST_4 | 0 | 0,
228 Instruction::IF_EQ, 4,
229 Instruction::CONST_4 | 4 << 12 | 0,
230 Instruction::GOTO | 0xFD00,
231 Instruction::CONST_4 | 5 << 12 | 1 << 8,
232 Instruction::RETURN | 1 << 8);
233
234 ArenaPool pool;
235 ArenaAllocator allocator(&pool);
236 HGraph* graph = BuildGraph(data, &allocator);
Nicolas Geoffray9ebc72c2014-09-25 16:33:42 +0100237 RemoveSuspendChecks(graph);
Nicolas Geoffray8a16d972014-09-11 10:30:02 +0100238 x86::CodeGeneratorX86 codegen(graph);
239 SsaLivenessAnalysis liveness(*graph, &codegen);
Nicolas Geoffrayddb311f2014-05-16 09:28:54 +0100240 liveness.Analyze();
241
242 // Test for the 0 constant.
243 LiveInterval* interval = liveness.GetInstructionFromSsaIndex(0)->GetLiveInterval();
Nicolas Geoffraya7062e02014-05-22 12:50:17 +0100244 LiveRange* range = interval->GetFirstRange();
245 ASSERT_EQ(2u, range->GetStart());
Nicolas Geoffrayddb311f2014-05-16 09:28:54 +0100246 // Last use is the loop phi so instruction is live until
247 // the end of the pre loop header.
Nicolas Geoffraya7062e02014-05-22 12:50:17 +0100248 ASSERT_EQ(14u, range->GetEnd());
249 ASSERT_TRUE(range->GetNext() == nullptr);
Nicolas Geoffrayddb311f2014-05-16 09:28:54 +0100250
251 // Test for the 4 constant.
252 interval = liveness.GetInstructionFromSsaIndex(1)->GetLiveInterval();
Nicolas Geoffraya7062e02014-05-22 12:50:17 +0100253 range = interval->GetFirstRange();
Nicolas Geoffrayddb311f2014-05-16 09:28:54 +0100254 // The instruction is live until the end of the loop.
Nicolas Geoffraya7062e02014-05-22 12:50:17 +0100255 ASSERT_EQ(4u, range->GetStart());
256 ASSERT_EQ(24u, range->GetEnd());
257 ASSERT_TRUE(range->GetNext() == nullptr);
Nicolas Geoffrayddb311f2014-05-16 09:28:54 +0100258
259 // Test for the 5 constant.
260 interval = liveness.GetInstructionFromSsaIndex(2)->GetLiveInterval();
Nicolas Geoffraya7062e02014-05-22 12:50:17 +0100261 range = interval->GetFirstRange();
262 // The instruction is live until the return instruction after the loop.
263 ASSERT_EQ(6u, range->GetStart());
Nicolas Geoffray8e3964b2014-10-17 11:06:38 +0100264 ASSERT_EQ(26u, range->GetEnd());
Nicolas Geoffraya7062e02014-05-22 12:50:17 +0100265 ASSERT_TRUE(range->GetNext() == nullptr);
Nicolas Geoffrayddb311f2014-05-16 09:28:54 +0100266
267 // Test for the phi.
268 interval = liveness.GetInstructionFromSsaIndex(3)->GetLiveInterval();
Nicolas Geoffraya7062e02014-05-22 12:50:17 +0100269 range = interval->GetFirstRange();
Nicolas Geoffrayddb311f2014-05-16 09:28:54 +0100270 // Instruction is consumed by the if.
Nicolas Geoffraya7062e02014-05-22 12:50:17 +0100271 ASSERT_EQ(14u, range->GetStart());
Nicolas Geoffray8e3964b2014-10-17 11:06:38 +0100272 ASSERT_EQ(17u, range->GetEnd());
Nicolas Geoffraya7062e02014-05-22 12:50:17 +0100273 ASSERT_TRUE(range->GetNext() == nullptr);
Nicolas Geoffrayddb311f2014-05-16 09:28:54 +0100274}
275
Nicolas Geoffray8ddb00c2014-09-29 12:00:40 +0100276TEST(LiveRangesTest, Loop2) {
277 /*
278 * Test the following snippet:
279 * var a = 0;
280 * while (a == a) {
281 * a = a + a;
282 * }
283 * return a;
284 *
285 * Which becomes the following graph (numbered by lifetime position):
286 * 2: constant0
287 * 4: goto
288 * |
289 * 8: goto
290 * |
291 * 10: phi
292 * 12: equal
293 * 14: if +++++
294 * | \ +
295 * | 18: suspend
296 * | 20: add
297 * | 22: goto
298 * |
299 * 26: return
300 * |
301 * 30: exit
302 *
303 * We want to make sure the phi at 10 has a lifetime hole after the add at 20.
304 */
305
306 const uint16_t data[] = ONE_REGISTER_CODE_ITEM(
307 Instruction::CONST_4 | 0 | 0,
308 Instruction::IF_EQ, 6,
309 Instruction::ADD_INT, 0, 0,
310 Instruction::GOTO | 0xFB00,
311 Instruction::RETURN | 0 << 8);
312
313 ArenaPool pool;
314 ArenaAllocator allocator(&pool);
315 HGraph* graph = BuildGraph(data, &allocator);
316 x86::CodeGeneratorX86 codegen(graph);
317 SsaLivenessAnalysis liveness(*graph, &codegen);
318 liveness.Analyze();
319
320 // Test for the 0 constant.
321 HIntConstant* constant = liveness.GetInstructionFromSsaIndex(0)->AsIntConstant();
322 LiveInterval* interval = constant->GetLiveInterval();
323 LiveRange* range = interval->GetFirstRange();
324 ASSERT_EQ(2u, range->GetStart());
325 // Last use is the loop phi so instruction is live until
326 // the end of the pre loop header.
327 ASSERT_EQ(10u, range->GetEnd());
328 ASSERT_TRUE(range->GetNext() == nullptr);
329
330 // Test for the loop phi.
331 HPhi* phi = liveness.GetInstructionFromSsaIndex(1)->AsPhi();
332 interval = phi->GetLiveInterval();
333 range = interval->GetFirstRange();
334 ASSERT_EQ(10u, range->GetStart());
335 ASSERT_EQ(21u, range->GetEnd());
336 range = range->GetNext();
337 ASSERT_TRUE(range != nullptr);
338 ASSERT_EQ(24u, range->GetStart());
Nicolas Geoffray8e3964b2014-10-17 11:06:38 +0100339 ASSERT_EQ(26u, range->GetEnd());
Nicolas Geoffray8ddb00c2014-09-29 12:00:40 +0100340
341 // Test for the add instruction.
342 HAdd* add = liveness.GetInstructionFromSsaIndex(2)->AsAdd();
343 interval = add->GetLiveInterval();
344 range = interval->GetFirstRange();
345 ASSERT_EQ(20u, range->GetStart());
346 ASSERT_EQ(24u, range->GetEnd());
347 ASSERT_TRUE(range->GetNext() == nullptr);
348}
349
350TEST(LiveRangesTest, CFG4) {
351 /*
352 * Test the following snippet:
353 * var a = 0;
354 * var b = 4;
355 * if (a == a) {
356 * a = b + a;
357 * } else {
358 * a = b + a
359 * }
360 * return b;
361 *
362 * Which becomes the following graph (numbered by lifetime position):
363 * 2: constant0
364 * 4: constant4
365 * 6: goto
366 * |
367 * 10: equal
368 * 12: if
369 * / \
370 * 16: add 22: add
371 * 18: goto 24: goto
372 * \ /
373 * 26: phi
374 * 28: return
375 * |
376 * 32: exit
377 *
378 * We want to make sure the constant0 has a lifetime hole after the 16: add.
379 */
380 const uint16_t data[] = TWO_REGISTERS_CODE_ITEM(
381 Instruction::CONST_4 | 0 | 0,
382 Instruction::CONST_4 | 4 << 12 | 1 << 8,
383 Instruction::IF_EQ, 5,
384 Instruction::ADD_INT, 1 << 8,
385 Instruction::GOTO | 0x300,
386 Instruction::ADD_INT, 1 << 8,
Nicolas Geoffraya3c00e52014-11-25 11:18:37 +0000387 Instruction::RETURN);
Nicolas Geoffray8ddb00c2014-09-29 12:00:40 +0100388
389 ArenaPool pool;
390 ArenaAllocator allocator(&pool);
391 HGraph* graph = BuildGraph(data, &allocator);
392 x86::CodeGeneratorX86 codegen(graph);
393 SsaLivenessAnalysis liveness(*graph, &codegen);
394 liveness.Analyze();
395
396 // Test for the 0 constant.
397 LiveInterval* interval = liveness.GetInstructionFromSsaIndex(0)->GetLiveInterval();
398 LiveRange* range = interval->GetFirstRange();
399 ASSERT_EQ(2u, range->GetStart());
400 ASSERT_EQ(16u, range->GetEnd());
401 range = range->GetNext();
402 ASSERT_TRUE(range != nullptr);
403 ASSERT_EQ(20u, range->GetStart());
404 ASSERT_EQ(22u, range->GetEnd());
405 ASSERT_TRUE(range->GetNext() == nullptr);
406
407 // Test for the 4 constant.
408 interval = liveness.GetInstructionFromSsaIndex(1)->GetLiveInterval();
409 range = interval->GetFirstRange();
410 ASSERT_EQ(4u, range->GetStart());
Nicolas Geoffraya3c00e52014-11-25 11:18:37 +0000411 ASSERT_EQ(17u, range->GetEnd());
412 range = range->GetNext();
413 ASSERT_EQ(20u, range->GetStart());
414 ASSERT_EQ(23u, range->GetEnd());
Nicolas Geoffray8ddb00c2014-09-29 12:00:40 +0100415 ASSERT_TRUE(range->GetNext() == nullptr);
416
417 // Test for the first add.
418 HAdd* add = liveness.GetInstructionFromSsaIndex(2)->AsAdd();
419 interval = add->GetLiveInterval();
420 range = interval->GetFirstRange();
421 ASSERT_EQ(16u, range->GetStart());
422 ASSERT_EQ(20u, range->GetEnd());
423 ASSERT_TRUE(range->GetNext() == nullptr);
424
425 // Test for the second add.
426 add = liveness.GetInstructionFromSsaIndex(3)->AsAdd();
427 interval = add->GetLiveInterval();
428 range = interval->GetFirstRange();
429 ASSERT_EQ(22u, range->GetStart());
430 ASSERT_EQ(26u, range->GetEnd());
431 ASSERT_TRUE(range->GetNext() == nullptr);
432
Nicolas Geoffray8ddb00c2014-09-29 12:00:40 +0100433 HPhi* phi = liveness.GetInstructionFromSsaIndex(4)->AsPhi();
Nicolas Geoffraya3c00e52014-11-25 11:18:37 +0000434 ASSERT_EQ(phi->NumberOfUses(), 1u);
Nicolas Geoffray8ddb00c2014-09-29 12:00:40 +0100435 interval = phi->GetLiveInterval();
436 range = interval->GetFirstRange();
437 ASSERT_EQ(26u, range->GetStart());
438 ASSERT_EQ(28u, range->GetEnd());
439 ASSERT_TRUE(range->GetNext() == nullptr);
440}
441
Nicolas Geoffrayddb311f2014-05-16 09:28:54 +0100442} // namespace art