Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(391)

Side by Side Diff: runtime/vm/flow_graph_allocator.cc

Issue 2974233002: VM: Re-format to use at most one newline between functions (Closed)
Patch Set: Rebase and merge Created 3 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « runtime/vm/flow_graph_allocator.h ('k') | runtime/vm/flow_graph_builder.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a 2 // for details. All rights reserved. Use of this source code is governed by a
3 // BSD-style license that can be found in the LICENSE file. 3 // BSD-style license that can be found in the LICENSE file.
4 4
5 #include "vm/flow_graph_allocator.h" 5 #include "vm/flow_graph_allocator.h"
6 6
7 #include "vm/bit_vector.h" 7 #include "vm/bit_vector.h"
8 #include "vm/intermediate_language.h"
9 #include "vm/il_printer.h"
10 #include "vm/flow_graph.h" 8 #include "vm/flow_graph.h"
11 #include "vm/flow_graph_compiler.h" 9 #include "vm/flow_graph_compiler.h"
10 #include "vm/il_printer.h"
11 #include "vm/intermediate_language.h"
12 #include "vm/log.h" 12 #include "vm/log.h"
13 #include "vm/parser.h" 13 #include "vm/parser.h"
14 #include "vm/stack_frame.h" 14 #include "vm/stack_frame.h"
15 15
16 namespace dart { 16 namespace dart {
17 17
18 #if defined(DEBUG) 18 #if defined(DEBUG)
19 #define TRACE_ALLOC(statement) \ 19 #define TRACE_ALLOC(statement) \
20 do { \ 20 do { \
21 if (FLAG_trace_ssa_allocator) statement; \ 21 if (FLAG_trace_ssa_allocator) statement; \
22 } while (0) 22 } while (0)
23 #else 23 #else
24 #define TRACE_ALLOC(statement) 24 #define TRACE_ALLOC(statement)
25 #endif 25 #endif
26 26
27
28 static const intptr_t kNoVirtualRegister = -1; 27 static const intptr_t kNoVirtualRegister = -1;
29 static const intptr_t kTempVirtualRegister = -2; 28 static const intptr_t kTempVirtualRegister = -2;
30 static const intptr_t kIllegalPosition = -1; 29 static const intptr_t kIllegalPosition = -1;
31 static const intptr_t kMaxPosition = 0x7FFFFFFF; 30 static const intptr_t kMaxPosition = 0x7FFFFFFF;
32 static const intptr_t kPairVirtualRegisterOffset = 1; 31 static const intptr_t kPairVirtualRegisterOffset = 1;
33 32
34 // Definitions which have pair representations 33 // Definitions which have pair representations
35 // (kPairOfTagged) use two virtual register names. 34 // (kPairOfTagged) use two virtual register names.
36 // At SSA index allocation time each definition reserves two SSA indexes, 35 // At SSA index allocation time each definition reserves two SSA indexes,
37 // the second index is only used for pairs. This function maps from the first 36 // the second index is only used for pairs. This function maps from the first
38 // SSA index to the second. 37 // SSA index to the second.
39 static intptr_t ToSecondPairVreg(intptr_t vreg) { 38 static intptr_t ToSecondPairVreg(intptr_t vreg) {
40 // Map vreg to its pair vreg. 39 // Map vreg to its pair vreg.
41 return vreg + kPairVirtualRegisterOffset; 40 return vreg + kPairVirtualRegisterOffset;
42 } 41 }
43 42
44
45 static intptr_t MinPosition(intptr_t a, intptr_t b) { 43 static intptr_t MinPosition(intptr_t a, intptr_t b) {
46 return (a < b) ? a : b; 44 return (a < b) ? a : b;
47 } 45 }
48 46
49
50 static bool IsInstructionStartPosition(intptr_t pos) { 47 static bool IsInstructionStartPosition(intptr_t pos) {
51 return (pos & 1) == 0; 48 return (pos & 1) == 0;
52 } 49 }
53 50
54
55 static bool IsInstructionEndPosition(intptr_t pos) { 51 static bool IsInstructionEndPosition(intptr_t pos) {
56 return (pos & 1) == 1; 52 return (pos & 1) == 1;
57 } 53 }
58 54
59
60 static intptr_t ToInstructionStart(intptr_t pos) { 55 static intptr_t ToInstructionStart(intptr_t pos) {
61 return (pos & ~1); 56 return (pos & ~1);
62 } 57 }
63 58
64
65 static intptr_t ToInstructionEnd(intptr_t pos) { 59 static intptr_t ToInstructionEnd(intptr_t pos) {
66 return (pos | 1); 60 return (pos | 1);
67 } 61 }
68 62
69
70 FlowGraphAllocator::FlowGraphAllocator(const FlowGraph& flow_graph, 63 FlowGraphAllocator::FlowGraphAllocator(const FlowGraph& flow_graph,
71 bool intrinsic_mode) 64 bool intrinsic_mode)
72 : flow_graph_(flow_graph), 65 : flow_graph_(flow_graph),
73 reaching_defs_(flow_graph), 66 reaching_defs_(flow_graph),
74 value_representations_(flow_graph.max_virtual_register_number()), 67 value_representations_(flow_graph.max_virtual_register_number()),
75 block_order_(flow_graph.reverse_postorder()), 68 block_order_(flow_graph.reverse_postorder()),
76 postorder_(flow_graph.postorder()), 69 postorder_(flow_graph.postorder()),
77 liveness_(flow_graph), 70 liveness_(flow_graph),
78 vreg_count_(flow_graph.max_virtual_register_number()), 71 vreg_count_(flow_graph.max_virtual_register_number()),
79 live_ranges_(flow_graph.max_virtual_register_number()), 72 live_ranges_(flow_graph.max_virtual_register_number()),
(...skipping 30 matching lines...) Expand all
110 if (intrinsic_mode) { 103 if (intrinsic_mode) {
111 blocked_cpu_registers_[ARGS_DESC_REG] = true; 104 blocked_cpu_registers_[ARGS_DESC_REG] = true;
112 #if !defined(TARGET_ARCH_IA32) 105 #if !defined(TARGET_ARCH_IA32)
113 // Need to preserve CODE_REG to be able to store the PC marker 106 // Need to preserve CODE_REG to be able to store the PC marker
114 // and load the pool pointer. 107 // and load the pool pointer.
115 blocked_cpu_registers_[CODE_REG] = true; 108 blocked_cpu_registers_[CODE_REG] = true;
116 #endif 109 #endif
117 } 110 }
118 } 111 }
119 112
120
121 static void DeepLiveness(MaterializeObjectInstr* mat, BitVector* live_in) { 113 static void DeepLiveness(MaterializeObjectInstr* mat, BitVector* live_in) {
122 if (mat->was_visited_for_liveness()) { 114 if (mat->was_visited_for_liveness()) {
123 return; 115 return;
124 } 116 }
125 mat->mark_visited_for_liveness(); 117 mat->mark_visited_for_liveness();
126 118
127 for (intptr_t i = 0; i < mat->InputCount(); i++) { 119 for (intptr_t i = 0; i < mat->InputCount(); i++) {
128 if (!mat->InputAt(i)->BindsToConstant()) { 120 if (!mat->InputAt(i)->BindsToConstant()) {
129 Definition* defn = mat->InputAt(i)->definition(); 121 Definition* defn = mat->InputAt(i)->definition();
130 MaterializeObjectInstr* inner_mat = defn->AsMaterializeObject(); 122 MaterializeObjectInstr* inner_mat = defn->AsMaterializeObject();
131 if (inner_mat != NULL) { 123 if (inner_mat != NULL) {
132 DeepLiveness(inner_mat, live_in); 124 DeepLiveness(inner_mat, live_in);
133 } else { 125 } else {
134 intptr_t idx = defn->ssa_temp_index(); 126 intptr_t idx = defn->ssa_temp_index();
135 live_in->Add(idx); 127 live_in->Add(idx);
136 } 128 }
137 } 129 }
138 } 130 }
139 } 131 }
140 132
141
142 void SSALivenessAnalysis::ComputeInitialSets() { 133 void SSALivenessAnalysis::ComputeInitialSets() {
143 const intptr_t block_count = postorder_.length(); 134 const intptr_t block_count = postorder_.length();
144 for (intptr_t i = 0; i < block_count; i++) { 135 for (intptr_t i = 0; i < block_count; i++) {
145 BlockEntryInstr* block = postorder_[i]; 136 BlockEntryInstr* block = postorder_[i];
146 137
147 BitVector* kill = kill_[i]; 138 BitVector* kill = kill_[i];
148 BitVector* live_in = live_in_[i]; 139 BitVector* live_in = live_in_[i];
149 140
150 // Iterate backwards starting at the last instruction. 141 // Iterate backwards starting at the last instruction.
151 for (BackwardInstructionIterator it(block); !it.Done(); it.Advance()) { 142 for (BackwardInstructionIterator it(block); !it.Done(); it.Advance()) {
(...skipping 108 matching lines...) Expand 10 before | Expand all | Expand 10 after
260 251
261 // Process initial definitions, ie, constants and incoming parameters. 252 // Process initial definitions, ie, constants and incoming parameters.
262 for (intptr_t i = 0; i < graph_entry_->initial_definitions()->length(); i++) { 253 for (intptr_t i = 0; i < graph_entry_->initial_definitions()->length(); i++) {
263 Definition* def = (*graph_entry_->initial_definitions())[i]; 254 Definition* def = (*graph_entry_->initial_definitions())[i];
264 const intptr_t vreg = def->ssa_temp_index(); 255 const intptr_t vreg = def->ssa_temp_index();
265 kill_[graph_entry_->postorder_number()]->Add(vreg); 256 kill_[graph_entry_->postorder_number()]->Add(vreg);
266 live_in_[graph_entry_->postorder_number()]->Remove(vreg); 257 live_in_[graph_entry_->postorder_number()]->Remove(vreg);
267 } 258 }
268 } 259 }
269 260
270
271 UsePosition* LiveRange::AddUse(intptr_t pos, Location* location_slot) { 261 UsePosition* LiveRange::AddUse(intptr_t pos, Location* location_slot) {
272 ASSERT(location_slot != NULL); 262 ASSERT(location_slot != NULL);
273 ASSERT((first_use_interval_->start_ <= pos) && 263 ASSERT((first_use_interval_->start_ <= pos) &&
274 (pos <= first_use_interval_->end_)); 264 (pos <= first_use_interval_->end_));
275 if (uses_ != NULL) { 265 if (uses_ != NULL) {
276 if ((uses_->pos() == pos) && (uses_->location_slot() == location_slot)) { 266 if ((uses_->pos() == pos) && (uses_->location_slot() == location_slot)) {
277 return uses_; 267 return uses_;
278 } else if (uses_->pos() < pos) { 268 } else if (uses_->pos() < pos) {
279 // If an instruction at position P is using the same value both as 269 // If an instruction at position P is using the same value both as
280 // a fixed register input and a non-fixed input (in this order) we will 270 // a fixed register input and a non-fixed input (in this order) we will
(...skipping 15 matching lines...) Expand all
296 286
297 insert_after->set_next( 287 insert_after->set_next(
298 new UsePosition(pos, insert_after->next(), location_slot)); 288 new UsePosition(pos, insert_after->next(), location_slot));
299 return insert_after->next(); 289 return insert_after->next();
300 } 290 }
301 } 291 }
302 uses_ = new UsePosition(pos, uses_, location_slot); 292 uses_ = new UsePosition(pos, uses_, location_slot);
303 return uses_; 293 return uses_;
304 } 294 }
305 295
306
307 void LiveRange::AddSafepoint(intptr_t pos, LocationSummary* locs) { 296 void LiveRange::AddSafepoint(intptr_t pos, LocationSummary* locs) {
308 ASSERT(IsInstructionStartPosition(pos)); 297 ASSERT(IsInstructionStartPosition(pos));
309 SafepointPosition* safepoint = 298 SafepointPosition* safepoint =
310 new SafepointPosition(ToInstructionEnd(pos), locs); 299 new SafepointPosition(ToInstructionEnd(pos), locs);
311 300
312 if (first_safepoint_ == NULL) { 301 if (first_safepoint_ == NULL) {
313 ASSERT(last_safepoint_ == NULL); 302 ASSERT(last_safepoint_ == NULL);
314 first_safepoint_ = last_safepoint_ = safepoint; 303 first_safepoint_ = last_safepoint_ = safepoint;
315 } else { 304 } else {
316 ASSERT(last_safepoint_ != NULL); 305 ASSERT(last_safepoint_ != NULL);
317 // We assume that safepoints list is sorted by position and that 306 // We assume that safepoints list is sorted by position and that
318 // safepoints are added in this order. 307 // safepoints are added in this order.
319 ASSERT(last_safepoint_->pos() < pos); 308 ASSERT(last_safepoint_->pos() < pos);
320 last_safepoint_->set_next(safepoint); 309 last_safepoint_->set_next(safepoint);
321 last_safepoint_ = safepoint; 310 last_safepoint_ = safepoint;
322 } 311 }
323 } 312 }
324 313
325
326 void LiveRange::AddHintedUse(intptr_t pos, 314 void LiveRange::AddHintedUse(intptr_t pos,
327 Location* location_slot, 315 Location* location_slot,
328 Location* hint) { 316 Location* hint) {
329 ASSERT(hint != NULL); 317 ASSERT(hint != NULL);
330 AddUse(pos, location_slot)->set_hint(hint); 318 AddUse(pos, location_slot)->set_hint(hint);
331 } 319 }
332 320
333
334 void LiveRange::AddUseInterval(intptr_t start, intptr_t end) { 321 void LiveRange::AddUseInterval(intptr_t start, intptr_t end) {
335 ASSERT(start < end); 322 ASSERT(start < end);
336 323
337 // Live ranges are being build by visiting instructions in post-order. 324 // Live ranges are being build by visiting instructions in post-order.
338 // This implies that use intervals will be prepended in a monotonically 325 // This implies that use intervals will be prepended in a monotonically
339 // decreasing order. 326 // decreasing order.
340 if (first_use_interval() != NULL) { 327 if (first_use_interval() != NULL) {
341 // If the first use interval and the use interval we are adding 328 // If the first use interval and the use interval we are adding
342 // touch then we can just extend the first interval to cover their 329 // touch then we can just extend the first interval to cover their
343 // union. 330 // union.
(...skipping 16 matching lines...) Expand all
360 ASSERT(end < first_use_interval()->start()); 347 ASSERT(end < first_use_interval()->start());
361 } 348 }
362 349
363 first_use_interval_ = new UseInterval(start, end, first_use_interval_); 350 first_use_interval_ = new UseInterval(start, end, first_use_interval_);
364 if (last_use_interval_ == NULL) { 351 if (last_use_interval_ == NULL) {
365 ASSERT(first_use_interval_->next() == NULL); 352 ASSERT(first_use_interval_->next() == NULL);
366 last_use_interval_ = first_use_interval_; 353 last_use_interval_ = first_use_interval_;
367 } 354 }
368 } 355 }
369 356
370
371 void LiveRange::DefineAt(intptr_t pos) { 357 void LiveRange::DefineAt(intptr_t pos) {
372 // Live ranges are being build by visiting instructions in post-order. 358 // Live ranges are being build by visiting instructions in post-order.
373 // This implies that use intervals will be prepended in a monotonically 359 // This implies that use intervals will be prepended in a monotonically
374 // decreasing order. 360 // decreasing order.
375 // When we encounter a use of a value inside a block we optimistically 361 // When we encounter a use of a value inside a block we optimistically
376 // expand the first use interval to cover the block from the start 362 // expand the first use interval to cover the block from the start
377 // to the last use in the block and then we shrink it if we encounter 363 // to the last use in the block and then we shrink it if we encounter
378 // definition of the value inside the same block. 364 // definition of the value inside the same block.
379 if (first_use_interval_ == NULL) { 365 if (first_use_interval_ == NULL) {
380 // Definition without a use. 366 // Definition without a use.
381 first_use_interval_ = new UseInterval(pos, pos + 1, NULL); 367 first_use_interval_ = new UseInterval(pos, pos + 1, NULL);
382 last_use_interval_ = first_use_interval_; 368 last_use_interval_ = first_use_interval_;
383 } else { 369 } else {
384 // Shrink the first use interval. It was optimistically expanded to 370 // Shrink the first use interval. It was optimistically expanded to
385 // cover the block from the start to the last use in the block. 371 // cover the block from the start to the last use in the block.
386 ASSERT(first_use_interval_->start_ <= pos); 372 ASSERT(first_use_interval_->start_ <= pos);
387 first_use_interval_->start_ = pos; 373 first_use_interval_->start_ = pos;
388 } 374 }
389 } 375 }
390 376
391
392 LiveRange* FlowGraphAllocator::GetLiveRange(intptr_t vreg) { 377 LiveRange* FlowGraphAllocator::GetLiveRange(intptr_t vreg) {
393 if (live_ranges_[vreg] == NULL) { 378 if (live_ranges_[vreg] == NULL) {
394 Representation rep = value_representations_[vreg]; 379 Representation rep = value_representations_[vreg];
395 ASSERT(rep != kNoRepresentation); 380 ASSERT(rep != kNoRepresentation);
396 live_ranges_[vreg] = new LiveRange(vreg, rep); 381 live_ranges_[vreg] = new LiveRange(vreg, rep);
397 } 382 }
398 return live_ranges_[vreg]; 383 return live_ranges_[vreg];
399 } 384 }
400 385
401
402 LiveRange* FlowGraphAllocator::MakeLiveRangeForTemporary() { 386 LiveRange* FlowGraphAllocator::MakeLiveRangeForTemporary() {
403 // Representation does not matter for temps. 387 // Representation does not matter for temps.
404 Representation ignored = kNoRepresentation; 388 Representation ignored = kNoRepresentation;
405 LiveRange* range = new LiveRange(kTempVirtualRegister, ignored); 389 LiveRange* range = new LiveRange(kTempVirtualRegister, ignored);
406 #if defined(DEBUG) 390 #if defined(DEBUG)
407 temporaries_.Add(range); 391 temporaries_.Add(range);
408 #endif 392 #endif
409 return range; 393 return range;
410 } 394 }
411 395
412
413 void FlowGraphAllocator::BlockRegisterLocation(Location loc, 396 void FlowGraphAllocator::BlockRegisterLocation(Location loc,
414 intptr_t from, 397 intptr_t from,
415 intptr_t to, 398 intptr_t to,
416 bool* blocked_registers, 399 bool* blocked_registers,
417 LiveRange** blocking_ranges) { 400 LiveRange** blocking_ranges) {
418 if (blocked_registers[loc.register_code()]) { 401 if (blocked_registers[loc.register_code()]) {
419 return; 402 return;
420 } 403 }
421 404
422 if (blocking_ranges[loc.register_code()] == NULL) { 405 if (blocking_ranges[loc.register_code()] == NULL) {
423 Representation ignored = kNoRepresentation; 406 Representation ignored = kNoRepresentation;
424 LiveRange* range = new LiveRange(kNoVirtualRegister, ignored); 407 LiveRange* range = new LiveRange(kNoVirtualRegister, ignored);
425 blocking_ranges[loc.register_code()] = range; 408 blocking_ranges[loc.register_code()] = range;
426 range->set_assigned_location(loc); 409 range->set_assigned_location(loc);
427 #if defined(DEBUG) 410 #if defined(DEBUG)
428 temporaries_.Add(range); 411 temporaries_.Add(range);
429 #endif 412 #endif
430 } 413 }
431 414
432 blocking_ranges[loc.register_code()]->AddUseInterval(from, to); 415 blocking_ranges[loc.register_code()]->AddUseInterval(from, to);
433 } 416 }
434 417
435
436 // Block location from the start of the instruction to its end. 418 // Block location from the start of the instruction to its end.
437 void FlowGraphAllocator::BlockLocation(Location loc, 419 void FlowGraphAllocator::BlockLocation(Location loc,
438 intptr_t from, 420 intptr_t from,
439 intptr_t to) { 421 intptr_t to) {
440 if (loc.IsRegister()) { 422 if (loc.IsRegister()) {
441 BlockRegisterLocation(loc, from, to, blocked_cpu_registers_, cpu_regs_); 423 BlockRegisterLocation(loc, from, to, blocked_cpu_registers_, cpu_regs_);
442 #if defined(TARGET_ARCH_DBC) 424 #if defined(TARGET_ARCH_DBC)
443 last_used_register_ = 425 last_used_register_ =
444 Utils::Maximum(last_used_register_, loc.register_code()); 426 Utils::Maximum(last_used_register_, loc.register_code());
445 #endif 427 #endif
446 } else if (loc.IsFpuRegister()) { 428 } else if (loc.IsFpuRegister()) {
447 BlockRegisterLocation(loc, from, to, blocked_fpu_registers_, fpu_regs_); 429 BlockRegisterLocation(loc, from, to, blocked_fpu_registers_, fpu_regs_);
448 } else { 430 } else {
449 UNREACHABLE(); 431 UNREACHABLE();
450 } 432 }
451 } 433 }
452 434
453
454 void LiveRange::Print() { 435 void LiveRange::Print() {
455 if (first_use_interval() == NULL) { 436 if (first_use_interval() == NULL) {
456 return; 437 return;
457 } 438 }
458 439
459 THR_Print(" live range v%" Pd " [%" Pd ", %" Pd ") in ", vreg(), Start(), 440 THR_Print(" live range v%" Pd " [%" Pd ", %" Pd ") in ", vreg(), Start(),
460 End()); 441 End());
461 assigned_location().Print(); 442 assigned_location().Print();
462 if (spill_slot_.HasStackIndex()) { 443 if (spill_slot_.HasStackIndex()) {
463 intptr_t stack_slot = spill_slot_.stack_index(); 444 intptr_t stack_slot = spill_slot_.stack_index();
(...skipping 23 matching lines...) Expand all
487 THR_Print("\n"); 468 THR_Print("\n");
488 use_pos = use_pos->next(); 469 use_pos = use_pos->next();
489 } 470 }
490 } 471 }
491 472
492 if (next_sibling() != NULL) { 473 if (next_sibling() != NULL) {
493 next_sibling()->Print(); 474 next_sibling()->Print();
494 } 475 }
495 } 476 }
496 477
497
498 void FlowGraphAllocator::PrintLiveRanges() { 478 void FlowGraphAllocator::PrintLiveRanges() {
499 #if defined(DEBUG) 479 #if defined(DEBUG)
500 for (intptr_t i = 0; i < temporaries_.length(); i++) { 480 for (intptr_t i = 0; i < temporaries_.length(); i++) {
501 temporaries_[i]->Print(); 481 temporaries_[i]->Print();
502 } 482 }
503 #endif 483 #endif
504 484
505 for (intptr_t i = 0; i < live_ranges_.length(); i++) { 485 for (intptr_t i = 0; i < live_ranges_.length(); i++) {
506 if (live_ranges_[i] != NULL) { 486 if (live_ranges_[i] != NULL) {
507 live_ranges_[i]->Print(); 487 live_ranges_[i]->Print();
508 } 488 }
509 } 489 }
510 } 490 }
511 491
512
513 // Returns true if all uses of the given range inside the given loop 492 // Returns true if all uses of the given range inside the given loop
514 // have Any allocation policy. 493 // have Any allocation policy.
515 static bool HasOnlyUnconstrainedUsesInLoop(LiveRange* range, 494 static bool HasOnlyUnconstrainedUsesInLoop(LiveRange* range,
516 BlockInfo* loop_header) { 495 BlockInfo* loop_header) {
517 const intptr_t boundary = loop_header->last_block()->end_pos(); 496 const intptr_t boundary = loop_header->last_block()->end_pos();
518 497
519 UsePosition* use = range->first_use(); 498 UsePosition* use = range->first_use();
520 while ((use != NULL) && (use->pos() < boundary)) { 499 while ((use != NULL) && (use->pos() < boundary)) {
521 if (!use->location_slot()->Equals(Location::Any())) { 500 if (!use->location_slot()->Equals(Location::Any())) {
522 return false; 501 return false;
523 } 502 }
524 use = use->next(); 503 use = use->next();
525 } 504 }
526 505
527 return true; 506 return true;
528 } 507 }
529 508
530
531 // Returns true if all uses of the given range have Any allocation policy. 509 // Returns true if all uses of the given range have Any allocation policy.
532 static bool HasOnlyUnconstrainedUses(LiveRange* range) { 510 static bool HasOnlyUnconstrainedUses(LiveRange* range) {
533 UsePosition* use = range->first_use(); 511 UsePosition* use = range->first_use();
534 while (use != NULL) { 512 while (use != NULL) {
535 if (!use->location_slot()->Equals(Location::Any())) { 513 if (!use->location_slot()->Equals(Location::Any())) {
536 return false; 514 return false;
537 } 515 }
538 use = use->next(); 516 use = use->next();
539 } 517 }
540 return true; 518 return true;
541 } 519 }
542 520
543
544 void FlowGraphAllocator::BuildLiveRanges() { 521 void FlowGraphAllocator::BuildLiveRanges() {
545 const intptr_t block_count = postorder_.length(); 522 const intptr_t block_count = postorder_.length();
546 ASSERT(postorder_.Last()->IsGraphEntry()); 523 ASSERT(postorder_.Last()->IsGraphEntry());
547 BitVector* current_interference_set = NULL; 524 BitVector* current_interference_set = NULL;
548 Zone* zone = flow_graph_.zone(); 525 Zone* zone = flow_graph_.zone();
549 for (intptr_t i = 0; i < (block_count - 1); i++) { 526 for (intptr_t i = 0; i < (block_count - 1); i++) {
550 BlockEntryInstr* block = postorder_[i]; 527 BlockEntryInstr* block = postorder_[i];
551 528
552 BlockInfo* block_info = BlockInfoAt(block->start_pos()); 529 BlockInfo* block_info = BlockInfoAt(block->start_pos());
553 530
(...skipping 25 matching lines...) Expand all
579 556
580 // Now process all instructions in reverse order. 557 // Now process all instructions in reverse order.
581 while (current != block) { 558 while (current != block) {
582 // Skip parallel moves that we insert while processing instructions. 559 // Skip parallel moves that we insert while processing instructions.
583 if (!current->IsParallelMove()) { 560 if (!current->IsParallelMove()) {
584 ProcessOneInstruction(block, current, current_interference_set); 561 ProcessOneInstruction(block, current, current_interference_set);
585 } 562 }
586 current = current->previous(); 563 current = current->previous();
587 } 564 }
588 565
589
590 // Check if any values live into the loop can be spilled for free. 566 // Check if any values live into the loop can be spilled for free.
591 if (block_info->is_loop_header()) { 567 if (block_info->is_loop_header()) {
592 current_interference_set = NULL; 568 current_interference_set = NULL;
593 for (BitVector::Iterator it(liveness_.GetLiveInSetAt(i)); !it.Done(); 569 for (BitVector::Iterator it(liveness_.GetLiveInSetAt(i)); !it.Done();
594 it.Advance()) { 570 it.Advance()) {
595 LiveRange* range = GetLiveRange(it.Current()); 571 LiveRange* range = GetLiveRange(it.Current());
596 if (HasOnlyUnconstrainedUsesInLoop(range, block_info)) { 572 if (HasOnlyUnconstrainedUsesInLoop(range, block_info)) {
597 range->MarkHasOnlyUnconstrainedUsesInLoop(block_info->loop_id()); 573 range->MarkHasOnlyUnconstrainedUsesInLoop(block_info->loop_id());
598 } 574 }
599 } 575 }
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
640 for (intptr_t i = 0; i < graph_entry->initial_definitions()->length(); i++) { 616 for (intptr_t i = 0; i < graph_entry->initial_definitions()->length(); i++) {
641 Definition* defn = (*graph_entry->initial_definitions())[i]; 617 Definition* defn = (*graph_entry->initial_definitions())[i];
642 ASSERT(!defn->HasPairRepresentation()); 618 ASSERT(!defn->HasPairRepresentation());
643 LiveRange* range = GetLiveRange(defn->ssa_temp_index()); 619 LiveRange* range = GetLiveRange(defn->ssa_temp_index());
644 range->AddUseInterval(graph_entry->start_pos(), graph_entry->end_pos()); 620 range->AddUseInterval(graph_entry->start_pos(), graph_entry->end_pos());
645 range->DefineAt(graph_entry->start_pos()); 621 range->DefineAt(graph_entry->start_pos());
646 ProcessInitialDefinition(defn, range, graph_entry); 622 ProcessInitialDefinition(defn, range, graph_entry);
647 } 623 }
648 } 624 }
649 625
650
651 void FlowGraphAllocator::SplitInitialDefinitionAt(LiveRange* range, 626 void FlowGraphAllocator::SplitInitialDefinitionAt(LiveRange* range,
652 intptr_t pos) { 627 intptr_t pos) {
653 if (range->End() > pos) { 628 if (range->End() > pos) {
654 LiveRange* tail = range->SplitAt(pos); 629 LiveRange* tail = range->SplitAt(pos);
655 CompleteRange(tail, Location::kRegister); 630 CompleteRange(tail, Location::kRegister);
656 } 631 }
657 } 632 }
658 633
659
660 void FlowGraphAllocator::ProcessInitialDefinition(Definition* defn, 634 void FlowGraphAllocator::ProcessInitialDefinition(Definition* defn,
661 LiveRange* range, 635 LiveRange* range,
662 BlockEntryInstr* block) { 636 BlockEntryInstr* block) {
663 #if defined(TARGET_ARCH_DBC) 637 #if defined(TARGET_ARCH_DBC)
664 if (block->IsCatchBlockEntry()) { 638 if (block->IsCatchBlockEntry()) {
665 if (defn->IsParameter()) { 639 if (defn->IsParameter()) {
666 // This must be in sync with FlowGraphCompiler::CatchEntryRegForVariable. 640 // This must be in sync with FlowGraphCompiler::CatchEntryRegForVariable.
667 ParameterInstr* param = defn->AsParameter(); 641 ParameterInstr* param = defn->AsParameter();
668 intptr_t slot_index = param->index(); 642 intptr_t slot_index = param->index();
669 AssignSafepoints(defn, range); 643 AssignSafepoints(defn, range);
(...skipping 110 matching lines...) Expand 10 before | Expand all | Expand 10 after
780 // Note, all incoming parameters are assumed to be tagged. 754 // Note, all incoming parameters are assumed to be tagged.
781 MarkAsObjectAtSafepoints(range); 755 MarkAsObjectAtSafepoints(range);
782 } else if (defn->IsConstant() && block->IsCatchBlockEntry()) { 756 } else if (defn->IsConstant() && block->IsCatchBlockEntry()) {
783 // Constants at catch block entries consume spill slots. 757 // Constants at catch block entries consume spill slots.
784 spill_slots_.Add(range_end); 758 spill_slots_.Add(range_end);
785 quad_spill_slots_.Add(false); 759 quad_spill_slots_.Add(false);
786 untagged_spill_slots_.Add(false); 760 untagged_spill_slots_.Add(false);
787 } 761 }
788 } 762 }
789 763
790
791 static Location::Kind RegisterKindFromPolicy(Location loc) { 764 static Location::Kind RegisterKindFromPolicy(Location loc) {
792 if (loc.policy() == Location::kRequiresFpuRegister) { 765 if (loc.policy() == Location::kRequiresFpuRegister) {
793 return Location::kFpuRegister; 766 return Location::kFpuRegister;
794 } else { 767 } else {
795 return Location::kRegister; 768 return Location::kRegister;
796 } 769 }
797 } 770 }
798 771
799
800 static Location::Kind RegisterKindForResult(Instruction* instr) { 772 static Location::Kind RegisterKindForResult(Instruction* instr) {
801 const Representation rep = instr->representation(); 773 const Representation rep = instr->representation();
802 #if !defined(TARGET_ARCH_DBC) 774 #if !defined(TARGET_ARCH_DBC)
803 if ((rep == kUnboxedDouble) || (rep == kUnboxedFloat32x4) || 775 if ((rep == kUnboxedDouble) || (rep == kUnboxedFloat32x4) ||
804 (rep == kUnboxedInt32x4) || (rep == kUnboxedFloat64x2)) { 776 (rep == kUnboxedInt32x4) || (rep == kUnboxedFloat64x2)) {
805 return Location::kFpuRegister; 777 return Location::kFpuRegister;
806 } else { 778 } else {
807 return Location::kRegister; 779 return Location::kRegister;
808 } 780 }
809 #else 781 #else
810 // DBC supports only unboxed doubles and does not have distinguished FPU 782 // DBC supports only unboxed doubles and does not have distinguished FPU
811 // registers. 783 // registers.
812 ASSERT((rep != kUnboxedFloat32x4) && (rep != kUnboxedInt32x4) && 784 ASSERT((rep != kUnboxedFloat32x4) && (rep != kUnboxedInt32x4) &&
813 (rep != kUnboxedFloat64x2)); 785 (rep != kUnboxedFloat64x2));
814 return Location::kRegister; 786 return Location::kRegister;
815 #endif 787 #endif
816 } 788 }
817 789
818
819 // 790 //
820 // When describing shape of live ranges in comments below we are going to use 791 // When describing shape of live ranges in comments below we are going to use
821 // the following notation: 792 // the following notation:
822 // 793 //
823 // B block entry 794 // B block entry
824 // g g' start and end of goto instruction 795 // g g' start and end of goto instruction
825 // i i' start and end of any other instruction 796 // i i' start and end of any other instruction
826 // j j' start and end of any other instruction 797 // j j' start and end of any other instruction
827 798
828 // - body of a use interval 799 // - body of a use interval
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after
906 ->assigned_location_slot()); 877 ->assigned_location_slot());
907 move->set_src(Location::PrefersRegister()); 878 move->set_src(Location::PrefersRegister());
908 } 879 }
909 } 880 }
910 881
911 // Begin backward iteration with the instruction before the parallel 882 // Begin backward iteration with the instruction before the parallel
912 // move. 883 // move.
913 return goto_instr->previous(); 884 return goto_instr->previous();
914 } 885 }
915 886
916
917 void FlowGraphAllocator::ConnectIncomingPhiMoves(JoinEntryInstr* join) { 887 void FlowGraphAllocator::ConnectIncomingPhiMoves(JoinEntryInstr* join) {
918 // For join blocks we need to add destinations of phi resolution moves 888 // For join blocks we need to add destinations of phi resolution moves
919 // to phi's live range so that register allocator will fill them with moves. 889 // to phi's live range so that register allocator will fill them with moves.
920 890
921 // All uses are recorded at the start position in the block. 891 // All uses are recorded at the start position in the block.
922 const intptr_t pos = join->start_pos(); 892 const intptr_t pos = join->start_pos();
923 const bool is_loop_header = BlockInfoAt(join->start_pos())->is_loop_header(); 893 const bool is_loop_header = BlockInfoAt(join->start_pos())->is_loop_header();
924 intptr_t move_idx = 0; 894 intptr_t move_idx = 0;
925 for (PhiIterator it(join); !it.Done(); it.Advance()) { 895 for (PhiIterator it(join); !it.Done(); it.Advance()) {
926 PhiInstr* phi = it.Current(); 896 PhiInstr* phi = it.Current();
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
968 if (is_pair_phi) { 938 if (is_pair_phi) {
969 LiveRange* second_range = GetLiveRange(ToSecondPairVreg(vreg)); 939 LiveRange* second_range = GetLiveRange(ToSecondPairVreg(vreg));
970 AssignSafepoints(phi, second_range); 940 AssignSafepoints(phi, second_range);
971 CompleteRange(second_range, RegisterKindForResult(phi)); 941 CompleteRange(second_range, RegisterKindForResult(phi));
972 } 942 }
973 943
974 move_idx += is_pair_phi ? 2 : 1; 944 move_idx += is_pair_phi ? 2 : 1;
975 } 945 }
976 } 946 }
977 947
978
979 void FlowGraphAllocator::ProcessEnvironmentUses(BlockEntryInstr* block, 948 void FlowGraphAllocator::ProcessEnvironmentUses(BlockEntryInstr* block,
980 Instruction* current) { 949 Instruction* current) {
981 ASSERT(current->env() != NULL); 950 ASSERT(current->env() != NULL);
982 Environment* env = current->env(); 951 Environment* env = current->env();
983 while (env != NULL) { 952 while (env != NULL) {
984 // Any value mentioned in the deoptimization environment should survive 953 // Any value mentioned in the deoptimization environment should survive
985 // until the end of instruction but it does not need to be in the register. 954 // until the end of instruction but it does not need to be in the register.
986 // Expected shape of live range: 955 // Expected shape of live range:
987 // 956 //
988 // i i' 957 // i i'
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after
1050 range->AddUseInterval(block_start_pos, use_pos); 1019 range->AddUseInterval(block_start_pos, use_pos);
1051 range->AddUse(use_pos, &locations[i]); 1020 range->AddUse(use_pos, &locations[i]);
1052 } 1021 }
1053 } 1022 }
1054 1023
1055 env->set_locations(locations); 1024 env->set_locations(locations);
1056 env = env->outer(); 1025 env = env->outer();
1057 } 1026 }
1058 } 1027 }
1059 1028
1060
1061 void FlowGraphAllocator::ProcessMaterializationUses( 1029 void FlowGraphAllocator::ProcessMaterializationUses(
1062 BlockEntryInstr* block, 1030 BlockEntryInstr* block,
1063 const intptr_t block_start_pos, 1031 const intptr_t block_start_pos,
1064 const intptr_t use_pos, 1032 const intptr_t use_pos,
1065 MaterializeObjectInstr* mat) { 1033 MaterializeObjectInstr* mat) {
1066 // Materialization can occur several times in the same environment. 1034 // Materialization can occur several times in the same environment.
1067 // Check if we already processed this one. 1035 // Check if we already processed this one.
1068 if (mat->locations() != NULL) { 1036 if (mat->locations() != NULL) {
1069 return; // Already processed. 1037 return; // Already processed.
1070 } 1038 }
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
1104 def->AsMaterializeObject()); 1072 def->AsMaterializeObject());
1105 } else { 1073 } else {
1106 locations[i] = Location::Any(); 1074 locations[i] = Location::Any();
1107 LiveRange* range = GetLiveRange(def->ssa_temp_index()); 1075 LiveRange* range = GetLiveRange(def->ssa_temp_index());
1108 range->AddUseInterval(block_start_pos, use_pos); 1076 range->AddUseInterval(block_start_pos, use_pos);
1109 range->AddUse(use_pos, &locations[i]); 1077 range->AddUse(use_pos, &locations[i]);
1110 } 1078 }
1111 } 1079 }
1112 } 1080 }
1113 1081
1114
1115 void FlowGraphAllocator::ProcessOneInput(BlockEntryInstr* block, 1082 void FlowGraphAllocator::ProcessOneInput(BlockEntryInstr* block,
1116 intptr_t pos, 1083 intptr_t pos,
1117 Location* in_ref, 1084 Location* in_ref,
1118 Value* input, 1085 Value* input,
1119 intptr_t vreg, 1086 intptr_t vreg,
1120 RegisterSet* live_registers) { 1087 RegisterSet* live_registers) {
1121 ASSERT(in_ref != NULL); 1088 ASSERT(in_ref != NULL);
1122 ASSERT(!in_ref->IsPairLocation()); 1089 ASSERT(!in_ref->IsPairLocation());
1123 ASSERT(input != NULL); 1090 ASSERT(input != NULL);
1124 ASSERT(block != NULL); 1091 ASSERT(block != NULL);
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after
1168 // value -----* 1135 // value -----*
1169 // 1136 //
1170 range->AddUseInterval(block->start_pos(), pos + 1); 1137 range->AddUseInterval(block->start_pos(), pos + 1);
1171 range->AddUse(pos + 1, in_ref); 1138 range->AddUse(pos + 1, in_ref);
1172 } 1139 }
1173 } else { 1140 } else {
1174 ASSERT(in_ref->IsConstant()); 1141 ASSERT(in_ref->IsConstant());
1175 } 1142 }
1176 } 1143 }
1177 1144
1178
1179 void FlowGraphAllocator::ProcessOneOutput(BlockEntryInstr* block, 1145 void FlowGraphAllocator::ProcessOneOutput(BlockEntryInstr* block,
1180 intptr_t pos, 1146 intptr_t pos,
1181 Location* out, 1147 Location* out,
1182 Definition* def, 1148 Definition* def,
1183 intptr_t vreg, 1149 intptr_t vreg,
1184 bool output_same_as_first_input, 1150 bool output_same_as_first_input,
1185 Location* in_ref, 1151 Location* in_ref,
1186 Definition* input, 1152 Definition* input,
1187 intptr_t input_vreg, 1153 intptr_t input_vreg,
1188 BitVector* interference_set) { 1154 BitVector* interference_set) {
(...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after
1276 // Shorten live range to the point of definition and add use to be filled by 1242 // Shorten live range to the point of definition and add use to be filled by
1277 // allocator. 1243 // allocator.
1278 range->DefineAt(pos); 1244 range->DefineAt(pos);
1279 range->AddUse(pos, out); 1245 range->AddUse(pos, out);
1280 } 1246 }
1281 1247
1282 AssignSafepoints(def, range); 1248 AssignSafepoints(def, range);
1283 CompleteRange(range, RegisterKindForResult(def)); 1249 CompleteRange(range, RegisterKindForResult(def));
1284 } 1250 }
1285 1251
1286
1287 // Create and update live ranges corresponding to instruction's inputs, 1252 // Create and update live ranges corresponding to instruction's inputs,
1288 // temporaries and output. 1253 // temporaries and output.
1289 void FlowGraphAllocator::ProcessOneInstruction(BlockEntryInstr* block, 1254 void FlowGraphAllocator::ProcessOneInstruction(BlockEntryInstr* block,
1290 Instruction* current, 1255 Instruction* current,
1291 BitVector* interference_set) { 1256 BitVector* interference_set) {
1292 LocationSummary* locs = current->locs(); 1257 LocationSummary* locs = current->locs();
1293 1258
1294 Definition* def = current->AsDefinition(); 1259 Definition* def = current->AsDefinition();
1295 if ((def != NULL) && (def->AsConstant() != NULL)) { 1260 if ((def != NULL) && (def->AsConstant() != NULL)) {
1296 ASSERT(!def->HasPairRepresentation()); 1261 ASSERT(!def->HasPairRepresentation());
(...skipping 129 matching lines...) Expand 10 before | Expand all | Expand 10 after
1426 BlockLocation(Location::RegisterLocation(static_cast<Register>(reg)), pos, 1391 BlockLocation(Location::RegisterLocation(static_cast<Register>(reg)), pos,
1427 pos + 1); 1392 pos + 1);
1428 } 1393 }
1429 1394
1430 for (intptr_t reg = 0; reg < kNumberOfFpuRegisters; reg++) { 1395 for (intptr_t reg = 0; reg < kNumberOfFpuRegisters; reg++) {
1431 BlockLocation( 1396 BlockLocation(
1432 Location::FpuRegisterLocation(static_cast<FpuRegister>(reg)), pos, 1397 Location::FpuRegisterLocation(static_cast<FpuRegister>(reg)), pos,
1433 pos + 1); 1398 pos + 1);
1434 } 1399 }
1435 1400
1436
1437 #if defined(DEBUG) 1401 #if defined(DEBUG)
1438 // Verify that temps, inputs and output were specified as fixed 1402 // Verify that temps, inputs and output were specified as fixed
1439 // locations. Every register is blocked now so attempt to 1403 // locations. Every register is blocked now so attempt to
1440 // allocate will not succeed. 1404 // allocate will not succeed.
1441 for (intptr_t j = 0; j < locs->temp_count(); j++) { 1405 for (intptr_t j = 0; j < locs->temp_count(); j++) {
1442 ASSERT(!locs->temp(j).IsPairLocation()); 1406 ASSERT(!locs->temp(j).IsPairLocation());
1443 ASSERT(!locs->temp(j).IsUnallocated()); 1407 ASSERT(!locs->temp(j).IsUnallocated());
1444 } 1408 }
1445 1409
1446 for (intptr_t j = 0; j < locs->input_count(); j++) { 1410 for (intptr_t j = 0; j < locs->input_count(); j++) {
(...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after
1526 interference_set); 1490 interference_set);
1527 } else { 1491 } else {
1528 ProcessOneOutput(block, pos, out, def, def->ssa_temp_index(), 1492 ProcessOneOutput(block, pos, out, def, def->ssa_temp_index(),
1529 false, // output is not mapped to first input. 1493 false, // output is not mapped to first input.
1530 NULL, NULL, -1, // First input not needed. 1494 NULL, NULL, -1, // First input not needed.
1531 interference_set); 1495 interference_set);
1532 } 1496 }
1533 } 1497 }
1534 } 1498 }
1535 1499
1536
1537 static ParallelMoveInstr* CreateParallelMoveBefore(Instruction* instr, 1500 static ParallelMoveInstr* CreateParallelMoveBefore(Instruction* instr,
1538 intptr_t pos) { 1501 intptr_t pos) {
1539 ASSERT(pos > 0); 1502 ASSERT(pos > 0);
1540 Instruction* prev = instr->previous(); 1503 Instruction* prev = instr->previous();
1541 ParallelMoveInstr* move = prev->AsParallelMove(); 1504 ParallelMoveInstr* move = prev->AsParallelMove();
1542 if ((move == NULL) || (move->lifetime_position() != pos)) { 1505 if ((move == NULL) || (move->lifetime_position() != pos)) {
1543 move = new ParallelMoveInstr(); 1506 move = new ParallelMoveInstr();
1544 prev->LinkTo(move); 1507 prev->LinkTo(move);
1545 move->LinkTo(instr); 1508 move->LinkTo(instr);
1546 move->set_lifetime_position(pos); 1509 move->set_lifetime_position(pos);
1547 } 1510 }
1548 return move; 1511 return move;
1549 } 1512 }
1550 1513
1551
1552 static ParallelMoveInstr* CreateParallelMoveAfter(Instruction* instr, 1514 static ParallelMoveInstr* CreateParallelMoveAfter(Instruction* instr,
1553 intptr_t pos) { 1515 intptr_t pos) {
1554 Instruction* next = instr->next(); 1516 Instruction* next = instr->next();
1555 if (next->IsParallelMove() && (next->lifetime_position() == pos)) { 1517 if (next->IsParallelMove() && (next->lifetime_position() == pos)) {
1556 return next->AsParallelMove(); 1518 return next->AsParallelMove();
1557 } 1519 }
1558 return CreateParallelMoveBefore(next, pos); 1520 return CreateParallelMoveBefore(next, pos);
1559 } 1521 }
1560 1522
1561
1562 // Linearize the control flow graph. The chosen order will be used by the 1523 // Linearize the control flow graph. The chosen order will be used by the
1563 // linear-scan register allocator. Number most instructions with a pair of 1524 // linear-scan register allocator. Number most instructions with a pair of
1564 // numbers representing lifetime positions. Introduce explicit parallel 1525 // numbers representing lifetime positions. Introduce explicit parallel
1565 // move instructions in the predecessors of join nodes. The moves are used 1526 // move instructions in the predecessors of join nodes. The moves are used
1566 // for phi resolution. 1527 // for phi resolution.
1567 void FlowGraphAllocator::NumberInstructions() { 1528 void FlowGraphAllocator::NumberInstructions() {
1568 intptr_t pos = 0; 1529 intptr_t pos = 0;
1569 1530
1570 // The basic block order is reverse postorder. 1531 // The basic block order is reverse postorder.
1571 const intptr_t block_count = postorder_.length(); 1532 const intptr_t block_count = postorder_.length();
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after
1616 1577
1617 // Populate the ParallelMove with empty moves. 1578 // Populate the ParallelMove with empty moves.
1618 for (intptr_t j = 0; j < move_count; j++) { 1579 for (intptr_t j = 0; j < move_count; j++) {
1619 move->AddMove(Location::NoLocation(), Location::NoLocation()); 1580 move->AddMove(Location::NoLocation(), Location::NoLocation());
1620 } 1581 }
1621 } 1582 }
1622 } 1583 }
1623 } 1584 }
1624 } 1585 }
1625 1586
1626
1627 // Discover structural (reducible) loops nesting structure. 1587 // Discover structural (reducible) loops nesting structure.
1628 void FlowGraphAllocator::DiscoverLoops() { 1588 void FlowGraphAllocator::DiscoverLoops() {
1629 // This algorithm relies on the assumption that we emit blocks in reverse 1589 // This algorithm relies on the assumption that we emit blocks in reverse
1630 // postorder, so postorder number can be used to identify loop nesting. 1590 // postorder, so postorder number can be used to identify loop nesting.
1631 // 1591 //
1632 // TODO(vegorov): consider using a generic algorithm to correctly discover 1592 // TODO(vegorov): consider using a generic algorithm to correctly discover
1633 // both headers of reducible and irreducible loops. 1593 // both headers of reducible and irreducible loops.
1634 BlockInfo* current_loop = NULL; 1594 BlockInfo* current_loop = NULL;
1635 1595
1636 intptr_t loop_id = 0; // All loop headers have a unique id. 1596 intptr_t loop_id = 0; // All loop headers have a unique id.
(...skipping 29 matching lines...) Expand all
1666 if (current_info == current_loop) { 1626 if (current_info == current_loop) {
1667 ASSERT(current_loop->is_loop_header()); 1627 ASSERT(current_loop->is_loop_header());
1668 current_loop = current_info->loop(); 1628 current_loop = current_info->loop();
1669 } else { 1629 } else {
1670 current_info->set_loop(current_loop); 1630 current_info->set_loop(current_loop);
1671 } 1631 }
1672 } 1632 }
1673 } 1633 }
1674 } 1634 }
1675 1635
1676
1677 Instruction* FlowGraphAllocator::InstructionAt(intptr_t pos) const { 1636 Instruction* FlowGraphAllocator::InstructionAt(intptr_t pos) const {
1678 return instructions_[pos / 2]; 1637 return instructions_[pos / 2];
1679 } 1638 }
1680 1639
1681
1682 BlockInfo* FlowGraphAllocator::BlockInfoAt(intptr_t pos) const { 1640 BlockInfo* FlowGraphAllocator::BlockInfoAt(intptr_t pos) const {
1683 return block_info_[pos / 2]; 1641 return block_info_[pos / 2];
1684 } 1642 }
1685 1643
1686
1687 bool FlowGraphAllocator::IsBlockEntry(intptr_t pos) const { 1644 bool FlowGraphAllocator::IsBlockEntry(intptr_t pos) const {
1688 return IsInstructionStartPosition(pos) && InstructionAt(pos)->IsBlockEntry(); 1645 return IsInstructionStartPosition(pos) && InstructionAt(pos)->IsBlockEntry();
1689 } 1646 }
1690 1647
1691
1692 void AllocationFinger::Initialize(LiveRange* range) { 1648 void AllocationFinger::Initialize(LiveRange* range) {
1693 first_pending_use_interval_ = range->first_use_interval(); 1649 first_pending_use_interval_ = range->first_use_interval();
1694 first_register_use_ = range->first_use(); 1650 first_register_use_ = range->first_use();
1695 first_register_beneficial_use_ = range->first_use(); 1651 first_register_beneficial_use_ = range->first_use();
1696 first_hinted_use_ = range->first_use(); 1652 first_hinted_use_ = range->first_use();
1697 } 1653 }
1698 1654
1699
1700 bool AllocationFinger::Advance(const intptr_t start) { 1655 bool AllocationFinger::Advance(const intptr_t start) {
1701 UseInterval* a = first_pending_use_interval_; 1656 UseInterval* a = first_pending_use_interval_;
1702 while (a != NULL && a->end() <= start) 1657 while (a != NULL && a->end() <= start)
1703 a = a->next(); 1658 a = a->next();
1704 first_pending_use_interval_ = a; 1659 first_pending_use_interval_ = a;
1705 return (first_pending_use_interval_ == NULL); 1660 return (first_pending_use_interval_ == NULL);
1706 } 1661 }
1707 1662
1708
1709 Location AllocationFinger::FirstHint() { 1663 Location AllocationFinger::FirstHint() {
1710 UsePosition* use = first_hinted_use_; 1664 UsePosition* use = first_hinted_use_;
1711 1665
1712 while (use != NULL) { 1666 while (use != NULL) {
1713 if (use->HasHint()) return use->hint(); 1667 if (use->HasHint()) return use->hint();
1714 use = use->next(); 1668 use = use->next();
1715 } 1669 }
1716 1670
1717 return Location::NoLocation(); 1671 return Location::NoLocation();
1718 } 1672 }
1719 1673
1720
1721 static UsePosition* FirstUseAfter(UsePosition* use, intptr_t after) { 1674 static UsePosition* FirstUseAfter(UsePosition* use, intptr_t after) {
1722 while ((use != NULL) && (use->pos() < after)) { 1675 while ((use != NULL) && (use->pos() < after)) {
1723 use = use->next(); 1676 use = use->next();
1724 } 1677 }
1725 return use; 1678 return use;
1726 } 1679 }
1727 1680
1728
1729 UsePosition* AllocationFinger::FirstRegisterUse(intptr_t after) { 1681 UsePosition* AllocationFinger::FirstRegisterUse(intptr_t after) {
1730 for (UsePosition* use = FirstUseAfter(first_register_use_, after); 1682 for (UsePosition* use = FirstUseAfter(first_register_use_, after);
1731 use != NULL; use = use->next()) { 1683 use != NULL; use = use->next()) {
1732 Location* loc = use->location_slot(); 1684 Location* loc = use->location_slot();
1733 if (loc->IsUnallocated() && 1685 if (loc->IsUnallocated() &&
1734 ((loc->policy() == Location::kRequiresRegister) || 1686 ((loc->policy() == Location::kRequiresRegister) ||
1735 (loc->policy() == Location::kRequiresFpuRegister))) { 1687 (loc->policy() == Location::kRequiresFpuRegister))) {
1736 first_register_use_ = use; 1688 first_register_use_ = use;
1737 return use; 1689 return use;
1738 } 1690 }
1739 } 1691 }
1740 return NULL; 1692 return NULL;
1741 } 1693 }
1742 1694
1743
1744 UsePosition* AllocationFinger::FirstRegisterBeneficialUse(intptr_t after) { 1695 UsePosition* AllocationFinger::FirstRegisterBeneficialUse(intptr_t after) {
1745 for (UsePosition* use = FirstUseAfter(first_register_beneficial_use_, after); 1696 for (UsePosition* use = FirstUseAfter(first_register_beneficial_use_, after);
1746 use != NULL; use = use->next()) { 1697 use != NULL; use = use->next()) {
1747 Location* loc = use->location_slot(); 1698 Location* loc = use->location_slot();
1748 if (loc->IsUnallocated() && loc->IsRegisterBeneficial()) { 1699 if (loc->IsUnallocated() && loc->IsRegisterBeneficial()) {
1749 first_register_beneficial_use_ = use; 1700 first_register_beneficial_use_ = use;
1750 return use; 1701 return use;
1751 } 1702 }
1752 } 1703 }
1753 return NULL; 1704 return NULL;
1754 } 1705 }
1755 1706
1756
1757 UsePosition* AllocationFinger::FirstInterferingUse(intptr_t after) { 1707 UsePosition* AllocationFinger::FirstInterferingUse(intptr_t after) {
1758 if (IsInstructionEndPosition(after)) { 1708 if (IsInstructionEndPosition(after)) {
1759 // If after is a position at the end of the instruction disregard 1709 // If after is a position at the end of the instruction disregard
1760 // any use occurring at it. 1710 // any use occurring at it.
1761 after += 1; 1711 after += 1;
1762 } 1712 }
1763 return FirstRegisterUse(after); 1713 return FirstRegisterUse(after);
1764 } 1714 }
1765 1715
1766
1767 void AllocationFinger::UpdateAfterSplit(intptr_t first_use_after_split_pos) { 1716 void AllocationFinger::UpdateAfterSplit(intptr_t first_use_after_split_pos) {
1768 if ((first_register_use_ != NULL) && 1717 if ((first_register_use_ != NULL) &&
1769 (first_register_use_->pos() >= first_use_after_split_pos)) { 1718 (first_register_use_->pos() >= first_use_after_split_pos)) {
1770 first_register_use_ = NULL; 1719 first_register_use_ = NULL;
1771 } 1720 }
1772 1721
1773 if ((first_register_beneficial_use_ != NULL) && 1722 if ((first_register_beneficial_use_ != NULL) &&
1774 (first_register_beneficial_use_->pos() >= first_use_after_split_pos)) { 1723 (first_register_beneficial_use_->pos() >= first_use_after_split_pos)) {
1775 first_register_beneficial_use_ = NULL; 1724 first_register_beneficial_use_ = NULL;
1776 } 1725 }
1777 } 1726 }
1778 1727
1779
1780 intptr_t UseInterval::Intersect(UseInterval* other) { 1728 intptr_t UseInterval::Intersect(UseInterval* other) {
1781 if (this->start() <= other->start()) { 1729 if (this->start() <= other->start()) {
1782 if (other->start() < this->end()) return other->start(); 1730 if (other->start() < this->end()) return other->start();
1783 } else if (this->start() < other->end()) { 1731 } else if (this->start() < other->end()) {
1784 return this->start(); 1732 return this->start();
1785 } 1733 }
1786 return kIllegalPosition; 1734 return kIllegalPosition;
1787 } 1735 }
1788 1736
1789
1790 static intptr_t FirstIntersection(UseInterval* a, UseInterval* u) { 1737 static intptr_t FirstIntersection(UseInterval* a, UseInterval* u) {
1791 while (a != NULL && u != NULL) { 1738 while (a != NULL && u != NULL) {
1792 const intptr_t pos = a->Intersect(u); 1739 const intptr_t pos = a->Intersect(u);
1793 if (pos != kIllegalPosition) return pos; 1740 if (pos != kIllegalPosition) return pos;
1794 1741
1795 if (a->start() < u->start()) { 1742 if (a->start() < u->start()) {
1796 a = a->next(); 1743 a = a->next();
1797 } else { 1744 } else {
1798 u = u->next(); 1745 u = u->next();
1799 } 1746 }
1800 } 1747 }
1801 1748
1802 return kMaxPosition; 1749 return kMaxPosition;
1803 } 1750 }
1804 1751
1805
1806 template <typename PositionType> 1752 template <typename PositionType>
1807 PositionType* SplitListOfPositions(PositionType** head, 1753 PositionType* SplitListOfPositions(PositionType** head,
1808 intptr_t split_pos, 1754 intptr_t split_pos,
1809 bool split_at_start) { 1755 bool split_at_start) {
1810 PositionType* last_before_split = NULL; 1756 PositionType* last_before_split = NULL;
1811 PositionType* pos = *head; 1757 PositionType* pos = *head;
1812 if (split_at_start) { 1758 if (split_at_start) {
1813 while ((pos != NULL) && (pos->pos() < split_pos)) { 1759 while ((pos != NULL) && (pos->pos() < split_pos)) {
1814 last_before_split = pos; 1760 last_before_split = pos;
1815 pos = pos->next(); 1761 pos = pos->next();
1816 } 1762 }
1817 } else { 1763 } else {
1818 while ((pos != NULL) && (pos->pos() <= split_pos)) { 1764 while ((pos != NULL) && (pos->pos() <= split_pos)) {
1819 last_before_split = pos; 1765 last_before_split = pos;
1820 pos = pos->next(); 1766 pos = pos->next();
1821 } 1767 }
1822 } 1768 }
1823 1769
1824 if (last_before_split == NULL) { 1770 if (last_before_split == NULL) {
1825 *head = NULL; 1771 *head = NULL;
1826 } else { 1772 } else {
1827 last_before_split->set_next(NULL); 1773 last_before_split->set_next(NULL);
1828 } 1774 }
1829 1775
1830 return pos; 1776 return pos;
1831 } 1777 }
1832 1778
1833
1834 LiveRange* LiveRange::SplitAt(intptr_t split_pos) { 1779 LiveRange* LiveRange::SplitAt(intptr_t split_pos) {
1835 if (Start() == split_pos) return this; 1780 if (Start() == split_pos) return this;
1836 1781
1837 UseInterval* interval = finger_.first_pending_use_interval(); 1782 UseInterval* interval = finger_.first_pending_use_interval();
1838 if (interval == NULL) { 1783 if (interval == NULL) {
1839 finger_.Initialize(this); 1784 finger_.Initialize(this);
1840 interval = finger_.first_pending_use_interval(); 1785 interval = finger_.first_pending_use_interval();
1841 } 1786 }
1842 1787
1843 ASSERT(split_pos < End()); 1788 ASSERT(split_pos < End());
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after
1887 last_use_interval_ = last_before_split; 1832 last_use_interval_ = last_before_split;
1888 last_use_interval_->next_ = NULL; 1833 last_use_interval_->next_ = NULL;
1889 1834
1890 if (first_use_after_split != NULL) { 1835 if (first_use_after_split != NULL) {
1891 finger_.UpdateAfterSplit(first_use_after_split->pos()); 1836 finger_.UpdateAfterSplit(first_use_after_split->pos());
1892 } 1837 }
1893 1838
1894 return next_sibling_; 1839 return next_sibling_;
1895 } 1840 }
1896 1841
1897
1898 LiveRange* FlowGraphAllocator::SplitBetween(LiveRange* range, 1842 LiveRange* FlowGraphAllocator::SplitBetween(LiveRange* range,
1899 intptr_t from, 1843 intptr_t from,
1900 intptr_t to) { 1844 intptr_t to) {
1901 TRACE_ALLOC(THR_Print("split v%" Pd " [%" Pd ", %" Pd ") between [%" Pd 1845 TRACE_ALLOC(THR_Print("split v%" Pd " [%" Pd ", %" Pd ") between [%" Pd
1902 ", %" Pd ")\n", 1846 ", %" Pd ")\n",
1903 range->vreg(), range->Start(), range->End(), from, to)); 1847 range->vreg(), range->Start(), range->End(), from, to));
1904 1848
1905 intptr_t split_pos = kIllegalPosition; 1849 intptr_t split_pos = kIllegalPosition;
1906 1850
1907 BlockInfo* split_block = BlockInfoAt(to); 1851 BlockInfo* split_block = BlockInfoAt(to);
(...skipping 18 matching lines...) Expand all
1926 // instruction. 1870 // instruction.
1927 split_pos = ToInstructionStart(to) - 1; 1871 split_pos = ToInstructionStart(to) - 1;
1928 } 1872 }
1929 1873
1930 ASSERT(split_pos != kIllegalPosition); 1874 ASSERT(split_pos != kIllegalPosition);
1931 ASSERT(from < split_pos); 1875 ASSERT(from < split_pos);
1932 1876
1933 return range->SplitAt(split_pos); 1877 return range->SplitAt(split_pos);
1934 } 1878 }
1935 1879
1936
1937 void FlowGraphAllocator::SpillBetween(LiveRange* range, 1880 void FlowGraphAllocator::SpillBetween(LiveRange* range,
1938 intptr_t from, 1881 intptr_t from,
1939 intptr_t to) { 1882 intptr_t to) {
1940 ASSERT(from < to); 1883 ASSERT(from < to);
1941 TRACE_ALLOC(THR_Print("spill v%" Pd " [%" Pd ", %" Pd ") " 1884 TRACE_ALLOC(THR_Print("spill v%" Pd " [%" Pd ", %" Pd ") "
1942 "between [%" Pd ", %" Pd ")\n", 1885 "between [%" Pd ", %" Pd ")\n",
1943 range->vreg(), range->Start(), range->End(), from, to)); 1886 range->vreg(), range->Start(), range->End(), from, to));
1944 LiveRange* tail = range->SplitAt(from); 1887 LiveRange* tail = range->SplitAt(from);
1945 1888
1946 if (tail->Start() < to) { 1889 if (tail->Start() < to) {
1947 // There is an intersection of tail and [from, to). 1890 // There is an intersection of tail and [from, to).
1948 LiveRange* tail_tail = SplitBetween(tail, tail->Start(), to); 1891 LiveRange* tail_tail = SplitBetween(tail, tail->Start(), to);
1949 Spill(tail); 1892 Spill(tail);
1950 AddToUnallocated(tail_tail); 1893 AddToUnallocated(tail_tail);
1951 } else { 1894 } else {
1952 // No intersection between tail and [from, to). 1895 // No intersection between tail and [from, to).
1953 AddToUnallocated(tail); 1896 AddToUnallocated(tail);
1954 } 1897 }
1955 } 1898 }
1956 1899
1957
1958 void FlowGraphAllocator::SpillAfter(LiveRange* range, intptr_t from) { 1900 void FlowGraphAllocator::SpillAfter(LiveRange* range, intptr_t from) {
1959 TRACE_ALLOC(THR_Print("spill v%" Pd " [%" Pd ", %" Pd ") after %" Pd "\n", 1901 TRACE_ALLOC(THR_Print("spill v%" Pd " [%" Pd ", %" Pd ") after %" Pd "\n",
1960 range->vreg(), range->Start(), range->End(), from)); 1902 range->vreg(), range->Start(), range->End(), from));
1961 1903
1962 // When spilling the value inside the loop check if this spill can 1904 // When spilling the value inside the loop check if this spill can
1963 // be moved outside. 1905 // be moved outside.
1964 BlockInfo* block_info = BlockInfoAt(from); 1906 BlockInfo* block_info = BlockInfoAt(from);
1965 if (block_info->is_loop_header() || (block_info->loop() != NULL)) { 1907 if (block_info->is_loop_header() || (block_info->loop() != NULL)) {
1966 BlockInfo* loop_header = 1908 BlockInfo* loop_header =
1967 block_info->is_loop_header() ? block_info : block_info->loop(); 1909 block_info->is_loop_header() ? block_info : block_info->loop();
1968 1910
1969 if ((range->Start() <= loop_header->entry()->start_pos()) && 1911 if ((range->Start() <= loop_header->entry()->start_pos()) &&
1970 RangeHasOnlyUnconstrainedUsesInLoop(range, loop_header->loop_id())) { 1912 RangeHasOnlyUnconstrainedUsesInLoop(range, loop_header->loop_id())) {
1971 ASSERT(loop_header->entry()->start_pos() <= from); 1913 ASSERT(loop_header->entry()->start_pos() <= from);
1972 from = loop_header->entry()->start_pos(); 1914 from = loop_header->entry()->start_pos();
1973 TRACE_ALLOC( 1915 TRACE_ALLOC(
1974 THR_Print(" moved spill position to loop header %" Pd "\n", from)); 1916 THR_Print(" moved spill position to loop header %" Pd "\n", from));
1975 } 1917 }
1976 } 1918 }
1977 1919
1978 LiveRange* tail = range->SplitAt(from); 1920 LiveRange* tail = range->SplitAt(from);
1979 Spill(tail); 1921 Spill(tail);
1980 } 1922 }
1981 1923
1982
1983 void FlowGraphAllocator::AllocateSpillSlotFor(LiveRange* range) { 1924 void FlowGraphAllocator::AllocateSpillSlotFor(LiveRange* range) {
1984 #if defined(TARGET_ARCH_DBC) 1925 #if defined(TARGET_ARCH_DBC)
1985 // There is no need to support spilling on DBC because we have a lot of 1926 // There is no need to support spilling on DBC because we have a lot of
1986 // registers and registers and spill-slots have the same performance 1927 // registers and registers and spill-slots have the same performance
1987 // characteristics. 1928 // characteristics.
1988 flow_graph_.parsed_function().Bailout("FlowGraphAllocator", "SPILL"); 1929 flow_graph_.parsed_function().Bailout("FlowGraphAllocator", "SPILL");
1989 UNREACHABLE(); 1930 UNREACHABLE();
1990 #endif 1931 #endif
1991 1932
1992 ASSERT(range->spill_slot().IsInvalid()); 1933 ASSERT(range->spill_slot().IsInvalid());
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after
2070 } else { 2011 } else {
2071 ASSERT((range->representation() == kUnboxedDouble)); 2012 ASSERT((range->representation() == kUnboxedDouble));
2072 location = Location::DoubleStackSlot(slot_idx); 2013 location = Location::DoubleStackSlot(slot_idx);
2073 } 2014 }
2074 range->set_spill_slot(location); 2015 range->set_spill_slot(location);
2075 } 2016 }
2076 2017
2077 spilled_.Add(range); 2018 spilled_.Add(range);
2078 } 2019 }
2079 2020
2080
2081 void FlowGraphAllocator::MarkAsObjectAtSafepoints(LiveRange* range) { 2021 void FlowGraphAllocator::MarkAsObjectAtSafepoints(LiveRange* range) {
2082 intptr_t stack_index = range->spill_slot().stack_index(); 2022 intptr_t stack_index = range->spill_slot().stack_index();
2083 ASSERT(stack_index >= 0); 2023 ASSERT(stack_index >= 0);
2084 2024
2085 while (range != NULL) { 2025 while (range != NULL) {
2086 for (SafepointPosition* safepoint = range->first_safepoint(); 2026 for (SafepointPosition* safepoint = range->first_safepoint();
2087 safepoint != NULL; safepoint = safepoint->next()) { 2027 safepoint != NULL; safepoint = safepoint->next()) {
2088 // Mark the stack slot as having an object. 2028 // Mark the stack slot as having an object.
2089 safepoint->locs()->SetStackBit(stack_index); 2029 safepoint->locs()->SetStackBit(stack_index);
2090 } 2030 }
2091 range = range->next_sibling(); 2031 range = range->next_sibling();
2092 } 2032 }
2093 } 2033 }
2094 2034
2095
2096 void FlowGraphAllocator::Spill(LiveRange* range) { 2035 void FlowGraphAllocator::Spill(LiveRange* range) {
2097 LiveRange* parent = GetLiveRange(range->vreg()); 2036 LiveRange* parent = GetLiveRange(range->vreg());
2098 if (parent->spill_slot().IsInvalid()) { 2037 if (parent->spill_slot().IsInvalid()) {
2099 AllocateSpillSlotFor(parent); 2038 AllocateSpillSlotFor(parent);
2100 if (range->representation() == kTagged) { 2039 if (range->representation() == kTagged) {
2101 MarkAsObjectAtSafepoints(parent); 2040 MarkAsObjectAtSafepoints(parent);
2102 } 2041 }
2103 } 2042 }
2104 range->set_assigned_location(parent->spill_slot()); 2043 range->set_assigned_location(parent->spill_slot());
2105 ConvertAllUses(range); 2044 ConvertAllUses(range);
2106 } 2045 }
2107 2046
2108
2109 intptr_t FlowGraphAllocator::FirstIntersectionWithAllocated( 2047 intptr_t FlowGraphAllocator::FirstIntersectionWithAllocated(
2110 intptr_t reg, 2048 intptr_t reg,
2111 LiveRange* unallocated) { 2049 LiveRange* unallocated) {
2112 intptr_t intersection = kMaxPosition; 2050 intptr_t intersection = kMaxPosition;
2113 for (intptr_t i = 0; i < registers_[reg]->length(); i++) { 2051 for (intptr_t i = 0; i < registers_[reg]->length(); i++) {
2114 LiveRange* allocated = (*registers_[reg])[i]; 2052 LiveRange* allocated = (*registers_[reg])[i];
2115 if (allocated == NULL) continue; 2053 if (allocated == NULL) continue;
2116 2054
2117 UseInterval* allocated_head = 2055 UseInterval* allocated_head =
2118 allocated->finger()->first_pending_use_interval(); 2056 allocated->finger()->first_pending_use_interval();
2119 if (allocated_head->start() >= intersection) continue; 2057 if (allocated_head->start() >= intersection) continue;
2120 2058
2121 const intptr_t pos = FirstIntersection( 2059 const intptr_t pos = FirstIntersection(
2122 unallocated->finger()->first_pending_use_interval(), allocated_head); 2060 unallocated->finger()->first_pending_use_interval(), allocated_head);
2123 if (pos < intersection) intersection = pos; 2061 if (pos < intersection) intersection = pos;
2124 } 2062 }
2125 return intersection; 2063 return intersection;
2126 } 2064 }
2127 2065
2128
2129 void ReachingDefs::AddPhi(PhiInstr* phi) { 2066 void ReachingDefs::AddPhi(PhiInstr* phi) {
2130 if (phi->reaching_defs() == NULL) { 2067 if (phi->reaching_defs() == NULL) {
2131 Zone* zone = flow_graph_.zone(); 2068 Zone* zone = flow_graph_.zone();
2132 phi->set_reaching_defs( 2069 phi->set_reaching_defs(
2133 new (zone) BitVector(zone, flow_graph_.max_virtual_register_number())); 2070 new (zone) BitVector(zone, flow_graph_.max_virtual_register_number()));
2134 2071
2135 // Compute initial set reaching defs set. 2072 // Compute initial set reaching defs set.
2136 bool depends_on_phi = false; 2073 bool depends_on_phi = false;
2137 for (intptr_t i = 0; i < phi->InputCount(); i++) { 2074 for (intptr_t i = 0; i < phi->InputCount(); i++) {
2138 Definition* input = phi->InputAt(i)->definition(); 2075 Definition* input = phi->InputAt(i)->definition();
2139 if (input->IsPhi()) { 2076 if (input->IsPhi()) {
2140 depends_on_phi = true; 2077 depends_on_phi = true;
2141 } 2078 }
2142 phi->reaching_defs()->Add(input->ssa_temp_index()); 2079 phi->reaching_defs()->Add(input->ssa_temp_index());
2143 if (phi->HasPairRepresentation()) { 2080 if (phi->HasPairRepresentation()) {
2144 phi->reaching_defs()->Add(ToSecondPairVreg(input->ssa_temp_index())); 2081 phi->reaching_defs()->Add(ToSecondPairVreg(input->ssa_temp_index()));
2145 } 2082 }
2146 } 2083 }
2147 2084
2148 // If this phi depends on another phi then we need fix point iteration. 2085 // If this phi depends on another phi then we need fix point iteration.
2149 if (depends_on_phi) phis_.Add(phi); 2086 if (depends_on_phi) phis_.Add(phi);
2150 } 2087 }
2151 } 2088 }
2152 2089
2153
2154 void ReachingDefs::Compute() { 2090 void ReachingDefs::Compute() {
2155 // Transitively collect all phis that are used by the given phi. 2091 // Transitively collect all phis that are used by the given phi.
2156 for (intptr_t i = 0; i < phis_.length(); i++) { 2092 for (intptr_t i = 0; i < phis_.length(); i++) {
2157 PhiInstr* phi = phis_[i]; 2093 PhiInstr* phi = phis_[i];
2158 2094
2159 // Add all phis that affect this phi to the list. 2095 // Add all phis that affect this phi to the list.
2160 for (intptr_t i = 0; i < phi->InputCount(); i++) { 2096 for (intptr_t i = 0; i < phi->InputCount(); i++) {
2161 PhiInstr* input_phi = phi->InputAt(i)->definition()->AsPhi(); 2097 PhiInstr* input_phi = phi->InputAt(i)->definition()->AsPhi();
2162 if (input_phi != NULL) { 2098 if (input_phi != NULL) {
2163 AddPhi(input_phi); 2099 AddPhi(input_phi);
(...skipping 14 matching lines...) Expand all
2178 changed = true; 2114 changed = true;
2179 } 2115 }
2180 } 2116 }
2181 } 2117 }
2182 } 2118 }
2183 } while (changed); 2119 } while (changed);
2184 2120
2185 phis_.Clear(); 2121 phis_.Clear();
2186 } 2122 }
2187 2123
2188
2189 BitVector* ReachingDefs::Get(PhiInstr* phi) { 2124 BitVector* ReachingDefs::Get(PhiInstr* phi) {
2190 if (phi->reaching_defs() == NULL) { 2125 if (phi->reaching_defs() == NULL) {
2191 ASSERT(phis_.is_empty()); 2126 ASSERT(phis_.is_empty());
2192 AddPhi(phi); 2127 AddPhi(phi);
2193 Compute(); 2128 Compute();
2194 } 2129 }
2195 return phi->reaching_defs(); 2130 return phi->reaching_defs();
2196 } 2131 }
2197 2132
2198
2199 bool FlowGraphAllocator::AllocateFreeRegister(LiveRange* unallocated) { 2133 bool FlowGraphAllocator::AllocateFreeRegister(LiveRange* unallocated) {
2200 intptr_t candidate = kNoRegister; 2134 intptr_t candidate = kNoRegister;
2201 intptr_t free_until = 0; 2135 intptr_t free_until = 0;
2202 2136
2203 // If hint is available try hint first. 2137 // If hint is available try hint first.
2204 // TODO(vegorov): ensure that phis are hinted on the back edge. 2138 // TODO(vegorov): ensure that phis are hinted on the back edge.
2205 Location hint = unallocated->finger()->FirstHint(); 2139 Location hint = unallocated->finger()->FirstHint();
2206 if (hint.IsMachineRegister()) { 2140 if (hint.IsMachineRegister()) {
2207 if (!blocked_registers_[hint.register_code()]) { 2141 if (!blocked_registers_[hint.register_code()]) {
2208 free_until = 2142 free_until =
(...skipping 109 matching lines...) Expand 10 before | Expand all | Expand 10 after
2318 2252
2319 registers_[candidate]->Add(unallocated); 2253 registers_[candidate]->Add(unallocated);
2320 unallocated->set_assigned_location(MakeRegisterLocation(candidate)); 2254 unallocated->set_assigned_location(MakeRegisterLocation(candidate));
2321 #if defined(TARGET_ARCH_DBC) 2255 #if defined(TARGET_ARCH_DBC)
2322 last_used_register_ = Utils::Maximum(last_used_register_, candidate); 2256 last_used_register_ = Utils::Maximum(last_used_register_, candidate);
2323 #endif 2257 #endif
2324 2258
2325 return true; 2259 return true;
2326 } 2260 }
2327 2261
2328
2329 bool FlowGraphAllocator::RangeHasOnlyUnconstrainedUsesInLoop(LiveRange* range, 2262 bool FlowGraphAllocator::RangeHasOnlyUnconstrainedUsesInLoop(LiveRange* range,
2330 intptr_t loop_id) { 2263 intptr_t loop_id) {
2331 if (range->vreg() >= 0) { 2264 if (range->vreg() >= 0) {
2332 LiveRange* parent = GetLiveRange(range->vreg()); 2265 LiveRange* parent = GetLiveRange(range->vreg());
2333 return parent->HasOnlyUnconstrainedUsesInLoop(loop_id); 2266 return parent->HasOnlyUnconstrainedUsesInLoop(loop_id);
2334 } 2267 }
2335 return false; 2268 return false;
2336 } 2269 }
2337 2270
2338
2339 bool FlowGraphAllocator::IsCheapToEvictRegisterInLoop(BlockInfo* loop, 2271 bool FlowGraphAllocator::IsCheapToEvictRegisterInLoop(BlockInfo* loop,
2340 intptr_t reg) { 2272 intptr_t reg) {
2341 const intptr_t loop_start = loop->entry()->start_pos(); 2273 const intptr_t loop_start = loop->entry()->start_pos();
2342 const intptr_t loop_end = loop->last_block()->end_pos(); 2274 const intptr_t loop_end = loop->last_block()->end_pos();
2343 2275
2344 for (intptr_t i = 0; i < registers_[reg]->length(); i++) { 2276 for (intptr_t i = 0; i < registers_[reg]->length(); i++) {
2345 LiveRange* allocated = (*registers_[reg])[i]; 2277 LiveRange* allocated = (*registers_[reg])[i];
2346 2278
2347 UseInterval* interval = allocated->finger()->first_pending_use_interval(); 2279 UseInterval* interval = allocated->finger()->first_pending_use_interval();
2348 if (interval->Contains(loop_start)) { 2280 if (interval->Contains(loop_start)) {
2349 if (!RangeHasOnlyUnconstrainedUsesInLoop(allocated, loop->loop_id())) { 2281 if (!RangeHasOnlyUnconstrainedUsesInLoop(allocated, loop->loop_id())) {
2350 return false; 2282 return false;
2351 } 2283 }
2352 } else if (interval->start() < loop_end) { 2284 } else if (interval->start() < loop_end) {
2353 return false; 2285 return false;
2354 } 2286 }
2355 } 2287 }
2356 2288
2357 return true; 2289 return true;
2358 } 2290 }
2359 2291
2360
2361 bool FlowGraphAllocator::HasCheapEvictionCandidate(LiveRange* phi_range) { 2292 bool FlowGraphAllocator::HasCheapEvictionCandidate(LiveRange* phi_range) {
2362 ASSERT(phi_range->is_loop_phi()); 2293 ASSERT(phi_range->is_loop_phi());
2363 2294
2364 BlockInfo* loop_header = BlockInfoAt(phi_range->Start()); 2295 BlockInfo* loop_header = BlockInfoAt(phi_range->Start());
2365 ASSERT(loop_header->is_loop_header()); 2296 ASSERT(loop_header->is_loop_header());
2366 ASSERT(phi_range->Start() == loop_header->entry()->start_pos()); 2297 ASSERT(phi_range->Start() == loop_header->entry()->start_pos());
2367 2298
2368 for (intptr_t reg = 0; reg < NumberOfRegisters(); ++reg) { 2299 for (intptr_t reg = 0; reg < NumberOfRegisters(); ++reg) {
2369 if (blocked_registers_[reg]) continue; 2300 if (blocked_registers_[reg]) continue;
2370 if (IsCheapToEvictRegisterInLoop(loop_header, reg)) { 2301 if (IsCheapToEvictRegisterInLoop(loop_header, reg)) {
2371 return true; 2302 return true;
2372 } 2303 }
2373 } 2304 }
2374 2305
2375 return false; 2306 return false;
2376 } 2307 }
2377 2308
2378
2379 void FlowGraphAllocator::AllocateAnyRegister(LiveRange* unallocated) { 2309 void FlowGraphAllocator::AllocateAnyRegister(LiveRange* unallocated) {
2380 // If a loop phi has no register uses we might still want to allocate it 2310 // If a loop phi has no register uses we might still want to allocate it
2381 // to the register to reduce amount of memory moves on the back edge. 2311 // to the register to reduce amount of memory moves on the back edge.
2382 // This is possible if there is a register blocked by a range that can be 2312 // This is possible if there is a register blocked by a range that can be
2383 // cheaply evicted i.e. it has no register beneficial uses inside the 2313 // cheaply evicted i.e. it has no register beneficial uses inside the
2384 // loop. 2314 // loop.
2385 UsePosition* register_use = 2315 UsePosition* register_use =
2386 unallocated->finger()->FirstRegisterUse(unallocated->Start()); 2316 unallocated->finger()->FirstRegisterUse(unallocated->Start());
2387 if ((register_use == NULL) && 2317 if ((register_use == NULL) &&
2388 !(unallocated->is_loop_phi() && HasCheapEvictionCandidate(unallocated))) { 2318 !(unallocated->is_loop_phi() && HasCheapEvictionCandidate(unallocated))) {
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
2421 // Register is blocked before the end of the live range. Split the range 2351 // Register is blocked before the end of the live range. Split the range
2422 // at latest at blocked_at position. 2352 // at latest at blocked_at position.
2423 LiveRange* tail = 2353 LiveRange* tail =
2424 SplitBetween(unallocated, unallocated->Start(), blocked_at + 1); 2354 SplitBetween(unallocated, unallocated->Start(), blocked_at + 1);
2425 AddToUnallocated(tail); 2355 AddToUnallocated(tail);
2426 } 2356 }
2427 2357
2428 AssignNonFreeRegister(unallocated, candidate); 2358 AssignNonFreeRegister(unallocated, candidate);
2429 } 2359 }
2430 2360
2431
2432 bool FlowGraphAllocator::UpdateFreeUntil(intptr_t reg, 2361 bool FlowGraphAllocator::UpdateFreeUntil(intptr_t reg,
2433 LiveRange* unallocated, 2362 LiveRange* unallocated,
2434 intptr_t* cur_free_until, 2363 intptr_t* cur_free_until,
2435 intptr_t* cur_blocked_at) { 2364 intptr_t* cur_blocked_at) {
2436 intptr_t free_until = kMaxPosition; 2365 intptr_t free_until = kMaxPosition;
2437 intptr_t blocked_at = kMaxPosition; 2366 intptr_t blocked_at = kMaxPosition;
2438 const intptr_t start = unallocated->Start(); 2367 const intptr_t start = unallocated->Start();
2439 2368
2440 for (intptr_t i = 0; i < registers_[reg]->length(); i++) { 2369 for (intptr_t i = 0; i < registers_[reg]->length(); i++) {
2441 LiveRange* allocated = (*registers_[reg])[i]; 2370 LiveRange* allocated = (*registers_[reg])[i];
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
2475 return false; 2404 return false;
2476 } 2405 }
2477 } 2406 }
2478 2407
2479 ASSERT(free_until > *cur_free_until); 2408 ASSERT(free_until > *cur_free_until);
2480 *cur_free_until = free_until; 2409 *cur_free_until = free_until;
2481 *cur_blocked_at = blocked_at; 2410 *cur_blocked_at = blocked_at;
2482 return true; 2411 return true;
2483 } 2412 }
2484 2413
2485
2486 void FlowGraphAllocator::RemoveEvicted(intptr_t reg, intptr_t first_evicted) { 2414 void FlowGraphAllocator::RemoveEvicted(intptr_t reg, intptr_t first_evicted) {
2487 intptr_t to = first_evicted; 2415 intptr_t to = first_evicted;
2488 intptr_t from = first_evicted + 1; 2416 intptr_t from = first_evicted + 1;
2489 while (from < registers_[reg]->length()) { 2417 while (from < registers_[reg]->length()) {
2490 LiveRange* allocated = (*registers_[reg])[from++]; 2418 LiveRange* allocated = (*registers_[reg])[from++];
2491 if (allocated != NULL) (*registers_[reg])[to++] = allocated; 2419 if (allocated != NULL) (*registers_[reg])[to++] = allocated;
2492 } 2420 }
2493 registers_[reg]->TruncateTo(to); 2421 registers_[reg]->TruncateTo(to);
2494 } 2422 }
2495 2423
2496
2497 void FlowGraphAllocator::AssignNonFreeRegister(LiveRange* unallocated, 2424 void FlowGraphAllocator::AssignNonFreeRegister(LiveRange* unallocated,
2498 intptr_t reg) { 2425 intptr_t reg) {
2499 intptr_t first_evicted = -1; 2426 intptr_t first_evicted = -1;
2500 for (intptr_t i = registers_[reg]->length() - 1; i >= 0; i--) { 2427 for (intptr_t i = registers_[reg]->length() - 1; i >= 0; i--) {
2501 LiveRange* allocated = (*registers_[reg])[i]; 2428 LiveRange* allocated = (*registers_[reg])[i];
2502 if (allocated->vreg() < 0) continue; // Can't be evicted. 2429 if (allocated->vreg() < 0) continue; // Can't be evicted.
2503 if (EvictIntersection(allocated, unallocated)) { 2430 if (EvictIntersection(allocated, unallocated)) {
2504 // If allocated was not spilled convert all pending uses. 2431 // If allocated was not spilled convert all pending uses.
2505 if (allocated->assigned_location().IsMachineRegister()) { 2432 if (allocated->assigned_location().IsMachineRegister()) {
2506 ASSERT(allocated->End() <= unallocated->Start()); 2433 ASSERT(allocated->End() <= unallocated->Start());
2507 ConvertAllUses(allocated); 2434 ConvertAllUses(allocated);
2508 } 2435 }
2509 (*registers_[reg])[i] = NULL; 2436 (*registers_[reg])[i] = NULL;
2510 first_evicted = i; 2437 first_evicted = i;
2511 } 2438 }
2512 } 2439 }
2513 2440
2514 // Remove evicted ranges from the array. 2441 // Remove evicted ranges from the array.
2515 if (first_evicted != -1) RemoveEvicted(reg, first_evicted); 2442 if (first_evicted != -1) RemoveEvicted(reg, first_evicted);
2516 2443
2517 registers_[reg]->Add(unallocated); 2444 registers_[reg]->Add(unallocated);
2518 unallocated->set_assigned_location(MakeRegisterLocation(reg)); 2445 unallocated->set_assigned_location(MakeRegisterLocation(reg));
2519 #if defined(TARGET_ARCH_DBC) 2446 #if defined(TARGET_ARCH_DBC)
2520 last_used_register_ = Utils::Maximum(last_used_register_, reg); 2447 last_used_register_ = Utils::Maximum(last_used_register_, reg);
2521 #endif 2448 #endif
2522 } 2449 }
2523 2450
2524
2525 bool FlowGraphAllocator::EvictIntersection(LiveRange* allocated, 2451 bool FlowGraphAllocator::EvictIntersection(LiveRange* allocated,
2526 LiveRange* unallocated) { 2452 LiveRange* unallocated) {
2527 UseInterval* first_unallocated = 2453 UseInterval* first_unallocated =
2528 unallocated->finger()->first_pending_use_interval(); 2454 unallocated->finger()->first_pending_use_interval();
2529 const intptr_t intersection = FirstIntersection( 2455 const intptr_t intersection = FirstIntersection(
2530 allocated->finger()->first_pending_use_interval(), first_unallocated); 2456 allocated->finger()->first_pending_use_interval(), first_unallocated);
2531 if (intersection == kMaxPosition) return false; 2457 if (intersection == kMaxPosition) return false;
2532 2458
2533 const intptr_t spill_position = first_unallocated->start(); 2459 const intptr_t spill_position = first_unallocated->start();
2534 UsePosition* use = allocated->finger()->FirstInterferingUse(spill_position); 2460 UsePosition* use = allocated->finger()->FirstInterferingUse(spill_position);
2535 if (use == NULL) { 2461 if (use == NULL) {
2536 // No register uses after this point. 2462 // No register uses after this point.
2537 SpillAfter(allocated, spill_position); 2463 SpillAfter(allocated, spill_position);
2538 } else { 2464 } else {
2539 const intptr_t restore_position = 2465 const intptr_t restore_position =
2540 (spill_position < intersection) ? MinPosition(intersection, use->pos()) 2466 (spill_position < intersection) ? MinPosition(intersection, use->pos())
2541 : use->pos(); 2467 : use->pos();
2542 2468
2543 SpillBetween(allocated, spill_position, restore_position); 2469 SpillBetween(allocated, spill_position, restore_position);
2544 } 2470 }
2545 2471
2546 return true; 2472 return true;
2547 } 2473 }
2548 2474
2549
2550 MoveOperands* FlowGraphAllocator::AddMoveAt(intptr_t pos, 2475 MoveOperands* FlowGraphAllocator::AddMoveAt(intptr_t pos,
2551 Location to, 2476 Location to,
2552 Location from) { 2477 Location from) {
2553 ASSERT(!IsBlockEntry(pos)); 2478 ASSERT(!IsBlockEntry(pos));
2554 2479
2555 if (pos < kNormalEntryPos) { 2480 if (pos < kNormalEntryPos) {
2556 ASSERT(pos > 0); 2481 ASSERT(pos > 0);
2557 // Parallel moves added to the GraphEntry (B0) will be added at the start 2482 // Parallel moves added to the GraphEntry (B0) will be added at the start
2558 // of the normal entry (B1) 2483 // of the normal entry (B1)
2559 BlockEntryInstr* entry = InstructionAt(kNormalEntryPos)->AsBlockEntry(); 2484 BlockEntryInstr* entry = InstructionAt(kNormalEntryPos)->AsBlockEntry();
2560 return entry->GetParallelMove()->AddMove(to, from); 2485 return entry->GetParallelMove()->AddMove(to, from);
2561 } 2486 }
2562 2487
2563 Instruction* instr = InstructionAt(pos); 2488 Instruction* instr = InstructionAt(pos);
2564 2489
2565 ParallelMoveInstr* parallel_move = NULL; 2490 ParallelMoveInstr* parallel_move = NULL;
2566 if (IsInstructionStartPosition(pos)) { 2491 if (IsInstructionStartPosition(pos)) {
2567 parallel_move = CreateParallelMoveBefore(instr, pos); 2492 parallel_move = CreateParallelMoveBefore(instr, pos);
2568 } else { 2493 } else {
2569 parallel_move = CreateParallelMoveAfter(instr, pos); 2494 parallel_move = CreateParallelMoveAfter(instr, pos);
2570 } 2495 }
2571 2496
2572 return parallel_move->AddMove(to, from); 2497 return parallel_move->AddMove(to, from);
2573 } 2498 }
2574 2499
2575
2576 void FlowGraphAllocator::ConvertUseTo(UsePosition* use, Location loc) { 2500 void FlowGraphAllocator::ConvertUseTo(UsePosition* use, Location loc) {
2577 ASSERT(!loc.IsPairLocation()); 2501 ASSERT(!loc.IsPairLocation());
2578 ASSERT(use->location_slot() != NULL); 2502 ASSERT(use->location_slot() != NULL);
2579 Location* slot = use->location_slot(); 2503 Location* slot = use->location_slot();
2580 ASSERT(slot->IsUnallocated()); 2504 ASSERT(slot->IsUnallocated());
2581 TRACE_ALLOC(THR_Print(" use at %" Pd " converted to ", use->pos())); 2505 TRACE_ALLOC(THR_Print(" use at %" Pd " converted to ", use->pos()));
2582 TRACE_ALLOC(loc.Print()); 2506 TRACE_ALLOC(loc.Print());
2583 TRACE_ALLOC(THR_Print("\n")); 2507 TRACE_ALLOC(THR_Print("\n"));
2584 *slot = loc; 2508 *slot = loc;
2585 } 2509 }
2586 2510
2587
2588 void FlowGraphAllocator::ConvertAllUses(LiveRange* range) { 2511 void FlowGraphAllocator::ConvertAllUses(LiveRange* range) {
2589 if (range->vreg() == kNoVirtualRegister) return; 2512 if (range->vreg() == kNoVirtualRegister) return;
2590 2513
2591 const Location loc = range->assigned_location(); 2514 const Location loc = range->assigned_location();
2592 ASSERT(!loc.IsInvalid()); 2515 ASSERT(!loc.IsInvalid());
2593 2516
2594 TRACE_ALLOC(THR_Print("range [%" Pd ", %" Pd ") " 2517 TRACE_ALLOC(THR_Print("range [%" Pd ", %" Pd ") "
2595 "for v%" Pd " has been allocated to ", 2518 "for v%" Pd " has been allocated to ",
2596 range->Start(), range->End(), range->vreg())); 2519 range->Start(), range->End(), range->vreg()));
2597 TRACE_ALLOC(loc.Print()); 2520 TRACE_ALLOC(loc.Print());
(...skipping 15 matching lines...) Expand all
2613 } 2536 }
2614 #else 2537 #else
2615 if (range->representation() == kTagged) { 2538 if (range->representation() == kTagged) {
2616 safepoint->locs()->SetStackBit(loc.reg()); 2539 safepoint->locs()->SetStackBit(loc.reg());
2617 } 2540 }
2618 #endif // !defined(TARGET_ARCH_DBC) 2541 #endif // !defined(TARGET_ARCH_DBC)
2619 } 2542 }
2620 } 2543 }
2621 } 2544 }
2622 2545
2623
2624 void FlowGraphAllocator::AdvanceActiveIntervals(const intptr_t start) { 2546 void FlowGraphAllocator::AdvanceActiveIntervals(const intptr_t start) {
2625 for (intptr_t reg = 0; reg < NumberOfRegisters(); reg++) { 2547 for (intptr_t reg = 0; reg < NumberOfRegisters(); reg++) {
2626 if (registers_[reg]->is_empty()) continue; 2548 if (registers_[reg]->is_empty()) continue;
2627 2549
2628 intptr_t first_evicted = -1; 2550 intptr_t first_evicted = -1;
2629 for (intptr_t i = registers_[reg]->length() - 1; i >= 0; i--) { 2551 for (intptr_t i = registers_[reg]->length() - 1; i >= 0; i--) {
2630 LiveRange* range = (*registers_[reg])[i]; 2552 LiveRange* range = (*registers_[reg])[i];
2631 if (range->finger()->Advance(start)) { 2553 if (range->finger()->Advance(start)) {
2632 ConvertAllUses(range); 2554 ConvertAllUses(range);
2633 (*registers_[reg])[i] = NULL; 2555 (*registers_[reg])[i] = NULL;
2634 first_evicted = i; 2556 first_evicted = i;
2635 } 2557 }
2636 } 2558 }
2637 2559
2638 if (first_evicted != -1) RemoveEvicted(reg, first_evicted); 2560 if (first_evicted != -1) RemoveEvicted(reg, first_evicted);
2639 } 2561 }
2640 } 2562 }
2641 2563
2642
2643 bool LiveRange::Contains(intptr_t pos) const { 2564 bool LiveRange::Contains(intptr_t pos) const {
2644 if (!CanCover(pos)) return false; 2565 if (!CanCover(pos)) return false;
2645 2566
2646 for (UseInterval* interval = first_use_interval_; interval != NULL; 2567 for (UseInterval* interval = first_use_interval_; interval != NULL;
2647 interval = interval->next()) { 2568 interval = interval->next()) {
2648 if (interval->Contains(pos)) { 2569 if (interval->Contains(pos)) {
2649 return true; 2570 return true;
2650 } 2571 }
2651 } 2572 }
2652 2573
2653 return false; 2574 return false;
2654 } 2575 }
2655 2576
2656
2657 void FlowGraphAllocator::AssignSafepoints(Definition* defn, LiveRange* range) { 2577 void FlowGraphAllocator::AssignSafepoints(Definition* defn, LiveRange* range) {
2658 for (intptr_t i = safepoints_.length() - 1; i >= 0; i--) { 2578 for (intptr_t i = safepoints_.length() - 1; i >= 0; i--) {
2659 Instruction* safepoint_instr = safepoints_[i]; 2579 Instruction* safepoint_instr = safepoints_[i];
2660 if (safepoint_instr == defn) { 2580 if (safepoint_instr == defn) {
2661 // The value is not live until after the definition is fully executed, 2581 // The value is not live until after the definition is fully executed,
2662 // don't assign the safepoint inside the definition itself to 2582 // don't assign the safepoint inside the definition itself to
2663 // definition's liverange. 2583 // definition's liverange.
2664 continue; 2584 continue;
2665 } 2585 }
2666 2586
2667 const intptr_t pos = safepoint_instr->lifetime_position(); 2587 const intptr_t pos = safepoint_instr->lifetime_position();
2668 if (range->End() <= pos) break; 2588 if (range->End() <= pos) break;
2669 2589
2670 if (range->Contains(pos)) { 2590 if (range->Contains(pos)) {
2671 range->AddSafepoint(pos, safepoint_instr->locs()); 2591 range->AddSafepoint(pos, safepoint_instr->locs());
2672 } 2592 }
2673 } 2593 }
2674 } 2594 }
2675 2595
2676
2677 static inline bool ShouldBeAllocatedBefore(LiveRange* a, LiveRange* b) { 2596 static inline bool ShouldBeAllocatedBefore(LiveRange* a, LiveRange* b) {
2678 // TODO(vegorov): consider first hint position when ordering live ranges. 2597 // TODO(vegorov): consider first hint position when ordering live ranges.
2679 return a->Start() <= b->Start(); 2598 return a->Start() <= b->Start();
2680 } 2599 }
2681 2600
2682
2683 static void AddToSortedListOfRanges(GrowableArray<LiveRange*>* list, 2601 static void AddToSortedListOfRanges(GrowableArray<LiveRange*>* list,
2684 LiveRange* range) { 2602 LiveRange* range) {
2685 range->finger()->Initialize(range); 2603 range->finger()->Initialize(range);
2686 2604
2687 if (list->is_empty()) { 2605 if (list->is_empty()) {
2688 list->Add(range); 2606 list->Add(range);
2689 return; 2607 return;
2690 } 2608 }
2691 2609
2692 for (intptr_t i = list->length() - 1; i >= 0; i--) { 2610 for (intptr_t i = list->length() - 1; i >= 0; i--) {
2693 if (ShouldBeAllocatedBefore(range, (*list)[i])) { 2611 if (ShouldBeAllocatedBefore(range, (*list)[i])) {
2694 list->InsertAt(i + 1, range); 2612 list->InsertAt(i + 1, range);
2695 return; 2613 return;
2696 } 2614 }
2697 } 2615 }
2698 list->InsertAt(0, range); 2616 list->InsertAt(0, range);
2699 } 2617 }
2700 2618
2701
2702 void FlowGraphAllocator::AddToUnallocated(LiveRange* range) { 2619 void FlowGraphAllocator::AddToUnallocated(LiveRange* range) {
2703 AddToSortedListOfRanges(&unallocated_, range); 2620 AddToSortedListOfRanges(&unallocated_, range);
2704 } 2621 }
2705 2622
2706
2707 void FlowGraphAllocator::CompleteRange(LiveRange* range, Location::Kind kind) { 2623 void FlowGraphAllocator::CompleteRange(LiveRange* range, Location::Kind kind) {
2708 switch (kind) { 2624 switch (kind) {
2709 case Location::kRegister: 2625 case Location::kRegister:
2710 AddToSortedListOfRanges(&unallocated_cpu_, range); 2626 AddToSortedListOfRanges(&unallocated_cpu_, range);
2711 break; 2627 break;
2712 2628
2713 case Location::kFpuRegister: 2629 case Location::kFpuRegister:
2714 AddToSortedListOfRanges(&unallocated_xmm_, range); 2630 AddToSortedListOfRanges(&unallocated_xmm_, range);
2715 break; 2631 break;
2716 2632
2717 default: 2633 default:
2718 UNREACHABLE(); 2634 UNREACHABLE();
2719 } 2635 }
2720 } 2636 }
2721 2637
2722
2723 #if defined(DEBUG) 2638 #if defined(DEBUG)
2724 bool FlowGraphAllocator::UnallocatedIsSorted() { 2639 bool FlowGraphAllocator::UnallocatedIsSorted() {
2725 for (intptr_t i = unallocated_.length() - 1; i >= 1; i--) { 2640 for (intptr_t i = unallocated_.length() - 1; i >= 1; i--) {
2726 LiveRange* a = unallocated_[i]; 2641 LiveRange* a = unallocated_[i];
2727 LiveRange* b = unallocated_[i - 1]; 2642 LiveRange* b = unallocated_[i - 1];
2728 if (!ShouldBeAllocatedBefore(a, b)) { 2643 if (!ShouldBeAllocatedBefore(a, b)) {
2729 UNREACHABLE(); 2644 UNREACHABLE();
2730 return false; 2645 return false;
2731 } 2646 }
2732 } 2647 }
2733 return true; 2648 return true;
2734 } 2649 }
2735 #endif 2650 #endif
2736 2651
2737
2738 void FlowGraphAllocator::PrepareForAllocation( 2652 void FlowGraphAllocator::PrepareForAllocation(
2739 Location::Kind register_kind, 2653 Location::Kind register_kind,
2740 intptr_t number_of_registers, 2654 intptr_t number_of_registers,
2741 const GrowableArray<LiveRange*>& unallocated, 2655 const GrowableArray<LiveRange*>& unallocated,
2742 LiveRange** blocking_ranges, 2656 LiveRange** blocking_ranges,
2743 bool* blocked_registers) { 2657 bool* blocked_registers) {
2744 register_kind_ = register_kind; 2658 register_kind_ = register_kind;
2745 number_of_registers_ = number_of_registers; 2659 number_of_registers_ = number_of_registers;
2746 2660
2747 blocked_registers_.Clear(); 2661 blocked_registers_.Clear();
(...skipping 10 matching lines...) Expand all
2758 ASSERT(registers_[reg]->is_empty()); 2672 ASSERT(registers_[reg]->is_empty());
2759 2673
2760 LiveRange* range = blocking_ranges[reg]; 2674 LiveRange* range = blocking_ranges[reg];
2761 if (range != NULL) { 2675 if (range != NULL) {
2762 range->finger()->Initialize(range); 2676 range->finger()->Initialize(range);
2763 registers_[reg]->Add(range); 2677 registers_[reg]->Add(range);
2764 } 2678 }
2765 } 2679 }
2766 } 2680 }
2767 2681
2768
2769 void FlowGraphAllocator::AllocateUnallocatedRanges() { 2682 void FlowGraphAllocator::AllocateUnallocatedRanges() {
2770 #if defined(DEBUG) 2683 #if defined(DEBUG)
2771 ASSERT(UnallocatedIsSorted()); 2684 ASSERT(UnallocatedIsSorted());
2772 #endif 2685 #endif
2773 2686
2774 while (!unallocated_.is_empty()) { 2687 while (!unallocated_.is_empty()) {
2775 LiveRange* range = unallocated_.RemoveLast(); 2688 LiveRange* range = unallocated_.RemoveLast();
2776 const intptr_t start = range->Start(); 2689 const intptr_t start = range->Start();
2777 TRACE_ALLOC(THR_Print("Processing live range for v%" Pd " " 2690 TRACE_ALLOC(THR_Print("Processing live range for v%" Pd " "
2778 "starting at %" Pd "\n", 2691 "starting at %" Pd "\n",
(...skipping 14 matching lines...) Expand all
2793 } 2706 }
2794 2707
2795 // All allocation decisions were done. 2708 // All allocation decisions were done.
2796 ASSERT(unallocated_.is_empty()); 2709 ASSERT(unallocated_.is_empty());
2797 2710
2798 // Finish allocation. 2711 // Finish allocation.
2799 AdvanceActiveIntervals(kMaxPosition); 2712 AdvanceActiveIntervals(kMaxPosition);
2800 TRACE_ALLOC(THR_Print("Allocation completed\n")); 2713 TRACE_ALLOC(THR_Print("Allocation completed\n"));
2801 } 2714 }
2802 2715
2803
2804 bool FlowGraphAllocator::TargetLocationIsSpillSlot(LiveRange* range, 2716 bool FlowGraphAllocator::TargetLocationIsSpillSlot(LiveRange* range,
2805 Location target) { 2717 Location target) {
2806 if (target.IsStackSlot() || target.IsDoubleStackSlot() || 2718 if (target.IsStackSlot() || target.IsDoubleStackSlot() ||
2807 target.IsConstant()) { 2719 target.IsConstant()) {
2808 ASSERT(GetLiveRange(range->vreg())->spill_slot().Equals(target)); 2720 ASSERT(GetLiveRange(range->vreg())->spill_slot().Equals(target));
2809 return true; 2721 return true;
2810 } 2722 }
2811 return false; 2723 return false;
2812 } 2724 }
2813 2725
2814
2815 void FlowGraphAllocator::ConnectSplitSiblings(LiveRange* parent, 2726 void FlowGraphAllocator::ConnectSplitSiblings(LiveRange* parent,
2816 BlockEntryInstr* source_block, 2727 BlockEntryInstr* source_block,
2817 BlockEntryInstr* target_block) { 2728 BlockEntryInstr* target_block) {
2818 TRACE_ALLOC(THR_Print("Connect v%" Pd " on the edge B%" Pd " -> B%" Pd "\n", 2729 TRACE_ALLOC(THR_Print("Connect v%" Pd " on the edge B%" Pd " -> B%" Pd "\n",
2819 parent->vreg(), source_block->block_id(), 2730 parent->vreg(), source_block->block_id(),
2820 target_block->block_id())); 2731 target_block->block_id()));
2821 if (parent->next_sibling() == NULL) { 2732 if (parent->next_sibling() == NULL) {
2822 // Nothing to connect. The whole range was allocated to the same location. 2733 // Nothing to connect. The whole range was allocated to the same location.
2823 TRACE_ALLOC(THR_Print("range v%" Pd " has no siblings\n", parent->vreg())); 2734 TRACE_ALLOC(THR_Print("range v%" Pd " has no siblings\n", parent->vreg()));
2824 return; 2735 return;
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after
2874 2785
2875 Instruction* last = source_block->last_instruction(); 2786 Instruction* last = source_block->last_instruction();
2876 if ((last->SuccessorCount() == 1) && !source_block->IsGraphEntry()) { 2787 if ((last->SuccessorCount() == 1) && !source_block->IsGraphEntry()) {
2877 ASSERT(last->IsGoto()); 2788 ASSERT(last->IsGoto());
2878 last->AsGoto()->GetParallelMove()->AddMove(target, source); 2789 last->AsGoto()->GetParallelMove()->AddMove(target, source);
2879 } else { 2790 } else {
2880 target_block->GetParallelMove()->AddMove(target, source); 2791 target_block->GetParallelMove()->AddMove(target, source);
2881 } 2792 }
2882 } 2793 }
2883 2794
2884
2885 void FlowGraphAllocator::ResolveControlFlow() { 2795 void FlowGraphAllocator::ResolveControlFlow() {
2886 // Resolve linear control flow between touching split siblings 2796 // Resolve linear control flow between touching split siblings
2887 // inside basic blocks. 2797 // inside basic blocks.
2888 for (intptr_t vreg = 0; vreg < live_ranges_.length(); vreg++) { 2798 for (intptr_t vreg = 0; vreg < live_ranges_.length(); vreg++) {
2889 LiveRange* range = live_ranges_[vreg]; 2799 LiveRange* range = live_ranges_[vreg];
2890 if (range == NULL) continue; 2800 if (range == NULL) continue;
2891 2801
2892 while (range->next_sibling() != NULL) { 2802 while (range->next_sibling() != NULL) {
2893 LiveRange* sibling = range->next_sibling(); 2803 LiveRange* sibling = range->next_sibling();
2894 TRACE_ALLOC(THR_Print("connecting [%" Pd ", %" Pd ") [", range->Start(), 2804 TRACE_ALLOC(THR_Print("connecting [%" Pd ", %" Pd ") [", range->Start(),
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
2930 range->assigned_location().IsDoubleStackSlot() || 2840 range->assigned_location().IsDoubleStackSlot() ||
2931 range->assigned_location().IsConstant()) { 2841 range->assigned_location().IsConstant()) {
2932 ASSERT(range->assigned_location().Equals(range->spill_slot())); 2842 ASSERT(range->assigned_location().Equals(range->spill_slot()));
2933 } else { 2843 } else {
2934 AddMoveAt(range->Start() + 1, range->spill_slot(), 2844 AddMoveAt(range->Start() + 1, range->spill_slot(),
2935 range->assigned_location()); 2845 range->assigned_location());
2936 } 2846 }
2937 } 2847 }
2938 } 2848 }
2939 2849
2940
2941 static Representation RepresentationForRange(Representation definition_rep) { 2850 static Representation RepresentationForRange(Representation definition_rep) {
2942 if (definition_rep == kUnboxedMint) { 2851 if (definition_rep == kUnboxedMint) {
2943 // kUnboxedMint is split into two ranges, each of which are kUntagged. 2852 // kUnboxedMint is split into two ranges, each of which are kUntagged.
2944 return kUntagged; 2853 return kUntagged;
2945 } else if (definition_rep == kUnboxedUint32) { 2854 } else if (definition_rep == kUnboxedUint32) {
2946 // kUnboxedUint32 is untagged. 2855 // kUnboxedUint32 is untagged.
2947 return kUntagged; 2856 return kUntagged;
2948 } 2857 }
2949 return definition_rep; 2858 return definition_rep;
2950 } 2859 }
2951 2860
2952
2953 void FlowGraphAllocator::CollectRepresentations() { 2861 void FlowGraphAllocator::CollectRepresentations() {
2954 // Parameters. 2862 // Parameters.
2955 GraphEntryInstr* graph_entry = flow_graph_.graph_entry(); 2863 GraphEntryInstr* graph_entry = flow_graph_.graph_entry();
2956 for (intptr_t i = 0; i < graph_entry->initial_definitions()->length(); ++i) { 2864 for (intptr_t i = 0; i < graph_entry->initial_definitions()->length(); ++i) {
2957 Definition* def = (*graph_entry->initial_definitions())[i]; 2865 Definition* def = (*graph_entry->initial_definitions())[i];
2958 value_representations_[def->ssa_temp_index()] = 2866 value_representations_[def->ssa_temp_index()] =
2959 RepresentationForRange(def->representation()); 2867 RepresentationForRange(def->representation());
2960 ASSERT(!def->HasPairRepresentation()); 2868 ASSERT(!def->HasPairRepresentation());
2961 } 2869 }
2962 2870
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
2999 RepresentationForRange(def->representation()); 2907 RepresentationForRange(def->representation());
3000 if (def->HasPairRepresentation()) { 2908 if (def->HasPairRepresentation()) {
3001 value_representations_[ToSecondPairVreg(vreg)] = 2909 value_representations_[ToSecondPairVreg(vreg)] =
3002 RepresentationForRange(def->representation()); 2910 RepresentationForRange(def->representation());
3003 } 2911 }
3004 } 2912 }
3005 } 2913 }
3006 } 2914 }
3007 } 2915 }
3008 2916
3009
3010 void FlowGraphAllocator::AllocateRegisters() { 2917 void FlowGraphAllocator::AllocateRegisters() {
3011 CollectRepresentations(); 2918 CollectRepresentations();
3012 2919
3013 liveness_.Analyze(); 2920 liveness_.Analyze();
3014 2921
3015 NumberInstructions(); 2922 NumberInstructions();
3016 2923
3017 DiscoverLoops(); 2924 DiscoverLoops();
3018 2925
3019 #if defined(TARGET_ARCH_DBC) 2926 #if defined(TARGET_ARCH_DBC)
(...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after
3101 if (FLAG_support_il_printer) { 3008 if (FLAG_support_il_printer) {
3102 #ifndef PRODUCT 3009 #ifndef PRODUCT
3103 FlowGraphPrinter printer(flow_graph_, true); 3010 FlowGraphPrinter printer(flow_graph_, true);
3104 printer.PrintBlocks(); 3011 printer.PrintBlocks();
3105 #endif 3012 #endif
3106 } 3013 }
3107 THR_Print("----------------------------------------------\n"); 3014 THR_Print("----------------------------------------------\n");
3108 } 3015 }
3109 } 3016 }
3110 3017
3111
3112 } // namespace dart 3018 } // namespace dart
OLDNEW
« no previous file with comments | « runtime/vm/flow_graph_allocator.h ('k') | runtime/vm/flow_graph_builder.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698