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 588 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
599 // Slot index for the leftmost copied parameter is 0. | 599 // Slot index for the leftmost copied parameter is 0. |
600 intptr_t slot_index = param->index(); | 600 intptr_t slot_index = param->index(); |
601 // Slot index for the rightmost fixed parameter is -1. | 601 // Slot index for the rightmost fixed parameter is -1. |
602 slot_index -= flow_graph_.num_non_copied_params(); | 602 slot_index -= flow_graph_.num_non_copied_params(); |
603 | 603 |
604 range->set_assigned_location(Location::StackSlot(slot_index)); | 604 range->set_assigned_location(Location::StackSlot(slot_index)); |
605 range->set_spill_slot(Location::StackSlot(slot_index)); | 605 range->set_spill_slot(Location::StackSlot(slot_index)); |
606 if (flow_graph_.num_copied_params() > 0) { | 606 if (flow_graph_.num_copied_params() > 0) { |
607 ASSERT(spill_slots_.length() == slot_index); | 607 ASSERT(spill_slots_.length() == slot_index); |
608 spill_slots_.Add(range->End()); | 608 spill_slots_.Add(range->End()); |
| 609 quad_spill_slots_.Add(false); |
609 } | 610 } |
610 AssignSafepoints(range); | 611 AssignSafepoints(range); |
611 } else { | 612 } else { |
612 ConstantInstr* constant = defn->AsConstant(); | 613 ConstantInstr* constant = defn->AsConstant(); |
613 ASSERT(constant != NULL); | 614 ASSERT(constant != NULL); |
614 range->set_assigned_location(Location::Constant(constant->value())); | 615 range->set_assigned_location(Location::Constant(constant->value())); |
615 range->set_spill_slot(Location::Constant(constant->value())); | 616 range->set_spill_slot(Location::Constant(constant->value())); |
616 } | 617 } |
617 range->finger()->Initialize(range); | 618 range->finger()->Initialize(range); |
618 UsePosition* use = | 619 UsePosition* use = |
(...skipping 367 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
986 // [--) | 987 // [--) |
987 // | 988 // |
988 // The stack bitmap describes the position i. | 989 // The stack bitmap describes the position i. |
989 for (intptr_t reg = 0; reg < kNumberOfCpuRegisters; reg++) { | 990 for (intptr_t reg = 0; reg < kNumberOfCpuRegisters; reg++) { |
990 BlockLocation(Location::RegisterLocation(static_cast<Register>(reg)), | 991 BlockLocation(Location::RegisterLocation(static_cast<Register>(reg)), |
991 pos, | 992 pos, |
992 pos + 1); | 993 pos + 1); |
993 } | 994 } |
994 | 995 |
995 for (intptr_t reg = 0; reg < kNumberOfFpuRegisters; reg++) { | 996 for (intptr_t reg = 0; reg < kNumberOfFpuRegisters; reg++) { |
996 Representation ignored = kNoRepresentation; | |
997 BlockLocation( | 997 BlockLocation( |
998 Location::FpuRegisterLocation(static_cast<FpuRegister>(reg), ignored), | 998 Location::FpuRegisterLocation(static_cast<FpuRegister>(reg)), |
999 pos, | 999 pos, |
1000 pos + 1); | 1000 pos + 1); |
1001 } | 1001 } |
1002 | 1002 |
1003 | 1003 |
1004 #if defined(DEBUG) | 1004 #if defined(DEBUG) |
1005 // Verify that temps, inputs and output were specified as fixed | 1005 // Verify that temps, inputs and output were specified as fixed |
1006 // locations. Every register is blocked now so attempt to | 1006 // locations. Every register is blocked now so attempt to |
1007 // allocate will not succeed. | 1007 // allocate will not succeed. |
1008 for (intptr_t j = 0; j < locs->temp_count(); j++) { | 1008 for (intptr_t j = 0; j < locs->temp_count(); j++) { |
(...skipping 565 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1574 } | 1574 } |
1575 | 1575 |
1576 LiveRange* tail = range->SplitAt(from); | 1576 LiveRange* tail = range->SplitAt(from); |
1577 Spill(tail); | 1577 Spill(tail); |
1578 } | 1578 } |
1579 | 1579 |
1580 | 1580 |
1581 void FlowGraphAllocator::AllocateSpillSlotFor(LiveRange* range) { | 1581 void FlowGraphAllocator::AllocateSpillSlotFor(LiveRange* range) { |
1582 ASSERT(range->spill_slot().IsInvalid()); | 1582 ASSERT(range->spill_slot().IsInvalid()); |
1583 | 1583 |
1584 intptr_t idx = 0; | 1584 // Compute range start and end. |
1585 for (; idx < spill_slots_.length(); idx++) { | |
1586 if (spill_slots_[idx] <= range->Start()) break; | |
1587 } | |
1588 | |
1589 if (idx == spill_slots_.length()) spill_slots_.Add(0); | |
1590 | |
1591 LiveRange* last_sibling = range; | 1585 LiveRange* last_sibling = range; |
1592 while (last_sibling->next_sibling() != NULL) { | 1586 while (last_sibling->next_sibling() != NULL) { |
1593 last_sibling = last_sibling->next_sibling(); | 1587 last_sibling = last_sibling->next_sibling(); |
1594 } | 1588 } |
1595 | 1589 |
1596 spill_slots_[idx] = last_sibling->End(); | 1590 const intptr_t start = range->Start(); |
| 1591 const intptr_t end = last_sibling->End(); |
1597 | 1592 |
| 1593 // During fpu register allocation spill slot indices are computed in terms of |
| 1594 // double (64bit) stack slots. We treat quad stack slot (128bit) as a |
| 1595 // consecutive pair of two double spill slots. |
| 1596 // Special care is taken to never allocate the same index to both |
| 1597 // double and quad spill slots as it complicates disambiguation during |
| 1598 // parallel move resolution. |
| 1599 const bool need_quad = (register_kind_ == Location::kFpuRegister) && |
| 1600 ((range->representation() == kUnboxedFloat32x4) || |
| 1601 (range->representation() == kUnboxedUint32x4)); |
| 1602 |
| 1603 // Search for a free spill slot among allocated: the value in it should be |
| 1604 // dead and its type should match (e.g. it should not be a part of the quad if |
| 1605 // we are allocating normal double slot). |
| 1606 intptr_t idx = 0; |
| 1607 for (; idx < spill_slots_.length(); idx++) { |
| 1608 if ((need_quad == quad_spill_slots_[idx]) && |
| 1609 (spill_slots_[idx] <= start)) { |
| 1610 break; |
| 1611 } |
| 1612 } |
| 1613 |
| 1614 if (idx == spill_slots_.length()) { |
| 1615 // No free spill slot found. Allocate a new one. |
| 1616 spill_slots_.Add(0); |
| 1617 quad_spill_slots_.Add(need_quad); |
| 1618 if (need_quad) { // Allocate two double stack slots if we need quad slot. |
| 1619 spill_slots_.Add(0); |
| 1620 quad_spill_slots_.Add(need_quad); |
| 1621 } |
| 1622 } |
| 1623 |
| 1624 |
| 1625 // Set spill slot expiration boundary to the live range's end. |
| 1626 spill_slots_[idx] = end; |
| 1627 if (need_quad) { |
| 1628 ASSERT(quad_spill_slots_[idx] && quad_spill_slots_[idx + 1]); |
| 1629 idx++; // Use the higher index it corresponds to the lower stack address. |
| 1630 spill_slots_[idx] = end; |
| 1631 } else { |
| 1632 ASSERT(!quad_spill_slots_[idx]); |
| 1633 } |
| 1634 |
| 1635 // Assign spill slot to the range. |
1598 if (register_kind_ == Location::kRegister) { | 1636 if (register_kind_ == Location::kRegister) { |
1599 range->set_spill_slot(Location::StackSlot(idx)); | 1637 range->set_spill_slot(Location::StackSlot(idx)); |
1600 } else { | 1638 } else { |
1601 // FPU register spill slots are essentially two (x64) or four (ia32) normal | 1639 // We use the index of the slot with the lowest address as an index for the |
1602 // word size spill slots. We use the index of the slot with the lowest | 1640 // FPU register spill slot. In terms of indexes this relation is inverted: |
1603 // address as an index for the FPU register spill slot. In terms of indexes | 1641 // so we have to take the highest index. |
1604 // this relation is inverted: so we have to take the highest index. | |
1605 const intptr_t slot_idx = cpu_spill_slot_count_ + | 1642 const intptr_t slot_idx = cpu_spill_slot_count_ + |
1606 idx * kFpuRegisterSpillFactor + (kFpuRegisterSpillFactor - 1); | 1643 idx * kDoubleSpillFactor + (kDoubleSpillFactor - 1); |
1607 | 1644 |
1608 Location location; | 1645 Location location; |
1609 if (range->representation() == kUnboxedFloat32x4) { | 1646 if ((range->representation() == kUnboxedFloat32x4) || |
1610 location = Location::Float32x4StackSlot(slot_idx); | 1647 (range->representation() == kUnboxedUint32x4)) { |
1611 } else if (range->representation() == kUnboxedUint32x4) { | 1648 ASSERT(need_quad); |
1612 location = Location::Uint32x4StackSlot(slot_idx); | 1649 location = Location::QuadStackSlot(slot_idx); |
1613 } else { | 1650 } else { |
1614 ASSERT((range->representation() == kUnboxedDouble) || | 1651 ASSERT((range->representation() == kUnboxedDouble) || |
1615 (range->representation() == kUnboxedMint)); | 1652 (range->representation() == kUnboxedMint)); |
1616 location = Location::DoubleStackSlot(slot_idx, | 1653 location = Location::DoubleStackSlot(slot_idx); |
1617 range->representation()); | |
1618 } | 1654 } |
1619 range->set_spill_slot(location); | 1655 range->set_spill_slot(location); |
1620 } | 1656 } |
1621 | 1657 |
1622 spilled_.Add(range); | 1658 spilled_.Add(range); |
1623 } | 1659 } |
1624 | 1660 |
1625 | 1661 |
1626 void FlowGraphAllocator::MarkAsObjectAtSafepoints(LiveRange* range) { | 1662 void FlowGraphAllocator::MarkAsObjectAtSafepoints(LiveRange* range) { |
1627 intptr_t stack_index = range->spill_slot().stack_index(); | 1663 intptr_t stack_index = range->spill_slot().stack_index(); |
(...skipping 180 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1808 if (!reaching_defs_.Get(phi)->Contains(unallocated->vreg())) { | 1844 if (!reaching_defs_.Get(phi)->Contains(unallocated->vreg())) { |
1809 used_on_backedge[reg] = true; | 1845 used_on_backedge[reg] = true; |
1810 } | 1846 } |
1811 } | 1847 } |
1812 } | 1848 } |
1813 | 1849 |
1814 if (used_on_backedge[candidate]) { | 1850 if (used_on_backedge[candidate]) { |
1815 TRACE_ALLOC(OS::Print( | 1851 TRACE_ALLOC(OS::Print( |
1816 "considering %s for v%"Pd": has interference on the back edge" | 1852 "considering %s for v%"Pd": has interference on the back edge" |
1817 " {loop [%"Pd", %"Pd")}\n", | 1853 " {loop [%"Pd", %"Pd")}\n", |
1818 MakeRegisterLocation(candidate, kUnboxedDouble).Name(), | 1854 MakeRegisterLocation(candidate).Name(), |
1819 unallocated->vreg(), | 1855 unallocated->vreg(), |
1820 loop_header->entry()->start_pos(), | 1856 loop_header->entry()->start_pos(), |
1821 loop_header->last_block()->end_pos())); | 1857 loop_header->last_block()->end_pos())); |
1822 for (intptr_t reg = 0; reg < NumberOfRegisters(); ++reg) { | 1858 for (intptr_t reg = 0; reg < NumberOfRegisters(); ++reg) { |
1823 if (blocked_registers_[reg] || | 1859 if (blocked_registers_[reg] || |
1824 (reg == candidate) || | 1860 (reg == candidate) || |
1825 used_on_backedge[reg]) { | 1861 used_on_backedge[reg]) { |
1826 continue; | 1862 continue; |
1827 } | 1863 } |
1828 | 1864 |
1829 const intptr_t intersection = | 1865 const intptr_t intersection = |
1830 FirstIntersectionWithAllocated(reg, unallocated); | 1866 FirstIntersectionWithAllocated(reg, unallocated); |
1831 if (intersection >= free_until) { | 1867 if (intersection >= free_until) { |
1832 candidate = reg; | 1868 candidate = reg; |
1833 free_until = intersection; | 1869 free_until = intersection; |
1834 TRACE_ALLOC(OS::Print( | 1870 TRACE_ALLOC(OS::Print( |
1835 "found %s for v%"Pd" with no interference on the back edge\n", | 1871 "found %s for v%"Pd" with no interference on the back edge\n", |
1836 MakeRegisterLocation(candidate, kUnboxedDouble).Name(), | 1872 MakeRegisterLocation(candidate).Name(), |
1837 candidate)); | 1873 candidate)); |
1838 break; | 1874 break; |
1839 } | 1875 } |
1840 } | 1876 } |
1841 } | 1877 } |
1842 } | 1878 } |
1843 | 1879 |
1844 TRACE_ALLOC(OS::Print("assigning free register ")); | 1880 TRACE_ALLOC(OS::Print("assigning free register ")); |
1845 TRACE_ALLOC(MakeRegisterLocation(candidate, kUnboxedDouble).Print()); | 1881 TRACE_ALLOC(MakeRegisterLocation(candidate).Print()); |
1846 TRACE_ALLOC(OS::Print(" to v%"Pd"\n", unallocated->vreg())); | 1882 TRACE_ALLOC(OS::Print(" to v%"Pd"\n", unallocated->vreg())); |
1847 | 1883 |
1848 if (free_until != kMaxPosition) { | 1884 if (free_until != kMaxPosition) { |
1849 // There was an intersection. Split unallocated. | 1885 // There was an intersection. Split unallocated. |
1850 TRACE_ALLOC(OS::Print(" splitting at %"Pd"\n", free_until)); | 1886 TRACE_ALLOC(OS::Print(" splitting at %"Pd"\n", free_until)); |
1851 LiveRange* tail = unallocated->SplitAt(free_until); | 1887 LiveRange* tail = unallocated->SplitAt(free_until); |
1852 AddToUnallocated(tail); | 1888 AddToUnallocated(tail); |
1853 } | 1889 } |
1854 | 1890 |
1855 registers_[candidate].Add(unallocated); | 1891 registers_[candidate].Add(unallocated); |
1856 unallocated->set_assigned_location( | 1892 unallocated->set_assigned_location(MakeRegisterLocation(candidate)); |
1857 MakeRegisterLocation(candidate, unallocated->representation())); | |
1858 | 1893 |
1859 return true; | 1894 return true; |
1860 } | 1895 } |
1861 | 1896 |
1862 | 1897 |
1863 bool FlowGraphAllocator::RangeHasOnlyUnconstrainedUsesInLoop(LiveRange* range, | 1898 bool FlowGraphAllocator::RangeHasOnlyUnconstrainedUsesInLoop(LiveRange* range, |
1864 intptr_t loop_id) { | 1899 intptr_t loop_id) { |
1865 if (range->vreg() >= 0) { | 1900 if (range->vreg() >= 0) { |
1866 return GetLiveRange(range->vreg())->HasOnlyUnconstrainedUsesInLoop(loop_id); | 1901 return GetLiveRange(range->vreg())->HasOnlyUnconstrainedUsesInLoop(loop_id); |
1867 } | 1902 } |
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1938 (register_use != NULL) ? register_use->pos() | 1973 (register_use != NULL) ? register_use->pos() |
1939 : unallocated->Start(); | 1974 : unallocated->Start(); |
1940 if (free_until < register_use_pos) { | 1975 if (free_until < register_use_pos) { |
1941 // Can't acquire free register. Spill until we really need one. | 1976 // Can't acquire free register. Spill until we really need one. |
1942 ASSERT(unallocated->Start() < ToInstructionStart(register_use_pos)); | 1977 ASSERT(unallocated->Start() < ToInstructionStart(register_use_pos)); |
1943 SpillBetween(unallocated, unallocated->Start(), register_use->pos()); | 1978 SpillBetween(unallocated, unallocated->Start(), register_use->pos()); |
1944 return; | 1979 return; |
1945 } | 1980 } |
1946 | 1981 |
1947 TRACE_ALLOC(OS::Print("assigning blocked register ")); | 1982 TRACE_ALLOC(OS::Print("assigning blocked register ")); |
1948 TRACE_ALLOC(MakeRegisterLocation(candidate, kUnboxedDouble).Print()); | 1983 TRACE_ALLOC(MakeRegisterLocation(candidate).Print()); |
1949 TRACE_ALLOC(OS::Print(" to live range v%"Pd" until %"Pd"\n", | 1984 TRACE_ALLOC(OS::Print(" to live range v%"Pd" until %"Pd"\n", |
1950 unallocated->vreg(), blocked_at)); | 1985 unallocated->vreg(), blocked_at)); |
1951 | 1986 |
1952 if (blocked_at < unallocated->End()) { | 1987 if (blocked_at < unallocated->End()) { |
1953 // Register is blocked before the end of the live range. Split the range | 1988 // Register is blocked before the end of the live range. Split the range |
1954 // at latest at blocked_at position. | 1989 // at latest at blocked_at position. |
1955 LiveRange* tail = SplitBetween(unallocated, | 1990 LiveRange* tail = SplitBetween(unallocated, |
1956 unallocated->Start(), | 1991 unallocated->Start(), |
1957 blocked_at + 1); | 1992 blocked_at + 1); |
1958 AddToUnallocated(tail); | 1993 AddToUnallocated(tail); |
(...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2044 } | 2079 } |
2045 registers_[reg][i] = NULL; | 2080 registers_[reg][i] = NULL; |
2046 first_evicted = i; | 2081 first_evicted = i; |
2047 } | 2082 } |
2048 } | 2083 } |
2049 | 2084 |
2050 // Remove evicted ranges from the array. | 2085 // Remove evicted ranges from the array. |
2051 if (first_evicted != -1) RemoveEvicted(reg, first_evicted); | 2086 if (first_evicted != -1) RemoveEvicted(reg, first_evicted); |
2052 | 2087 |
2053 registers_[reg].Add(unallocated); | 2088 registers_[reg].Add(unallocated); |
2054 unallocated->set_assigned_location( | 2089 unallocated->set_assigned_location(MakeRegisterLocation(reg)); |
2055 MakeRegisterLocation(reg, unallocated->representation())); | |
2056 } | 2090 } |
2057 | 2091 |
2058 | 2092 |
2059 bool FlowGraphAllocator::EvictIntersection(LiveRange* allocated, | 2093 bool FlowGraphAllocator::EvictIntersection(LiveRange* allocated, |
2060 LiveRange* unallocated) { | 2094 LiveRange* unallocated) { |
2061 UseInterval* first_unallocated = | 2095 UseInterval* first_unallocated = |
2062 unallocated->finger()->first_pending_use_interval(); | 2096 unallocated->finger()->first_pending_use_interval(); |
2063 const intptr_t intersection = FirstIntersection( | 2097 const intptr_t intersection = FirstIntersection( |
2064 allocated->finger()->first_pending_use_interval(), | 2098 allocated->finger()->first_pending_use_interval(), |
2065 first_unallocated); | 2099 first_unallocated); |
(...skipping 449 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2515 | 2549 |
2516 PrepareForAllocation(Location::kRegister, | 2550 PrepareForAllocation(Location::kRegister, |
2517 kNumberOfCpuRegisters, | 2551 kNumberOfCpuRegisters, |
2518 unallocated_cpu_, | 2552 unallocated_cpu_, |
2519 cpu_regs_, | 2553 cpu_regs_, |
2520 blocked_cpu_registers_); | 2554 blocked_cpu_registers_); |
2521 AllocateUnallocatedRanges(); | 2555 AllocateUnallocatedRanges(); |
2522 | 2556 |
2523 cpu_spill_slot_count_ = spill_slots_.length(); | 2557 cpu_spill_slot_count_ = spill_slots_.length(); |
2524 spill_slots_.Clear(); | 2558 spill_slots_.Clear(); |
| 2559 quad_spill_slots_.Clear(); |
2525 | 2560 |
2526 PrepareForAllocation(Location::kFpuRegister, | 2561 PrepareForAllocation(Location::kFpuRegister, |
2527 kNumberOfFpuRegisters, | 2562 kNumberOfFpuRegisters, |
2528 unallocated_xmm_, | 2563 unallocated_xmm_, |
2529 fpu_regs_, | 2564 fpu_regs_, |
2530 blocked_fpu_registers_); | 2565 blocked_fpu_registers_); |
2531 AllocateUnallocatedRanges(); | 2566 AllocateUnallocatedRanges(); |
2532 | 2567 |
2533 ResolveControlFlow(); | 2568 ResolveControlFlow(); |
2534 | 2569 |
2535 GraphEntryInstr* entry = block_order_[0]->AsGraphEntry(); | 2570 GraphEntryInstr* entry = block_order_[0]->AsGraphEntry(); |
2536 ASSERT(entry != NULL); | 2571 ASSERT(entry != NULL); |
2537 intptr_t double_spill_slot_count = | 2572 intptr_t double_spill_slot_count = spill_slots_.length() * kDoubleSpillFactor; |
2538 spill_slots_.length() * kFpuRegisterSpillFactor; | |
2539 entry->set_spill_slot_count(cpu_spill_slot_count_ + double_spill_slot_count); | 2573 entry->set_spill_slot_count(cpu_spill_slot_count_ + double_spill_slot_count); |
2540 | 2574 |
2541 if (FLAG_print_ssa_liveranges) { | 2575 if (FLAG_print_ssa_liveranges) { |
2542 const Function& function = flow_graph_.parsed_function().function(); | 2576 const Function& function = flow_graph_.parsed_function().function(); |
2543 | 2577 |
2544 OS::Print("-- [after ssa allocator] ranges [%s] ---------\n", | 2578 OS::Print("-- [after ssa allocator] ranges [%s] ---------\n", |
2545 function.ToFullyQualifiedCString()); | 2579 function.ToFullyQualifiedCString()); |
2546 PrintLiveRanges(); | 2580 PrintLiveRanges(); |
2547 OS::Print("----------------------------------------------\n"); | 2581 OS::Print("----------------------------------------------\n"); |
2548 | 2582 |
2549 OS::Print("-- [after ssa allocator] ir [%s] -------------\n", | 2583 OS::Print("-- [after ssa allocator] ir [%s] -------------\n", |
2550 function.ToFullyQualifiedCString()); | 2584 function.ToFullyQualifiedCString()); |
2551 FlowGraphPrinter printer(flow_graph_, true); | 2585 FlowGraphPrinter printer(flow_graph_, true); |
2552 printer.PrintBlocks(); | 2586 printer.PrintBlocks(); |
2553 OS::Print("----------------------------------------------\n"); | 2587 OS::Print("----------------------------------------------\n"); |
2554 } | 2588 } |
2555 } | 2589 } |
2556 | 2590 |
2557 | 2591 |
2558 } // namespace dart | 2592 } // namespace dart |
OLD | NEW |