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

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

Issue 10828115: Implement simple spill store elimination. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: address Srdjan's comments Created 8 years, 4 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 | Annotate | Revision Log
« no previous file with comments | « runtime/vm/flow_graph_allocator.h ('k') | runtime/vm/locations.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) 2012, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2012, 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" 8 #include "vm/intermediate_language.h"
9 #include "vm/il_printer.h" 9 #include "vm/il_printer.h"
10 #include "vm/flow_graph_builder.h" 10 #include "vm/flow_graph_builder.h"
11 #include "vm/flow_graph_compiler.h" 11 #include "vm/flow_graph_compiler.h"
12 #include "vm/parser.h" 12 #include "vm/parser.h"
13 13
14 namespace dart { 14 namespace dart {
15 15
16 DEFINE_FLAG(bool, print_ssa_liveness, false, 16 DEFINE_FLAG(bool, print_ssa_liveness, false,
17 "Print liveness for ssa variables."); 17 "Print liveness for ssa variables.");
18 DEFINE_FLAG(bool, trace_ssa_allocator, false, 18 DEFINE_FLAG(bool, trace_ssa_allocator, false,
19 "Trace register allocation over SSA."); 19 "Trace register allocation over SSA.");
20 DEFINE_FLAG(bool, print_ssa_liveranges, false,
21 "Print live ranges after allocation.");
20 22
21 #ifdef DEBUG 23 #if defined(DEBUG)
22 #define TRACE_ALLOC(m) do { \ 24 #define TRACE_ALLOC(m) do { \
23 if (FLAG_trace_ssa_allocator) OS::Print m ; \ 25 if (FLAG_trace_ssa_allocator) OS::Print m ; \
24 } while (0) 26 } while (0)
25 #else 27 #else
26 #define TRACE_ALLOC(m) 28 #define TRACE_ALLOC(m)
27 #endif 29 #endif
28 30
29 31
30 static const intptr_t kNoVirtualRegister = -1; 32 static const intptr_t kNoVirtualRegister = -1;
31 static const intptr_t kTempVirtualRegister = -2; 33 static const intptr_t kTempVirtualRegister = -2;
(...skipping 300 matching lines...) Expand 10 before | Expand all | Expand 10 after
332 334
333 335
334 LiveRange* FlowGraphAllocator::GetLiveRange(intptr_t vreg) { 336 LiveRange* FlowGraphAllocator::GetLiveRange(intptr_t vreg) {
335 if (live_ranges_[vreg] == NULL) { 337 if (live_ranges_[vreg] == NULL) {
336 live_ranges_[vreg] = new LiveRange(vreg); 338 live_ranges_[vreg] = new LiveRange(vreg);
337 } 339 }
338 return live_ranges_[vreg]; 340 return live_ranges_[vreg];
339 } 341 }
340 342
341 343
344 LiveRange* FlowGraphAllocator::MakeLiveRangeForTemporary() {
345 LiveRange* range = new LiveRange(kTempVirtualRegister);
346 #if defined(DEBUG)
347 temporaries_.Add(range);
348 #endif
349 return range;
350 }
351
352
342 // Block location from the start of the instruction to its end. 353 // Block location from the start of the instruction to its end.
343 void FlowGraphAllocator::BlockLocation(Location loc, intptr_t pos) { 354 void FlowGraphAllocator::BlockLocation(Location loc, intptr_t pos) {
344 ASSERT(loc.IsRegister()); 355 ASSERT(loc.IsRegister());
345 ASSERT(IsInstructionStartPosition(pos)); 356 ASSERT(IsInstructionStartPosition(pos));
346 const Register reg = loc.reg(); 357 const Register reg = loc.reg();
347 if (blocked_cpu_regs_[reg]) return; 358 if (blocked_cpu_regs_[reg]) return;
348 if (cpu_regs_[reg].length() == 0) { 359 if (cpu_regs_[reg].length() == 0) {
349 cpu_regs_[reg].Add(new LiveRange(kNoVirtualRegister)); 360 LiveRange* range = new LiveRange(kNoVirtualRegister);
361 cpu_regs_[reg].Add(range);
362 range->set_assigned_location(loc);
363 #if defined(DEBUG)
364 temporaries_.Add(range);
365 #endif
350 } 366 }
351 cpu_regs_[reg][0]->AddUseInterval(pos, pos + 1); 367 cpu_regs_[reg][0]->AddUseInterval(pos, pos + 1);
352 } 368 }
353 369
354 370
355 void LiveRange::Print() { 371 void LiveRange::Print() {
356 OS::Print(" live range v%d [%d, %d)\n", vreg(), Start(), End()); 372 if (first_use_interval() == NULL) {
373 return;
374 }
375
376 OS::Print(" live range v%d [%d, %d) in ", vreg(), Start(), End());
377 assigned_location().Print();
378 OS::Print("\n");
379
357 UsePosition* use_pos = uses_; 380 UsePosition* use_pos = uses_;
358 for (UseInterval* interval = first_use_interval_; 381 for (UseInterval* interval = first_use_interval_;
359 interval != NULL; 382 interval != NULL;
360 interval = interval->next()) { 383 interval = interval->next()) {
361 OS::Print(" use interval [%d, %d)\n", 384 OS::Print(" use interval [%d, %d)\n",
362 interval->start(), 385 interval->start(),
363 interval->end()); 386 interval->end());
364 while ((use_pos != NULL) && (use_pos->pos() <= interval->end())) { 387 while ((use_pos != NULL) && (use_pos->pos() <= interval->end())) {
365 OS::Print(" use at %d as %s\n", 388 OS::Print(" use at %d", use_pos->pos());
366 use_pos->pos(), 389 if (use_pos->location_slot() != NULL) {
367 (use_pos->location_slot() == NULL) 390 OS::Print(" as ");
368 ? "-" : use_pos->location_slot()->Name()); 391 use_pos->location_slot()->Print();
392 }
393 OS::Print("\n");
369 use_pos = use_pos->next(); 394 use_pos = use_pos->next();
370 } 395 }
371 } 396 }
372 397
373 if (next_sibling() != NULL) { 398 if (next_sibling() != NULL) {
374 next_sibling()->Print(); 399 next_sibling()->Print();
375 } 400 }
376 } 401 }
377 402
378 403
379 void FlowGraphAllocator::PrintLiveRanges() { 404 void FlowGraphAllocator::PrintLiveRanges() {
380 for (intptr_t i = 0; i < unallocated_.length(); i++) { 405 #if defined(DEBUG)
381 unallocated_[i]->Print(); 406 for (intptr_t i = 0; i < temporaries_.length(); i++) {
407 temporaries_[i]->Print();
382 } 408 }
409 #endif
383 410
384 for (intptr_t reg = 0; reg < kNumberOfCpuRegisters; reg++) { 411 for (intptr_t i = 0; i < live_ranges_.length(); i++) {
385 if (blocked_cpu_regs_[reg]) continue; 412 if (live_ranges_[i] != NULL) {
386 if (cpu_regs_[reg].length() == 0) continue; 413 live_ranges_[i]->Print();
387 414 }
388 ASSERT(cpu_regs_[reg].length() == 1);
389 OS::Print("blocking live range for %s\n",
390 Location::RegisterLocation(static_cast<Register>(reg)).Name());
391 cpu_regs_[reg][0]->Print();
392 } 415 }
393 } 416 }
394 417
395 418
396 void FlowGraphAllocator::BuildLiveRanges() { 419 void FlowGraphAllocator::BuildLiveRanges() {
397 NumberInstructions(); 420 NumberInstructions();
398 421
399 const intptr_t block_count = postorder_.length(); 422 const intptr_t block_count = postorder_.length();
400 ASSERT(postorder_[block_count - 1]->IsGraphEntry()); 423 ASSERT(postorder_[block_count - 1]->IsGraphEntry());
401 for (intptr_t i = 0; i < (block_count - 1); i++) { 424 for (intptr_t i = 0; i < (block_count - 1); i++) {
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
435 if (val->IsUse()) { 458 if (val->IsUse()) {
436 ParameterInstr* param = val->AsUse()->definition()->AsParameter(); 459 ParameterInstr* param = val->AsUse()->definition()->AsParameter();
437 460
438 LiveRange* range = GetLiveRange(param->ssa_temp_index()); 461 LiveRange* range = GetLiveRange(param->ssa_temp_index());
439 range->AddUseInterval(graph_entry->start_pos(), graph_entry->end_pos()); 462 range->AddUseInterval(graph_entry->start_pos(), graph_entry->end_pos());
440 range->DefineAt(graph_entry->start_pos()); 463 range->DefineAt(graph_entry->start_pos());
441 464
442 // Slot index for the rightmost parameter is -1. 465 // Slot index for the rightmost parameter is -1.
443 const intptr_t slot_index = param->index() - fixed_parameters_count; 466 const intptr_t slot_index = param->index() - fixed_parameters_count;
444 range->set_assigned_location(Location::StackSlot(slot_index)); 467 range->set_assigned_location(Location::StackSlot(slot_index));
468 range->set_spill_slot(Location::StackSlot(slot_index));
445 469
446 range->finger()->Initialize(range); 470 range->finger()->Initialize(range);
447 UsePosition* use = range->finger()->FirstRegisterBeneficialUse( 471 UsePosition* use = range->finger()->FirstRegisterBeneficialUse(
448 graph_entry->start_pos()); 472 graph_entry->start_pos());
449 if (use != NULL) { 473 if (use != NULL) {
450 LiveRange* tail = SplitBetween(range, 474 LiveRange* tail = SplitBetween(range,
451 graph_entry->start_pos(), 475 graph_entry->start_pos(),
452 use->pos()); 476 use->pos());
453 AddToUnallocated(tail); 477 AddToUnallocated(tail);
454 } 478 }
(...skipping 233 matching lines...) Expand 10 before | Expand all | Expand 10 after
688 // Expected shape of live range: 712 // Expected shape of live range:
689 // 713 //
690 // i i' 714 // i i'
691 // [--) 715 // [--)
692 // 716 //
693 717
694 Location temp = locs->temp(j); 718 Location temp = locs->temp(j);
695 if (temp.IsRegister()) { 719 if (temp.IsRegister()) {
696 BlockLocation(temp, pos); 720 BlockLocation(temp, pos);
697 } else if (temp.IsUnallocated()) { 721 } else if (temp.IsUnallocated()) {
698 LiveRange* range = new LiveRange(kTempVirtualRegister); 722 LiveRange* range = MakeLiveRangeForTemporary();
699 range->AddUseInterval(pos, pos + 1); 723 range->AddUseInterval(pos, pos + 1);
700 range->AddUse(pos, locs->temp_slot(j)); 724 range->AddUse(pos, locs->temp_slot(j));
701 AddToUnallocated(range); 725 AddToUnallocated(range);
702 } else { 726 } else {
703 UNREACHABLE(); 727 UNREACHABLE();
704 } 728 }
705 } 729 }
706 730
707 // Block all allocatable registers for calls. 731 // Block all allocatable registers for calls.
708 if (locs->is_call()) { 732 if (locs->is_call()) {
709 // Expected shape of live range: 733 // Expected shape of live range:
710 // 734 //
711 // i i' 735 // i i'
712 // [--) 736 // [--)
713 // 737 //
714 738
715 for (intptr_t reg = 0; reg < kNumberOfCpuRegisters; reg++) { 739 for (intptr_t reg = 0; reg < kNumberOfCpuRegisters; reg++) {
716 BlockLocation(Location::RegisterLocation(static_cast<Register>(reg)), 740 BlockLocation(Location::RegisterLocation(static_cast<Register>(reg)),
717 pos); 741 pos);
718 } 742 }
719 743
720 #ifdef DEBUG 744 #if defined(DEBUG)
721 // Verify that temps, inputs and output were specified as fixed 745 // Verify that temps, inputs and output were specified as fixed
722 // locations. Every register is blocked now so attempt to 746 // locations. Every register is blocked now so attempt to
723 // allocate will not succeed. 747 // allocate will not succeed.
724 for (intptr_t j = 0; j < locs->temp_count(); j++) { 748 for (intptr_t j = 0; j < locs->temp_count(); j++) {
725 ASSERT(!locs->temp(j).IsUnallocated()); 749 ASSERT(!locs->temp(j).IsUnallocated());
726 } 750 }
727 751
728 for (intptr_t j = 0; j < locs->input_count(); j++) { 752 for (intptr_t j = 0; j < locs->input_count(); j++) {
729 ASSERT(!locs->in(j).IsUnallocated()); 753 ASSERT(!locs->in(j).IsUnallocated());
730 } 754 }
(...skipping 10 matching lines...) Expand all
741 765
742 if (locs->out().IsInvalid()) { 766 if (locs->out().IsInvalid()) {
743 ASSERT(def->ssa_temp_index() < 0); 767 ASSERT(def->ssa_temp_index() < 0);
744 return; 768 return;
745 } 769 }
746 770
747 // We might have a definition without use. We do not assign SSA index to 771 // We might have a definition without use. We do not assign SSA index to
748 // such definitions. 772 // such definitions.
749 LiveRange* range = (def->ssa_temp_index() >= 0) ? 773 LiveRange* range = (def->ssa_temp_index() >= 0) ?
750 GetLiveRange(def->ssa_temp_index()) : 774 GetLiveRange(def->ssa_temp_index()) :
751 new LiveRange(kTempVirtualRegister); 775 MakeLiveRangeForTemporary();
752 Location* out = locs->out_slot(); 776 Location* out = locs->out_slot();
753 777
754 // Process output and finalize its liverange. 778 // Process output and finalize its liverange.
755 if (out->IsRegister()) { 779 if (out->IsRegister()) {
756 // Fixed output location. Expected shape of live range: 780 // Fixed output location. Expected shape of live range:
757 // 781 //
758 // i i' j j' 782 // i i' j j'
759 // register [--) 783 // register [--)
760 // output [------- 784 // output [-------
761 // 785 //
(...skipping 386 matching lines...) Expand 10 before | Expand all | Expand 10 after
1148 1172
1149 1173
1150 void FlowGraphAllocator::SpillAfter(LiveRange* range, intptr_t from) { 1174 void FlowGraphAllocator::SpillAfter(LiveRange* range, intptr_t from) {
1151 TRACE_ALLOC(("spill %d [%d, %d) after %d\n", 1175 TRACE_ALLOC(("spill %d [%d, %d) after %d\n",
1152 range->vreg(), range->Start(), range->End(), from)); 1176 range->vreg(), range->Start(), range->End(), from));
1153 LiveRange* tail = range->SplitAt(from); 1177 LiveRange* tail = range->SplitAt(from);
1154 Spill(tail); 1178 Spill(tail);
1155 } 1179 }
1156 1180
1157 1181
1158 intptr_t FlowGraphAllocator::AllocateSpillSlotFor(LiveRange* range) { 1182 void FlowGraphAllocator::AllocateSpillSlotFor(LiveRange* range) {
1159 for (intptr_t i = 0; i < spill_slots_.length(); i++) { 1183 ASSERT(range->spill_slot().IsInvalid());
1160 if (spill_slots_[i] <= range->Start()) { 1184
1161 return i; 1185 intptr_t idx = 0;
1162 } 1186 for (; idx < spill_slots_.length(); idx++) {
1187 if (spill_slots_[idx] <= range->Start()) break;
1163 } 1188 }
1164 spill_slots_.Add(0); 1189
1165 return spill_slots_.length() - 1; 1190 if (idx == spill_slots_.length()) spill_slots_.Add(0);
1191
1192 LiveRange* last_sibling = range;
1193 while (last_sibling->next_sibling() != NULL) {
1194 last_sibling = last_sibling->next_sibling();
1195 }
1196
1197 spill_slots_[idx] = last_sibling->End();
1198
1199 range->set_spill_slot(Location::StackSlot(idx));
1200
1201 spilled_.Add(range);
1166 } 1202 }
1167 1203
1168 1204
1169 void FlowGraphAllocator::Spill(LiveRange* range) { 1205 void FlowGraphAllocator::Spill(LiveRange* range) {
1170 const intptr_t spill_index = AllocateSpillSlotFor(range); 1206 LiveRange* parent = GetLiveRange(range->vreg());
1171 ASSERT(spill_slots_[spill_index] <= range->Start()); 1207
1172 spill_slots_[spill_index] = range->End(); 1208 if (parent->spill_slot().IsInvalid()) AllocateSpillSlotFor(parent);
1173 range->set_assigned_location(Location::StackSlot(spill_index)); 1209
1210 range->set_assigned_location(parent->spill_slot());
1174 ConvertAllUses(range); 1211 ConvertAllUses(range);
1175 } 1212 }
1176 1213
1177 1214
1178 intptr_t FlowGraphAllocator::FirstIntersectionWithAllocated( 1215 intptr_t FlowGraphAllocator::FirstIntersectionWithAllocated(
1179 Register reg, LiveRange* unallocated) { 1216 Register reg, LiveRange* unallocated) {
1180 intptr_t intersection = kMaxPosition; 1217 intptr_t intersection = kMaxPosition;
1181 for (intptr_t i = 0; i < cpu_regs_[reg].length(); i++) { 1218 for (intptr_t i = 0; i < cpu_regs_[reg].length(); i++) {
1182 LiveRange* allocated = cpu_regs_[reg][i]; 1219 LiveRange* allocated = cpu_regs_[reg][i];
1183 if (allocated == NULL) continue; 1220 if (allocated == NULL) continue;
(...skipping 320 matching lines...) Expand 10 before | Expand all | Expand 10 after
1504 for (intptr_t i = unallocated_.length() - 1; i >= 0; i--) { 1541 for (intptr_t i = unallocated_.length() - 1; i >= 0; i--) {
1505 if (ShouldBeAllocatedBefore(range, unallocated_[i])) { 1542 if (ShouldBeAllocatedBefore(range, unallocated_[i])) {
1506 unallocated_.InsertAt(i + 1, range); 1543 unallocated_.InsertAt(i + 1, range);
1507 return; 1544 return;
1508 } 1545 }
1509 } 1546 }
1510 unallocated_.InsertAt(0, range); 1547 unallocated_.InsertAt(0, range);
1511 } 1548 }
1512 1549
1513 1550
1514 #ifdef DEBUG 1551 #if defined(DEBUG)
1515 bool FlowGraphAllocator::UnallocatedIsSorted() { 1552 bool FlowGraphAllocator::UnallocatedIsSorted() {
1516 for (intptr_t i = unallocated_.length() - 1; i >= 1; i--) { 1553 for (intptr_t i = unallocated_.length() - 1; i >= 1; i--) {
1517 LiveRange* a = unallocated_[i]; 1554 LiveRange* a = unallocated_[i];
1518 LiveRange* b = unallocated_[i - 1]; 1555 LiveRange* b = unallocated_[i - 1];
1519 if (!ShouldBeAllocatedBefore(a, b)) return false; 1556 if (!ShouldBeAllocatedBefore(a, b)) return false;
1520 } 1557 }
1521 return true; 1558 return true;
1522 } 1559 }
1523 #endif 1560 #endif
1524 1561
1525 1562
1526 void FlowGraphAllocator::AllocateCPURegisters() { 1563 void FlowGraphAllocator::AllocateCPURegisters() {
1527 #ifdef DEBUG 1564 #if defined(DEBUG)
1528 ASSERT(UnallocatedIsSorted()); 1565 ASSERT(UnallocatedIsSorted());
1529 #endif 1566 #endif
1530 1567
1531 for (intptr_t i = 0; i < kNumberOfCpuRegisters; i++) { 1568 for (intptr_t i = 0; i < kNumberOfCpuRegisters; i++) {
1532 if (cpu_regs_[i].length() == 1) { 1569 if (cpu_regs_[i].length() == 1) {
1533 LiveRange* range = cpu_regs_[i][0]; 1570 LiveRange* range = cpu_regs_[i][0];
1534 range->finger()->Initialize(range); 1571 range->finger()->Initialize(range);
1535 } 1572 }
1536 } 1573 }
1537 1574
(...skipping 15 matching lines...) Expand all
1553 1590
1554 // All allocation decisions were done. 1591 // All allocation decisions were done.
1555 ASSERT(unallocated_.is_empty()); 1592 ASSERT(unallocated_.is_empty());
1556 1593
1557 // Finish allocation. 1594 // Finish allocation.
1558 AdvanceActiveIntervals(kMaxPosition); 1595 AdvanceActiveIntervals(kMaxPosition);
1559 TRACE_ALLOC(("Allocation completed\n")); 1596 TRACE_ALLOC(("Allocation completed\n"));
1560 } 1597 }
1561 1598
1562 1599
1563 void FlowGraphAllocator::ConnectSplitSiblings(LiveRange* range, 1600 void FlowGraphAllocator::ConnectSplitSiblings(LiveRange* parent,
1564 BlockEntryInstr* source_block, 1601 BlockEntryInstr* source_block,
1565 BlockEntryInstr* target_block) { 1602 BlockEntryInstr* target_block) {
1566 TRACE_ALLOC(("Connect source_block=%d, target_block=%d\n", 1603 TRACE_ALLOC(("Connect source_block=%d, target_block=%d\n",
1567 source_block->block_id(), 1604 source_block->block_id(),
1568 target_block->block_id())); 1605 target_block->block_id()));
1569 if (range->next_sibling() == NULL) { 1606 if (parent->next_sibling() == NULL) {
1570 // Nothing to connect. The whole range was allocated to the same location. 1607 // Nothing to connect. The whole range was allocated to the same location.
1571 TRACE_ALLOC(("range %d has no siblings\n", range->vreg())); 1608 TRACE_ALLOC(("range %d has no siblings\n", parent->vreg()));
1572 return; 1609 return;
1573 } 1610 }
1574 1611
1575 const intptr_t source_pos = source_block->end_pos() - 1; 1612 const intptr_t source_pos = source_block->end_pos() - 1;
1576 ASSERT(IsInstructionEndPosition(source_pos)); 1613 ASSERT(IsInstructionEndPosition(source_pos));
1577 1614
1578 const intptr_t target_pos = target_block->start_pos(); 1615 const intptr_t target_pos = target_block->start_pos();
1579 1616
1580 Location target; 1617 Location target;
1581 Location source; 1618 Location source;
1582 1619
1583 #ifdef DEBUG 1620 #if defined(DEBUG)
1584 LiveRange* source_cover = NULL; 1621 LiveRange* source_cover = NULL;
1585 LiveRange* target_cover = NULL; 1622 LiveRange* target_cover = NULL;
1586 #endif 1623 #endif
1587 1624
1625 LiveRange* range = parent;
1588 while ((range != NULL) && (source.IsInvalid() || target.IsInvalid())) { 1626 while ((range != NULL) && (source.IsInvalid() || target.IsInvalid())) {
1589 if (range->CanCover(source_pos)) { 1627 if (range->CanCover(source_pos)) {
1590 ASSERT(source.IsInvalid()); 1628 ASSERT(source.IsInvalid());
1591 source = range->assigned_location(); 1629 source = range->assigned_location();
1592 #ifdef DEBUG 1630 #if defined(DEBUG)
1593 source_cover = range; 1631 source_cover = range;
1594 #endif 1632 #endif
1595 } 1633 }
1596 if (range->CanCover(target_pos)) { 1634 if (range->CanCover(target_pos)) {
1597 ASSERT(target.IsInvalid()); 1635 ASSERT(target.IsInvalid());
1598 target = range->assigned_location(); 1636 target = range->assigned_location();
1599 #ifdef DEBUG 1637 #if defined(DEBUG)
1600 target_cover = range; 1638 target_cover = range;
1601 #endif 1639 #endif
1602 } 1640 }
1603 1641
1604 range = range->next_sibling(); 1642 range = range->next_sibling();
1605 } 1643 }
1606 1644
1607 TRACE_ALLOC(("connecting [%d, %d) [%s] to [%d, %d) [%s]\n", 1645 TRACE_ALLOC(("connecting [%d, %d) [%s] to [%d, %d) [%s]\n",
1608 source_cover->Start(), source_cover->End(), source.Name(), 1646 source_cover->Start(), source_cover->End(), source.Name(),
1609 target_cover->Start(), target_cover->End(), target.Name())); 1647 target_cover->Start(), target_cover->End(), target.Name()));
1610 1648
1611 // Siblings were allocated to the same register. 1649 // Siblings were allocated to the same register.
1612 if (source.Equals(target)) return; 1650 if (source.Equals(target)) return;
1613 1651
1652 // Values are eagerly spilled. Spill slot already contains appropriate value.
1653 if (target.IsStackSlot()) {
1654 ASSERT(parent->spill_slot().Equals(target));
1655 return;
1656 }
1657
1614 Instruction* last = source_block->last_instruction(); 1658 Instruction* last = source_block->last_instruction();
1615 if (last->SuccessorCount() == 1) { 1659 if (last->SuccessorCount() == 1) {
1616 ASSERT(last->IsGoto()); 1660 ASSERT(last->IsGoto());
1617 last->AsGoto()->GetParallelMove()->AddMove(target, source); 1661 last->AsGoto()->GetParallelMove()->AddMove(target, source);
1618 } else { 1662 } else {
1619 target_block->GetParallelMove()->AddMove(target, source); 1663 target_block->GetParallelMove()->AddMove(target, source);
1620 } 1664 }
1621 } 1665 }
1622 1666
1623 1667
1624 void FlowGraphAllocator::ResolveControlFlow() { 1668 void FlowGraphAllocator::ResolveControlFlow() {
1625 // Resolve linear control flow between touching split siblings 1669 // Resolve linear control flow between touching split siblings
1626 // inside basic blocks. 1670 // inside basic blocks.
1627 for (intptr_t vreg = 0; vreg < live_ranges_.length(); vreg++) { 1671 for (intptr_t vreg = 0; vreg < live_ranges_.length(); vreg++) {
1628 LiveRange* range = live_ranges_[vreg]; 1672 LiveRange* range = live_ranges_[vreg];
1629 if (range == NULL) continue; 1673 if (range == NULL) continue;
1630 1674
1631 while (range->next_sibling() != NULL) { 1675 while (range->next_sibling() != NULL) {
1632 LiveRange* sibling = range->next_sibling(); 1676 LiveRange* sibling = range->next_sibling();
1633 TRACE_ALLOC(("connecting [%d, %d) [%s] to [%d, %d) [%s]\n", 1677 TRACE_ALLOC(("connecting [%d, %d) [%s] to [%d, %d) [%s]\n",
1634 range->Start(), range->End(), 1678 range->Start(), range->End(),
1635 range->assigned_location().Name(), 1679 range->assigned_location().Name(),
1636 sibling->Start(), sibling->End(), 1680 sibling->Start(), sibling->End(),
1637 sibling->assigned_location().Name())); 1681 sibling->assigned_location().Name()));
1638 if ((range->End() == sibling->Start()) && 1682 if ((range->End() == sibling->Start()) &&
1683 !sibling->assigned_location().IsStackSlot() &&
1639 !range->assigned_location().Equals(sibling->assigned_location()) && 1684 !range->assigned_location().Equals(sibling->assigned_location()) &&
1640 !IsBlockEntry(range->End())) { 1685 !IsBlockEntry(range->End())) {
1641 AddMoveAt(sibling->Start(), 1686 AddMoveAt(sibling->Start(),
1642 sibling->assigned_location(), 1687 sibling->assigned_location(),
1643 range->assigned_location()); 1688 range->assigned_location());
1644 } 1689 }
1645 range = sibling; 1690 range = sibling;
1646 } 1691 }
1647 } 1692 }
1648 1693
1649 // Resolve non-linear control flow across branches. 1694 // Resolve non-linear control flow across branches.
1650 for (intptr_t i = 1; i < block_order_.length(); i++) { 1695 for (intptr_t i = 1; i < block_order_.length(); i++) {
1651 BlockEntryInstr* block = block_order_[i]; 1696 BlockEntryInstr* block = block_order_[i];
1652 BitVector* live = live_in_[block->postorder_number()]; 1697 BitVector* live = live_in_[block->postorder_number()];
1653 for (BitVector::Iterator it(live); !it.Done(); it.Advance()) { 1698 for (BitVector::Iterator it(live); !it.Done(); it.Advance()) {
1654 LiveRange* range = GetLiveRange(it.Current()); 1699 LiveRange* range = GetLiveRange(it.Current());
1655 for (intptr_t j = 0; j < block->PredecessorCount(); j++) { 1700 for (intptr_t j = 0; j < block->PredecessorCount(); j++) {
1656 ConnectSplitSiblings(range, block->PredecessorAt(j), block); 1701 ConnectSplitSiblings(range, block->PredecessorAt(j), block);
1657 } 1702 }
1658 } 1703 }
1659 } 1704 }
1705
1706 // Eagerly spill values.
1707 // TODO(vegorov): if value is spilled on the cold path (e.g. by the call)
1708 // this will cause spilling to occur on the fast path (at the definition).
1709 for (intptr_t i = 0; i < spilled_.length(); i++) {
1710 LiveRange* range = spilled_[i];
1711 if (range->assigned_location().IsStackSlot()) {
1712 ASSERT(range->assigned_location().Equals(range->spill_slot()));
1713 } else {
1714 AddMoveAt(range->Start() + 1,
1715 range->spill_slot(),
1716 range->assigned_location());
1717 }
1718 }
1660 } 1719 }
1661 1720
1662 1721
1663 void FlowGraphAllocator::AllocateRegisters() { 1722 void FlowGraphAllocator::AllocateRegisters() {
1664 EliminateEnvironmentUses(); 1723 EliminateEnvironmentUses();
1665 1724
1666 AnalyzeLiveness(); 1725 AnalyzeLiveness();
1667 1726
1668 BuildLiveRanges(); 1727 BuildLiveRanges();
1669 1728
1670 if (FLAG_print_ssa_liveness) { 1729 if (FLAG_print_ssa_liveness) {
1671 DumpLiveness(); 1730 DumpLiveness();
1672 } 1731 }
1673 1732
1674 if (FLAG_trace_ssa_allocator) {
1675 PrintLiveRanges();
1676 }
1677
1678 AllocateCPURegisters(); 1733 AllocateCPURegisters();
1679 1734
1680 ResolveControlFlow(); 1735 ResolveControlFlow();
1681 1736
1682 GraphEntryInstr* entry = block_order_[0]->AsGraphEntry(); 1737 GraphEntryInstr* entry = block_order_[0]->AsGraphEntry();
1683 ASSERT(entry != NULL); 1738 ASSERT(entry != NULL);
1684 entry->set_spill_slot_count(spill_slots_.length()); 1739 entry->set_spill_slot_count(spill_slots_.length());
1685 1740
1686 if (FLAG_trace_ssa_allocator) { 1741 if (FLAG_print_ssa_liveranges) {
1687 OS::Print("-- ir after allocation -------------------------\n"); 1742 const Function& function = builder_->parsed_function().function();
1743
1744 OS::Print("-- [after ssa allocator] ranges [%s] ---------\n",
1745 function.ToFullyQualifiedCString());
1746 PrintLiveRanges();
1747 OS::Print("----------------------------------------------\n");
1748
1749 OS::Print("-- [after ssa allocator] ir [%s] -------------\n",
1750 function.ToFullyQualifiedCString());
1688 FlowGraphPrinter printer(Function::Handle(), block_order_, true); 1751 FlowGraphPrinter printer(Function::Handle(), block_order_, true);
1689 printer.PrintBlocks(); 1752 printer.PrintBlocks();
1753 OS::Print("----------------------------------------------\n");
1690 } 1754 }
1691 } 1755 }
1692 1756
1693 1757
1694 } // namespace dart 1758 } // namespace dart
OLDNEW
« no previous file with comments | « runtime/vm/flow_graph_allocator.h ('k') | runtime/vm/locations.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698