Chromium Code Reviews| OLD | NEW |
|---|---|
| 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 Loading... | |
| 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 Loading... | |
| 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 | |
|
Florian Schneider
2013/03/21 13:17:06
insert : after the TODO(vegorov).
Vyacheslav Egorov (Google)
2013/03/22 11:30:35
Done.
| |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 |
| OLD | NEW |