| 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" |
| 11 #include "vm/flow_graph_compiler.h" | 11 #include "vm/flow_graph_compiler.h" |
| 12 #include "vm/log.h" |
| 12 #include "vm/parser.h" | 13 #include "vm/parser.h" |
| 13 | 14 |
| 14 namespace dart { | 15 namespace dart { |
| 15 | 16 |
| 16 DEFINE_FLAG(bool, print_ssa_liveness, false, | 17 DEFINE_FLAG(bool, print_ssa_liveness, false, |
| 17 "Print liveness for ssa variables."); | 18 "Print liveness for ssa variables."); |
| 18 DEFINE_FLAG(bool, trace_ssa_allocator, false, | 19 DEFINE_FLAG(bool, trace_ssa_allocator, false, |
| 19 "Trace register allocation over SSA."); | 20 "Trace register allocation over SSA."); |
| 20 DEFINE_FLAG(bool, print_ssa_liveranges, false, | 21 DEFINE_FLAG(bool, print_ssa_liveranges, false, |
| 21 "Print live ranges after allocation."); | 22 "Print live ranges after allocation."); |
| (...skipping 419 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 441 UNREACHABLE(); | 442 UNREACHABLE(); |
| 442 } | 443 } |
| 443 } | 444 } |
| 444 | 445 |
| 445 | 446 |
| 446 void LiveRange::Print() { | 447 void LiveRange::Print() { |
| 447 if (first_use_interval() == NULL) { | 448 if (first_use_interval() == NULL) { |
| 448 return; | 449 return; |
| 449 } | 450 } |
| 450 | 451 |
| 451 OS::Print(" live range v%" Pd " [%" Pd ", %" Pd ") in ", vreg(), | 452 ISL_Print(" live range v%" Pd " [%" Pd ", %" Pd ") in ", vreg(), |
| 452 Start(), | 453 Start(), |
| 453 End()); | 454 End()); |
| 454 assigned_location().Print(); | 455 assigned_location().Print(); |
| 455 if (spill_slot_.HasStackIndex()) { | 456 if (spill_slot_.HasStackIndex()) { |
| 456 intptr_t stack_slot = spill_slot_.stack_index(); | 457 intptr_t stack_slot = spill_slot_.stack_index(); |
| 457 OS::Print(" allocated spill slot: %" Pd "", stack_slot); | 458 ISL_Print(" allocated spill slot: %" Pd "", stack_slot); |
| 458 } | 459 } |
| 459 OS::Print("\n"); | 460 ISL_Print("\n"); |
| 460 | 461 |
| 461 SafepointPosition* safepoint = first_safepoint(); | 462 SafepointPosition* safepoint = first_safepoint(); |
| 462 while (safepoint != NULL) { | 463 while (safepoint != NULL) { |
| 463 OS::Print(" Safepoint [%" Pd "]: ", safepoint->pos()); | 464 ISL_Print(" Safepoint [%" Pd "]: ", safepoint->pos()); |
| 464 safepoint->locs()->stack_bitmap()->Print(); | 465 safepoint->locs()->stack_bitmap()->Print(); |
| 465 OS::Print("\n"); | 466 ISL_Print("\n"); |
| 466 safepoint = safepoint->next(); | 467 safepoint = safepoint->next(); |
| 467 } | 468 } |
| 468 | 469 |
| 469 UsePosition* use_pos = uses_; | 470 UsePosition* use_pos = uses_; |
| 470 for (UseInterval* interval = first_use_interval_; | 471 for (UseInterval* interval = first_use_interval_; |
| 471 interval != NULL; | 472 interval != NULL; |
| 472 interval = interval->next()) { | 473 interval = interval->next()) { |
| 473 OS::Print(" use interval [%" Pd ", %" Pd ")\n", | 474 ISL_Print(" use interval [%" Pd ", %" Pd ")\n", |
| 474 interval->start(), | 475 interval->start(), |
| 475 interval->end()); | 476 interval->end()); |
| 476 while ((use_pos != NULL) && (use_pos->pos() <= interval->end())) { | 477 while ((use_pos != NULL) && (use_pos->pos() <= interval->end())) { |
| 477 OS::Print(" use at %" Pd "", use_pos->pos()); | 478 ISL_Print(" use at %" Pd "", use_pos->pos()); |
| 478 if (use_pos->location_slot() != NULL) { | 479 if (use_pos->location_slot() != NULL) { |
| 479 OS::Print(" as "); | 480 ISL_Print(" as "); |
| 480 use_pos->location_slot()->Print(); | 481 use_pos->location_slot()->Print(); |
| 481 } | 482 } |
| 482 OS::Print("\n"); | 483 ISL_Print("\n"); |
| 483 use_pos = use_pos->next(); | 484 use_pos = use_pos->next(); |
| 484 } | 485 } |
| 485 } | 486 } |
| 486 | 487 |
| 487 if (next_sibling() != NULL) { | 488 if (next_sibling() != NULL) { |
| 488 next_sibling()->Print(); | 489 next_sibling()->Print(); |
| 489 } | 490 } |
| 490 } | 491 } |
| 491 | 492 |
| 492 | 493 |
| (...skipping 1282 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1775 UseInterval* last_use_interval = (last_before_split == last_use_interval_) ? | 1776 UseInterval* last_use_interval = (last_before_split == last_use_interval_) ? |
| 1776 first_after_split : last_use_interval_; | 1777 first_after_split : last_use_interval_; |
| 1777 next_sibling_ = new LiveRange(vreg(), | 1778 next_sibling_ = new LiveRange(vreg(), |
| 1778 representation(), | 1779 representation(), |
| 1779 first_use_after_split, | 1780 first_use_after_split, |
| 1780 first_after_split, | 1781 first_after_split, |
| 1781 last_use_interval, | 1782 last_use_interval, |
| 1782 first_safepoint_after_split, | 1783 first_safepoint_after_split, |
| 1783 next_sibling_); | 1784 next_sibling_); |
| 1784 | 1785 |
| 1785 TRACE_ALLOC(OS::Print(" split sibling [%" Pd ", %" Pd ")\n", | 1786 TRACE_ALLOC(ISL_Print(" split sibling [%" Pd ", %" Pd ")\n", |
| 1786 next_sibling_->Start(), next_sibling_->End())); | 1787 next_sibling_->Start(), next_sibling_->End())); |
| 1787 | 1788 |
| 1788 last_use_interval_ = last_before_split; | 1789 last_use_interval_ = last_before_split; |
| 1789 last_use_interval_->next_ = NULL; | 1790 last_use_interval_->next_ = NULL; |
| 1790 | 1791 |
| 1791 if (first_use_after_split != NULL) { | 1792 if (first_use_after_split != NULL) { |
| 1792 finger_.UpdateAfterSplit(first_use_after_split->pos()); | 1793 finger_.UpdateAfterSplit(first_use_after_split->pos()); |
| 1793 } | 1794 } |
| 1794 | 1795 |
| 1795 return next_sibling_; | 1796 return next_sibling_; |
| 1796 } | 1797 } |
| 1797 | 1798 |
| 1798 | 1799 |
| 1799 LiveRange* FlowGraphAllocator::SplitBetween(LiveRange* range, | 1800 LiveRange* FlowGraphAllocator::SplitBetween(LiveRange* range, |
| 1800 intptr_t from, | 1801 intptr_t from, |
| 1801 intptr_t to) { | 1802 intptr_t to) { |
| 1802 TRACE_ALLOC(OS::Print("split v%" Pd " [%" Pd ", %" Pd | 1803 TRACE_ALLOC(ISL_Print("split v%" Pd " [%" Pd ", %" Pd |
| 1803 ") between [%" Pd ", %" Pd ")\n", | 1804 ") between [%" Pd ", %" Pd ")\n", |
| 1804 range->vreg(), range->Start(), range->End(), from, to)); | 1805 range->vreg(), range->Start(), range->End(), from, to)); |
| 1805 | 1806 |
| 1806 intptr_t split_pos = kIllegalPosition; | 1807 intptr_t split_pos = kIllegalPosition; |
| 1807 | 1808 |
| 1808 BlockInfo* split_block = BlockInfoAt(to); | 1809 BlockInfo* split_block = BlockInfoAt(to); |
| 1809 if (from < split_block->entry()->lifetime_position()) { | 1810 if (from < split_block->entry()->lifetime_position()) { |
| 1810 // Interval [from, to) spans multiple blocks. | 1811 // Interval [from, to) spans multiple blocks. |
| 1811 | 1812 |
| 1812 // If last block is inside a loop prefer splitting at outermost loop's | 1813 // If last block is inside a loop prefer splitting at outermost loop's |
| (...skipping 19 matching lines...) Expand all Loading... |
| 1832 ASSERT(from < split_pos); | 1833 ASSERT(from < split_pos); |
| 1833 | 1834 |
| 1834 return range->SplitAt(split_pos); | 1835 return range->SplitAt(split_pos); |
| 1835 } | 1836 } |
| 1836 | 1837 |
| 1837 | 1838 |
| 1838 void FlowGraphAllocator::SpillBetween(LiveRange* range, | 1839 void FlowGraphAllocator::SpillBetween(LiveRange* range, |
| 1839 intptr_t from, | 1840 intptr_t from, |
| 1840 intptr_t to) { | 1841 intptr_t to) { |
| 1841 ASSERT(from < to); | 1842 ASSERT(from < to); |
| 1842 TRACE_ALLOC(OS::Print("spill v%" Pd " [%" Pd ", %" Pd ") " | 1843 TRACE_ALLOC(ISL_Print("spill v%" Pd " [%" Pd ", %" Pd ") " |
| 1843 "between [%" Pd ", %" Pd ")\n", | 1844 "between [%" Pd ", %" Pd ")\n", |
| 1844 range->vreg(), range->Start(), range->End(), from, to)); | 1845 range->vreg(), range->Start(), range->End(), from, to)); |
| 1845 LiveRange* tail = range->SplitAt(from); | 1846 LiveRange* tail = range->SplitAt(from); |
| 1846 | 1847 |
| 1847 if (tail->Start() < to) { | 1848 if (tail->Start() < to) { |
| 1848 // There is an intersection of tail and [from, to). | 1849 // There is an intersection of tail and [from, to). |
| 1849 LiveRange* tail_tail = SplitBetween(tail, tail->Start(), to); | 1850 LiveRange* tail_tail = SplitBetween(tail, tail->Start(), to); |
| 1850 Spill(tail); | 1851 Spill(tail); |
| 1851 AddToUnallocated(tail_tail); | 1852 AddToUnallocated(tail_tail); |
| 1852 } else { | 1853 } else { |
| 1853 // No intersection between tail and [from, to). | 1854 // No intersection between tail and [from, to). |
| 1854 AddToUnallocated(tail); | 1855 AddToUnallocated(tail); |
| 1855 } | 1856 } |
| 1856 } | 1857 } |
| 1857 | 1858 |
| 1858 | 1859 |
| 1859 void FlowGraphAllocator::SpillAfter(LiveRange* range, intptr_t from) { | 1860 void FlowGraphAllocator::SpillAfter(LiveRange* range, intptr_t from) { |
| 1860 TRACE_ALLOC(OS::Print("spill v%" Pd " [%" Pd ", %" Pd ") after %" Pd "\n", | 1861 TRACE_ALLOC(ISL_Print("spill v%" Pd " [%" Pd ", %" Pd ") after %" Pd "\n", |
| 1861 range->vreg(), range->Start(), range->End(), from)); | 1862 range->vreg(), range->Start(), range->End(), from)); |
| 1862 | 1863 |
| 1863 // When spilling the value inside the loop check if this spill can | 1864 // When spilling the value inside the loop check if this spill can |
| 1864 // be moved outside. | 1865 // be moved outside. |
| 1865 BlockInfo* block_info = BlockInfoAt(from); | 1866 BlockInfo* block_info = BlockInfoAt(from); |
| 1866 if (block_info->is_loop_header() || (block_info->loop() != NULL)) { | 1867 if (block_info->is_loop_header() || (block_info->loop() != NULL)) { |
| 1867 BlockInfo* loop_header = | 1868 BlockInfo* loop_header = |
| 1868 block_info->is_loop_header() ? block_info : block_info->loop(); | 1869 block_info->is_loop_header() ? block_info : block_info->loop(); |
| 1869 | 1870 |
| 1870 if ((range->Start() <= loop_header->entry()->start_pos()) && | 1871 if ((range->Start() <= loop_header->entry()->start_pos()) && |
| 1871 RangeHasOnlyUnconstrainedUsesInLoop(range, loop_header->loop_id())) { | 1872 RangeHasOnlyUnconstrainedUsesInLoop(range, loop_header->loop_id())) { |
| 1872 ASSERT(loop_header->entry()->start_pos() <= from); | 1873 ASSERT(loop_header->entry()->start_pos() <= from); |
| 1873 from = loop_header->entry()->start_pos(); | 1874 from = loop_header->entry()->start_pos(); |
| 1874 TRACE_ALLOC(OS::Print(" moved spill position to loop header %" Pd "\n", | 1875 TRACE_ALLOC(ISL_Print(" moved spill position to loop header %" Pd "\n", |
| 1875 from)); | 1876 from)); |
| 1876 } | 1877 } |
| 1877 } | 1878 } |
| 1878 | 1879 |
| 1879 LiveRange* tail = range->SplitAt(from); | 1880 LiveRange* tail = range->SplitAt(from); |
| 1880 Spill(tail); | 1881 Spill(tail); |
| 1881 } | 1882 } |
| 1882 | 1883 |
| 1883 | 1884 |
| 1884 void FlowGraphAllocator::AllocateSpillSlotFor(LiveRange* range) { | 1885 void FlowGraphAllocator::AllocateSpillSlotFor(LiveRange* range) { |
| (...skipping 211 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2096 // If hint is available try hint first. | 2097 // If hint is available try hint first. |
| 2097 // TODO(vegorov): ensure that phis are hinted on the back edge. | 2098 // TODO(vegorov): ensure that phis are hinted on the back edge. |
| 2098 Location hint = unallocated->finger()->FirstHint(); | 2099 Location hint = unallocated->finger()->FirstHint(); |
| 2099 if (hint.IsMachineRegister()) { | 2100 if (hint.IsMachineRegister()) { |
| 2100 if (!blocked_registers_[hint.register_code()]) { | 2101 if (!blocked_registers_[hint.register_code()]) { |
| 2101 free_until = FirstIntersectionWithAllocated(hint.register_code(), | 2102 free_until = FirstIntersectionWithAllocated(hint.register_code(), |
| 2102 unallocated); | 2103 unallocated); |
| 2103 candidate = hint.register_code(); | 2104 candidate = hint.register_code(); |
| 2104 } | 2105 } |
| 2105 | 2106 |
| 2106 TRACE_ALLOC(OS::Print("found hint %s for v%" Pd ": free until %" Pd "\n", | 2107 TRACE_ALLOC(ISL_Print("found hint %s for v%" Pd ": free until %" Pd "\n", |
| 2107 hint.Name(), | 2108 hint.Name(), |
| 2108 unallocated->vreg(), | 2109 unallocated->vreg(), |
| 2109 free_until)); | 2110 free_until)); |
| 2110 } else { | 2111 } else { |
| 2111 for (intptr_t reg = 0; reg < NumberOfRegisters(); ++reg) { | 2112 for (intptr_t reg = 0; reg < NumberOfRegisters(); ++reg) { |
| 2112 if (!blocked_registers_[reg] && (registers_[reg]->length() == 0)) { | 2113 if (!blocked_registers_[reg] && (registers_[reg]->length() == 0)) { |
| 2113 candidate = reg; | 2114 candidate = reg; |
| 2114 free_until = kMaxPosition; | 2115 free_until = kMaxPosition; |
| 2115 break; | 2116 break; |
| 2116 } | 2117 } |
| (...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2159 if (range->assigned_location().kind() == register_kind_) { | 2160 if (range->assigned_location().kind() == register_kind_) { |
| 2160 const intptr_t reg = range->assigned_location().register_code(); | 2161 const intptr_t reg = range->assigned_location().register_code(); |
| 2161 | 2162 |
| 2162 if (!reaching_defs_.Get(phi)->Contains(unallocated->vreg())) { | 2163 if (!reaching_defs_.Get(phi)->Contains(unallocated->vreg())) { |
| 2163 used_on_backedge[reg] = true; | 2164 used_on_backedge[reg] = true; |
| 2164 } | 2165 } |
| 2165 } | 2166 } |
| 2166 } | 2167 } |
| 2167 | 2168 |
| 2168 if (used_on_backedge[candidate]) { | 2169 if (used_on_backedge[candidate]) { |
| 2169 TRACE_ALLOC(OS::Print( | 2170 TRACE_ALLOC(ISL_Print( |
| 2170 "considering %s for v%" Pd ": has interference on the back edge" | 2171 "considering %s for v%" Pd ": has interference on the back edge" |
| 2171 " {loop [%" Pd ", %" Pd ")}\n", | 2172 " {loop [%" Pd ", %" Pd ")}\n", |
| 2172 MakeRegisterLocation(candidate).Name(), | 2173 MakeRegisterLocation(candidate).Name(), |
| 2173 unallocated->vreg(), | 2174 unallocated->vreg(), |
| 2174 loop_header->entry()->start_pos(), | 2175 loop_header->entry()->start_pos(), |
| 2175 loop_header->last_block()->end_pos())); | 2176 loop_header->last_block()->end_pos())); |
| 2176 for (intptr_t reg = 0; reg < NumberOfRegisters(); ++reg) { | 2177 for (intptr_t reg = 0; reg < NumberOfRegisters(); ++reg) { |
| 2177 if (blocked_registers_[reg] || | 2178 if (blocked_registers_[reg] || |
| 2178 (reg == candidate) || | 2179 (reg == candidate) || |
| 2179 used_on_backedge[reg]) { | 2180 used_on_backedge[reg]) { |
| 2180 continue; | 2181 continue; |
| 2181 } | 2182 } |
| 2182 | 2183 |
| 2183 const intptr_t intersection = | 2184 const intptr_t intersection = |
| 2184 FirstIntersectionWithAllocated(reg, unallocated); | 2185 FirstIntersectionWithAllocated(reg, unallocated); |
| 2185 if (intersection >= free_until) { | 2186 if (intersection >= free_until) { |
| 2186 candidate = reg; | 2187 candidate = reg; |
| 2187 free_until = intersection; | 2188 free_until = intersection; |
| 2188 TRACE_ALLOC(OS::Print( | 2189 TRACE_ALLOC(ISL_Print( |
| 2189 "found %s for v%" Pd " with no interference on the back edge\n", | 2190 "found %s for v%" Pd " with no interference on the back edge\n", |
| 2190 MakeRegisterLocation(candidate).Name(), | 2191 MakeRegisterLocation(candidate).Name(), |
| 2191 candidate)); | 2192 candidate)); |
| 2192 break; | 2193 break; |
| 2193 } | 2194 } |
| 2194 } | 2195 } |
| 2195 } | 2196 } |
| 2196 } | 2197 } |
| 2197 | 2198 |
| 2198 TRACE_ALLOC(OS::Print("assigning free register ")); | 2199 TRACE_ALLOC(ISL_Print("assigning free register ")); |
| 2199 TRACE_ALLOC(MakeRegisterLocation(candidate).Print()); | 2200 TRACE_ALLOC(MakeRegisterLocation(candidate).Print()); |
| 2200 TRACE_ALLOC(OS::Print(" to v%" Pd "\n", unallocated->vreg())); | 2201 TRACE_ALLOC(ISL_Print(" to v%" Pd "\n", unallocated->vreg())); |
| 2201 | 2202 |
| 2202 if (free_until != kMaxPosition) { | 2203 if (free_until != kMaxPosition) { |
| 2203 // There was an intersection. Split unallocated. | 2204 // There was an intersection. Split unallocated. |
| 2204 TRACE_ALLOC(OS::Print(" splitting at %" Pd "\n", free_until)); | 2205 TRACE_ALLOC(ISL_Print(" splitting at %" Pd "\n", free_until)); |
| 2205 LiveRange* tail = unallocated->SplitAt(free_until); | 2206 LiveRange* tail = unallocated->SplitAt(free_until); |
| 2206 AddToUnallocated(tail); | 2207 AddToUnallocated(tail); |
| 2207 } | 2208 } |
| 2208 | 2209 |
| 2209 registers_[candidate]->Add(unallocated); | 2210 registers_[candidate]->Add(unallocated); |
| 2210 unallocated->set_assigned_location(MakeRegisterLocation(candidate)); | 2211 unallocated->set_assigned_location(MakeRegisterLocation(candidate)); |
| 2211 | 2212 |
| 2212 return true; | 2213 return true; |
| 2213 } | 2214 } |
| 2214 | 2215 |
| (...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2293 : unallocated->Start(); | 2294 : unallocated->Start(); |
| 2294 if (free_until < register_use_pos) { | 2295 if (free_until < register_use_pos) { |
| 2295 // Can't acquire free register. Spill until we really need one. | 2296 // Can't acquire free register. Spill until we really need one. |
| 2296 ASSERT(unallocated->Start() < ToInstructionStart(register_use_pos)); | 2297 ASSERT(unallocated->Start() < ToInstructionStart(register_use_pos)); |
| 2297 SpillBetween(unallocated, unallocated->Start(), register_use->pos()); | 2298 SpillBetween(unallocated, unallocated->Start(), register_use->pos()); |
| 2298 return; | 2299 return; |
| 2299 } | 2300 } |
| 2300 | 2301 |
| 2301 ASSERT(candidate != kNoRegister); | 2302 ASSERT(candidate != kNoRegister); |
| 2302 | 2303 |
| 2303 TRACE_ALLOC(OS::Print("assigning blocked register ")); | 2304 TRACE_ALLOC(ISL_Print("assigning blocked register ")); |
| 2304 TRACE_ALLOC(MakeRegisterLocation(candidate).Print()); | 2305 TRACE_ALLOC(MakeRegisterLocation(candidate).Print()); |
| 2305 TRACE_ALLOC(OS::Print(" to live range v%" Pd " until %" Pd "\n", | 2306 TRACE_ALLOC(ISL_Print(" to live range v%" Pd " until %" Pd "\n", |
| 2306 unallocated->vreg(), blocked_at)); | 2307 unallocated->vreg(), blocked_at)); |
| 2307 | 2308 |
| 2308 if (blocked_at < unallocated->End()) { | 2309 if (blocked_at < unallocated->End()) { |
| 2309 // Register is blocked before the end of the live range. Split the range | 2310 // Register is blocked before the end of the live range. Split the range |
| 2310 // at latest at blocked_at position. | 2311 // at latest at blocked_at position. |
| 2311 LiveRange* tail = SplitBetween(unallocated, | 2312 LiveRange* tail = SplitBetween(unallocated, |
| 2312 unallocated->Start(), | 2313 unallocated->Start(), |
| 2313 blocked_at + 1); | 2314 blocked_at + 1); |
| 2314 AddToUnallocated(tail); | 2315 AddToUnallocated(tail); |
| 2315 } | 2316 } |
| (...skipping 144 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2460 | 2461 |
| 2461 return parallel_move->AddMove(to, from); | 2462 return parallel_move->AddMove(to, from); |
| 2462 } | 2463 } |
| 2463 | 2464 |
| 2464 | 2465 |
| 2465 void FlowGraphAllocator::ConvertUseTo(UsePosition* use, Location loc) { | 2466 void FlowGraphAllocator::ConvertUseTo(UsePosition* use, Location loc) { |
| 2466 ASSERT(!loc.IsPairLocation()); | 2467 ASSERT(!loc.IsPairLocation()); |
| 2467 ASSERT(use->location_slot() != NULL); | 2468 ASSERT(use->location_slot() != NULL); |
| 2468 Location* slot = use->location_slot(); | 2469 Location* slot = use->location_slot(); |
| 2469 ASSERT(slot->IsUnallocated()); | 2470 ASSERT(slot->IsUnallocated()); |
| 2470 TRACE_ALLOC(OS::Print(" use at %" Pd " converted to ", use->pos())); | 2471 TRACE_ALLOC(ISL_Print(" use at %" Pd " converted to ", use->pos())); |
| 2471 TRACE_ALLOC(loc.Print()); | 2472 TRACE_ALLOC(loc.Print()); |
| 2472 TRACE_ALLOC(OS::Print("\n")); | 2473 TRACE_ALLOC(ISL_Print("\n")); |
| 2473 *slot = loc; | 2474 *slot = loc; |
| 2474 } | 2475 } |
| 2475 | 2476 |
| 2476 | 2477 |
| 2477 void FlowGraphAllocator::ConvertAllUses(LiveRange* range) { | 2478 void FlowGraphAllocator::ConvertAllUses(LiveRange* range) { |
| 2478 if (range->vreg() == kNoVirtualRegister) return; | 2479 if (range->vreg() == kNoVirtualRegister) return; |
| 2479 | 2480 |
| 2480 const Location loc = range->assigned_location(); | 2481 const Location loc = range->assigned_location(); |
| 2481 ASSERT(!loc.IsInvalid()); | 2482 ASSERT(!loc.IsInvalid()); |
| 2482 | 2483 |
| 2483 TRACE_ALLOC(OS::Print("range [%" Pd ", %" Pd ") " | 2484 TRACE_ALLOC(ISL_Print("range [%" Pd ", %" Pd ") " |
| 2484 "for v%" Pd " has been allocated to ", | 2485 "for v%" Pd " has been allocated to ", |
| 2485 range->Start(), range->End(), range->vreg())); | 2486 range->Start(), range->End(), range->vreg())); |
| 2486 TRACE_ALLOC(loc.Print()); | 2487 TRACE_ALLOC(loc.Print()); |
| 2487 TRACE_ALLOC(OS::Print(":\n")); | 2488 TRACE_ALLOC(ISL_Print(":\n")); |
| 2488 | 2489 |
| 2489 for (UsePosition* use = range->first_use(); use != NULL; use = use->next()) { | 2490 for (UsePosition* use = range->first_use(); use != NULL; use = use->next()) { |
| 2490 ConvertUseTo(use, loc); | 2491 ConvertUseTo(use, loc); |
| 2491 } | 2492 } |
| 2492 | 2493 |
| 2493 // Add live registers at all safepoints for instructions with slow-path | 2494 // Add live registers at all safepoints for instructions with slow-path |
| 2494 // code. | 2495 // code. |
| 2495 if (loc.IsMachineRegister()) { | 2496 if (loc.IsMachineRegister()) { |
| 2496 for (SafepointPosition* safepoint = range->first_safepoint(); | 2497 for (SafepointPosition* safepoint = range->first_safepoint(); |
| 2497 safepoint != NULL; | 2498 safepoint != NULL; |
| (...skipping 155 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2653 | 2654 |
| 2654 | 2655 |
| 2655 void FlowGraphAllocator::AllocateUnallocatedRanges() { | 2656 void FlowGraphAllocator::AllocateUnallocatedRanges() { |
| 2656 #if defined(DEBUG) | 2657 #if defined(DEBUG) |
| 2657 ASSERT(UnallocatedIsSorted()); | 2658 ASSERT(UnallocatedIsSorted()); |
| 2658 #endif | 2659 #endif |
| 2659 | 2660 |
| 2660 while (!unallocated_.is_empty()) { | 2661 while (!unallocated_.is_empty()) { |
| 2661 LiveRange* range = unallocated_.RemoveLast(); | 2662 LiveRange* range = unallocated_.RemoveLast(); |
| 2662 const intptr_t start = range->Start(); | 2663 const intptr_t start = range->Start(); |
| 2663 TRACE_ALLOC(OS::Print("Processing live range for v%" Pd " " | 2664 TRACE_ALLOC(ISL_Print("Processing live range for v%" Pd " " |
| 2664 "starting at %" Pd "\n", | 2665 "starting at %" Pd "\n", |
| 2665 range->vreg(), | 2666 range->vreg(), |
| 2666 start)); | 2667 start)); |
| 2667 | 2668 |
| 2668 // TODO(vegorov): eagerly spill liveranges without register uses. | 2669 // TODO(vegorov): eagerly spill liveranges without register uses. |
| 2669 AdvanceActiveIntervals(start); | 2670 AdvanceActiveIntervals(start); |
| 2670 | 2671 |
| 2671 if (!AllocateFreeRegister(range)) { | 2672 if (!AllocateFreeRegister(range)) { |
| 2672 if (intrinsic_mode_) { | 2673 if (intrinsic_mode_) { |
| 2673 // No spilling when compiling intrinsics. | 2674 // No spilling when compiling intrinsics. |
| 2674 // TODO(fschneider): Handle spilling in intrinsics. For now, the | 2675 // TODO(fschneider): Handle spilling in intrinsics. For now, the |
| 2675 // IR has to be built so that there are enough free registers. | 2676 // IR has to be built so that there are enough free registers. |
| 2676 UNREACHABLE(); | 2677 UNREACHABLE(); |
| 2677 } | 2678 } |
| 2678 AllocateAnyRegister(range); | 2679 AllocateAnyRegister(range); |
| 2679 } | 2680 } |
| 2680 } | 2681 } |
| 2681 | 2682 |
| 2682 // All allocation decisions were done. | 2683 // All allocation decisions were done. |
| 2683 ASSERT(unallocated_.is_empty()); | 2684 ASSERT(unallocated_.is_empty()); |
| 2684 | 2685 |
| 2685 // Finish allocation. | 2686 // Finish allocation. |
| 2686 AdvanceActiveIntervals(kMaxPosition); | 2687 AdvanceActiveIntervals(kMaxPosition); |
| 2687 TRACE_ALLOC(OS::Print("Allocation completed\n")); | 2688 TRACE_ALLOC(ISL_Print("Allocation completed\n")); |
| 2688 } | 2689 } |
| 2689 | 2690 |
| 2690 | 2691 |
| 2691 bool FlowGraphAllocator::TargetLocationIsSpillSlot(LiveRange* range, | 2692 bool FlowGraphAllocator::TargetLocationIsSpillSlot(LiveRange* range, |
| 2692 Location target) { | 2693 Location target) { |
| 2693 if (target.IsStackSlot() || | 2694 if (target.IsStackSlot() || |
| 2694 target.IsDoubleStackSlot() || | 2695 target.IsDoubleStackSlot() || |
| 2695 target.IsConstant()) { | 2696 target.IsConstant()) { |
| 2696 ASSERT(GetLiveRange(range->vreg())->spill_slot().Equals(target)); | 2697 ASSERT(GetLiveRange(range->vreg())->spill_slot().Equals(target)); |
| 2697 return true; | 2698 return true; |
| 2698 } | 2699 } |
| 2699 return false; | 2700 return false; |
| 2700 } | 2701 } |
| 2701 | 2702 |
| 2702 | 2703 |
| 2703 void FlowGraphAllocator::ConnectSplitSiblings(LiveRange* parent, | 2704 void FlowGraphAllocator::ConnectSplitSiblings(LiveRange* parent, |
| 2704 BlockEntryInstr* source_block, | 2705 BlockEntryInstr* source_block, |
| 2705 BlockEntryInstr* target_block) { | 2706 BlockEntryInstr* target_block) { |
| 2706 TRACE_ALLOC(OS::Print("Connect v%" Pd " on the edge B%" Pd " -> B%" Pd "\n", | 2707 TRACE_ALLOC(ISL_Print("Connect v%" Pd " on the edge B%" Pd " -> B%" Pd "\n", |
| 2707 parent->vreg(), | 2708 parent->vreg(), |
| 2708 source_block->block_id(), | 2709 source_block->block_id(), |
| 2709 target_block->block_id())); | 2710 target_block->block_id())); |
| 2710 if (parent->next_sibling() == NULL) { | 2711 if (parent->next_sibling() == NULL) { |
| 2711 // Nothing to connect. The whole range was allocated to the same location. | 2712 // Nothing to connect. The whole range was allocated to the same location. |
| 2712 TRACE_ALLOC(OS::Print("range v%" Pd " has no siblings\n", parent->vreg())); | 2713 TRACE_ALLOC(ISL_Print("range v%" Pd " has no siblings\n", parent->vreg())); |
| 2713 return; | 2714 return; |
| 2714 } | 2715 } |
| 2715 | 2716 |
| 2716 const intptr_t source_pos = source_block->end_pos() - 1; | 2717 const intptr_t source_pos = source_block->end_pos() - 1; |
| 2717 ASSERT(IsInstructionEndPosition(source_pos)); | 2718 ASSERT(IsInstructionEndPosition(source_pos)); |
| 2718 | 2719 |
| 2719 const intptr_t target_pos = target_block->start_pos(); | 2720 const intptr_t target_pos = target_block->start_pos(); |
| 2720 | 2721 |
| 2721 Location target; | 2722 Location target; |
| 2722 Location source; | 2723 Location source; |
| (...skipping 16 matching lines...) Expand all Loading... |
| 2739 ASSERT(target.IsInvalid()); | 2740 ASSERT(target.IsInvalid()); |
| 2740 target = range->assigned_location(); | 2741 target = range->assigned_location(); |
| 2741 #if defined(DEBUG) | 2742 #if defined(DEBUG) |
| 2742 target_cover = range; | 2743 target_cover = range; |
| 2743 #endif | 2744 #endif |
| 2744 } | 2745 } |
| 2745 | 2746 |
| 2746 range = range->next_sibling(); | 2747 range = range->next_sibling(); |
| 2747 } | 2748 } |
| 2748 | 2749 |
| 2749 TRACE_ALLOC(OS::Print("connecting v%" Pd " between [%" Pd ", %" Pd ") {%s} " | 2750 TRACE_ALLOC(ISL_Print("connecting v%" Pd " between [%" Pd ", %" Pd ") {%s} " |
| 2750 "to [%" Pd ", %" Pd ") {%s}\n", | 2751 "to [%" Pd ", %" Pd ") {%s}\n", |
| 2751 parent->vreg(), | 2752 parent->vreg(), |
| 2752 source_cover->Start(), | 2753 source_cover->Start(), |
| 2753 source_cover->End(), | 2754 source_cover->End(), |
| 2754 source.Name(), | 2755 source.Name(), |
| 2755 target_cover->Start(), | 2756 target_cover->Start(), |
| 2756 target_cover->End(), | 2757 target_cover->End(), |
| 2757 target.Name())); | 2758 target.Name())); |
| 2758 | 2759 |
| 2759 // Siblings were allocated to the same register. | 2760 // Siblings were allocated to the same register. |
| (...skipping 16 matching lines...) Expand all Loading... |
| 2776 | 2777 |
| 2777 void FlowGraphAllocator::ResolveControlFlow() { | 2778 void FlowGraphAllocator::ResolveControlFlow() { |
| 2778 // Resolve linear control flow between touching split siblings | 2779 // Resolve linear control flow between touching split siblings |
| 2779 // inside basic blocks. | 2780 // inside basic blocks. |
| 2780 for (intptr_t vreg = 0; vreg < live_ranges_.length(); vreg++) { | 2781 for (intptr_t vreg = 0; vreg < live_ranges_.length(); vreg++) { |
| 2781 LiveRange* range = live_ranges_[vreg]; | 2782 LiveRange* range = live_ranges_[vreg]; |
| 2782 if (range == NULL) continue; | 2783 if (range == NULL) continue; |
| 2783 | 2784 |
| 2784 while (range->next_sibling() != NULL) { | 2785 while (range->next_sibling() != NULL) { |
| 2785 LiveRange* sibling = range->next_sibling(); | 2786 LiveRange* sibling = range->next_sibling(); |
| 2786 TRACE_ALLOC(OS::Print("connecting [%" Pd ", %" Pd ") [", | 2787 TRACE_ALLOC(ISL_Print("connecting [%" Pd ", %" Pd ") [", |
| 2787 range->Start(), range->End())); | 2788 range->Start(), range->End())); |
| 2788 TRACE_ALLOC(range->assigned_location().Print()); | 2789 TRACE_ALLOC(range->assigned_location().Print()); |
| 2789 TRACE_ALLOC(OS::Print("] to [%" Pd ", %" Pd ") [", | 2790 TRACE_ALLOC(ISL_Print("] to [%" Pd ", %" Pd ") [", |
| 2790 sibling->Start(), sibling->End())); | 2791 sibling->Start(), sibling->End())); |
| 2791 TRACE_ALLOC(sibling->assigned_location().Print()); | 2792 TRACE_ALLOC(sibling->assigned_location().Print()); |
| 2792 TRACE_ALLOC(OS::Print("]\n")); | 2793 TRACE_ALLOC(ISL_Print("]\n")); |
| 2793 if ((range->End() == sibling->Start()) && | 2794 if ((range->End() == sibling->Start()) && |
| 2794 !TargetLocationIsSpillSlot(range, sibling->assigned_location()) && | 2795 !TargetLocationIsSpillSlot(range, sibling->assigned_location()) && |
| 2795 !range->assigned_location().Equals(sibling->assigned_location()) && | 2796 !range->assigned_location().Equals(sibling->assigned_location()) && |
| 2796 !IsBlockEntry(range->End())) { | 2797 !IsBlockEntry(range->End())) { |
| 2797 AddMoveAt(sibling->Start(), | 2798 AddMoveAt(sibling->Start(), |
| 2798 sibling->assigned_location(), | 2799 sibling->assigned_location(), |
| 2799 range->assigned_location()); | 2800 range->assigned_location()); |
| 2800 } | 2801 } |
| 2801 range = sibling; | 2802 range = sibling; |
| 2802 } | 2803 } |
| (...skipping 110 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2913 DiscoverLoops(); | 2914 DiscoverLoops(); |
| 2914 | 2915 |
| 2915 BuildLiveRanges(); | 2916 BuildLiveRanges(); |
| 2916 | 2917 |
| 2917 if (FLAG_print_ssa_liveness) { | 2918 if (FLAG_print_ssa_liveness) { |
| 2918 liveness_.Dump(); | 2919 liveness_.Dump(); |
| 2919 } | 2920 } |
| 2920 | 2921 |
| 2921 if (FLAG_print_ssa_liveranges) { | 2922 if (FLAG_print_ssa_liveranges) { |
| 2922 const Function& function = flow_graph_.function(); | 2923 const Function& function = flow_graph_.function(); |
| 2923 OS::Print("-- [before ssa allocator] ranges [%s] ---------\n", | 2924 ISL_Print("-- [before ssa allocator] ranges [%s] ---------\n", |
| 2924 function.ToFullyQualifiedCString()); | 2925 function.ToFullyQualifiedCString()); |
| 2925 PrintLiveRanges(); | 2926 PrintLiveRanges(); |
| 2926 OS::Print("----------------------------------------------\n"); | 2927 ISL_Print("----------------------------------------------\n"); |
| 2927 | 2928 |
| 2928 OS::Print("-- [before ssa allocator] ir [%s] -------------\n", | 2929 ISL_Print("-- [before ssa allocator] ir [%s] -------------\n", |
| 2929 function.ToFullyQualifiedCString()); | 2930 function.ToFullyQualifiedCString()); |
| 2930 FlowGraphPrinter printer(flow_graph_, true); | 2931 FlowGraphPrinter printer(flow_graph_, true); |
| 2931 printer.PrintBlocks(); | 2932 printer.PrintBlocks(); |
| 2932 OS::Print("----------------------------------------------\n"); | 2933 ISL_Print("----------------------------------------------\n"); |
| 2933 } | 2934 } |
| 2934 | 2935 |
| 2935 PrepareForAllocation(Location::kRegister, | 2936 PrepareForAllocation(Location::kRegister, |
| 2936 kNumberOfCpuRegisters, | 2937 kNumberOfCpuRegisters, |
| 2937 unallocated_cpu_, | 2938 unallocated_cpu_, |
| 2938 cpu_regs_, | 2939 cpu_regs_, |
| 2939 blocked_cpu_registers_); | 2940 blocked_cpu_registers_); |
| 2940 AllocateUnallocatedRanges(); | 2941 AllocateUnallocatedRanges(); |
| 2941 | 2942 |
| 2942 cpu_spill_slot_count_ = spill_slots_.length(); | 2943 cpu_spill_slot_count_ = spill_slots_.length(); |
| (...skipping 11 matching lines...) Expand all Loading... |
| 2954 ResolveControlFlow(); | 2955 ResolveControlFlow(); |
| 2955 | 2956 |
| 2956 GraphEntryInstr* entry = block_order_[0]->AsGraphEntry(); | 2957 GraphEntryInstr* entry = block_order_[0]->AsGraphEntry(); |
| 2957 ASSERT(entry != NULL); | 2958 ASSERT(entry != NULL); |
| 2958 intptr_t double_spill_slot_count = spill_slots_.length() * kDoubleSpillFactor; | 2959 intptr_t double_spill_slot_count = spill_slots_.length() * kDoubleSpillFactor; |
| 2959 entry->set_spill_slot_count(cpu_spill_slot_count_ + double_spill_slot_count); | 2960 entry->set_spill_slot_count(cpu_spill_slot_count_ + double_spill_slot_count); |
| 2960 | 2961 |
| 2961 if (FLAG_print_ssa_liveranges) { | 2962 if (FLAG_print_ssa_liveranges) { |
| 2962 const Function& function = flow_graph_.function(); | 2963 const Function& function = flow_graph_.function(); |
| 2963 | 2964 |
| 2964 OS::Print("-- [after ssa allocator] ranges [%s] ---------\n", | 2965 ISL_Print("-- [after ssa allocator] ranges [%s] ---------\n", |
| 2965 function.ToFullyQualifiedCString()); | 2966 function.ToFullyQualifiedCString()); |
| 2966 PrintLiveRanges(); | 2967 PrintLiveRanges(); |
| 2967 OS::Print("----------------------------------------------\n"); | 2968 ISL_Print("----------------------------------------------\n"); |
| 2968 | 2969 |
| 2969 OS::Print("-- [after ssa allocator] ir [%s] -------------\n", | 2970 ISL_Print("-- [after ssa allocator] ir [%s] -------------\n", |
| 2970 function.ToFullyQualifiedCString()); | 2971 function.ToFullyQualifiedCString()); |
| 2971 FlowGraphPrinter printer(flow_graph_, true); | 2972 FlowGraphPrinter printer(flow_graph_, true); |
| 2972 printer.PrintBlocks(); | 2973 printer.PrintBlocks(); |
| 2973 OS::Print("----------------------------------------------\n"); | 2974 ISL_Print("----------------------------------------------\n"); |
| 2974 } | 2975 } |
| 2975 } | 2976 } |
| 2976 | 2977 |
| 2977 | 2978 |
| 2978 } // namespace dart | 2979 } // namespace dart |
| OLD | NEW |