OLD | NEW |
1 // Copyright 2014 the V8 project authors. All rights reserved. | 1 // Copyright 2014 the V8 project authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "src/base/adapters.h" | 5 #include "src/base/adapters.h" |
6 #include "src/compiler/linkage.h" | 6 #include "src/compiler/linkage.h" |
7 #include "src/compiler/register-allocator.h" | 7 #include "src/compiler/register-allocator.h" |
8 #include "src/string-stream.h" | 8 #include "src/string-stream.h" |
9 | 9 |
10 namespace v8 { | 10 namespace v8 { |
(...skipping 15 matching lines...) Expand all Loading... |
26 } | 26 } |
27 | 27 |
28 int GetRegisterCount(const RegisterConfiguration* cfg, RegisterKind kind) { | 28 int GetRegisterCount(const RegisterConfiguration* cfg, RegisterKind kind) { |
29 return kind == FP_REGISTERS ? cfg->num_double_registers() | 29 return kind == FP_REGISTERS ? cfg->num_double_registers() |
30 : cfg->num_general_registers(); | 30 : cfg->num_general_registers(); |
31 } | 31 } |
32 | 32 |
33 | 33 |
34 int GetAllocatableRegisterCount(const RegisterConfiguration* cfg, | 34 int GetAllocatableRegisterCount(const RegisterConfiguration* cfg, |
35 RegisterKind kind) { | 35 RegisterKind kind) { |
36 return kind == FP_REGISTERS ? cfg->num_allocatable_double_registers() | 36 return kind == FP_REGISTERS ? cfg->num_allocatable_aliased_double_registers() |
37 : cfg->num_allocatable_general_registers(); | 37 : cfg->num_allocatable_general_registers(); |
38 } | 38 } |
39 | 39 |
40 | 40 |
41 const int* GetAllocatableRegisterCodes(const RegisterConfiguration* cfg, | 41 const int* GetAllocatableRegisterCodes(const RegisterConfiguration* cfg, |
42 RegisterKind kind) { | 42 RegisterKind kind) { |
43 return kind == FP_REGISTERS ? cfg->allocatable_double_codes() | 43 return kind == FP_REGISTERS ? cfg->allocatable_double_codes() |
44 : cfg->allocatable_general_codes(); | 44 : cfg->allocatable_general_codes(); |
45 } | 45 } |
46 | 46 |
(...skipping 18 matching lines...) Expand all Loading... |
65 } | 65 } |
66 | 66 |
67 // TODO(dcarney): fix frame to allow frame accesses to half size location. | 67 // TODO(dcarney): fix frame to allow frame accesses to half size location. |
68 int GetByteWidth(MachineRepresentation rep) { | 68 int GetByteWidth(MachineRepresentation rep) { |
69 switch (rep) { | 69 switch (rep) { |
70 case MachineRepresentation::kBit: | 70 case MachineRepresentation::kBit: |
71 case MachineRepresentation::kWord8: | 71 case MachineRepresentation::kWord8: |
72 case MachineRepresentation::kWord16: | 72 case MachineRepresentation::kWord16: |
73 case MachineRepresentation::kWord32: | 73 case MachineRepresentation::kWord32: |
74 case MachineRepresentation::kTagged: | 74 case MachineRepresentation::kTagged: |
| 75 return kPointerSize; |
75 case MachineRepresentation::kFloat32: | 76 case MachineRepresentation::kFloat32: |
| 77 // TODO(bbudge) Eliminate this when FP register aliasing works. |
| 78 #if V8_TARGET_ARCH_ARM |
| 79 return kDoubleSize; |
| 80 #else |
76 return kPointerSize; | 81 return kPointerSize; |
| 82 #endif |
77 case MachineRepresentation::kWord64: | 83 case MachineRepresentation::kWord64: |
78 case MachineRepresentation::kFloat64: | 84 case MachineRepresentation::kFloat64: |
79 return 8; | 85 return kDoubleSize; |
80 case MachineRepresentation::kSimd128: | 86 case MachineRepresentation::kSimd128: |
81 return 16; | 87 return kSimd128Size; |
82 case MachineRepresentation::kNone: | 88 case MachineRepresentation::kNone: |
83 break; | 89 break; |
84 } | 90 } |
85 UNREACHABLE(); | 91 UNREACHABLE(); |
86 return 0; | 92 return 0; |
87 } | 93 } |
88 | 94 |
89 } // namespace | 95 } // namespace |
90 | 96 |
91 class LiveRangeBound { | 97 class LiveRangeBound { |
(...skipping 1236 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1328 code_(code), | 1334 code_(code), |
1329 debug_name_(debug_name), | 1335 debug_name_(debug_name), |
1330 config_(config), | 1336 config_(config), |
1331 phi_map_(allocation_zone()), | 1337 phi_map_(allocation_zone()), |
1332 live_in_sets_(code->InstructionBlockCount(), nullptr, allocation_zone()), | 1338 live_in_sets_(code->InstructionBlockCount(), nullptr, allocation_zone()), |
1333 live_out_sets_(code->InstructionBlockCount(), nullptr, allocation_zone()), | 1339 live_out_sets_(code->InstructionBlockCount(), nullptr, allocation_zone()), |
1334 live_ranges_(code->VirtualRegisterCount() * 2, nullptr, | 1340 live_ranges_(code->VirtualRegisterCount() * 2, nullptr, |
1335 allocation_zone()), | 1341 allocation_zone()), |
1336 fixed_live_ranges_(this->config()->num_general_registers(), nullptr, | 1342 fixed_live_ranges_(this->config()->num_general_registers(), nullptr, |
1337 allocation_zone()), | 1343 allocation_zone()), |
1338 fixed_float_live_ranges_(this->config()->num_float_registers(), nullptr, | |
1339 allocation_zone()), | |
1340 fixed_double_live_ranges_(this->config()->num_double_registers(), nullptr, | 1344 fixed_double_live_ranges_(this->config()->num_double_registers(), nullptr, |
1341 allocation_zone()), | 1345 allocation_zone()), |
1342 fixed_simd128_live_ranges_(this->config()->num_simd128_registers(), | |
1343 nullptr, allocation_zone()), | |
1344 spill_ranges_(code->VirtualRegisterCount(), nullptr, allocation_zone()), | 1346 spill_ranges_(code->VirtualRegisterCount(), nullptr, allocation_zone()), |
1345 delayed_references_(allocation_zone()), | 1347 delayed_references_(allocation_zone()), |
1346 assigned_registers_(nullptr), | 1348 assigned_registers_(nullptr), |
1347 assigned_double_registers_(nullptr), | 1349 assigned_double_registers_(nullptr), |
1348 virtual_register_count_(code->VirtualRegisterCount()), | 1350 virtual_register_count_(code->VirtualRegisterCount()), |
1349 preassigned_slot_ranges_(zone) { | 1351 preassigned_slot_ranges_(zone) { |
1350 assigned_registers_ = new (code_zone()) | 1352 assigned_registers_ = new (code_zone()) |
1351 BitVector(this->config()->num_general_registers(), code_zone()); | 1353 BitVector(this->config()->num_general_registers(), code_zone()); |
1352 assigned_double_registers_ = new (code_zone()) | 1354 assigned_double_registers_ = new (code_zone()) |
1353 BitVector(this->config()->num_double_registers(), code_zone()); | 1355 BitVector(this->config()->num_double_registers(), code_zone()); |
(...skipping 157 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1511 DCHECK(!range->IsSplinter()); | 1513 DCHECK(!range->IsSplinter()); |
1512 SpillRange* spill_range = | 1514 SpillRange* spill_range = |
1513 new (allocation_zone()) SpillRange(range, allocation_zone()); | 1515 new (allocation_zone()) SpillRange(range, allocation_zone()); |
1514 return spill_range; | 1516 return spill_range; |
1515 } | 1517 } |
1516 | 1518 |
1517 void RegisterAllocationData::MarkAllocated(MachineRepresentation rep, | 1519 void RegisterAllocationData::MarkAllocated(MachineRepresentation rep, |
1518 int index) { | 1520 int index) { |
1519 switch (rep) { | 1521 switch (rep) { |
1520 case MachineRepresentation::kFloat32: | 1522 case MachineRepresentation::kFloat32: |
| 1523 case MachineRepresentation::kFloat64: |
1521 case MachineRepresentation::kSimd128: | 1524 case MachineRepresentation::kSimd128: |
1522 if (kSimpleFPAliasing) { | |
1523 assigned_double_registers_->Add(index); | |
1524 } else { | |
1525 int alias_base_index = -1; | |
1526 int aliases = config()->GetAliases( | |
1527 rep, index, MachineRepresentation::kFloat64, &alias_base_index); | |
1528 DCHECK(aliases > 0 || (aliases == 0 && alias_base_index == -1)); | |
1529 while (aliases--) { | |
1530 int aliased_reg = alias_base_index + aliases; | |
1531 assigned_double_registers_->Add(aliased_reg); | |
1532 } | |
1533 } | |
1534 break; | |
1535 case MachineRepresentation::kFloat64: | |
1536 assigned_double_registers_->Add(index); | 1525 assigned_double_registers_->Add(index); |
1537 break; | 1526 break; |
1538 default: | 1527 default: |
1539 DCHECK(!IsFloatingPoint(rep)); | 1528 DCHECK(!IsFloatingPoint(rep)); |
1540 assigned_registers_->Add(index); | 1529 assigned_registers_->Add(index); |
1541 break; | 1530 break; |
1542 } | 1531 } |
1543 } | 1532 } |
1544 | 1533 |
1545 bool RegisterAllocationData::IsBlockBoundary(LifetimePosition pos) const { | 1534 bool RegisterAllocationData::IsBlockBoundary(LifetimePosition pos) const { |
(...skipping 306 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1852 TopLevelLiveRange* range = data()->GetOrCreateLiveRangeFor(operand_index); | 1841 TopLevelLiveRange* range = data()->GetOrCreateLiveRangeFor(operand_index); |
1853 range->AddUseInterval(start, end, allocation_zone()); | 1842 range->AddUseInterval(start, end, allocation_zone()); |
1854 iterator.Advance(); | 1843 iterator.Advance(); |
1855 } | 1844 } |
1856 } | 1845 } |
1857 | 1846 |
1858 int LiveRangeBuilder::FixedFPLiveRangeID(int index, MachineRepresentation rep) { | 1847 int LiveRangeBuilder::FixedFPLiveRangeID(int index, MachineRepresentation rep) { |
1859 int result = -index - 1; | 1848 int result = -index - 1; |
1860 switch (rep) { | 1849 switch (rep) { |
1861 case MachineRepresentation::kSimd128: | 1850 case MachineRepresentation::kSimd128: |
1862 result -= config()->num_float_registers(); | |
1863 // Fall through. | |
1864 case MachineRepresentation::kFloat32: | 1851 case MachineRepresentation::kFloat32: |
1865 result -= config()->num_double_registers(); | |
1866 // Fall through. | |
1867 case MachineRepresentation::kFloat64: | 1852 case MachineRepresentation::kFloat64: |
1868 result -= config()->num_general_registers(); | 1853 result -= config()->num_general_registers(); |
1869 break; | 1854 break; |
1870 default: | 1855 default: |
1871 UNREACHABLE(); | 1856 UNREACHABLE(); |
1872 break; | 1857 break; |
1873 } | 1858 } |
1874 return result; | 1859 return result; |
1875 } | 1860 } |
1876 | 1861 |
1877 TopLevelLiveRange* LiveRangeBuilder::FixedLiveRangeFor(int index) { | 1862 TopLevelLiveRange* LiveRangeBuilder::FixedLiveRangeFor(int index) { |
1878 DCHECK(index < config()->num_general_registers()); | 1863 DCHECK(index < config()->num_general_registers()); |
1879 TopLevelLiveRange* result = data()->fixed_live_ranges()[index]; | 1864 TopLevelLiveRange* result = data()->fixed_live_ranges()[index]; |
1880 if (result == nullptr) { | 1865 if (result == nullptr) { |
1881 MachineRepresentation rep = InstructionSequence::DefaultRepresentation(); | 1866 MachineRepresentation rep = InstructionSequence::DefaultRepresentation(); |
1882 result = data()->NewLiveRange(FixedLiveRangeID(index), rep); | 1867 result = data()->NewLiveRange(FixedLiveRangeID(index), rep); |
1883 DCHECK(result->IsFixed()); | 1868 DCHECK(result->IsFixed()); |
1884 result->set_assigned_register(index); | 1869 result->set_assigned_register(index); |
1885 data()->MarkAllocated(rep, index); | 1870 data()->MarkAllocated(rep, index); |
1886 data()->fixed_live_ranges()[index] = result; | 1871 data()->fixed_live_ranges()[index] = result; |
1887 } | 1872 } |
1888 return result; | 1873 return result; |
1889 } | 1874 } |
1890 | 1875 |
1891 TopLevelLiveRange* LiveRangeBuilder::FixedFPLiveRangeFor( | 1876 TopLevelLiveRange* LiveRangeBuilder::FixedFPLiveRangeFor( |
1892 int index, MachineRepresentation rep) { | 1877 int index, MachineRepresentation rep) { |
1893 TopLevelLiveRange* result = nullptr; | 1878 TopLevelLiveRange* result = nullptr; |
1894 switch (rep) { | 1879 switch (rep) { |
1895 case MachineRepresentation::kFloat32: | 1880 case MachineRepresentation::kFloat32: |
1896 DCHECK(rep == MachineRepresentation::kFloat32); | |
1897 DCHECK(index < config()->num_float_registers()); | |
1898 result = data()->fixed_float_live_ranges()[index]; | |
1899 if (result == nullptr) { | |
1900 result = data()->NewLiveRange(FixedFPLiveRangeID(index, rep), rep); | |
1901 DCHECK(result->IsFixed()); | |
1902 result->set_assigned_register(index); | |
1903 data()->MarkAllocated(rep, index); | |
1904 data()->fixed_float_live_ranges()[index] = result; | |
1905 } | |
1906 break; | |
1907 case MachineRepresentation::kFloat64: | 1881 case MachineRepresentation::kFloat64: |
| 1882 case MachineRepresentation::kSimd128: |
1908 DCHECK(index < config()->num_double_registers()); | 1883 DCHECK(index < config()->num_double_registers()); |
1909 result = data()->fixed_double_live_ranges()[index]; | 1884 result = data()->fixed_double_live_ranges()[index]; |
1910 if (result == nullptr) { | 1885 if (result == nullptr) { |
1911 result = data()->NewLiveRange(FixedFPLiveRangeID(index, rep), rep); | 1886 result = data()->NewLiveRange(FixedFPLiveRangeID(index, rep), rep); |
1912 DCHECK(result->IsFixed()); | 1887 DCHECK(result->IsFixed()); |
1913 result->set_assigned_register(index); | 1888 result->set_assigned_register(index); |
1914 data()->MarkAllocated(rep, index); | 1889 data()->MarkAllocated(rep, index); |
1915 data()->fixed_double_live_ranges()[index] = result; | 1890 data()->fixed_double_live_ranges()[index] = result; |
1916 } | 1891 } |
1917 break; | 1892 break; |
1918 case MachineRepresentation::kSimd128: | |
1919 DCHECK(index < config()->num_simd128_registers()); | |
1920 result = data()->fixed_simd128_live_ranges()[index]; | |
1921 if (result == nullptr) { | |
1922 result = data()->NewLiveRange(FixedFPLiveRangeID(index, rep), rep); | |
1923 DCHECK(result->IsFixed()); | |
1924 result->set_assigned_register(index); | |
1925 data()->MarkAllocated(rep, index); | |
1926 data()->fixed_simd128_live_ranges()[index] = result; | |
1927 } | |
1928 break; | |
1929 default: | 1893 default: |
1930 UNREACHABLE(); | 1894 UNREACHABLE(); |
1931 break; | 1895 break; |
1932 } | 1896 } |
1933 return result; | 1897 return result; |
1934 } | 1898 } |
1935 | 1899 |
1936 TopLevelLiveRange* LiveRangeBuilder::LiveRangeFor(InstructionOperand* operand) { | 1900 TopLevelLiveRange* LiveRangeBuilder::LiveRangeFor(InstructionOperand* operand) { |
1937 if (operand->IsUnallocated()) { | 1901 if (operand->IsUnallocated()) { |
1938 return data()->GetOrCreateLiveRangeFor( | 1902 return data()->GetOrCreateLiveRangeFor( |
(...skipping 106 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2045 // is OK because AddUseInterval will just merge it with the existing | 2009 // is OK because AddUseInterval will just merge it with the existing |
2046 // one at the end of the range. | 2010 // one at the end of the range. |
2047 int code = config()->GetAllocatableGeneralCode(i); | 2011 int code = config()->GetAllocatableGeneralCode(i); |
2048 TopLevelLiveRange* range = FixedLiveRangeFor(code); | 2012 TopLevelLiveRange* range = FixedLiveRangeFor(code); |
2049 range->AddUseInterval(curr_position, curr_position.End(), | 2013 range->AddUseInterval(curr_position, curr_position.End(), |
2050 allocation_zone()); | 2014 allocation_zone()); |
2051 } | 2015 } |
2052 } | 2016 } |
2053 | 2017 |
2054 if (instr->ClobbersDoubleRegisters()) { | 2018 if (instr->ClobbersDoubleRegisters()) { |
2055 for (int i = 0; i < config()->num_allocatable_double_registers(); ++i) { | 2019 for (int i = 0; i < config()->num_allocatable_aliased_double_registers(); |
| 2020 ++i) { |
2056 // Add a UseInterval for all DoubleRegisters. See comment above for | 2021 // Add a UseInterval for all DoubleRegisters. See comment above for |
2057 // general registers. | 2022 // general registers. |
2058 int code = config()->GetAllocatableDoubleCode(i); | 2023 int code = config()->GetAllocatableDoubleCode(i); |
2059 TopLevelLiveRange* range = | 2024 TopLevelLiveRange* range = |
2060 FixedFPLiveRangeFor(code, MachineRepresentation::kFloat64); | 2025 FixedFPLiveRangeFor(code, MachineRepresentation::kFloat64); |
2061 range->AddUseInterval(curr_position, curr_position.End(), | 2026 range->AddUseInterval(curr_position, curr_position.End(), |
2062 allocation_zone()); | 2027 allocation_zone()); |
2063 } | 2028 } |
2064 // Preserve fixed float registers on archs with non-simple aliasing. | |
2065 if (!kSimpleFPAliasing) { | |
2066 for (int i = 0; i < config()->num_allocatable_float_registers(); ++i) { | |
2067 // Add a UseInterval for all FloatRegisters. See comment above for | |
2068 // general registers. | |
2069 int code = config()->GetAllocatableFloatCode(i); | |
2070 TopLevelLiveRange* range = | |
2071 FixedFPLiveRangeFor(code, MachineRepresentation::kFloat32); | |
2072 range->AddUseInterval(curr_position, curr_position.End(), | |
2073 allocation_zone()); | |
2074 } | |
2075 for (int i = 0; i < config()->num_allocatable_simd128_registers(); | |
2076 ++i) { | |
2077 int code = config()->GetAllocatableSimd128Code(i); | |
2078 TopLevelLiveRange* range = | |
2079 FixedFPLiveRangeFor(code, MachineRepresentation::kSimd128); | |
2080 range->AddUseInterval(curr_position, curr_position.End(), | |
2081 allocation_zone()); | |
2082 } | |
2083 } | |
2084 } | 2029 } |
2085 | 2030 |
2086 for (size_t i = 0; i < instr->InputCount(); i++) { | 2031 for (size_t i = 0; i < instr->InputCount(); i++) { |
2087 InstructionOperand* input = instr->InputAt(i); | 2032 InstructionOperand* input = instr->InputAt(i); |
2088 if (input->IsImmediate() || input->IsExplicit()) { | 2033 if (input->IsImmediate() || input->IsExplicit()) { |
2089 continue; // Ignore immediates and explicitly reserved registers. | 2034 continue; // Ignore immediates and explicitly reserved registers. |
2090 } | 2035 } |
2091 LifetimePosition use_pos; | 2036 LifetimePosition use_pos; |
2092 if (input->IsUnallocated() && | 2037 if (input->IsUnallocated() && |
2093 UnallocatedOperand::cast(input)->IsUsedAtStart()) { | 2038 UnallocatedOperand::cast(input)->IsUsedAtStart()) { |
(...skipping 543 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2637 } | 2582 } |
2638 } | 2583 } |
2639 SortUnhandled(); | 2584 SortUnhandled(); |
2640 DCHECK(UnhandledIsSorted()); | 2585 DCHECK(UnhandledIsSorted()); |
2641 | 2586 |
2642 if (mode() == GENERAL_REGISTERS) { | 2587 if (mode() == GENERAL_REGISTERS) { |
2643 for (TopLevelLiveRange* current : data()->fixed_live_ranges()) { | 2588 for (TopLevelLiveRange* current : data()->fixed_live_ranges()) { |
2644 if (current != nullptr) AddToInactive(current); | 2589 if (current != nullptr) AddToInactive(current); |
2645 } | 2590 } |
2646 } else { | 2591 } else { |
2647 for (TopLevelLiveRange* current : data()->fixed_float_live_ranges()) { | |
2648 if (current != nullptr) AddToInactive(current); | |
2649 } | |
2650 for (TopLevelLiveRange* current : data()->fixed_double_live_ranges()) { | 2592 for (TopLevelLiveRange* current : data()->fixed_double_live_ranges()) { |
2651 if (current != nullptr) AddToInactive(current); | 2593 if (current != nullptr) AddToInactive(current); |
2652 } | 2594 } |
2653 for (TopLevelLiveRange* current : data()->fixed_simd128_live_ranges()) { | |
2654 if (current != nullptr) AddToInactive(current); | |
2655 } | |
2656 } | 2595 } |
2657 | 2596 |
2658 while (!unhandled_live_ranges().empty()) { | 2597 while (!unhandled_live_ranges().empty()) { |
2659 DCHECK(UnhandledIsSorted()); | 2598 DCHECK(UnhandledIsSorted()); |
2660 LiveRange* current = unhandled_live_ranges().back(); | 2599 LiveRange* current = unhandled_live_ranges().back(); |
2661 unhandled_live_ranges().pop_back(); | 2600 unhandled_live_ranges().pop_back(); |
2662 DCHECK(UnhandledIsSorted()); | 2601 DCHECK(UnhandledIsSorted()); |
2663 LifetimePosition position = current->Start(); | 2602 LifetimePosition position = current->Start(); |
2664 #ifdef DEBUG | 2603 #ifdef DEBUG |
2665 allocation_finger_ = position; | 2604 allocation_finger_ = position; |
(...skipping 146 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2812 | 2751 |
2813 void LinearScanAllocator::InactiveToActive(LiveRange* range) { | 2752 void LinearScanAllocator::InactiveToActive(LiveRange* range) { |
2814 RemoveElement(&inactive_live_ranges(), range); | 2753 RemoveElement(&inactive_live_ranges(), range); |
2815 active_live_ranges().push_back(range); | 2754 active_live_ranges().push_back(range); |
2816 TRACE("Moving live range %d:%d from inactive to active\n", | 2755 TRACE("Moving live range %d:%d from inactive to active\n", |
2817 range->TopLevel()->vreg(), range->relative_id()); | 2756 range->TopLevel()->vreg(), range->relative_id()); |
2818 } | 2757 } |
2819 | 2758 |
2820 | 2759 |
2821 bool LinearScanAllocator::TryAllocateFreeReg(LiveRange* current) { | 2760 bool LinearScanAllocator::TryAllocateFreeReg(LiveRange* current) { |
2822 MachineRepresentation rep = current->representation(); | |
2823 int num_regs = num_registers(); | 2761 int num_regs = num_registers(); |
2824 int num_codes = num_allocatable_registers(); | 2762 int num_codes = num_allocatable_registers(); |
2825 const int* codes = allocatable_register_codes(); | 2763 const int* codes = allocatable_register_codes(); |
2826 if (!kSimpleFPAliasing) { | |
2827 if (rep == MachineRepresentation::kFloat32) { | |
2828 num_regs = data()->config()->num_float_registers(); | |
2829 num_codes = data()->config()->num_allocatable_float_registers(); | |
2830 codes = data()->config()->allocatable_float_codes(); | |
2831 } else if (rep == MachineRepresentation::kSimd128) { | |
2832 num_regs = data()->config()->num_simd128_registers(); | |
2833 num_codes = data()->config()->num_allocatable_simd128_registers(); | |
2834 codes = data()->config()->allocatable_simd128_codes(); | |
2835 } | |
2836 } | |
2837 | 2764 |
2838 LifetimePosition free_until_pos[RegisterConfiguration::kMaxFPRegisters]; | 2765 LifetimePosition free_until_pos[RegisterConfiguration::kMaxFPRegisters]; |
2839 for (int i = 0; i < num_regs; i++) { | 2766 for (int i = 0; i < num_regs; i++) { |
2840 free_until_pos[i] = LifetimePosition::MaxPosition(); | 2767 free_until_pos[i] = LifetimePosition::MaxPosition(); |
2841 } | 2768 } |
2842 | 2769 |
2843 for (LiveRange* cur_active : active_live_ranges()) { | 2770 for (LiveRange* cur_active : active_live_ranges()) { |
2844 int cur_reg = cur_active->assigned_register(); | 2771 int cur_reg = cur_active->assigned_register(); |
2845 if (kSimpleFPAliasing || mode() == GENERAL_REGISTERS) { | 2772 free_until_pos[cur_reg] = LifetimePosition::GapFromInstructionIndex(0); |
2846 free_until_pos[cur_reg] = LifetimePosition::GapFromInstructionIndex(0); | 2773 TRACE("Register %s is free until pos %d (1)\n", RegisterName(cur_reg), |
2847 TRACE("Register %s is free until pos %d (1)\n", RegisterName(cur_reg), | 2774 LifetimePosition::GapFromInstructionIndex(0).value()); |
2848 LifetimePosition::GapFromInstructionIndex(0).value()); | |
2849 } else { | |
2850 int alias_base_index = -1; | |
2851 int aliases = data()->config()->GetAliases( | |
2852 cur_active->representation(), cur_reg, rep, &alias_base_index); | |
2853 DCHECK(aliases > 0 || (aliases == 0 && alias_base_index == -1)); | |
2854 while (aliases--) { | |
2855 int aliased_reg = alias_base_index + aliases; | |
2856 free_until_pos[aliased_reg] = | |
2857 LifetimePosition::GapFromInstructionIndex(0); | |
2858 } | |
2859 } | |
2860 } | 2775 } |
2861 | 2776 |
2862 for (LiveRange* cur_inactive : inactive_live_ranges()) { | 2777 for (LiveRange* cur_inactive : inactive_live_ranges()) { |
2863 DCHECK(cur_inactive->End() > current->Start()); | 2778 DCHECK(cur_inactive->End() > current->Start()); |
2864 LifetimePosition next_intersection = | 2779 LifetimePosition next_intersection = |
2865 cur_inactive->FirstIntersection(current); | 2780 cur_inactive->FirstIntersection(current); |
2866 if (!next_intersection.IsValid()) continue; | 2781 if (!next_intersection.IsValid()) continue; |
2867 int cur_reg = cur_inactive->assigned_register(); | 2782 int cur_reg = cur_inactive->assigned_register(); |
2868 if (kSimpleFPAliasing || mode() == GENERAL_REGISTERS) { | 2783 free_until_pos[cur_reg] = Min(free_until_pos[cur_reg], next_intersection); |
2869 free_until_pos[cur_reg] = Min(free_until_pos[cur_reg], next_intersection); | 2784 TRACE("Register %s is free until pos %d (2)\n", RegisterName(cur_reg), |
2870 TRACE("Register %s is free until pos %d (2)\n", RegisterName(cur_reg), | 2785 Min(free_until_pos[cur_reg], next_intersection).value()); |
2871 Min(free_until_pos[cur_reg], next_intersection).value()); | |
2872 } else { | |
2873 int alias_base_index = -1; | |
2874 int aliases = data()->config()->GetAliases( | |
2875 cur_inactive->representation(), cur_reg, rep, &alias_base_index); | |
2876 DCHECK(aliases > 0 || (aliases == 0 && alias_base_index == -1)); | |
2877 while (aliases--) { | |
2878 int aliased_reg = alias_base_index + aliases; | |
2879 free_until_pos[aliased_reg] = | |
2880 Min(free_until_pos[aliased_reg], next_intersection); | |
2881 } | |
2882 } | |
2883 } | 2786 } |
2884 | 2787 |
2885 int hint_register; | 2788 int hint_register; |
2886 if (current->FirstHintPosition(&hint_register) != nullptr) { | 2789 if (current->FirstHintPosition(&hint_register) != nullptr) { |
2887 TRACE( | 2790 TRACE( |
2888 "Found reg hint %s (free until [%d) for live range %d:%d (end %d[).\n", | 2791 "Found reg hint %s (free until [%d) for live range %d:%d (end %d[).\n", |
2889 RegisterName(hint_register), free_until_pos[hint_register].value(), | 2792 RegisterName(hint_register), free_until_pos[hint_register].value(), |
2890 current->TopLevel()->vreg(), current->relative_id(), | 2793 current->TopLevel()->vreg(), current->relative_id(), |
2891 current->End().value()); | 2794 current->End().value()); |
2892 | 2795 |
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2936 | 2839 |
2937 void LinearScanAllocator::AllocateBlockedReg(LiveRange* current) { | 2840 void LinearScanAllocator::AllocateBlockedReg(LiveRange* current) { |
2938 UsePosition* register_use = current->NextRegisterPosition(current->Start()); | 2841 UsePosition* register_use = current->NextRegisterPosition(current->Start()); |
2939 if (register_use == nullptr) { | 2842 if (register_use == nullptr) { |
2940 // There is no use in the current live range that requires a register. | 2843 // There is no use in the current live range that requires a register. |
2941 // We can just spill it. | 2844 // We can just spill it. |
2942 Spill(current); | 2845 Spill(current); |
2943 return; | 2846 return; |
2944 } | 2847 } |
2945 | 2848 |
2946 MachineRepresentation rep = current->representation(); | |
2947 int num_regs = num_registers(); | 2849 int num_regs = num_registers(); |
2948 int num_codes = num_allocatable_registers(); | 2850 int num_codes = num_allocatable_registers(); |
2949 const int* codes = allocatable_register_codes(); | 2851 const int* codes = allocatable_register_codes(); |
2950 if (!kSimpleFPAliasing) { | |
2951 if (rep == MachineRepresentation::kFloat32) { | |
2952 num_regs = data()->config()->num_float_registers(); | |
2953 num_codes = data()->config()->num_allocatable_float_registers(); | |
2954 codes = data()->config()->allocatable_float_codes(); | |
2955 } else if (rep == MachineRepresentation::kSimd128) { | |
2956 num_regs = data()->config()->num_simd128_registers(); | |
2957 num_codes = data()->config()->num_allocatable_simd128_registers(); | |
2958 codes = data()->config()->allocatable_simd128_codes(); | |
2959 } | |
2960 } | |
2961 | 2852 |
2962 LifetimePosition use_pos[RegisterConfiguration::kMaxFPRegisters]; | 2853 LifetimePosition use_pos[RegisterConfiguration::kMaxFPRegisters]; |
2963 LifetimePosition block_pos[RegisterConfiguration::kMaxFPRegisters]; | 2854 LifetimePosition block_pos[RegisterConfiguration::kMaxFPRegisters]; |
2964 for (int i = 0; i < num_regs; i++) { | 2855 for (int i = 0; i < num_regs; i++) { |
2965 use_pos[i] = block_pos[i] = LifetimePosition::MaxPosition(); | 2856 use_pos[i] = block_pos[i] = LifetimePosition::MaxPosition(); |
2966 } | 2857 } |
2967 | 2858 |
2968 for (LiveRange* range : active_live_ranges()) { | 2859 for (LiveRange* range : active_live_ranges()) { |
2969 int cur_reg = range->assigned_register(); | 2860 int cur_reg = range->assigned_register(); |
2970 bool is_fixed_or_cant_spill = | 2861 bool is_fixed_or_cant_spill = |
2971 range->TopLevel()->IsFixed() || !range->CanBeSpilled(current->Start()); | 2862 range->TopLevel()->IsFixed() || !range->CanBeSpilled(current->Start()); |
2972 if (kSimpleFPAliasing || mode() == GENERAL_REGISTERS) { | 2863 if (is_fixed_or_cant_spill) { |
2973 if (is_fixed_or_cant_spill) { | 2864 block_pos[cur_reg] = use_pos[cur_reg] = |
2974 block_pos[cur_reg] = use_pos[cur_reg] = | 2865 LifetimePosition::GapFromInstructionIndex(0); |
2975 LifetimePosition::GapFromInstructionIndex(0); | 2866 } else { |
| 2867 UsePosition* next_use = |
| 2868 range->NextUsePositionRegisterIsBeneficial(current->Start()); |
| 2869 if (next_use == nullptr) { |
| 2870 use_pos[cur_reg] = range->End(); |
2976 } else { | 2871 } else { |
2977 UsePosition* next_use = | 2872 use_pos[cur_reg] = next_use->pos(); |
2978 range->NextUsePositionRegisterIsBeneficial(current->Start()); | |
2979 if (next_use == nullptr) { | |
2980 use_pos[cur_reg] = range->End(); | |
2981 } else { | |
2982 use_pos[cur_reg] = next_use->pos(); | |
2983 } | |
2984 } | |
2985 } else { | |
2986 int alias_base_index = -1; | |
2987 int aliases = data()->config()->GetAliases( | |
2988 range->representation(), cur_reg, rep, &alias_base_index); | |
2989 DCHECK(aliases > 0 || (aliases == 0 && alias_base_index == -1)); | |
2990 while (aliases--) { | |
2991 int aliased_reg = alias_base_index + aliases; | |
2992 if (is_fixed_or_cant_spill) { | |
2993 block_pos[aliased_reg] = use_pos[aliased_reg] = | |
2994 LifetimePosition::GapFromInstructionIndex(0); | |
2995 } else { | |
2996 UsePosition* next_use = | |
2997 range->NextUsePositionRegisterIsBeneficial(current->Start()); | |
2998 if (next_use == nullptr) { | |
2999 use_pos[aliased_reg] = range->End(); | |
3000 } else { | |
3001 use_pos[aliased_reg] = next_use->pos(); | |
3002 } | |
3003 } | |
3004 } | 2873 } |
3005 } | 2874 } |
3006 } | 2875 } |
3007 | 2876 |
3008 for (LiveRange* range : inactive_live_ranges()) { | 2877 for (LiveRange* range : inactive_live_ranges()) { |
3009 DCHECK(range->End() > current->Start()); | 2878 DCHECK(range->End() > current->Start()); |
3010 LifetimePosition next_intersection = range->FirstIntersection(current); | 2879 LifetimePosition next_intersection = range->FirstIntersection(current); |
3011 if (!next_intersection.IsValid()) continue; | 2880 if (!next_intersection.IsValid()) continue; |
3012 int cur_reg = range->assigned_register(); | 2881 int cur_reg = range->assigned_register(); |
3013 bool is_fixed = range->TopLevel()->IsFixed(); | 2882 bool is_fixed = range->TopLevel()->IsFixed(); |
3014 if (kSimpleFPAliasing || mode() == GENERAL_REGISTERS) { | 2883 if (is_fixed) { |
3015 if (is_fixed) { | 2884 block_pos[cur_reg] = Min(block_pos[cur_reg], next_intersection); |
3016 block_pos[cur_reg] = Min(block_pos[cur_reg], next_intersection); | 2885 use_pos[cur_reg] = Min(block_pos[cur_reg], use_pos[cur_reg]); |
3017 use_pos[cur_reg] = Min(block_pos[cur_reg], use_pos[cur_reg]); | |
3018 } else { | |
3019 use_pos[cur_reg] = Min(use_pos[cur_reg], next_intersection); | |
3020 } | |
3021 } else { | 2886 } else { |
3022 int alias_base_index = -1; | 2887 use_pos[cur_reg] = Min(use_pos[cur_reg], next_intersection); |
3023 int aliases = data()->config()->GetAliases( | |
3024 range->representation(), cur_reg, rep, &alias_base_index); | |
3025 DCHECK(aliases > 0 || (aliases == 0 && alias_base_index == -1)); | |
3026 while (aliases--) { | |
3027 int aliased_reg = alias_base_index + aliases; | |
3028 if (is_fixed) { | |
3029 block_pos[aliased_reg] = | |
3030 Min(block_pos[aliased_reg], next_intersection); | |
3031 use_pos[aliased_reg] = | |
3032 Min(block_pos[aliased_reg], use_pos[aliased_reg]); | |
3033 } else { | |
3034 use_pos[aliased_reg] = Min(use_pos[aliased_reg], next_intersection); | |
3035 } | |
3036 } | |
3037 } | 2888 } |
3038 } | 2889 } |
3039 | 2890 |
3040 int reg = codes[0]; | 2891 int reg = codes[0]; |
3041 for (int i = 1; i < num_codes; ++i) { | 2892 for (int i = 1; i < num_codes; ++i) { |
3042 int code = codes[i]; | 2893 int code = codes[i]; |
3043 if (use_pos[code] > use_pos[reg]) { | 2894 if (use_pos[code] > use_pos[reg]) { |
3044 reg = code; | 2895 reg = code; |
3045 } | 2896 } |
3046 } | 2897 } |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3078 SplitAndSpillIntersecting(current); | 2929 SplitAndSpillIntersecting(current); |
3079 } | 2930 } |
3080 | 2931 |
3081 | 2932 |
3082 void LinearScanAllocator::SplitAndSpillIntersecting(LiveRange* current) { | 2933 void LinearScanAllocator::SplitAndSpillIntersecting(LiveRange* current) { |
3083 DCHECK(current->HasRegisterAssigned()); | 2934 DCHECK(current->HasRegisterAssigned()); |
3084 int reg = current->assigned_register(); | 2935 int reg = current->assigned_register(); |
3085 LifetimePosition split_pos = current->Start(); | 2936 LifetimePosition split_pos = current->Start(); |
3086 for (size_t i = 0; i < active_live_ranges().size(); ++i) { | 2937 for (size_t i = 0; i < active_live_ranges().size(); ++i) { |
3087 LiveRange* range = active_live_ranges()[i]; | 2938 LiveRange* range = active_live_ranges()[i]; |
3088 if (kSimpleFPAliasing || mode() == GENERAL_REGISTERS) { | 2939 if (range->assigned_register() != reg) continue; |
3089 if (range->assigned_register() != reg) continue; | |
3090 } else { | |
3091 if (!data()->config()->AreAliases(current->representation(), reg, | |
3092 range->representation(), | |
3093 range->assigned_register())) { | |
3094 continue; | |
3095 } | |
3096 } | |
3097 | 2940 |
3098 UsePosition* next_pos = range->NextRegisterPosition(current->Start()); | 2941 UsePosition* next_pos = range->NextRegisterPosition(current->Start()); |
3099 LifetimePosition spill_pos = FindOptimalSpillingPos(range, split_pos); | 2942 LifetimePosition spill_pos = FindOptimalSpillingPos(range, split_pos); |
3100 if (next_pos == nullptr) { | 2943 if (next_pos == nullptr) { |
3101 SpillAfter(range, spill_pos); | 2944 SpillAfter(range, spill_pos); |
3102 } else { | 2945 } else { |
3103 // When spilling between spill_pos and next_pos ensure that the range | 2946 // When spilling between spill_pos and next_pos ensure that the range |
3104 // remains spilled at least until the start of the current live range. | 2947 // remains spilled at least until the start of the current live range. |
3105 // This guarantees that we will not introduce new unhandled ranges that | 2948 // This guarantees that we will not introduce new unhandled ranges that |
3106 // start before the current range as this violates allocation invariants | 2949 // start before the current range as this violates allocation invariants |
3107 // and will lead to an inconsistent state of active and inactive | 2950 // and will lead to an inconsistent state of active and inactive |
3108 // live-ranges: ranges are allocated in order of their start positions, | 2951 // live-ranges: ranges are allocated in order of their start positions, |
3109 // ranges are retired from active/inactive when the start of the | 2952 // ranges are retired from active/inactive when the start of the |
3110 // current live-range is larger than their end. | 2953 // current live-range is larger than their end. |
3111 DCHECK(LifetimePosition::ExistsGapPositionBetween(current->Start(), | 2954 DCHECK(LifetimePosition::ExistsGapPositionBetween(current->Start(), |
3112 next_pos->pos())); | 2955 next_pos->pos())); |
3113 SpillBetweenUntil(range, spill_pos, current->Start(), next_pos->pos()); | 2956 SpillBetweenUntil(range, spill_pos, current->Start(), next_pos->pos()); |
3114 } | 2957 } |
3115 ActiveToHandled(range); | 2958 ActiveToHandled(range); |
3116 --i; | 2959 --i; |
3117 } | 2960 } |
3118 | 2961 |
3119 for (size_t i = 0; i < inactive_live_ranges().size(); ++i) { | 2962 for (size_t i = 0; i < inactive_live_ranges().size(); ++i) { |
3120 LiveRange* range = inactive_live_ranges()[i]; | 2963 LiveRange* range = inactive_live_ranges()[i]; |
3121 DCHECK(range->End() > current->Start()); | 2964 DCHECK(range->End() > current->Start()); |
3122 if (range->TopLevel()->IsFixed()) continue; | 2965 if (range->TopLevel()->IsFixed()) continue; |
3123 if (kSimpleFPAliasing || mode() == GENERAL_REGISTERS) { | 2966 if (range->assigned_register() != reg) continue; |
3124 if (range->assigned_register() != reg) continue; | |
3125 } else { | |
3126 if (!data()->config()->AreAliases(current->representation(), reg, | |
3127 range->representation(), | |
3128 range->assigned_register())) | |
3129 continue; | |
3130 } | |
3131 | 2967 |
3132 LifetimePosition next_intersection = range->FirstIntersection(current); | 2968 LifetimePosition next_intersection = range->FirstIntersection(current); |
3133 if (next_intersection.IsValid()) { | 2969 if (next_intersection.IsValid()) { |
3134 UsePosition* next_pos = range->NextRegisterPosition(current->Start()); | 2970 UsePosition* next_pos = range->NextRegisterPosition(current->Start()); |
3135 if (next_pos == nullptr) { | 2971 if (next_pos == nullptr) { |
3136 SpillAfter(range, split_pos); | 2972 SpillAfter(range, split_pos); |
3137 } else { | 2973 } else { |
3138 next_intersection = Min(next_intersection, next_pos->pos()); | 2974 next_intersection = Min(next_intersection, next_pos->pos()); |
3139 SpillBetween(range, split_pos, next_intersection); | 2975 SpillBetween(range, split_pos, next_intersection); |
3140 } | 2976 } |
(...skipping 642 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3783 } | 3619 } |
3784 } | 3620 } |
3785 } | 3621 } |
3786 } | 3622 } |
3787 } | 3623 } |
3788 | 3624 |
3789 | 3625 |
3790 } // namespace compiler | 3626 } // namespace compiler |
3791 } // namespace internal | 3627 } // namespace internal |
3792 } // namespace v8 | 3628 } // namespace v8 |
OLD | NEW |