Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(2)

Side by Side Diff: src/compiler/register-allocator.cc

Issue 2410673002: [Turbofan] Add concept of FP register aliasing on ARM 32. (Closed)
Patch Set: Fix reg codes (ia32) and register allocator (arm32). Created 4 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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
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_aliased_double_registers() 36 return kind == FP_REGISTERS ? cfg->num_allocatable_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 20 matching lines...) Expand all
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::kTaggedSigned: 74 case MachineRepresentation::kTaggedSigned:
75 case MachineRepresentation::kTaggedPointer: 75 case MachineRepresentation::kTaggedPointer:
76 case MachineRepresentation::kTagged: 76 case MachineRepresentation::kTagged:
77 case MachineRepresentation::kFloat32:
77 return kPointerSize; 78 return kPointerSize;
78 case MachineRepresentation::kFloat32:
79 // TODO(bbudge) Eliminate this when FP register aliasing works.
80 #if V8_TARGET_ARCH_ARM
81 return kDoubleSize;
82 #else
83 return kPointerSize;
84 #endif
85 case MachineRepresentation::kWord64: 79 case MachineRepresentation::kWord64:
86 case MachineRepresentation::kFloat64: 80 case MachineRepresentation::kFloat64:
87 return kDoubleSize; 81 return 8;
Mircea Trofin 2016/10/12 21:09:26 here and below, don't we have a constant somewhere
bbudge 2016/10/12 23:07:18 Indeed. Done.
88 case MachineRepresentation::kSimd128: 82 case MachineRepresentation::kSimd128:
89 return kSimd128Size; 83 return 16;
90 case MachineRepresentation::kNone: 84 case MachineRepresentation::kNone:
91 break; 85 break;
92 } 86 }
93 UNREACHABLE(); 87 UNREACHABLE();
94 return 0; 88 return 0;
95 } 89 }
96 90
97 } // namespace 91 } // namespace
98 92
99 class LiveRangeBound { 93 class LiveRangeBound {
(...skipping 1253 matching lines...) Expand 10 before | Expand all | Expand 10 after
1353 code_(code), 1347 code_(code),
1354 debug_name_(debug_name), 1348 debug_name_(debug_name),
1355 config_(config), 1349 config_(config),
1356 phi_map_(allocation_zone()), 1350 phi_map_(allocation_zone()),
1357 live_in_sets_(code->InstructionBlockCount(), nullptr, allocation_zone()), 1351 live_in_sets_(code->InstructionBlockCount(), nullptr, allocation_zone()),
1358 live_out_sets_(code->InstructionBlockCount(), nullptr, allocation_zone()), 1352 live_out_sets_(code->InstructionBlockCount(), nullptr, allocation_zone()),
1359 live_ranges_(code->VirtualRegisterCount() * 2, nullptr, 1353 live_ranges_(code->VirtualRegisterCount() * 2, nullptr,
1360 allocation_zone()), 1354 allocation_zone()),
1361 fixed_live_ranges_(this->config()->num_general_registers(), nullptr, 1355 fixed_live_ranges_(this->config()->num_general_registers(), nullptr,
1362 allocation_zone()), 1356 allocation_zone()),
1357 fixed_float_live_ranges_(this->config()->num_float_registers(), nullptr,
1358 allocation_zone()),
1363 fixed_double_live_ranges_(this->config()->num_double_registers(), nullptr, 1359 fixed_double_live_ranges_(this->config()->num_double_registers(), nullptr,
1364 allocation_zone()), 1360 allocation_zone()),
1361 fixed_simd128_live_ranges_(this->config()->num_simd128_registers(),
1362 nullptr, allocation_zone()),
1365 spill_ranges_(code->VirtualRegisterCount(), nullptr, allocation_zone()), 1363 spill_ranges_(code->VirtualRegisterCount(), nullptr, allocation_zone()),
1366 delayed_references_(allocation_zone()), 1364 delayed_references_(allocation_zone()),
1367 assigned_registers_(nullptr), 1365 assigned_registers_(nullptr),
1368 assigned_double_registers_(nullptr), 1366 assigned_double_registers_(nullptr),
1369 virtual_register_count_(code->VirtualRegisterCount()), 1367 virtual_register_count_(code->VirtualRegisterCount()),
1370 preassigned_slot_ranges_(zone) { 1368 preassigned_slot_ranges_(zone) {
1371 assigned_registers_ = new (code_zone()) 1369 assigned_registers_ = new (code_zone())
1372 BitVector(this->config()->num_general_registers(), code_zone()); 1370 BitVector(this->config()->num_general_registers(), code_zone());
1373 assigned_double_registers_ = new (code_zone()) 1371 assigned_double_registers_ = new (code_zone())
1374 BitVector(this->config()->num_double_registers(), code_zone()); 1372 BitVector(this->config()->num_double_registers(), code_zone());
(...skipping 157 matching lines...) Expand 10 before | Expand all | Expand 10 after
1532 DCHECK(!range->IsSplinter()); 1530 DCHECK(!range->IsSplinter());
1533 SpillRange* spill_range = 1531 SpillRange* spill_range =
1534 new (allocation_zone()) SpillRange(range, allocation_zone()); 1532 new (allocation_zone()) SpillRange(range, allocation_zone());
1535 return spill_range; 1533 return spill_range;
1536 } 1534 }
1537 1535
1538 void RegisterAllocationData::MarkAllocated(MachineRepresentation rep, 1536 void RegisterAllocationData::MarkAllocated(MachineRepresentation rep,
1539 int index) { 1537 int index) {
1540 switch (rep) { 1538 switch (rep) {
1541 case MachineRepresentation::kFloat32: 1539 case MachineRepresentation::kFloat32:
1540 case MachineRepresentation::kSimd128:
1541 if (kSimpleFPAliasing) {
1542 assigned_double_registers_->Add(index);
1543 } else {
1544 int alias_base_index = -1;
1545 int aliases = config()->GetAliases(
1546 rep, index, MachineRepresentation::kFloat64, &alias_base_index);
1547 DCHECK(aliases > 0 || (aliases == 0 && alias_base_index == -1));
1548 while (aliases--) {
1549 int aliased_reg = alias_base_index + aliases;
1550 assigned_double_registers_->Add(aliased_reg);
1551 }
1552 }
1553 break;
1542 case MachineRepresentation::kFloat64: 1554 case MachineRepresentation::kFloat64:
1543 case MachineRepresentation::kSimd128:
1544 assigned_double_registers_->Add(index); 1555 assigned_double_registers_->Add(index);
1545 break; 1556 break;
1546 default: 1557 default:
1547 DCHECK(!IsFloatingPoint(rep)); 1558 DCHECK(!IsFloatingPoint(rep));
1548 assigned_registers_->Add(index); 1559 assigned_registers_->Add(index);
1549 break; 1560 break;
1550 } 1561 }
1551 } 1562 }
1552 1563
1553 bool RegisterAllocationData::IsBlockBoundary(LifetimePosition pos) const { 1564 bool RegisterAllocationData::IsBlockBoundary(LifetimePosition pos) const {
(...skipping 306 matching lines...) Expand 10 before | Expand all | Expand 10 after
1860 TopLevelLiveRange* range = data()->GetOrCreateLiveRangeFor(operand_index); 1871 TopLevelLiveRange* range = data()->GetOrCreateLiveRangeFor(operand_index);
1861 range->AddUseInterval(start, end, allocation_zone()); 1872 range->AddUseInterval(start, end, allocation_zone());
1862 iterator.Advance(); 1873 iterator.Advance();
1863 } 1874 }
1864 } 1875 }
1865 1876
1866 int LiveRangeBuilder::FixedFPLiveRangeID(int index, MachineRepresentation rep) { 1877 int LiveRangeBuilder::FixedFPLiveRangeID(int index, MachineRepresentation rep) {
1867 int result = -index - 1; 1878 int result = -index - 1;
1868 switch (rep) { 1879 switch (rep) {
1869 case MachineRepresentation::kSimd128: 1880 case MachineRepresentation::kSimd128:
1881 result -= config()->num_float_registers();
1882 // Fall through.
1870 case MachineRepresentation::kFloat32: 1883 case MachineRepresentation::kFloat32:
1884 result -= config()->num_double_registers();
1885 // Fall through.
1871 case MachineRepresentation::kFloat64: 1886 case MachineRepresentation::kFloat64:
1872 result -= config()->num_general_registers(); 1887 result -= config()->num_general_registers();
1873 break; 1888 break;
1874 default: 1889 default:
1875 UNREACHABLE(); 1890 UNREACHABLE();
1876 break; 1891 break;
1877 } 1892 }
1878 return result; 1893 return result;
1879 } 1894 }
1880 1895
1881 TopLevelLiveRange* LiveRangeBuilder::FixedLiveRangeFor(int index) { 1896 TopLevelLiveRange* LiveRangeBuilder::FixedLiveRangeFor(int index) {
1882 DCHECK(index < config()->num_general_registers()); 1897 DCHECK(index < config()->num_general_registers());
1883 TopLevelLiveRange* result = data()->fixed_live_ranges()[index]; 1898 TopLevelLiveRange* result = data()->fixed_live_ranges()[index];
1884 if (result == nullptr) { 1899 if (result == nullptr) {
1885 MachineRepresentation rep = InstructionSequence::DefaultRepresentation(); 1900 MachineRepresentation rep = InstructionSequence::DefaultRepresentation();
1886 result = data()->NewLiveRange(FixedLiveRangeID(index), rep); 1901 result = data()->NewLiveRange(FixedLiveRangeID(index), rep);
1887 DCHECK(result->IsFixed()); 1902 DCHECK(result->IsFixed());
1888 result->set_assigned_register(index); 1903 result->set_assigned_register(index);
1889 data()->MarkAllocated(rep, index); 1904 data()->MarkAllocated(rep, index);
1890 data()->fixed_live_ranges()[index] = result; 1905 data()->fixed_live_ranges()[index] = result;
1891 } 1906 }
1892 return result; 1907 return result;
1893 } 1908 }
1894 1909
1895 TopLevelLiveRange* LiveRangeBuilder::FixedFPLiveRangeFor( 1910 TopLevelLiveRange* LiveRangeBuilder::FixedFPLiveRangeFor(
1896 int index, MachineRepresentation rep) { 1911 int index, MachineRepresentation rep) {
1897 TopLevelLiveRange* result = nullptr; 1912 int num_regs = -1;
1913 ZoneVector<TopLevelLiveRange*>* live_ranges = nullptr;
1898 switch (rep) { 1914 switch (rep) {
1899 case MachineRepresentation::kFloat32: 1915 case MachineRepresentation::kFloat32:
1916 num_regs = config()->num_float_registers();
1917 live_ranges = &data()->fixed_float_live_ranges();
1918 break;
1900 case MachineRepresentation::kFloat64: 1919 case MachineRepresentation::kFloat64:
1920 num_regs = config()->num_double_registers();
1921 live_ranges = &data()->fixed_double_live_ranges();
1922 break;
1901 case MachineRepresentation::kSimd128: 1923 case MachineRepresentation::kSimd128:
1902 DCHECK(index < config()->num_double_registers()); 1924 num_regs = config()->num_simd128_registers();
1903 result = data()->fixed_double_live_ranges()[index]; 1925 live_ranges = &data()->fixed_simd128_live_ranges();
1904 if (result == nullptr) {
1905 result = data()->NewLiveRange(FixedFPLiveRangeID(index, rep), rep);
1906 DCHECK(result->IsFixed());
1907 result->set_assigned_register(index);
1908 data()->MarkAllocated(rep, index);
1909 data()->fixed_double_live_ranges()[index] = result;
1910 }
1911 break; 1926 break;
1912 default: 1927 default:
1913 UNREACHABLE(); 1928 UNREACHABLE();
1914 break; 1929 break;
1915 } 1930 }
1931
1932 DCHECK(index < num_regs);
1933 TopLevelLiveRange* result = (*live_ranges)[index];
1934 if (result == nullptr) {
1935 result = data()->NewLiveRange(FixedFPLiveRangeID(index, rep), rep);
1936 DCHECK(result->IsFixed());
1937 result->set_assigned_register(index);
1938 data()->MarkAllocated(rep, index);
1939 (*live_ranges)[index] = result;
1940 }
1916 return result; 1941 return result;
1917 } 1942 }
1918 1943
1919 TopLevelLiveRange* LiveRangeBuilder::LiveRangeFor(InstructionOperand* operand) { 1944 TopLevelLiveRange* LiveRangeBuilder::LiveRangeFor(InstructionOperand* operand) {
1920 if (operand->IsUnallocated()) { 1945 if (operand->IsUnallocated()) {
1921 return data()->GetOrCreateLiveRangeFor( 1946 return data()->GetOrCreateLiveRangeFor(
1922 UnallocatedOperand::cast(operand)->virtual_register()); 1947 UnallocatedOperand::cast(operand)->virtual_register());
1923 } else if (operand->IsConstant()) { 1948 } else if (operand->IsConstant()) {
1924 return data()->GetOrCreateLiveRangeFor( 1949 return data()->GetOrCreateLiveRangeFor(
1925 ConstantOperand::cast(operand)->virtual_register()); 1950 ConstantOperand::cast(operand)->virtual_register());
(...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after
2028 // is OK because AddUseInterval will just merge it with the existing 2053 // is OK because AddUseInterval will just merge it with the existing
2029 // one at the end of the range. 2054 // one at the end of the range.
2030 int code = config()->GetAllocatableGeneralCode(i); 2055 int code = config()->GetAllocatableGeneralCode(i);
2031 TopLevelLiveRange* range = FixedLiveRangeFor(code); 2056 TopLevelLiveRange* range = FixedLiveRangeFor(code);
2032 range->AddUseInterval(curr_position, curr_position.End(), 2057 range->AddUseInterval(curr_position, curr_position.End(),
2033 allocation_zone()); 2058 allocation_zone());
2034 } 2059 }
2035 } 2060 }
2036 2061
2037 if (instr->ClobbersDoubleRegisters()) { 2062 if (instr->ClobbersDoubleRegisters()) {
2038 for (int i = 0; i < config()->num_allocatable_aliased_double_registers(); 2063 for (int i = 0; i < config()->num_allocatable_double_registers(); ++i) {
2039 ++i) {
2040 // Add a UseInterval for all DoubleRegisters. See comment above for 2064 // Add a UseInterval for all DoubleRegisters. See comment above for
2041 // general registers. 2065 // general registers.
2042 int code = config()->GetAllocatableDoubleCode(i); 2066 int code = config()->GetAllocatableDoubleCode(i);
2043 TopLevelLiveRange* range = 2067 TopLevelLiveRange* range =
2044 FixedFPLiveRangeFor(code, MachineRepresentation::kFloat64); 2068 FixedFPLiveRangeFor(code, MachineRepresentation::kFloat64);
2045 range->AddUseInterval(curr_position, curr_position.End(), 2069 range->AddUseInterval(curr_position, curr_position.End(),
2046 allocation_zone()); 2070 allocation_zone());
2047 } 2071 }
2072 // Preserve fixed float registers on archs with non-simple aliasing.
2073 if (!kSimpleFPAliasing) {
2074 for (int i = 0; i < config()->num_allocatable_float_registers(); ++i) {
2075 // Add a UseInterval for all FloatRegisters. See comment above for
2076 // general registers.
2077 int code = config()->GetAllocatableFloatCode(i);
2078 TopLevelLiveRange* range =
2079 FixedFPLiveRangeFor(code, MachineRepresentation::kFloat32);
2080 range->AddUseInterval(curr_position, curr_position.End(),
2081 allocation_zone());
2082 }
2083 for (int i = 0; i < config()->num_allocatable_simd128_registers();
2084 ++i) {
2085 int code = config()->GetAllocatableSimd128Code(i);
2086 TopLevelLiveRange* range =
2087 FixedFPLiveRangeFor(code, MachineRepresentation::kSimd128);
2088 range->AddUseInterval(curr_position, curr_position.End(),
2089 allocation_zone());
2090 }
2091 }
2048 } 2092 }
2049 2093
2050 for (size_t i = 0; i < instr->InputCount(); i++) { 2094 for (size_t i = 0; i < instr->InputCount(); i++) {
2051 InstructionOperand* input = instr->InputAt(i); 2095 InstructionOperand* input = instr->InputAt(i);
2052 if (input->IsImmediate() || input->IsExplicit()) { 2096 if (input->IsImmediate() || input->IsExplicit()) {
2053 continue; // Ignore immediates and explicitly reserved registers. 2097 continue; // Ignore immediates and explicitly reserved registers.
2054 } 2098 }
2055 LifetimePosition use_pos; 2099 LifetimePosition use_pos;
2056 if (input->IsUnallocated() && 2100 if (input->IsUnallocated() &&
2057 UnallocatedOperand::cast(input)->IsUsedAtStart()) { 2101 UnallocatedOperand::cast(input)->IsUsedAtStart()) {
(...skipping 546 matching lines...) Expand 10 before | Expand all | Expand 10 after
2604 } 2648 }
2605 } 2649 }
2606 SortUnhandled(); 2650 SortUnhandled();
2607 DCHECK(UnhandledIsSorted()); 2651 DCHECK(UnhandledIsSorted());
2608 2652
2609 if (mode() == GENERAL_REGISTERS) { 2653 if (mode() == GENERAL_REGISTERS) {
2610 for (TopLevelLiveRange* current : data()->fixed_live_ranges()) { 2654 for (TopLevelLiveRange* current : data()->fixed_live_ranges()) {
2611 if (current != nullptr) AddToInactive(current); 2655 if (current != nullptr) AddToInactive(current);
2612 } 2656 }
2613 } else { 2657 } else {
2658 for (TopLevelLiveRange* current : data()->fixed_float_live_ranges()) {
2659 if (current != nullptr) AddToInactive(current);
2660 }
2614 for (TopLevelLiveRange* current : data()->fixed_double_live_ranges()) { 2661 for (TopLevelLiveRange* current : data()->fixed_double_live_ranges()) {
2615 if (current != nullptr) AddToInactive(current); 2662 if (current != nullptr) AddToInactive(current);
2616 } 2663 }
2664 for (TopLevelLiveRange* current : data()->fixed_simd128_live_ranges()) {
2665 if (current != nullptr) AddToInactive(current);
2666 }
2617 } 2667 }
2618 2668
2619 while (!unhandled_live_ranges().empty()) { 2669 while (!unhandled_live_ranges().empty()) {
2620 DCHECK(UnhandledIsSorted()); 2670 DCHECK(UnhandledIsSorted());
2621 LiveRange* current = unhandled_live_ranges().back(); 2671 LiveRange* current = unhandled_live_ranges().back();
2622 unhandled_live_ranges().pop_back(); 2672 unhandled_live_ranges().pop_back();
2623 DCHECK(UnhandledIsSorted()); 2673 DCHECK(UnhandledIsSorted());
2624 LifetimePosition position = current->Start(); 2674 LifetimePosition position = current->Start();
2625 #ifdef DEBUG 2675 #ifdef DEBUG
2626 allocation_finger_ = position; 2676 allocation_finger_ = position;
(...skipping 160 matching lines...) Expand 10 before | Expand all | Expand 10 after
2787 2837
2788 void LinearScanAllocator::InactiveToActive(LiveRange* range) { 2838 void LinearScanAllocator::InactiveToActive(LiveRange* range) {
2789 RemoveElement(&inactive_live_ranges(), range); 2839 RemoveElement(&inactive_live_ranges(), range);
2790 active_live_ranges().push_back(range); 2840 active_live_ranges().push_back(range);
2791 TRACE("Moving live range %d:%d from inactive to active\n", 2841 TRACE("Moving live range %d:%d from inactive to active\n",
2792 range->TopLevel()->vreg(), range->relative_id()); 2842 range->TopLevel()->vreg(), range->relative_id());
2793 } 2843 }
2794 2844
2795 void LinearScanAllocator::FindFreeRegistersForRange( 2845 void LinearScanAllocator::FindFreeRegistersForRange(
2796 LiveRange* range, Vector<LifetimePosition> positions) { 2846 LiveRange* range, Vector<LifetimePosition> positions) {
2847 MachineRepresentation rep = range->representation();
2797 int num_regs = num_registers(); 2848 int num_regs = num_registers();
2849 int num_codes = num_allocatable_registers();
2850 const int* codes = allocatable_register_codes();
2851 if (!kSimpleFPAliasing) {
2852 if (rep == MachineRepresentation::kFloat32) {
2853 num_regs = data()->config()->num_float_registers();
2854 num_codes = data()->config()->num_allocatable_float_registers();
2855 codes = data()->config()->allocatable_float_codes();
Mircea Trofin 2016/10/12 21:09:26 would it make sense to move this logic to num_regi
bbudge 2016/10/12 23:07:17 I'd like to avoid the procedure call for non-ARM a
2856 } else if (rep == MachineRepresentation::kSimd128) {
2857 num_regs = data()->config()->num_simd128_registers();
2858 num_codes = data()->config()->num_allocatable_simd128_registers();
2859 codes = data()->config()->allocatable_simd128_codes();
2860 }
2861 }
2798 DCHECK_GE(positions.length(), num_regs); 2862 DCHECK_GE(positions.length(), num_regs);
2799 2863
2800 for (int i = 0; i < num_regs; i++) { 2864 for (int i = 0; i < num_regs; i++) {
2801 positions[i] = LifetimePosition::MaxPosition(); 2865 positions[i] = LifetimePosition::MaxPosition();
2802 } 2866 }
2803 2867
2804 for (LiveRange* cur_active : active_live_ranges()) { 2868 for (LiveRange* cur_active : active_live_ranges()) {
2805 int cur_reg = cur_active->assigned_register(); 2869 int cur_reg = cur_active->assigned_register();
2806 positions[cur_reg] = LifetimePosition::GapFromInstructionIndex(0); 2870 if (kSimpleFPAliasing || mode() == GENERAL_REGISTERS) {
2807 TRACE("Register %s is free until pos %d (1)\n", RegisterName(cur_reg), 2871 positions[cur_reg] = LifetimePosition::GapFromInstructionIndex(0);
2808 LifetimePosition::GapFromInstructionIndex(0).value()); 2872 TRACE("Register %s is free until pos %d (1)\n", RegisterName(cur_reg),
2873 LifetimePosition::GapFromInstructionIndex(0).value());
2874 } else {
2875 int alias_base_index = -1;
2876 int aliases = data()->config()->GetAliases(
2877 cur_active->representation(), cur_reg, rep, &alias_base_index);
2878 DCHECK(aliases > 0 || (aliases == 0 && alias_base_index == -1));
2879 while (aliases--) {
2880 int aliased_reg = alias_base_index + aliases;
2881 positions[aliased_reg] = LifetimePosition::GapFromInstructionIndex(0);
2882 }
2883 }
2809 } 2884 }
2810 2885
2811 for (LiveRange* cur_inactive : inactive_live_ranges()) { 2886 for (LiveRange* cur_inactive : inactive_live_ranges()) {
2812 DCHECK(cur_inactive->End() > range->Start()); 2887 DCHECK(cur_inactive->End() > range->Start());
2813 LifetimePosition next_intersection = cur_inactive->FirstIntersection(range); 2888 LifetimePosition next_intersection = cur_inactive->FirstIntersection(range);
2814 if (!next_intersection.IsValid()) continue; 2889 if (!next_intersection.IsValid()) continue;
2815 int cur_reg = cur_inactive->assigned_register(); 2890 int cur_reg = cur_inactive->assigned_register();
2816 positions[cur_reg] = Min(positions[cur_reg], next_intersection); 2891 if (kSimpleFPAliasing || mode() == GENERAL_REGISTERS) {
2817 TRACE("Register %s is free until pos %d (2)\n", RegisterName(cur_reg), 2892 positions[cur_reg] = Min(positions[cur_reg], next_intersection);
2818 Min(positions[cur_reg], next_intersection).value()); 2893 TRACE("Register %s is free until pos %d (2)\n", RegisterName(cur_reg),
2894 Min(positions[cur_reg], next_intersection).value());
2895 } else {
2896 int alias_base_index = -1;
2897 int aliases = data()->config()->GetAliases(
2898 cur_inactive->representation(), cur_reg, rep, &alias_base_index);
2899 DCHECK(aliases > 0 || (aliases == 0 && alias_base_index == -1));
2900 while (aliases--) {
2901 int aliased_reg = alias_base_index + aliases;
2902 positions[aliased_reg] = Min(positions[aliased_reg], next_intersection);
2903 }
2904 }
2819 } 2905 }
2820 } 2906 }
2821 2907
2822 // High-level register allocation summary: 2908 // High-level register allocation summary:
2823 // 2909 //
2824 // For regular, or hot (i.e. not splinter) ranges, we attempt to first 2910 // For regular, or hot (i.e. not splinter) ranges, we attempt to first
2825 // allocate first the preferred (hint) register. If that is not possible, 2911 // allocate first the preferred (hint) register. If that is not possible,
2826 // we find a register that's free, and allocate that. If that's not possible, 2912 // we find a register that's free, and allocate that. If that's not possible,
2827 // we search for a register to steal from a range that was allocated. The 2913 // we search for a register to steal from a range that was allocated. The
2828 // goal is to optimize for throughput by avoiding register-to-memory 2914 // goal is to optimize for throughput by avoiding register-to-memory
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after
2889 current->relative_id()); 2975 current->relative_id());
2890 SetLiveRangeAssignedRegister(current, hint_register); 2976 SetLiveRangeAssignedRegister(current, hint_register);
2891 return true; 2977 return true;
2892 } 2978 }
2893 } 2979 }
2894 return false; 2980 return false;
2895 } 2981 }
2896 2982
2897 bool LinearScanAllocator::TryAllocateFreeReg( 2983 bool LinearScanAllocator::TryAllocateFreeReg(
2898 LiveRange* current, const Vector<LifetimePosition>& free_until_pos) { 2984 LiveRange* current, const Vector<LifetimePosition>& free_until_pos) {
2985 MachineRepresentation rep = current->representation();
2899 int num_codes = num_allocatable_registers(); 2986 int num_codes = num_allocatable_registers();
2900 const int* codes = allocatable_register_codes(); 2987 const int* codes = allocatable_register_codes();
2988 if (!kSimpleFPAliasing) {
2989 if (rep == MachineRepresentation::kFloat32) {
2990 num_codes = data()->config()->num_allocatable_float_registers();
2991 codes = data()->config()->allocatable_float_codes();
2992 } else if (rep == MachineRepresentation::kSimd128) {
2993 num_codes = data()->config()->num_allocatable_simd128_registers();
2994 codes = data()->config()->allocatable_simd128_codes();
Mircea Trofin 2016/10/12 21:09:26 see factoring comment above about the num_allocata
bbudge 2016/10/12 23:07:18 Done.
2995 }
2996 }
2901 DCHECK_GE(free_until_pos.length(), num_codes); 2997 DCHECK_GE(free_until_pos.length(), num_codes);
2902 2998
2903 // Find the register which stays free for the longest time. 2999 // Find the register which stays free for the longest time.
2904 int reg = codes[0]; 3000 int reg = codes[0];
2905 for (int i = 1; i < num_codes; ++i) { 3001 for (int i = 1; i < num_codes; ++i) {
2906 int code = codes[i]; 3002 int code = codes[i];
2907 if (free_until_pos[code] > free_until_pos[reg]) { 3003 if (free_until_pos[code] > free_until_pos[reg]) {
2908 reg = code; 3004 reg = code;
2909 } 3005 }
2910 } 3006 }
(...skipping 24 matching lines...) Expand all
2935 3031
2936 void LinearScanAllocator::AllocateBlockedReg(LiveRange* current) { 3032 void LinearScanAllocator::AllocateBlockedReg(LiveRange* current) {
2937 UsePosition* register_use = current->NextRegisterPosition(current->Start()); 3033 UsePosition* register_use = current->NextRegisterPosition(current->Start());
2938 if (register_use == nullptr) { 3034 if (register_use == nullptr) {
2939 // There is no use in the current live range that requires a register. 3035 // There is no use in the current live range that requires a register.
2940 // We can just spill it. 3036 // We can just spill it.
2941 Spill(current); 3037 Spill(current);
2942 return; 3038 return;
2943 } 3039 }
2944 3040
3041 MachineRepresentation rep = current->representation();
2945 int num_regs = num_registers(); 3042 int num_regs = num_registers();
2946 int num_codes = num_allocatable_registers(); 3043 int num_codes = num_allocatable_registers();
2947 const int* codes = allocatable_register_codes(); 3044 const int* codes = allocatable_register_codes();
3045 if (!kSimpleFPAliasing) {
3046 if (rep == MachineRepresentation::kFloat32) {
3047 num_regs = data()->config()->num_float_registers();
3048 num_codes = data()->config()->num_allocatable_float_registers();
3049 codes = data()->config()->allocatable_float_codes();
3050 } else if (rep == MachineRepresentation::kSimd128) {
3051 num_regs = data()->config()->num_simd128_registers();
3052 num_codes = data()->config()->num_allocatable_simd128_registers();
3053 codes = data()->config()->allocatable_simd128_codes();
Mircea Trofin 2016/10/12 21:09:26 factoring comment above
bbudge 2016/10/12 23:07:17 Done.
3054 }
3055 }
2948 3056
2949 LifetimePosition use_pos[RegisterConfiguration::kMaxFPRegisters]; 3057 LifetimePosition use_pos[RegisterConfiguration::kMaxFPRegisters];
2950 LifetimePosition block_pos[RegisterConfiguration::kMaxFPRegisters]; 3058 LifetimePosition block_pos[RegisterConfiguration::kMaxFPRegisters];
2951 for (int i = 0; i < num_regs; i++) { 3059 for (int i = 0; i < num_regs; i++) {
2952 use_pos[i] = block_pos[i] = LifetimePosition::MaxPosition(); 3060 use_pos[i] = block_pos[i] = LifetimePosition::MaxPosition();
2953 } 3061 }
2954 3062
2955 for (LiveRange* range : active_live_ranges()) { 3063 for (LiveRange* range : active_live_ranges()) {
2956 int cur_reg = range->assigned_register(); 3064 int cur_reg = range->assigned_register();
2957 bool is_fixed_or_cant_spill = 3065 bool is_fixed_or_cant_spill =
2958 range->TopLevel()->IsFixed() || !range->CanBeSpilled(current->Start()); 3066 range->TopLevel()->IsFixed() || !range->CanBeSpilled(current->Start());
2959 if (is_fixed_or_cant_spill) { 3067 if (kSimpleFPAliasing || mode() == GENERAL_REGISTERS) {
2960 block_pos[cur_reg] = use_pos[cur_reg] = 3068 if (is_fixed_or_cant_spill) {
2961 LifetimePosition::GapFromInstructionIndex(0); 3069 block_pos[cur_reg] = use_pos[cur_reg] =
3070 LifetimePosition::GapFromInstructionIndex(0);
3071 } else {
3072 UsePosition* next_use =
3073 range->NextUsePositionRegisterIsBeneficial(current->Start());
3074 if (next_use == nullptr) {
3075 use_pos[cur_reg] = range->End();
Mircea Trofin 2016/10/12 21:09:26 this logic around next_use appears below, too. Cou
bbudge 2016/10/12 23:07:17 I added a LiveRange;:NextLifetimePositionRegisterI
3076 } else {
3077 use_pos[cur_reg] = next_use->pos();
3078 }
3079 }
2962 } else { 3080 } else {
2963 UsePosition* next_use = 3081 int alias_base_index = -1;
2964 range->NextUsePositionRegisterIsBeneficial(current->Start()); 3082 int aliases = data()->config()->GetAliases(
2965 if (next_use == nullptr) { 3083 range->representation(), cur_reg, rep, &alias_base_index);
2966 use_pos[cur_reg] = range->End(); 3084 DCHECK(aliases > 0 || (aliases == 0 && alias_base_index == -1));
2967 } else { 3085 while (aliases--) {
2968 use_pos[cur_reg] = next_use->pos(); 3086 int aliased_reg = alias_base_index + aliases;
3087 if (is_fixed_or_cant_spill) {
3088 block_pos[aliased_reg] = use_pos[aliased_reg] =
3089 LifetimePosition::GapFromInstructionIndex(0);
3090 } else {
3091 UsePosition* next_use =
3092 range->NextUsePositionRegisterIsBeneficial(current->Start());
3093 if (next_use == nullptr) {
3094 use_pos[aliased_reg] = range->End();
3095 } else {
3096 use_pos[aliased_reg] = next_use->pos();
3097 }
3098 }
2969 } 3099 }
2970 } 3100 }
2971 } 3101 }
2972 3102
2973 for (LiveRange* range : inactive_live_ranges()) { 3103 for (LiveRange* range : inactive_live_ranges()) {
2974 DCHECK(range->End() > current->Start()); 3104 DCHECK(range->End() > current->Start());
2975 LifetimePosition next_intersection = range->FirstIntersection(current); 3105 LifetimePosition next_intersection = range->FirstIntersection(current);
2976 if (!next_intersection.IsValid()) continue; 3106 if (!next_intersection.IsValid()) continue;
2977 int cur_reg = range->assigned_register(); 3107 int cur_reg = range->assigned_register();
2978 bool is_fixed = range->TopLevel()->IsFixed(); 3108 bool is_fixed = range->TopLevel()->IsFixed();
2979 if (is_fixed) { 3109 if (kSimpleFPAliasing || mode() == GENERAL_REGISTERS) {
2980 block_pos[cur_reg] = Min(block_pos[cur_reg], next_intersection); 3110 if (is_fixed) {
2981 use_pos[cur_reg] = Min(block_pos[cur_reg], use_pos[cur_reg]); 3111 block_pos[cur_reg] = Min(block_pos[cur_reg], next_intersection);
3112 use_pos[cur_reg] = Min(block_pos[cur_reg], use_pos[cur_reg]);
3113 } else {
3114 use_pos[cur_reg] = Min(use_pos[cur_reg], next_intersection);
3115 }
2982 } else { 3116 } else {
2983 use_pos[cur_reg] = Min(use_pos[cur_reg], next_intersection); 3117 int alias_base_index = -1;
3118 int aliases = data()->config()->GetAliases(
3119 range->representation(), cur_reg, rep, &alias_base_index);
3120 DCHECK(aliases > 0 || (aliases == 0 && alias_base_index == -1));
3121 while (aliases--) {
3122 int aliased_reg = alias_base_index + aliases;
3123 if (is_fixed) {
3124 block_pos[aliased_reg] =
3125 Min(block_pos[aliased_reg], next_intersection);
3126 use_pos[aliased_reg] =
3127 Min(block_pos[aliased_reg], use_pos[aliased_reg]);
3128 } else {
3129 use_pos[aliased_reg] = Min(use_pos[aliased_reg], next_intersection);
3130 }
3131 }
2984 } 3132 }
2985 } 3133 }
2986 3134
2987 int reg = codes[0]; 3135 int reg = codes[0];
2988 for (int i = 1; i < num_codes; ++i) { 3136 for (int i = 1; i < num_codes; ++i) {
2989 int code = codes[i]; 3137 int code = codes[i];
2990 if (use_pos[code] > use_pos[reg]) { 3138 if (use_pos[code] > use_pos[reg]) {
2991 reg = code; 3139 reg = code;
2992 } 3140 }
2993 } 3141 }
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
3025 SplitAndSpillIntersecting(current); 3173 SplitAndSpillIntersecting(current);
3026 } 3174 }
3027 3175
3028 3176
3029 void LinearScanAllocator::SplitAndSpillIntersecting(LiveRange* current) { 3177 void LinearScanAllocator::SplitAndSpillIntersecting(LiveRange* current) {
3030 DCHECK(current->HasRegisterAssigned()); 3178 DCHECK(current->HasRegisterAssigned());
3031 int reg = current->assigned_register(); 3179 int reg = current->assigned_register();
3032 LifetimePosition split_pos = current->Start(); 3180 LifetimePosition split_pos = current->Start();
3033 for (size_t i = 0; i < active_live_ranges().size(); ++i) { 3181 for (size_t i = 0; i < active_live_ranges().size(); ++i) {
3034 LiveRange* range = active_live_ranges()[i]; 3182 LiveRange* range = active_live_ranges()[i];
3035 if (range->assigned_register() != reg) continue; 3183 if (kSimpleFPAliasing || mode() == GENERAL_REGISTERS) {
3184 if (range->assigned_register() != reg) continue;
3185 } else {
3186 if (!data()->config()->AreAliases(current->representation(), reg,
3187 range->representation(),
3188 range->assigned_register())) {
3189 continue;
3190 }
3191 }
3036 3192
3037 UsePosition* next_pos = range->NextRegisterPosition(current->Start()); 3193 UsePosition* next_pos = range->NextRegisterPosition(current->Start());
3038 LifetimePosition spill_pos = FindOptimalSpillingPos(range, split_pos); 3194 LifetimePosition spill_pos = FindOptimalSpillingPos(range, split_pos);
3039 if (next_pos == nullptr) { 3195 if (next_pos == nullptr) {
3040 SpillAfter(range, spill_pos); 3196 SpillAfter(range, spill_pos);
3041 } else { 3197 } else {
3042 // When spilling between spill_pos and next_pos ensure that the range 3198 // When spilling between spill_pos and next_pos ensure that the range
3043 // remains spilled at least until the start of the current live range. 3199 // remains spilled at least until the start of the current live range.
3044 // This guarantees that we will not introduce new unhandled ranges that 3200 // This guarantees that we will not introduce new unhandled ranges that
3045 // start before the current range as this violates allocation invariants 3201 // start before the current range as this violates allocation invariants
3046 // and will lead to an inconsistent state of active and inactive 3202 // and will lead to an inconsistent state of active and inactive
3047 // live-ranges: ranges are allocated in order of their start positions, 3203 // live-ranges: ranges are allocated in order of their start positions,
3048 // ranges are retired from active/inactive when the start of the 3204 // ranges are retired from active/inactive when the start of the
3049 // current live-range is larger than their end. 3205 // current live-range is larger than their end.
3050 DCHECK(LifetimePosition::ExistsGapPositionBetween(current->Start(), 3206 DCHECK(LifetimePosition::ExistsGapPositionBetween(current->Start(),
3051 next_pos->pos())); 3207 next_pos->pos()));
3052 SpillBetweenUntil(range, spill_pos, current->Start(), next_pos->pos()); 3208 SpillBetweenUntil(range, spill_pos, current->Start(), next_pos->pos());
3053 } 3209 }
3054 ActiveToHandled(range); 3210 ActiveToHandled(range);
3055 --i; 3211 --i;
3056 } 3212 }
3057 3213
3058 for (size_t i = 0; i < inactive_live_ranges().size(); ++i) { 3214 for (size_t i = 0; i < inactive_live_ranges().size(); ++i) {
3059 LiveRange* range = inactive_live_ranges()[i]; 3215 LiveRange* range = inactive_live_ranges()[i];
3060 DCHECK(range->End() > current->Start()); 3216 DCHECK(range->End() > current->Start());
3061 if (range->TopLevel()->IsFixed()) continue; 3217 if (range->TopLevel()->IsFixed()) continue;
3062 if (range->assigned_register() != reg) continue; 3218 if (kSimpleFPAliasing || mode() == GENERAL_REGISTERS) {
3219 if (range->assigned_register() != reg) continue;
3220 } else {
3221 if (!data()->config()->AreAliases(current->representation(), reg,
3222 range->representation(),
3223 range->assigned_register()))
3224 continue;
3225 }
3063 3226
3064 LifetimePosition next_intersection = range->FirstIntersection(current); 3227 LifetimePosition next_intersection = range->FirstIntersection(current);
3065 if (next_intersection.IsValid()) { 3228 if (next_intersection.IsValid()) {
3066 UsePosition* next_pos = range->NextRegisterPosition(current->Start()); 3229 UsePosition* next_pos = range->NextRegisterPosition(current->Start());
3067 if (next_pos == nullptr) { 3230 if (next_pos == nullptr) {
3068 SpillAfter(range, split_pos); 3231 SpillAfter(range, split_pos);
3069 } else { 3232 } else {
3070 next_intersection = Min(next_intersection, next_pos->pos()); 3233 next_intersection = Min(next_intersection, next_pos->pos());
3071 SpillBetween(range, split_pos, next_intersection); 3234 SpillBetween(range, split_pos, next_intersection);
3072 } 3235 }
(...skipping 470 matching lines...) Expand 10 before | Expand all | Expand 10 after
3543 DCHECK(!code() 3706 DCHECK(!code()
3544 ->InstructionAt(pred->last_instruction_index()) 3707 ->InstructionAt(pred->last_instruction_index())
3545 ->HasReferenceMap()); 3708 ->HasReferenceMap());
3546 gap_index = pred->last_instruction_index(); 3709 gap_index = pred->last_instruction_index();
3547 position = Instruction::END; 3710 position = Instruction::END;
3548 } 3711 }
3549 data()->AddGapMove(gap_index, position, pred_op, cur_op); 3712 data()->AddGapMove(gap_index, position, pred_op, cur_op);
3550 return gap_index; 3713 return gap_index;
3551 } 3714 }
3552 3715
3553
3554 void LiveRangeConnector::ConnectRanges(Zone* local_zone) { 3716 void LiveRangeConnector::ConnectRanges(Zone* local_zone) {
3555 DelayedInsertionMap delayed_insertion_map(local_zone); 3717 DelayedInsertionMap delayed_insertion_map(local_zone);
3556 for (TopLevelLiveRange* top_range : data()->live_ranges()) { 3718 for (TopLevelLiveRange* top_range : data()->live_ranges()) {
3557 if (top_range == nullptr) continue; 3719 if (top_range == nullptr) continue;
3558 bool connect_spilled = top_range->IsSpilledOnlyInDeferredBlocks(); 3720 bool connect_spilled = top_range->IsSpilledOnlyInDeferredBlocks();
3559 LiveRange* first_range = top_range; 3721 LiveRange* first_range = top_range;
3560 for (LiveRange *second_range = first_range->next(); second_range != nullptr; 3722 for (LiveRange *second_range = first_range->next(); second_range != nullptr;
3561 first_range = second_range, second_range = second_range->next()) { 3723 first_range = second_range, second_range = second_range->next()) {
3562 LifetimePosition pos = second_range->Start(); 3724 LifetimePosition pos = second_range->Start();
3563 // Add gap move if the two live ranges touch and there is no block 3725 // Add gap move if the two live ranges touch and there is no block
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after
3631 } 3793 }
3632 if (done) break; 3794 if (done) break;
3633 // Reset state. 3795 // Reset state.
3634 to_eliminate.clear(); 3796 to_eliminate.clear();
3635 to_insert.clear(); 3797 to_insert.clear();
3636 moves = it->first.first; 3798 moves = it->first.first;
3637 } 3799 }
3638 // Gather all MoveOperands for a single ParallelMove. 3800 // Gather all MoveOperands for a single ParallelMove.
3639 MoveOperands* move = 3801 MoveOperands* move =
3640 new (code_zone()) MoveOperands(it->first.second, it->second); 3802 new (code_zone()) MoveOperands(it->first.second, it->second);
3641 MoveOperands* eliminate = moves->PrepareInsertAfter(move); 3803 moves->PrepareInsertAfter(move, &to_eliminate);
3642 to_insert.push_back(move); 3804 to_insert.push_back(move);
3643 if (eliminate != nullptr) to_eliminate.push_back(eliminate);
3644 } 3805 }
3645 } 3806 }
3646 3807
3647 3808
3648 void LiveRangeConnector::CommitSpillsInDeferredBlocks( 3809 void LiveRangeConnector::CommitSpillsInDeferredBlocks(
3649 TopLevelLiveRange* range, LiveRangeBoundArray* array, Zone* temp_zone) { 3810 TopLevelLiveRange* range, LiveRangeBoundArray* array, Zone* temp_zone) {
3650 DCHECK(range->IsSpilledOnlyInDeferredBlocks()); 3811 DCHECK(range->IsSpilledOnlyInDeferredBlocks());
3651 DCHECK(!range->spilled()); 3812 DCHECK(!range->spilled());
3652 3813
3653 InstructionSequence* code = data()->code(); 3814 InstructionSequence* code = data()->code();
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after
3715 } 3876 }
3716 } 3877 }
3717 } 3878 }
3718 } 3879 }
3719 } 3880 }
3720 3881
3721 3882
3722 } // namespace compiler 3883 } // namespace compiler
3723 } // namespace internal 3884 } // namespace internal
3724 } // namespace v8 3885 } // namespace v8
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698