| 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 |