blob: 89c949563bfd1c44a6ea486782d0372cf85aaf6d [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 Geoffrayddb311f2014-05-16 09:28:54 +010039 graph->BuildDominatorTree();
40 graph->TransformToSSA();
41 graph->FindNaturalLoops();
Nicolas Geoffray360231a2014-10-08 21:07:48 +010042 // `Inline` conditions into ifs.
43 PrepareForRegisterAllocation(graph).Run();
Nicolas Geoffrayddb311f2014-05-16 09:28:54 +010044 return graph;
45}
46
47TEST(LiveRangesTest, CFG1) {
48 /*
49 * Test the following snippet:
50 * return 0;
51 *
52 * Which becomes the following graph (numbered by lifetime position):
53 * 2: constant0
Nicolas Geoffraya7062e02014-05-22 12:50:17 +010054 * 4: goto
Nicolas Geoffrayddb311f2014-05-16 09:28:54 +010055 * |
Nicolas Geoffraya7062e02014-05-22 12:50:17 +010056 * 8: return
Nicolas Geoffrayddb311f2014-05-16 09:28:54 +010057 * |
Nicolas Geoffraya7062e02014-05-22 12:50:17 +010058 * 12: exit
Nicolas Geoffrayddb311f2014-05-16 09:28:54 +010059 */
60 const uint16_t data[] = ONE_REGISTER_CODE_ITEM(
61 Instruction::CONST_4 | 0 | 0,
62 Instruction::RETURN);
63
64 ArenaPool pool;
65 ArenaAllocator allocator(&pool);
66 HGraph* graph = BuildGraph(data, &allocator);
Nicolas Geoffray31d76b42014-06-09 15:02:22 +010067
Nicolas Geoffray8a16d972014-09-11 10:30:02 +010068 x86::CodeGeneratorX86 codegen(graph);
69 SsaLivenessAnalysis liveness(*graph, &codegen);
Nicolas Geoffrayddb311f2014-05-16 09:28:54 +010070 liveness.Analyze();
71
72 LiveInterval* interval = liveness.GetInstructionFromSsaIndex(0)->GetLiveInterval();
Nicolas Geoffraya7062e02014-05-22 12:50:17 +010073 LiveRange* range = interval->GetFirstRange();
74 ASSERT_EQ(2u, range->GetStart());
Nicolas Geoffrayddb311f2014-05-16 09:28:54 +010075 // Last use is the return instruction.
Nicolas Geoffray8e3964b2014-10-17 11:06:38 +010076 ASSERT_EQ(8u, range->GetEnd());
Nicolas Geoffrayddb311f2014-05-16 09:28:54 +010077 HBasicBlock* block = graph->GetBlocks().Get(1);
Roland Levillain476df552014-10-09 17:51:36 +010078 ASSERT_TRUE(block->GetLastInstruction()->IsReturn());
Nicolas Geoffraya7062e02014-05-22 12:50:17 +010079 ASSERT_EQ(8u, block->GetLastInstruction()->GetLifetimePosition());
80 ASSERT_TRUE(range->GetNext() == nullptr);
Nicolas Geoffrayddb311f2014-05-16 09:28:54 +010081}
82
83TEST(LiveRangesTest, CFG2) {
84 /*
85 * Test the following snippet:
86 * var a = 0;
87 * if (0 == 0) {
88 * } else {
89 * }
90 * return a;
91 *
92 * Which becomes the following graph (numbered by lifetime position):
93 * 2: constant0
Nicolas Geoffraya7062e02014-05-22 12:50:17 +010094 * 4: goto
Nicolas Geoffrayddb311f2014-05-16 09:28:54 +010095 * |
Nicolas Geoffraya7062e02014-05-22 12:50:17 +010096 * 8: equal
97 * 10: if
Nicolas Geoffrayddb311f2014-05-16 09:28:54 +010098 * / \
Nicolas Geoffraya7062e02014-05-22 12:50:17 +010099 * 14: goto 18: goto
Nicolas Geoffrayddb311f2014-05-16 09:28:54 +0100100 * \ /
Nicolas Geoffraya7062e02014-05-22 12:50:17 +0100101 * 22: return
Nicolas Geoffrayddb311f2014-05-16 09:28:54 +0100102 * |
Nicolas Geoffraya7062e02014-05-22 12:50:17 +0100103 * 26: exit
Nicolas Geoffrayddb311f2014-05-16 09:28:54 +0100104 */
105 const uint16_t data[] = ONE_REGISTER_CODE_ITEM(
106 Instruction::CONST_4 | 0 | 0,
107 Instruction::IF_EQ, 3,
108 Instruction::GOTO | 0x100,
109 Instruction::RETURN | 0 << 8);
110
111 ArenaPool pool;
112 ArenaAllocator allocator(&pool);
113 HGraph* graph = BuildGraph(data, &allocator);
Nicolas Geoffray8a16d972014-09-11 10:30:02 +0100114 x86::CodeGeneratorX86 codegen(graph);
115 SsaLivenessAnalysis liveness(*graph, &codegen);
Nicolas Geoffrayddb311f2014-05-16 09:28:54 +0100116 liveness.Analyze();
117
118 LiveInterval* interval = liveness.GetInstructionFromSsaIndex(0)->GetLiveInterval();
Nicolas Geoffraya7062e02014-05-22 12:50:17 +0100119 LiveRange* range = interval->GetFirstRange();
120 ASSERT_EQ(2u, range->GetStart());
Nicolas Geoffrayddb311f2014-05-16 09:28:54 +0100121 // Last use is the return instruction.
Nicolas Geoffray8e3964b2014-10-17 11:06:38 +0100122 ASSERT_EQ(22u, range->GetEnd());
Nicolas Geoffrayddb311f2014-05-16 09:28:54 +0100123 HBasicBlock* block = graph->GetBlocks().Get(3);
Roland Levillain476df552014-10-09 17:51:36 +0100124 ASSERT_TRUE(block->GetLastInstruction()->IsReturn());
Nicolas Geoffraya7062e02014-05-22 12:50:17 +0100125 ASSERT_EQ(22u, block->GetLastInstruction()->GetLifetimePosition());
126 ASSERT_TRUE(range->GetNext() == nullptr);
Nicolas Geoffrayddb311f2014-05-16 09:28:54 +0100127}
128
129TEST(LiveRangesTest, CFG3) {
130 /*
131 * Test the following snippet:
132 * var a = 0;
133 * if (0 == 0) {
134 * } else {
135 * a = 4;
136 * }
137 * return a;
138 *
139 * Which becomes the following graph (numbered by lifetime position):
140 * 2: constant0
Nicolas Geoffraya7062e02014-05-22 12:50:17 +0100141 * 4: constant4
142 * 6: goto
Nicolas Geoffrayddb311f2014-05-16 09:28:54 +0100143 * |
Nicolas Geoffraya7062e02014-05-22 12:50:17 +0100144 * 10: equal
145 * 12: if
Nicolas Geoffrayddb311f2014-05-16 09:28:54 +0100146 * / \
Nicolas Geoffraya7062e02014-05-22 12:50:17 +0100147 * 16: goto 20: goto
Nicolas Geoffrayddb311f2014-05-16 09:28:54 +0100148 * \ /
Nicolas Geoffraya7062e02014-05-22 12:50:17 +0100149 * 22: phi
150 * 24: return
Nicolas Geoffrayddb311f2014-05-16 09:28:54 +0100151 * |
Nicolas Geoffray8ddb00c2014-09-29 12:00:40 +0100152 * 28: exit
Nicolas Geoffrayddb311f2014-05-16 09:28:54 +0100153 */
154 const uint16_t data[] = ONE_REGISTER_CODE_ITEM(
155 Instruction::CONST_4 | 0 | 0,
156 Instruction::IF_EQ, 3,
157 Instruction::CONST_4 | 4 << 12 | 0,
158 Instruction::RETURN | 0 << 8);
159
160 ArenaPool pool;
161 ArenaAllocator allocator(&pool);
162 HGraph* graph = BuildGraph(data, &allocator);
Nicolas Geoffray8a16d972014-09-11 10:30:02 +0100163 x86::CodeGeneratorX86 codegen(graph);
164 SsaLivenessAnalysis liveness(*graph, &codegen);
Nicolas Geoffrayddb311f2014-05-16 09:28:54 +0100165 liveness.Analyze();
166
Nicolas Geoffrayec7e4722014-06-06 11:24:33 +0100167 // Test for the 4 constant.
168 LiveInterval* interval = liveness.GetInstructionFromSsaIndex(1)->GetLiveInterval();
Nicolas Geoffraya7062e02014-05-22 12:50:17 +0100169 LiveRange* range = interval->GetFirstRange();
Nicolas Geoffrayec7e4722014-06-06 11:24:33 +0100170 ASSERT_EQ(4u, range->GetStart());
Nicolas Geoffrayddb311f2014-05-16 09:28:54 +0100171 // Last use is the phi at the return block so instruction is live until
172 // the end of the then block.
Nicolas Geoffraya7062e02014-05-22 12:50:17 +0100173 ASSERT_EQ(18u, range->GetEnd());
174 ASSERT_TRUE(range->GetNext() == nullptr);
Nicolas Geoffrayddb311f2014-05-16 09:28:54 +0100175
Nicolas Geoffrayec7e4722014-06-06 11:24:33 +0100176 // Test for the 0 constant.
177 interval = liveness.GetInstructionFromSsaIndex(0)->GetLiveInterval();
Nicolas Geoffrayddb311f2014-05-16 09:28:54 +0100178 // The then branch is a hole for this constant, therefore its interval has 2 ranges.
Nicolas Geoffraya7062e02014-05-22 12:50:17 +0100179 // First range starts from the definition and ends at the if block.
180 range = interval->GetFirstRange();
Nicolas Geoffrayec7e4722014-06-06 11:24:33 +0100181 ASSERT_EQ(2u, range->GetStart());
182 // 14 is the end of the if block.
Nicolas Geoffraya7062e02014-05-22 12:50:17 +0100183 ASSERT_EQ(14u, range->GetEnd());
184 // Second range is the else block.
185 range = range->GetNext();
186 ASSERT_EQ(18u, range->GetStart());
187 // Last use is the phi at the return block.
188 ASSERT_EQ(22u, range->GetEnd());
189 ASSERT_TRUE(range->GetNext() == nullptr);
Nicolas Geoffrayddb311f2014-05-16 09:28:54 +0100190
191 // Test for the phi.
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100192 interval = liveness.GetInstructionFromSsaIndex(2)->GetLiveInterval();
Nicolas Geoffraya7062e02014-05-22 12:50:17 +0100193 range = interval->GetFirstRange();
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100194 ASSERT_EQ(22u, liveness.GetInstructionFromSsaIndex(2)->GetLifetimePosition());
Nicolas Geoffraya7062e02014-05-22 12:50:17 +0100195 ASSERT_EQ(22u, range->GetStart());
Nicolas Geoffray8e3964b2014-10-17 11:06:38 +0100196 ASSERT_EQ(24u, range->GetEnd());
Nicolas Geoffraya7062e02014-05-22 12:50:17 +0100197 ASSERT_TRUE(range->GetNext() == nullptr);
Nicolas Geoffrayddb311f2014-05-16 09:28:54 +0100198}
199
Nicolas Geoffray8ddb00c2014-09-29 12:00:40 +0100200TEST(LiveRangesTest, Loop1) {
Nicolas Geoffrayddb311f2014-05-16 09:28:54 +0100201 /*
202 * Test the following snippet:
203 * var a = 0;
204 * while (a == a) {
205 * a = 4;
206 * }
207 * return 5;
208 *
209 * Which becomes the following graph (numbered by lifetime position):
210 * 2: constant0
Nicolas Geoffraya7062e02014-05-22 12:50:17 +0100211 * 4: constant4
212 * 6: constant5
Nicolas Geoffrayddb311f2014-05-16 09:28:54 +0100213 * 8: goto
214 * |
Nicolas Geoffraya7062e02014-05-22 12:50:17 +0100215 * 12: goto
216 * |
217 * 14: phi
218 * 16: equal
219 * 18: if +++++
Nicolas Geoffrayddb311f2014-05-16 09:28:54 +0100220 * | \ +
Nicolas Geoffraya7062e02014-05-22 12:50:17 +0100221 * | 22: goto
Nicolas Geoffrayddb311f2014-05-16 09:28:54 +0100222 * |
Nicolas Geoffraya7062e02014-05-22 12:50:17 +0100223 * 26: return
Nicolas Geoffrayddb311f2014-05-16 09:28:54 +0100224 * |
Nicolas Geoffraya7062e02014-05-22 12:50:17 +0100225 * 30: exit
Nicolas Geoffrayddb311f2014-05-16 09:28:54 +0100226 */
227
228 const uint16_t data[] = TWO_REGISTERS_CODE_ITEM(
229 Instruction::CONST_4 | 0 | 0,
230 Instruction::IF_EQ, 4,
231 Instruction::CONST_4 | 4 << 12 | 0,
232 Instruction::GOTO | 0xFD00,
233 Instruction::CONST_4 | 5 << 12 | 1 << 8,
234 Instruction::RETURN | 1 << 8);
235
236 ArenaPool pool;
237 ArenaAllocator allocator(&pool);
238 HGraph* graph = BuildGraph(data, &allocator);
Nicolas Geoffray9ebc72c2014-09-25 16:33:42 +0100239 RemoveSuspendChecks(graph);
Nicolas Geoffray8a16d972014-09-11 10:30:02 +0100240 x86::CodeGeneratorX86 codegen(graph);
241 SsaLivenessAnalysis liveness(*graph, &codegen);
Nicolas Geoffrayddb311f2014-05-16 09:28:54 +0100242 liveness.Analyze();
243
244 // Test for the 0 constant.
245 LiveInterval* interval = liveness.GetInstructionFromSsaIndex(0)->GetLiveInterval();
Nicolas Geoffraya7062e02014-05-22 12:50:17 +0100246 LiveRange* range = interval->GetFirstRange();
247 ASSERT_EQ(2u, range->GetStart());
Nicolas Geoffrayddb311f2014-05-16 09:28:54 +0100248 // Last use is the loop phi so instruction is live until
249 // the end of the pre loop header.
Nicolas Geoffraya7062e02014-05-22 12:50:17 +0100250 ASSERT_EQ(14u, range->GetEnd());
251 ASSERT_TRUE(range->GetNext() == nullptr);
Nicolas Geoffrayddb311f2014-05-16 09:28:54 +0100252
253 // Test for the 4 constant.
254 interval = liveness.GetInstructionFromSsaIndex(1)->GetLiveInterval();
Nicolas Geoffraya7062e02014-05-22 12:50:17 +0100255 range = interval->GetFirstRange();
Nicolas Geoffrayddb311f2014-05-16 09:28:54 +0100256 // The instruction is live until the end of the loop.
Nicolas Geoffraya7062e02014-05-22 12:50:17 +0100257 ASSERT_EQ(4u, range->GetStart());
258 ASSERT_EQ(24u, range->GetEnd());
259 ASSERT_TRUE(range->GetNext() == nullptr);
Nicolas Geoffrayddb311f2014-05-16 09:28:54 +0100260
261 // Test for the 5 constant.
262 interval = liveness.GetInstructionFromSsaIndex(2)->GetLiveInterval();
Nicolas Geoffraya7062e02014-05-22 12:50:17 +0100263 range = interval->GetFirstRange();
264 // The instruction is live until the return instruction after the loop.
265 ASSERT_EQ(6u, range->GetStart());
Nicolas Geoffray8e3964b2014-10-17 11:06:38 +0100266 ASSERT_EQ(26u, range->GetEnd());
Nicolas Geoffraya7062e02014-05-22 12:50:17 +0100267 ASSERT_TRUE(range->GetNext() == nullptr);
Nicolas Geoffrayddb311f2014-05-16 09:28:54 +0100268
269 // Test for the phi.
270 interval = liveness.GetInstructionFromSsaIndex(3)->GetLiveInterval();
Nicolas Geoffraya7062e02014-05-22 12:50:17 +0100271 range = interval->GetFirstRange();
Nicolas Geoffrayddb311f2014-05-16 09:28:54 +0100272 // Instruction is consumed by the if.
Nicolas Geoffraya7062e02014-05-22 12:50:17 +0100273 ASSERT_EQ(14u, range->GetStart());
Nicolas Geoffray8e3964b2014-10-17 11:06:38 +0100274 ASSERT_EQ(17u, range->GetEnd());
Nicolas Geoffraya7062e02014-05-22 12:50:17 +0100275 ASSERT_TRUE(range->GetNext() == nullptr);
Nicolas Geoffrayddb311f2014-05-16 09:28:54 +0100276}
277
Nicolas Geoffray8ddb00c2014-09-29 12:00:40 +0100278TEST(LiveRangesTest, Loop2) {
279 /*
280 * Test the following snippet:
281 * var a = 0;
282 * while (a == a) {
283 * a = a + a;
284 * }
285 * return a;
286 *
287 * Which becomes the following graph (numbered by lifetime position):
288 * 2: constant0
289 * 4: goto
290 * |
291 * 8: goto
292 * |
293 * 10: phi
294 * 12: equal
295 * 14: if +++++
296 * | \ +
297 * | 18: suspend
298 * | 20: add
299 * | 22: goto
300 * |
301 * 26: return
302 * |
303 * 30: exit
304 *
305 * We want to make sure the phi at 10 has a lifetime hole after the add at 20.
306 */
307
308 const uint16_t data[] = ONE_REGISTER_CODE_ITEM(
309 Instruction::CONST_4 | 0 | 0,
310 Instruction::IF_EQ, 6,
311 Instruction::ADD_INT, 0, 0,
312 Instruction::GOTO | 0xFB00,
313 Instruction::RETURN | 0 << 8);
314
315 ArenaPool pool;
316 ArenaAllocator allocator(&pool);
317 HGraph* graph = BuildGraph(data, &allocator);
318 x86::CodeGeneratorX86 codegen(graph);
319 SsaLivenessAnalysis liveness(*graph, &codegen);
320 liveness.Analyze();
321
322 // Test for the 0 constant.
323 HIntConstant* constant = liveness.GetInstructionFromSsaIndex(0)->AsIntConstant();
324 LiveInterval* interval = constant->GetLiveInterval();
325 LiveRange* range = interval->GetFirstRange();
326 ASSERT_EQ(2u, range->GetStart());
327 // Last use is the loop phi so instruction is live until
328 // the end of the pre loop header.
329 ASSERT_EQ(10u, range->GetEnd());
330 ASSERT_TRUE(range->GetNext() == nullptr);
331
332 // Test for the loop phi.
333 HPhi* phi = liveness.GetInstructionFromSsaIndex(1)->AsPhi();
334 interval = phi->GetLiveInterval();
335 range = interval->GetFirstRange();
336 ASSERT_EQ(10u, range->GetStart());
337 ASSERT_EQ(21u, range->GetEnd());
338 range = range->GetNext();
339 ASSERT_TRUE(range != nullptr);
340 ASSERT_EQ(24u, range->GetStart());
Nicolas Geoffray8e3964b2014-10-17 11:06:38 +0100341 ASSERT_EQ(26u, range->GetEnd());
Nicolas Geoffray8ddb00c2014-09-29 12:00:40 +0100342
343 // Test for the add instruction.
344 HAdd* add = liveness.GetInstructionFromSsaIndex(2)->AsAdd();
345 interval = add->GetLiveInterval();
346 range = interval->GetFirstRange();
347 ASSERT_EQ(20u, range->GetStart());
348 ASSERT_EQ(24u, range->GetEnd());
349 ASSERT_TRUE(range->GetNext() == nullptr);
350}
351
352TEST(LiveRangesTest, CFG4) {
353 /*
354 * Test the following snippet:
355 * var a = 0;
356 * var b = 4;
357 * if (a == a) {
358 * a = b + a;
359 * } else {
360 * a = b + a
361 * }
362 * return b;
363 *
364 * Which becomes the following graph (numbered by lifetime position):
365 * 2: constant0
366 * 4: constant4
367 * 6: goto
368 * |
369 * 10: equal
370 * 12: if
371 * / \
372 * 16: add 22: add
373 * 18: goto 24: goto
374 * \ /
375 * 26: phi
376 * 28: return
377 * |
378 * 32: exit
379 *
380 * We want to make sure the constant0 has a lifetime hole after the 16: add.
381 */
382 const uint16_t data[] = TWO_REGISTERS_CODE_ITEM(
383 Instruction::CONST_4 | 0 | 0,
384 Instruction::CONST_4 | 4 << 12 | 1 << 8,
385 Instruction::IF_EQ, 5,
386 Instruction::ADD_INT, 1 << 8,
387 Instruction::GOTO | 0x300,
388 Instruction::ADD_INT, 1 << 8,
389 Instruction::RETURN | 1 << 8);
390
391 ArenaPool pool;
392 ArenaAllocator allocator(&pool);
393 HGraph* graph = BuildGraph(data, &allocator);
394 x86::CodeGeneratorX86 codegen(graph);
395 SsaLivenessAnalysis liveness(*graph, &codegen);
396 liveness.Analyze();
397
398 // Test for the 0 constant.
399 LiveInterval* interval = liveness.GetInstructionFromSsaIndex(0)->GetLiveInterval();
400 LiveRange* range = interval->GetFirstRange();
401 ASSERT_EQ(2u, range->GetStart());
402 ASSERT_EQ(16u, range->GetEnd());
403 range = range->GetNext();
404 ASSERT_TRUE(range != nullptr);
405 ASSERT_EQ(20u, range->GetStart());
406 ASSERT_EQ(22u, range->GetEnd());
407 ASSERT_TRUE(range->GetNext() == nullptr);
408
409 // Test for the 4 constant.
410 interval = liveness.GetInstructionFromSsaIndex(1)->GetLiveInterval();
411 range = interval->GetFirstRange();
412 ASSERT_EQ(4u, range->GetStart());
Nicolas Geoffray8e3964b2014-10-17 11:06:38 +0100413 ASSERT_EQ(28u, range->GetEnd());
Nicolas Geoffray8ddb00c2014-09-29 12:00:40 +0100414 ASSERT_TRUE(range->GetNext() == nullptr);
415
416 // Test for the first add.
417 HAdd* add = liveness.GetInstructionFromSsaIndex(2)->AsAdd();
418 interval = add->GetLiveInterval();
419 range = interval->GetFirstRange();
420 ASSERT_EQ(16u, range->GetStart());
421 ASSERT_EQ(20u, range->GetEnd());
422 ASSERT_TRUE(range->GetNext() == nullptr);
423
424 // Test for the second add.
425 add = liveness.GetInstructionFromSsaIndex(3)->AsAdd();
426 interval = add->GetLiveInterval();
427 range = interval->GetFirstRange();
428 ASSERT_EQ(22u, range->GetStart());
429 ASSERT_EQ(26u, range->GetEnd());
430 ASSERT_TRUE(range->GetNext() == nullptr);
431
432 // Test for the phi, which is unused.
433 HPhi* phi = liveness.GetInstructionFromSsaIndex(4)->AsPhi();
434 ASSERT_EQ(phi->NumberOfUses(), 0u);
435 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