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

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

Issue 12946004: Register allocation tweaks: (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 7 years, 9 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 | « no previous file | no next file » | 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" 8 #include "vm/intermediate_language.h"
9 #include "vm/il_printer.h" 9 #include "vm/il_printer.h"
10 #include "vm/flow_graph.h" 10 #include "vm/flow_graph.h"
(...skipping 492 matching lines...) Expand 10 before | Expand all | Expand 10 after
503 if (!use->location_slot()->Equals(Location::Any())) { 503 if (!use->location_slot()->Equals(Location::Any())) {
504 return false; 504 return false;
505 } 505 }
506 use = use->next(); 506 use = use->next();
507 } 507 }
508 508
509 return true; 509 return true;
510 } 510 }
511 511
512 512
513 // Returns true if all uses of the given range have Any allocation policy.
514 static bool HasOnlyUnconstrainedUses(LiveRange* range) {
515 UsePosition* use = range->first_use();
516 while (use != NULL) {
517 if (!use->location_slot()->Equals(Location::Any())) {
518 return false;
519 }
520 use = use->next();
521 }
522 return true;
523 }
524
525
513 void FlowGraphAllocator::BuildLiveRanges() { 526 void FlowGraphAllocator::BuildLiveRanges() {
514 const intptr_t block_count = postorder_.length(); 527 const intptr_t block_count = postorder_.length();
515 ASSERT(postorder_.Last()->IsGraphEntry()); 528 ASSERT(postorder_.Last()->IsGraphEntry());
516 BitVector* current_interference_set = NULL; 529 BitVector* current_interference_set = NULL;
517 for (intptr_t i = 0; i < (block_count - 1); i++) { 530 for (intptr_t i = 0; i < (block_count - 1); i++) {
518 BlockEntryInstr* block = postorder_[i]; 531 BlockEntryInstr* block = postorder_[i];
519 532
520 BlockInfo* block_info = BlockInfoAt(block->start_pos()); 533 BlockInfo* block_info = BlockInfoAt(block->start_pos());
521 534
522 // For every SSA value that is live out of this block, create an interval 535 // For every SSA value that is live out of this block, create an interval
523 // that covers the whole block. It will be shortened if we encounter a 536 // that covers the whole block. It will be shortened if we encounter a
524 // definition of this value in this block. 537 // definition of this value in this block.
525 for (BitVector::Iterator it(live_out_[i]); !it.Done(); it.Advance()) { 538 for (BitVector::Iterator it(live_out_[i]); !it.Done(); it.Advance()) {
526 LiveRange* range = GetLiveRange(it.Current()); 539 LiveRange* range = GetLiveRange(it.Current());
527 range->AddUseInterval(block->start_pos(), block->end_pos()); 540 range->AddUseInterval(block->start_pos(), block->end_pos());
528 } 541 }
529 542
530 BlockInfo* loop_header = block_info->loop_header(); 543 BlockInfo* loop_header = block_info->loop_header();
531 if ((loop_header != NULL) && (loop_header->last_block() == block)) { 544 if ((loop_header != NULL) && (loop_header->last_block() == block)) {
532 current_interference_set = 545 current_interference_set =
533 new BitVector(flow_graph_.max_virtual_register_number()); 546 new BitVector(flow_graph_.max_virtual_register_number());
534 ASSERT(loop_header->backedge_interference() == NULL); 547 ASSERT(loop_header->backedge_interference() == NULL);
548 // All values flowing into the loop header are live at the back-edge and
549 // can interfere with phi moves.
550 current_interference_set->AddAll(
551 live_in_[loop_header->entry()->postorder_number()]);
535 loop_header->set_backedge_interference( 552 loop_header->set_backedge_interference(
536 current_interference_set); 553 current_interference_set);
537 } 554 }
538 555
539 // Connect outgoing phi-moves that were created in NumberInstructions 556 // Connect outgoing phi-moves that were created in NumberInstructions
540 // and find last instruction that contributes to liveness. 557 // and find last instruction that contributes to liveness.
541 Instruction* current = ConnectOutgoingPhiMoves(block, 558 Instruction* current = ConnectOutgoingPhiMoves(block,
542 current_interference_set); 559 current_interference_set);
543 560
544 // Now process all instructions in reverse order. 561 // Now process all instructions in reverse order.
(...skipping 276 matching lines...) Expand 10 before | Expand all | Expand 10 after
821 838
822 839
823 // Create and update live ranges corresponding to instruction's inputs, 840 // Create and update live ranges corresponding to instruction's inputs,
824 // temporaries and output. 841 // temporaries and output.
825 void FlowGraphAllocator::ProcessOneInstruction(BlockEntryInstr* block, 842 void FlowGraphAllocator::ProcessOneInstruction(BlockEntryInstr* block,
826 Instruction* current, 843 Instruction* current,
827 BitVector* interference_set) { 844 BitVector* interference_set) {
828 LocationSummary* locs = current->locs(); 845 LocationSummary* locs = current->locs();
829 846
830 Definition* def = current->AsDefinition(); 847 Definition* def = current->AsDefinition();
831 if ((def != NULL) && 848 if ((def != NULL) && (def->AsConstant() != NULL)) {
832 (def->AsConstant() != NULL) && 849 LiveRange* range = (def->ssa_temp_index() != -1) ?
833 ((def->ssa_temp_index() == -1) || 850 GetLiveRange(def->ssa_temp_index()) : NULL;
834 (GetLiveRange(def->ssa_temp_index())->first_use() == NULL))) { 851
835 // Drop definitions of constants that have no uses. 852 // Drop definitions of constants that have no uses.
836 locs->set_out(Location::NoLocation()); 853 if ((range == NULL) || (range->first_use() == NULL)) {
837 return; 854 locs->set_out(Location::NoLocation());
855 return;
856 }
857
858 // If this constant has only unconstrained uses convert them all
859 // to use the constant directly and drop this definition.
860 // TODO(vegorov): improve allocation when we have enough registers to keep
861 // constants used in the loop in them.
862 if (HasOnlyUnconstrainedUses(range)) {
863 const Object& value = def->AsConstant()->value();
864 range->set_assigned_location(Location::Constant(value));
865 range->set_spill_slot(Location::Constant(value));
866 range->finger()->Initialize(range);
867 ConvertAllUses(range);
868
869 locs->set_out(Location::NoLocation());
870 return;
871 }
838 } 872 }
839 873
840 const intptr_t pos = current->lifetime_position(); 874 const intptr_t pos = current->lifetime_position();
841 ASSERT(IsInstructionStartPosition(pos)); 875 ASSERT(IsInstructionStartPosition(pos));
842 876
843 // Number of input locations and number of input operands have to agree. 877 // Number of input locations and number of input operands have to agree.
844 ASSERT(locs->input_count() == current->InputCount()); 878 ASSERT(locs->input_count() == current->InputCount());
845 879
846 // Normalize same-as-first-input output if input is specified as 880 // Normalize same-as-first-input output if input is specified as
847 // fixed register. 881 // fixed register.
(...skipping 854 matching lines...) Expand 10 before | Expand all | Expand 10 after
1702 if (!blocked_registers_[hint.register_code()]) { 1736 if (!blocked_registers_[hint.register_code()]) {
1703 free_until = FirstIntersectionWithAllocated(hint.register_code(), 1737 free_until = FirstIntersectionWithAllocated(hint.register_code(),
1704 unallocated); 1738 unallocated);
1705 candidate = hint.register_code(); 1739 candidate = hint.register_code();
1706 } 1740 }
1707 1741
1708 TRACE_ALLOC(OS::Print("found hint %s for v%"Pd": free until %"Pd"\n", 1742 TRACE_ALLOC(OS::Print("found hint %s for v%"Pd": free until %"Pd"\n",
1709 hint.Name(), 1743 hint.Name(),
1710 unallocated->vreg(), 1744 unallocated->vreg(),
1711 free_until)); 1745 free_until));
1712 } else if (free_until != kMaxPosition) { 1746 } else {
1713 for (intptr_t reg = 0; reg < NumberOfRegisters(); ++reg) { 1747 for (intptr_t reg = 0; reg < NumberOfRegisters(); ++reg) {
1714 if (!blocked_registers_[reg] && (registers_[reg].length() == 0)) { 1748 if (!blocked_registers_[reg] && (registers_[reg].length() == 0)) {
1715 candidate = reg; 1749 candidate = reg;
1716 free_until = kMaxPosition; 1750 free_until = kMaxPosition;
1717 break; 1751 break;
1718 } 1752 }
1719 } 1753 }
1720 } 1754 }
1721 1755
1756 ASSERT(0 <= kMaxPosition);
1757 if (free_until != kMaxPosition) {
1758 for (intptr_t reg = 0; reg < NumberOfRegisters(); ++reg) {
1759 if (blocked_registers_[reg] || (reg == candidate)) continue;
1760 const intptr_t intersection =
1761 FirstIntersectionWithAllocated(reg, unallocated);
1762 if (intersection > free_until) {
1763 candidate = reg;
1764 free_until = intersection;
1765 if (free_until == kMaxPosition) break;
1766 }
1767 }
1768 }
1769
1770 // All registers are blocked by active ranges.
1771 if (free_until <= unallocated->Start()) return false;
1772
1722 // We have a very good candidate (either hinted to us or completely free). 1773 // We have a very good candidate (either hinted to us or completely free).
1723 // If we are in a loop try to reduce number of moves on the back edge by 1774 // If we are in a loop try to reduce number of moves on the back edge by
1724 // searching for a candidate that does not interfere with phis on the back 1775 // searching for a candidate that does not interfere with phis on the back
1725 // edge. 1776 // edge.
1726 BlockInfo* loop_header = BlockInfoAt(unallocated->Start())->loop_header(); 1777 BlockInfo* loop_header = BlockInfoAt(unallocated->Start())->loop_header();
1727 if ((unallocated->vreg() >= 0) && 1778 if ((unallocated->vreg() >= 0) &&
1728 (loop_header != NULL) && 1779 (loop_header != NULL) &&
1729 (free_until >= loop_header->last_block()->end_pos()) && 1780 (free_until >= loop_header->last_block()->end_pos()) &&
1730 loop_header->backedge_interference()->Contains(unallocated->vreg())) { 1781 loop_header->backedge_interference()->Contains(unallocated->vreg())) {
1731 ASSERT(static_cast<intptr_t>(kNumberOfFpuRegisters) <= 1782 ASSERT(static_cast<intptr_t>(kNumberOfFpuRegisters) <=
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after
1771 TRACE_ALLOC(OS::Print( 1822 TRACE_ALLOC(OS::Print(
1772 "found %s for v%"Pd" with no interference on the back edge\n", 1823 "found %s for v%"Pd" with no interference on the back edge\n",
1773 MakeRegisterLocation(candidate, kUnboxedDouble).Name(), 1824 MakeRegisterLocation(candidate, kUnboxedDouble).Name(),
1774 candidate)); 1825 candidate));
1775 break; 1826 break;
1776 } 1827 }
1777 } 1828 }
1778 } 1829 }
1779 } 1830 }
1780 1831
1781 ASSERT(0 <= kMaxPosition);
1782 if (free_until != kMaxPosition) {
1783 for (intptr_t reg = 0; reg < NumberOfRegisters(); ++reg) {
1784 if (blocked_registers_[reg] || (reg == candidate)) continue;
1785 const intptr_t intersection =
1786 FirstIntersectionWithAllocated(reg, unallocated);
1787 if (intersection > free_until) {
1788 candidate = reg;
1789 free_until = intersection;
1790 if (free_until == kMaxPosition) break;
1791 }
1792 }
1793 }
1794
1795 // All registers are blocked by active ranges.
1796 if (free_until <= unallocated->Start()) return false;
1797
1798 TRACE_ALLOC(OS::Print("assigning free register ")); 1832 TRACE_ALLOC(OS::Print("assigning free register "));
1799 TRACE_ALLOC(MakeRegisterLocation(candidate, kUnboxedDouble).Print()); 1833 TRACE_ALLOC(MakeRegisterLocation(candidate, kUnboxedDouble).Print());
1800 TRACE_ALLOC(OS::Print(" to v%"Pd"\n", unallocated->vreg())); 1834 TRACE_ALLOC(OS::Print(" to v%"Pd"\n", unallocated->vreg()));
1801 1835
1802 if (free_until != kMaxPosition) { 1836 if (free_until != kMaxPosition) {
1803 // There was an intersection. Split unallocated. 1837 // There was an intersection. Split unallocated.
1804 TRACE_ALLOC(OS::Print(" splitting at %"Pd"\n", free_until)); 1838 TRACE_ALLOC(OS::Print(" splitting at %"Pd"\n", free_until));
1805 LiveRange* tail = unallocated->SplitAt(free_until); 1839 LiveRange* tail = unallocated->SplitAt(free_until);
1806 AddToUnallocated(tail); 1840 AddToUnallocated(tail);
1807 } 1841 }
(...skipping 695 matching lines...) Expand 10 before | Expand all | Expand 10 after
2503 OS::Print("-- [after ssa allocator] ir [%s] -------------\n", 2537 OS::Print("-- [after ssa allocator] ir [%s] -------------\n",
2504 function.ToFullyQualifiedCString()); 2538 function.ToFullyQualifiedCString());
2505 FlowGraphPrinter printer(flow_graph_, true); 2539 FlowGraphPrinter printer(flow_graph_, true);
2506 printer.PrintBlocks(); 2540 printer.PrintBlocks();
2507 OS::Print("----------------------------------------------\n"); 2541 OS::Print("----------------------------------------------\n");
2508 } 2542 }
2509 } 2543 }
2510 2544
2511 2545
2512 } // namespace dart 2546 } // namespace dart
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698