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