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

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

Issue 2410673002: [Turbofan] Add concept of FP register aliasing on ARM 32. (Closed)
Patch Set: Add a TODO. Created 4 years, 1 month 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
« no previous file with comments | « src/compiler/register-allocator.h ('k') | src/compiler/wasm-linkage.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 kDoubleSize;
88 case MachineRepresentation::kSimd128: 82 case MachineRepresentation::kSimd128:
89 return kSimd128Size; 83 return kSimd128Size;
90 case MachineRepresentation::kNone: 84 case MachineRepresentation::kNone:
91 break; 85 break;
92 } 86 }
93 UNREACHABLE(); 87 UNREACHABLE();
94 return 0; 88 return 0;
(...skipping 396 matching lines...) Expand 10 before | Expand all | Expand 10 after
491 485
492 UsePosition* LiveRange::NextUsePositionRegisterIsBeneficial( 486 UsePosition* LiveRange::NextUsePositionRegisterIsBeneficial(
493 LifetimePosition start) const { 487 LifetimePosition start) const {
494 UsePosition* pos = NextUsePosition(start); 488 UsePosition* pos = NextUsePosition(start);
495 while (pos != nullptr && !pos->RegisterIsBeneficial()) { 489 while (pos != nullptr && !pos->RegisterIsBeneficial()) {
496 pos = pos->next(); 490 pos = pos->next();
497 } 491 }
498 return pos; 492 return pos;
499 } 493 }
500 494
495 LifetimePosition LiveRange::NextLifetimePositionRegisterIsBeneficial(
496 const LifetimePosition& start) const {
497 UsePosition* next_use = NextUsePositionRegisterIsBeneficial(start);
498 if (next_use == nullptr) return End();
499 return next_use->pos();
500 }
501 501
502 UsePosition* LiveRange::PreviousUsePositionRegisterIsBeneficial( 502 UsePosition* LiveRange::PreviousUsePositionRegisterIsBeneficial(
503 LifetimePosition start) const { 503 LifetimePosition start) const {
504 UsePosition* pos = first_pos(); 504 UsePosition* pos = first_pos();
505 UsePosition* prev = nullptr; 505 UsePosition* prev = nullptr;
506 while (pos != nullptr && pos->pos() < start) { 506 while (pos != nullptr && pos->pos() < start) {
507 if (pos->RegisterIsBeneficial()) prev = pos; 507 if (pos->RegisterIsBeneficial()) prev = pos;
508 pos = pos->next(); 508 pos = pos->next();
509 } 509 }
510 return prev; 510 return prev;
(...skipping 842 matching lines...) Expand 10 before | Expand all | Expand 10 after
1353 code_(code), 1353 code_(code),
1354 debug_name_(debug_name), 1354 debug_name_(debug_name),
1355 config_(config), 1355 config_(config),
1356 phi_map_(allocation_zone()), 1356 phi_map_(allocation_zone()),
1357 live_in_sets_(code->InstructionBlockCount(), nullptr, allocation_zone()), 1357 live_in_sets_(code->InstructionBlockCount(), nullptr, allocation_zone()),
1358 live_out_sets_(code->InstructionBlockCount(), nullptr, allocation_zone()), 1358 live_out_sets_(code->InstructionBlockCount(), nullptr, allocation_zone()),
1359 live_ranges_(code->VirtualRegisterCount() * 2, nullptr, 1359 live_ranges_(code->VirtualRegisterCount() * 2, nullptr,
1360 allocation_zone()), 1360 allocation_zone()),
1361 fixed_live_ranges_(this->config()->num_general_registers(), nullptr, 1361 fixed_live_ranges_(this->config()->num_general_registers(), nullptr,
1362 allocation_zone()), 1362 allocation_zone()),
1363 fixed_float_live_ranges_(this->config()->num_float_registers(), nullptr,
1364 allocation_zone()),
1363 fixed_double_live_ranges_(this->config()->num_double_registers(), nullptr, 1365 fixed_double_live_ranges_(this->config()->num_double_registers(), nullptr,
1364 allocation_zone()), 1366 allocation_zone()),
1367 fixed_simd128_live_ranges_(this->config()->num_simd128_registers(),
1368 nullptr, allocation_zone()),
1365 spill_ranges_(code->VirtualRegisterCount(), nullptr, allocation_zone()), 1369 spill_ranges_(code->VirtualRegisterCount(), nullptr, allocation_zone()),
1366 delayed_references_(allocation_zone()), 1370 delayed_references_(allocation_zone()),
1367 assigned_registers_(nullptr), 1371 assigned_registers_(nullptr),
1368 assigned_double_registers_(nullptr), 1372 assigned_double_registers_(nullptr),
1369 virtual_register_count_(code->VirtualRegisterCount()), 1373 virtual_register_count_(code->VirtualRegisterCount()),
1370 preassigned_slot_ranges_(zone) { 1374 preassigned_slot_ranges_(zone) {
1371 assigned_registers_ = new (code_zone()) 1375 assigned_registers_ = new (code_zone())
1372 BitVector(this->config()->num_general_registers(), code_zone()); 1376 BitVector(this->config()->num_general_registers(), code_zone());
1373 assigned_double_registers_ = new (code_zone()) 1377 assigned_double_registers_ = new (code_zone())
1374 BitVector(this->config()->num_double_registers(), code_zone()); 1378 BitVector(this->config()->num_double_registers(), code_zone());
(...skipping 157 matching lines...) Expand 10 before | Expand all | Expand 10 after
1532 DCHECK(!range->IsSplinter()); 1536 DCHECK(!range->IsSplinter());
1533 SpillRange* spill_range = 1537 SpillRange* spill_range =
1534 new (allocation_zone()) SpillRange(range, allocation_zone()); 1538 new (allocation_zone()) SpillRange(range, allocation_zone());
1535 return spill_range; 1539 return spill_range;
1536 } 1540 }
1537 1541
1538 void RegisterAllocationData::MarkAllocated(MachineRepresentation rep, 1542 void RegisterAllocationData::MarkAllocated(MachineRepresentation rep,
1539 int index) { 1543 int index) {
1540 switch (rep) { 1544 switch (rep) {
1541 case MachineRepresentation::kFloat32: 1545 case MachineRepresentation::kFloat32:
1546 case MachineRepresentation::kSimd128:
1547 if (kSimpleFPAliasing) {
1548 assigned_double_registers_->Add(index);
1549 } else {
1550 int alias_base_index = -1;
1551 int aliases = config()->GetAliases(
1552 rep, index, MachineRepresentation::kFloat64, &alias_base_index);
1553 DCHECK(aliases > 0 || (aliases == 0 && alias_base_index == -1));
1554 while (aliases--) {
1555 int aliased_reg = alias_base_index + aliases;
1556 assigned_double_registers_->Add(aliased_reg);
1557 }
1558 }
1559 break;
1542 case MachineRepresentation::kFloat64: 1560 case MachineRepresentation::kFloat64:
1543 case MachineRepresentation::kSimd128:
1544 assigned_double_registers_->Add(index); 1561 assigned_double_registers_->Add(index);
1545 break; 1562 break;
1546 default: 1563 default:
1547 DCHECK(!IsFloatingPoint(rep)); 1564 DCHECK(!IsFloatingPoint(rep));
1548 assigned_registers_->Add(index); 1565 assigned_registers_->Add(index);
1549 break; 1566 break;
1550 } 1567 }
1551 } 1568 }
1552 1569
1553 bool RegisterAllocationData::IsBlockBoundary(LifetimePosition pos) const { 1570 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); 1877 TopLevelLiveRange* range = data()->GetOrCreateLiveRangeFor(operand_index);
1861 range->AddUseInterval(start, end, allocation_zone()); 1878 range->AddUseInterval(start, end, allocation_zone());
1862 iterator.Advance(); 1879 iterator.Advance();
1863 } 1880 }
1864 } 1881 }
1865 1882
1866 int LiveRangeBuilder::FixedFPLiveRangeID(int index, MachineRepresentation rep) { 1883 int LiveRangeBuilder::FixedFPLiveRangeID(int index, MachineRepresentation rep) {
1867 int result = -index - 1; 1884 int result = -index - 1;
1868 switch (rep) { 1885 switch (rep) {
1869 case MachineRepresentation::kSimd128: 1886 case MachineRepresentation::kSimd128:
1887 result -= config()->num_float_registers();
1888 // Fall through.
1870 case MachineRepresentation::kFloat32: 1889 case MachineRepresentation::kFloat32:
1890 result -= config()->num_double_registers();
1891 // Fall through.
1871 case MachineRepresentation::kFloat64: 1892 case MachineRepresentation::kFloat64:
1872 result -= config()->num_general_registers(); 1893 result -= config()->num_general_registers();
1873 break; 1894 break;
1874 default: 1895 default:
1875 UNREACHABLE(); 1896 UNREACHABLE();
1876 break; 1897 break;
1877 } 1898 }
1878 return result; 1899 return result;
1879 } 1900 }
1880 1901
1881 TopLevelLiveRange* LiveRangeBuilder::FixedLiveRangeFor(int index) { 1902 TopLevelLiveRange* LiveRangeBuilder::FixedLiveRangeFor(int index) {
1882 DCHECK(index < config()->num_general_registers()); 1903 DCHECK(index < config()->num_general_registers());
1883 TopLevelLiveRange* result = data()->fixed_live_ranges()[index]; 1904 TopLevelLiveRange* result = data()->fixed_live_ranges()[index];
1884 if (result == nullptr) { 1905 if (result == nullptr) {
1885 MachineRepresentation rep = InstructionSequence::DefaultRepresentation(); 1906 MachineRepresentation rep = InstructionSequence::DefaultRepresentation();
1886 result = data()->NewLiveRange(FixedLiveRangeID(index), rep); 1907 result = data()->NewLiveRange(FixedLiveRangeID(index), rep);
1887 DCHECK(result->IsFixed()); 1908 DCHECK(result->IsFixed());
1888 result->set_assigned_register(index); 1909 result->set_assigned_register(index);
1889 data()->MarkAllocated(rep, index); 1910 data()->MarkAllocated(rep, index);
1890 data()->fixed_live_ranges()[index] = result; 1911 data()->fixed_live_ranges()[index] = result;
1891 } 1912 }
1892 return result; 1913 return result;
1893 } 1914 }
1894 1915
1895 TopLevelLiveRange* LiveRangeBuilder::FixedFPLiveRangeFor( 1916 TopLevelLiveRange* LiveRangeBuilder::FixedFPLiveRangeFor(
1896 int index, MachineRepresentation rep) { 1917 int index, MachineRepresentation rep) {
1897 TopLevelLiveRange* result = nullptr; 1918 int num_regs = -1;
1919 ZoneVector<TopLevelLiveRange*>* live_ranges = nullptr;
1898 switch (rep) { 1920 switch (rep) {
1899 case MachineRepresentation::kFloat32: 1921 case MachineRepresentation::kFloat32:
1922 num_regs = config()->num_float_registers();
1923 live_ranges = &data()->fixed_float_live_ranges();
1924 break;
1900 case MachineRepresentation::kFloat64: 1925 case MachineRepresentation::kFloat64:
1926 num_regs = config()->num_double_registers();
1927 live_ranges = &data()->fixed_double_live_ranges();
1928 break;
1901 case MachineRepresentation::kSimd128: 1929 case MachineRepresentation::kSimd128:
1902 DCHECK(index < config()->num_double_registers()); 1930 num_regs = config()->num_simd128_registers();
1903 result = data()->fixed_double_live_ranges()[index]; 1931 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; 1932 break;
1912 default: 1933 default:
1913 UNREACHABLE(); 1934 UNREACHABLE();
1914 break; 1935 break;
1915 } 1936 }
1937
1938 DCHECK(index < num_regs);
1939 TopLevelLiveRange* result = (*live_ranges)[index];
1940 if (result == nullptr) {
1941 result = data()->NewLiveRange(FixedFPLiveRangeID(index, rep), rep);
1942 DCHECK(result->IsFixed());
1943 result->set_assigned_register(index);
1944 data()->MarkAllocated(rep, index);
1945 (*live_ranges)[index] = result;
1946 }
1916 return result; 1947 return result;
1917 } 1948 }
1918 1949
1919 TopLevelLiveRange* LiveRangeBuilder::LiveRangeFor(InstructionOperand* operand) { 1950 TopLevelLiveRange* LiveRangeBuilder::LiveRangeFor(InstructionOperand* operand) {
1920 if (operand->IsUnallocated()) { 1951 if (operand->IsUnallocated()) {
1921 return data()->GetOrCreateLiveRangeFor( 1952 return data()->GetOrCreateLiveRangeFor(
1922 UnallocatedOperand::cast(operand)->virtual_register()); 1953 UnallocatedOperand::cast(operand)->virtual_register());
1923 } else if (operand->IsConstant()) { 1954 } else if (operand->IsConstant()) {
1924 return data()->GetOrCreateLiveRangeFor( 1955 return data()->GetOrCreateLiveRangeFor(
1925 ConstantOperand::cast(operand)->virtual_register()); 1956 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 2059 // is OK because AddUseInterval will just merge it with the existing
2029 // one at the end of the range. 2060 // one at the end of the range.
2030 int code = config()->GetAllocatableGeneralCode(i); 2061 int code = config()->GetAllocatableGeneralCode(i);
2031 TopLevelLiveRange* range = FixedLiveRangeFor(code); 2062 TopLevelLiveRange* range = FixedLiveRangeFor(code);
2032 range->AddUseInterval(curr_position, curr_position.End(), 2063 range->AddUseInterval(curr_position, curr_position.End(),
2033 allocation_zone()); 2064 allocation_zone());
2034 } 2065 }
2035 } 2066 }
2036 2067
2037 if (instr->ClobbersDoubleRegisters()) { 2068 if (instr->ClobbersDoubleRegisters()) {
2038 for (int i = 0; i < config()->num_allocatable_aliased_double_registers(); 2069 for (int i = 0; i < config()->num_allocatable_double_registers(); ++i) {
2039 ++i) {
2040 // Add a UseInterval for all DoubleRegisters. See comment above for 2070 // Add a UseInterval for all DoubleRegisters. See comment above for
2041 // general registers. 2071 // general registers.
2042 int code = config()->GetAllocatableDoubleCode(i); 2072 int code = config()->GetAllocatableDoubleCode(i);
2043 TopLevelLiveRange* range = 2073 TopLevelLiveRange* range =
2044 FixedFPLiveRangeFor(code, MachineRepresentation::kFloat64); 2074 FixedFPLiveRangeFor(code, MachineRepresentation::kFloat64);
2045 range->AddUseInterval(curr_position, curr_position.End(), 2075 range->AddUseInterval(curr_position, curr_position.End(),
2046 allocation_zone()); 2076 allocation_zone());
2047 } 2077 }
2078 // Clobber fixed float registers on archs with non-simple aliasing.
2079 if (!kSimpleFPAliasing) {
2080 for (int i = 0; i < config()->num_allocatable_float_registers(); ++i) {
2081 // Add a UseInterval for all FloatRegisters. See comment above for
2082 // general registers.
2083 int code = config()->GetAllocatableFloatCode(i);
2084 TopLevelLiveRange* range =
2085 FixedFPLiveRangeFor(code, MachineRepresentation::kFloat32);
2086 range->AddUseInterval(curr_position, curr_position.End(),
2087 allocation_zone());
2088 }
2089 for (int i = 0; i < config()->num_allocatable_simd128_registers();
2090 ++i) {
2091 int code = config()->GetAllocatableSimd128Code(i);
2092 TopLevelLiveRange* range =
2093 FixedFPLiveRangeFor(code, MachineRepresentation::kSimd128);
2094 range->AddUseInterval(curr_position, curr_position.End(),
2095 allocation_zone());
2096 }
2097 }
2048 } 2098 }
2049 2099
2050 for (size_t i = 0; i < instr->InputCount(); i++) { 2100 for (size_t i = 0; i < instr->InputCount(); i++) {
2051 InstructionOperand* input = instr->InputAt(i); 2101 InstructionOperand* input = instr->InputAt(i);
2052 if (input->IsImmediate() || input->IsExplicit()) { 2102 if (input->IsImmediate() || input->IsExplicit()) {
2053 continue; // Ignore immediates and explicitly reserved registers. 2103 continue; // Ignore immediates and explicitly reserved registers.
2054 } 2104 }
2055 LifetimePosition use_pos; 2105 LifetimePosition use_pos;
2056 if (input->IsUnallocated() && 2106 if (input->IsUnallocated() &&
2057 UnallocatedOperand::cast(input)->IsUsedAtStart()) { 2107 UnallocatedOperand::cast(input)->IsUsedAtStart()) {
(...skipping 625 matching lines...) Expand 10 before | Expand all | Expand 10 after
2683 } 2733 }
2684 } 2734 }
2685 SortUnhandled(); 2735 SortUnhandled();
2686 DCHECK(UnhandledIsSorted()); 2736 DCHECK(UnhandledIsSorted());
2687 2737
2688 if (mode() == GENERAL_REGISTERS) { 2738 if (mode() == GENERAL_REGISTERS) {
2689 for (TopLevelLiveRange* current : data()->fixed_live_ranges()) { 2739 for (TopLevelLiveRange* current : data()->fixed_live_ranges()) {
2690 if (current != nullptr) AddToInactive(current); 2740 if (current != nullptr) AddToInactive(current);
2691 } 2741 }
2692 } else { 2742 } else {
2743 for (TopLevelLiveRange* current : data()->fixed_float_live_ranges()) {
2744 if (current != nullptr) AddToInactive(current);
2745 }
2693 for (TopLevelLiveRange* current : data()->fixed_double_live_ranges()) { 2746 for (TopLevelLiveRange* current : data()->fixed_double_live_ranges()) {
2694 if (current != nullptr) AddToInactive(current); 2747 if (current != nullptr) AddToInactive(current);
2695 } 2748 }
2749 for (TopLevelLiveRange* current : data()->fixed_simd128_live_ranges()) {
2750 if (current != nullptr) AddToInactive(current);
2751 }
2696 } 2752 }
2697 2753
2698 while (!unhandled_live_ranges().empty()) { 2754 while (!unhandled_live_ranges().empty()) {
2699 DCHECK(UnhandledIsSorted()); 2755 DCHECK(UnhandledIsSorted());
2700 LiveRange* current = unhandled_live_ranges().back(); 2756 LiveRange* current = unhandled_live_ranges().back();
2701 unhandled_live_ranges().pop_back(); 2757 unhandled_live_ranges().pop_back();
2702 DCHECK(UnhandledIsSorted()); 2758 DCHECK(UnhandledIsSorted());
2703 LifetimePosition position = current->Start(); 2759 LifetimePosition position = current->Start();
2704 #ifdef DEBUG 2760 #ifdef DEBUG
2705 allocation_finger_ = position; 2761 allocation_finger_ = position;
(...skipping 160 matching lines...) Expand 10 before | Expand all | Expand 10 after
2866 } 2922 }
2867 2923
2868 2924
2869 void LinearScanAllocator::InactiveToActive(LiveRange* range) { 2925 void LinearScanAllocator::InactiveToActive(LiveRange* range) {
2870 RemoveElement(&inactive_live_ranges(), range); 2926 RemoveElement(&inactive_live_ranges(), range);
2871 active_live_ranges().push_back(range); 2927 active_live_ranges().push_back(range);
2872 TRACE("Moving live range %d:%d from inactive to active\n", 2928 TRACE("Moving live range %d:%d from inactive to active\n",
2873 range->TopLevel()->vreg(), range->relative_id()); 2929 range->TopLevel()->vreg(), range->relative_id());
2874 } 2930 }
2875 2931
2932 void LinearScanAllocator::GetFPRegisterSet(MachineRepresentation rep,
2933 int* num_regs, int* num_codes,
2934 const int** codes) const {
2935 DCHECK(!kSimpleFPAliasing);
2936 if (rep == MachineRepresentation::kFloat32) {
2937 *num_regs = data()->config()->num_float_registers();
2938 *num_codes = data()->config()->num_allocatable_float_registers();
2939 *codes = data()->config()->allocatable_float_codes();
2940 } else if (rep == MachineRepresentation::kSimd128) {
2941 *num_regs = data()->config()->num_simd128_registers();
2942 *num_codes = data()->config()->num_allocatable_simd128_registers();
2943 *codes = data()->config()->allocatable_simd128_codes();
2944 } else {
2945 UNREACHABLE();
2946 }
2947 }
2948
2876 void LinearScanAllocator::FindFreeRegistersForRange( 2949 void LinearScanAllocator::FindFreeRegistersForRange(
2877 LiveRange* range, Vector<LifetimePosition> positions) { 2950 LiveRange* range, Vector<LifetimePosition> positions) {
2878 int num_regs = num_registers(); 2951 int num_regs = num_registers();
2952 int num_codes = num_allocatable_registers();
2953 const int* codes = allocatable_register_codes();
2954 MachineRepresentation rep = range->representation();
2955 if (!kSimpleFPAliasing && (rep == MachineRepresentation::kFloat32 ||
2956 rep == MachineRepresentation::kSimd128))
2957 GetFPRegisterSet(rep, &num_regs, &num_codes, &codes);
2879 DCHECK_GE(positions.length(), num_regs); 2958 DCHECK_GE(positions.length(), num_regs);
2880 2959
2881 for (int i = 0; i < num_regs; i++) { 2960 for (int i = 0; i < num_regs; i++) {
2882 positions[i] = LifetimePosition::MaxPosition(); 2961 positions[i] = LifetimePosition::MaxPosition();
2883 } 2962 }
2884 2963
2885 for (LiveRange* cur_active : active_live_ranges()) { 2964 for (LiveRange* cur_active : active_live_ranges()) {
2886 int cur_reg = cur_active->assigned_register(); 2965 int cur_reg = cur_active->assigned_register();
2887 positions[cur_reg] = LifetimePosition::GapFromInstructionIndex(0); 2966 if (kSimpleFPAliasing || mode() == GENERAL_REGISTERS) {
2888 TRACE("Register %s is free until pos %d (1)\n", RegisterName(cur_reg), 2967 positions[cur_reg] = LifetimePosition::GapFromInstructionIndex(0);
2889 LifetimePosition::GapFromInstructionIndex(0).value()); 2968 TRACE("Register %s is free until pos %d (1)\n", RegisterName(cur_reg),
2969 LifetimePosition::GapFromInstructionIndex(0).value());
2970 } else {
2971 int alias_base_index = -1;
2972 int aliases = data()->config()->GetAliases(
2973 cur_active->representation(), cur_reg, rep, &alias_base_index);
2974 DCHECK(aliases > 0 || (aliases == 0 && alias_base_index == -1));
2975 while (aliases--) {
2976 int aliased_reg = alias_base_index + aliases;
2977 positions[aliased_reg] = LifetimePosition::GapFromInstructionIndex(0);
2978 }
2979 }
2890 } 2980 }
2891 2981
2892 for (LiveRange* cur_inactive : inactive_live_ranges()) { 2982 for (LiveRange* cur_inactive : inactive_live_ranges()) {
2893 DCHECK(cur_inactive->End() > range->Start()); 2983 DCHECK(cur_inactive->End() > range->Start());
2894 LifetimePosition next_intersection = cur_inactive->FirstIntersection(range); 2984 LifetimePosition next_intersection = cur_inactive->FirstIntersection(range);
2895 if (!next_intersection.IsValid()) continue; 2985 if (!next_intersection.IsValid()) continue;
2896 int cur_reg = cur_inactive->assigned_register(); 2986 int cur_reg = cur_inactive->assigned_register();
2897 positions[cur_reg] = Min(positions[cur_reg], next_intersection); 2987 if (kSimpleFPAliasing || mode() == GENERAL_REGISTERS) {
2898 TRACE("Register %s is free until pos %d (2)\n", RegisterName(cur_reg), 2988 positions[cur_reg] = Min(positions[cur_reg], next_intersection);
2899 Min(positions[cur_reg], next_intersection).value()); 2989 TRACE("Register %s is free until pos %d (2)\n", RegisterName(cur_reg),
2990 Min(positions[cur_reg], next_intersection).value());
2991 } else {
2992 int alias_base_index = -1;
2993 int aliases = data()->config()->GetAliases(
2994 cur_inactive->representation(), cur_reg, rep, &alias_base_index);
2995 DCHECK(aliases > 0 || (aliases == 0 && alias_base_index == -1));
2996 while (aliases--) {
2997 int aliased_reg = alias_base_index + aliases;
2998 positions[aliased_reg] = Min(positions[aliased_reg], next_intersection);
2999 }
3000 }
2900 } 3001 }
2901 } 3002 }
2902 3003
2903 // High-level register allocation summary: 3004 // High-level register allocation summary:
2904 // 3005 //
2905 // For regular, or hot (i.e. not splinter) ranges, we attempt to first 3006 // For regular, or hot (i.e. not splinter) ranges, we attempt to first
2906 // allocate first the preferred (hint) register. If that is not possible, 3007 // allocate first the preferred (hint) register. If that is not possible,
2907 // we find a register that's free, and allocate that. If that's not possible, 3008 // we find a register that's free, and allocate that. If that's not possible,
2908 // we search for a register to steal from a range that was allocated. The 3009 // we search for a register to steal from a range that was allocated. The
2909 // goal is to optimize for throughput by avoiding register-to-memory 3010 // goal is to optimize for throughput by avoiding register-to-memory
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after
2970 current->relative_id()); 3071 current->relative_id());
2971 SetLiveRangeAssignedRegister(current, hint_register); 3072 SetLiveRangeAssignedRegister(current, hint_register);
2972 return true; 3073 return true;
2973 } 3074 }
2974 } 3075 }
2975 return false; 3076 return false;
2976 } 3077 }
2977 3078
2978 bool LinearScanAllocator::TryAllocateFreeReg( 3079 bool LinearScanAllocator::TryAllocateFreeReg(
2979 LiveRange* current, const Vector<LifetimePosition>& free_until_pos) { 3080 LiveRange* current, const Vector<LifetimePosition>& free_until_pos) {
3081 int num_regs = 0; // used only for the call to GetFPRegisterSet.
2980 int num_codes = num_allocatable_registers(); 3082 int num_codes = num_allocatable_registers();
2981 const int* codes = allocatable_register_codes(); 3083 const int* codes = allocatable_register_codes();
3084 MachineRepresentation rep = current->representation();
3085 if (!kSimpleFPAliasing && (rep == MachineRepresentation::kFloat32 ||
3086 rep == MachineRepresentation::kSimd128))
3087 GetFPRegisterSet(rep, &num_regs, &num_codes, &codes);
3088
2982 DCHECK_GE(free_until_pos.length(), num_codes); 3089 DCHECK_GE(free_until_pos.length(), num_codes);
2983 3090
2984 // Find the register which stays free for the longest time. 3091 // Find the register which stays free for the longest time.
2985 int reg = codes[0]; 3092 int reg = codes[0];
2986 for (int i = 1; i < num_codes; ++i) { 3093 for (int i = 1; i < num_codes; ++i) {
2987 int code = codes[i]; 3094 int code = codes[i];
2988 if (free_until_pos[code] > free_until_pos[reg]) { 3095 if (free_until_pos[code] > free_until_pos[reg]) {
2989 reg = code; 3096 reg = code;
2990 } 3097 }
2991 } 3098 }
(...skipping 27 matching lines...) Expand all
3019 if (register_use == nullptr) { 3126 if (register_use == nullptr) {
3020 // There is no use in the current live range that requires a register. 3127 // There is no use in the current live range that requires a register.
3021 // We can just spill it. 3128 // We can just spill it.
3022 Spill(current); 3129 Spill(current);
3023 return; 3130 return;
3024 } 3131 }
3025 3132
3026 int num_regs = num_registers(); 3133 int num_regs = num_registers();
3027 int num_codes = num_allocatable_registers(); 3134 int num_codes = num_allocatable_registers();
3028 const int* codes = allocatable_register_codes(); 3135 const int* codes = allocatable_register_codes();
3136 MachineRepresentation rep = current->representation();
3137 if (!kSimpleFPAliasing && (rep == MachineRepresentation::kFloat32 ||
3138 rep == MachineRepresentation::kSimd128))
3139 GetFPRegisterSet(rep, &num_regs, &num_codes, &codes);
3029 3140
3030 LifetimePosition use_pos[RegisterConfiguration::kMaxFPRegisters]; 3141 LifetimePosition use_pos[RegisterConfiguration::kMaxFPRegisters];
3031 LifetimePosition block_pos[RegisterConfiguration::kMaxFPRegisters]; 3142 LifetimePosition block_pos[RegisterConfiguration::kMaxFPRegisters];
3032 for (int i = 0; i < num_regs; i++) { 3143 for (int i = 0; i < num_regs; i++) {
3033 use_pos[i] = block_pos[i] = LifetimePosition::MaxPosition(); 3144 use_pos[i] = block_pos[i] = LifetimePosition::MaxPosition();
3034 } 3145 }
3035 3146
3036 for (LiveRange* range : active_live_ranges()) { 3147 for (LiveRange* range : active_live_ranges()) {
3037 int cur_reg = range->assigned_register(); 3148 int cur_reg = range->assigned_register();
3038 bool is_fixed_or_cant_spill = 3149 bool is_fixed_or_cant_spill =
3039 range->TopLevel()->IsFixed() || !range->CanBeSpilled(current->Start()); 3150 range->TopLevel()->IsFixed() || !range->CanBeSpilled(current->Start());
3040 if (is_fixed_or_cant_spill) { 3151 if (kSimpleFPAliasing || mode() == GENERAL_REGISTERS) {
3041 block_pos[cur_reg] = use_pos[cur_reg] = 3152 if (is_fixed_or_cant_spill) {
3042 LifetimePosition::GapFromInstructionIndex(0); 3153 block_pos[cur_reg] = use_pos[cur_reg] =
3154 LifetimePosition::GapFromInstructionIndex(0);
3155 } else {
3156 use_pos[cur_reg] =
3157 range->NextLifetimePositionRegisterIsBeneficial(current->Start());
3158 }
3043 } else { 3159 } else {
3044 UsePosition* next_use = 3160 int alias_base_index = -1;
3045 range->NextUsePositionRegisterIsBeneficial(current->Start()); 3161 int aliases = data()->config()->GetAliases(
3046 if (next_use == nullptr) { 3162 range->representation(), cur_reg, rep, &alias_base_index);
3047 use_pos[cur_reg] = range->End(); 3163 DCHECK(aliases > 0 || (aliases == 0 && alias_base_index == -1));
3048 } else { 3164 while (aliases--) {
3049 use_pos[cur_reg] = next_use->pos(); 3165 int aliased_reg = alias_base_index + aliases;
3166 if (is_fixed_or_cant_spill) {
3167 block_pos[aliased_reg] = use_pos[aliased_reg] =
3168 LifetimePosition::GapFromInstructionIndex(0);
3169 } else {
3170 use_pos[aliased_reg] =
3171 range->NextLifetimePositionRegisterIsBeneficial(current->Start());
3172 }
3050 } 3173 }
3051 } 3174 }
3052 } 3175 }
3053 3176
3054 for (LiveRange* range : inactive_live_ranges()) { 3177 for (LiveRange* range : inactive_live_ranges()) {
3055 DCHECK(range->End() > current->Start()); 3178 DCHECK(range->End() > current->Start());
3056 LifetimePosition next_intersection = range->FirstIntersection(current); 3179 LifetimePosition next_intersection = range->FirstIntersection(current);
3057 if (!next_intersection.IsValid()) continue; 3180 if (!next_intersection.IsValid()) continue;
3058 int cur_reg = range->assigned_register(); 3181 int cur_reg = range->assigned_register();
3059 bool is_fixed = range->TopLevel()->IsFixed(); 3182 bool is_fixed = range->TopLevel()->IsFixed();
3060 if (is_fixed) { 3183 if (kSimpleFPAliasing || mode() == GENERAL_REGISTERS) {
3061 block_pos[cur_reg] = Min(block_pos[cur_reg], next_intersection); 3184 if (is_fixed) {
3062 use_pos[cur_reg] = Min(block_pos[cur_reg], use_pos[cur_reg]); 3185 block_pos[cur_reg] = Min(block_pos[cur_reg], next_intersection);
3186 use_pos[cur_reg] = Min(block_pos[cur_reg], use_pos[cur_reg]);
3187 } else {
3188 use_pos[cur_reg] = Min(use_pos[cur_reg], next_intersection);
3189 }
3063 } else { 3190 } else {
3064 use_pos[cur_reg] = Min(use_pos[cur_reg], next_intersection); 3191 int alias_base_index = -1;
3192 int aliases = data()->config()->GetAliases(
3193 range->representation(), cur_reg, rep, &alias_base_index);
3194 DCHECK(aliases > 0 || (aliases == 0 && alias_base_index == -1));
3195 while (aliases--) {
3196 int aliased_reg = alias_base_index + aliases;
3197 if (is_fixed) {
3198 block_pos[aliased_reg] =
3199 Min(block_pos[aliased_reg], next_intersection);
3200 use_pos[aliased_reg] =
3201 Min(block_pos[aliased_reg], use_pos[aliased_reg]);
3202 } else {
3203 use_pos[aliased_reg] = Min(use_pos[aliased_reg], next_intersection);
3204 }
3205 }
3065 } 3206 }
3066 } 3207 }
3067 3208
3068 int reg = codes[0]; 3209 int reg = codes[0];
3069 for (int i = 1; i < num_codes; ++i) { 3210 for (int i = 1; i < num_codes; ++i) {
3070 int code = codes[i]; 3211 int code = codes[i];
3071 if (use_pos[code] > use_pos[reg]) { 3212 if (use_pos[code] > use_pos[reg]) {
3072 reg = code; 3213 reg = code;
3073 } 3214 }
3074 } 3215 }
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
3106 SplitAndSpillIntersecting(current); 3247 SplitAndSpillIntersecting(current);
3107 } 3248 }
3108 3249
3109 3250
3110 void LinearScanAllocator::SplitAndSpillIntersecting(LiveRange* current) { 3251 void LinearScanAllocator::SplitAndSpillIntersecting(LiveRange* current) {
3111 DCHECK(current->HasRegisterAssigned()); 3252 DCHECK(current->HasRegisterAssigned());
3112 int reg = current->assigned_register(); 3253 int reg = current->assigned_register();
3113 LifetimePosition split_pos = current->Start(); 3254 LifetimePosition split_pos = current->Start();
3114 for (size_t i = 0; i < active_live_ranges().size(); ++i) { 3255 for (size_t i = 0; i < active_live_ranges().size(); ++i) {
3115 LiveRange* range = active_live_ranges()[i]; 3256 LiveRange* range = active_live_ranges()[i];
3116 if (range->assigned_register() != reg) continue; 3257 if (kSimpleFPAliasing || mode() == GENERAL_REGISTERS) {
3258 if (range->assigned_register() != reg) continue;
3259 } else {
3260 if (!data()->config()->AreAliases(current->representation(), reg,
3261 range->representation(),
3262 range->assigned_register())) {
3263 continue;
3264 }
3265 }
3117 3266
3118 UsePosition* next_pos = range->NextRegisterPosition(current->Start()); 3267 UsePosition* next_pos = range->NextRegisterPosition(current->Start());
3119 LifetimePosition spill_pos = FindOptimalSpillingPos(range, split_pos); 3268 LifetimePosition spill_pos = FindOptimalSpillingPos(range, split_pos);
3120 if (next_pos == nullptr) { 3269 if (next_pos == nullptr) {
3121 SpillAfter(range, spill_pos); 3270 SpillAfter(range, spill_pos);
3122 } else { 3271 } else {
3123 // When spilling between spill_pos and next_pos ensure that the range 3272 // When spilling between spill_pos and next_pos ensure that the range
3124 // remains spilled at least until the start of the current live range. 3273 // remains spilled at least until the start of the current live range.
3125 // This guarantees that we will not introduce new unhandled ranges that 3274 // This guarantees that we will not introduce new unhandled ranges that
3126 // start before the current range as this violates allocation invariants 3275 // start before the current range as this violates allocation invariants
3127 // and will lead to an inconsistent state of active and inactive 3276 // and will lead to an inconsistent state of active and inactive
3128 // live-ranges: ranges are allocated in order of their start positions, 3277 // live-ranges: ranges are allocated in order of their start positions,
3129 // ranges are retired from active/inactive when the start of the 3278 // ranges are retired from active/inactive when the start of the
3130 // current live-range is larger than their end. 3279 // current live-range is larger than their end.
3131 DCHECK(LifetimePosition::ExistsGapPositionBetween(current->Start(), 3280 DCHECK(LifetimePosition::ExistsGapPositionBetween(current->Start(),
3132 next_pos->pos())); 3281 next_pos->pos()));
3133 SpillBetweenUntil(range, spill_pos, current->Start(), next_pos->pos()); 3282 SpillBetweenUntil(range, spill_pos, current->Start(), next_pos->pos());
3134 } 3283 }
3135 ActiveToHandled(range); 3284 ActiveToHandled(range);
3136 --i; 3285 --i;
3137 } 3286 }
3138 3287
3139 for (size_t i = 0; i < inactive_live_ranges().size(); ++i) { 3288 for (size_t i = 0; i < inactive_live_ranges().size(); ++i) {
3140 LiveRange* range = inactive_live_ranges()[i]; 3289 LiveRange* range = inactive_live_ranges()[i];
3141 DCHECK(range->End() > current->Start()); 3290 DCHECK(range->End() > current->Start());
3142 if (range->TopLevel()->IsFixed()) continue; 3291 if (range->TopLevel()->IsFixed()) continue;
3143 if (range->assigned_register() != reg) continue; 3292 if (kSimpleFPAliasing || mode() == GENERAL_REGISTERS) {
3293 if (range->assigned_register() != reg) continue;
3294 } else {
3295 if (!data()->config()->AreAliases(current->representation(), reg,
3296 range->representation(),
3297 range->assigned_register()))
3298 continue;
3299 }
3144 3300
3145 LifetimePosition next_intersection = range->FirstIntersection(current); 3301 LifetimePosition next_intersection = range->FirstIntersection(current);
3146 if (next_intersection.IsValid()) { 3302 if (next_intersection.IsValid()) {
3147 UsePosition* next_pos = range->NextRegisterPosition(current->Start()); 3303 UsePosition* next_pos = range->NextRegisterPosition(current->Start());
3148 if (next_pos == nullptr) { 3304 if (next_pos == nullptr) {
3149 SpillAfter(range, split_pos); 3305 SpillAfter(range, split_pos);
3150 } else { 3306 } else {
3151 next_intersection = Min(next_intersection, next_pos->pos()); 3307 next_intersection = Min(next_intersection, next_pos->pos());
3152 SpillBetween(range, split_pos, next_intersection); 3308 SpillBetween(range, split_pos, next_intersection);
3153 } 3309 }
(...skipping 470 matching lines...) Expand 10 before | Expand all | Expand 10 after
3624 DCHECK(!code() 3780 DCHECK(!code()
3625 ->InstructionAt(pred->last_instruction_index()) 3781 ->InstructionAt(pred->last_instruction_index())
3626 ->HasReferenceMap()); 3782 ->HasReferenceMap());
3627 gap_index = pred->last_instruction_index(); 3783 gap_index = pred->last_instruction_index();
3628 position = Instruction::END; 3784 position = Instruction::END;
3629 } 3785 }
3630 data()->AddGapMove(gap_index, position, pred_op, cur_op); 3786 data()->AddGapMove(gap_index, position, pred_op, cur_op);
3631 return gap_index; 3787 return gap_index;
3632 } 3788 }
3633 3789
3634
3635 void LiveRangeConnector::ConnectRanges(Zone* local_zone) { 3790 void LiveRangeConnector::ConnectRanges(Zone* local_zone) {
3636 DelayedInsertionMap delayed_insertion_map(local_zone); 3791 DelayedInsertionMap delayed_insertion_map(local_zone);
3637 for (TopLevelLiveRange* top_range : data()->live_ranges()) { 3792 for (TopLevelLiveRange* top_range : data()->live_ranges()) {
3638 if (top_range == nullptr) continue; 3793 if (top_range == nullptr) continue;
3639 bool connect_spilled = top_range->IsSpilledOnlyInDeferredBlocks(); 3794 bool connect_spilled = top_range->IsSpilledOnlyInDeferredBlocks();
3640 LiveRange* first_range = top_range; 3795 LiveRange* first_range = top_range;
3641 for (LiveRange *second_range = first_range->next(); second_range != nullptr; 3796 for (LiveRange *second_range = first_range->next(); second_range != nullptr;
3642 first_range = second_range, second_range = second_range->next()) { 3797 first_range = second_range, second_range = second_range->next()) {
3643 LifetimePosition pos = second_range->Start(); 3798 LifetimePosition pos = second_range->Start();
3644 // Add gap move if the two live ranges touch and there is no block 3799 // 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
3712 } 3867 }
3713 if (done) break; 3868 if (done) break;
3714 // Reset state. 3869 // Reset state.
3715 to_eliminate.clear(); 3870 to_eliminate.clear();
3716 to_insert.clear(); 3871 to_insert.clear();
3717 moves = it->first.first; 3872 moves = it->first.first;
3718 } 3873 }
3719 // Gather all MoveOperands for a single ParallelMove. 3874 // Gather all MoveOperands for a single ParallelMove.
3720 MoveOperands* move = 3875 MoveOperands* move =
3721 new (code_zone()) MoveOperands(it->first.second, it->second); 3876 new (code_zone()) MoveOperands(it->first.second, it->second);
3722 MoveOperands* eliminate = moves->PrepareInsertAfter(move); 3877 moves->PrepareInsertAfter(move, &to_eliminate);
3723 to_insert.push_back(move); 3878 to_insert.push_back(move);
3724 if (eliminate != nullptr) to_eliminate.push_back(eliminate);
3725 } 3879 }
3726 } 3880 }
3727 3881
3728 3882
3729 void LiveRangeConnector::CommitSpillsInDeferredBlocks( 3883 void LiveRangeConnector::CommitSpillsInDeferredBlocks(
3730 TopLevelLiveRange* range, LiveRangeBoundArray* array, Zone* temp_zone) { 3884 TopLevelLiveRange* range, LiveRangeBoundArray* array, Zone* temp_zone) {
3731 DCHECK(range->IsSpilledOnlyInDeferredBlocks()); 3885 DCHECK(range->IsSpilledOnlyInDeferredBlocks());
3732 DCHECK(!range->spilled()); 3886 DCHECK(!range->spilled());
3733 3887
3734 InstructionSequence* code = data()->code(); 3888 InstructionSequence* code = data()->code();
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after
3796 } 3950 }
3797 } 3951 }
3798 } 3952 }
3799 } 3953 }
3800 } 3954 }
3801 3955
3802 3956
3803 } // namespace compiler 3957 } // namespace compiler
3804 } // namespace internal 3958 } // namespace internal
3805 } // namespace v8 3959 } // namespace v8
OLDNEW
« no previous file with comments | « src/compiler/register-allocator.h ('k') | src/compiler/wasm-linkage.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698