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_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 10 matching lines...) Expand all Loading... | |
57 LifetimePosition pos) { | 57 LifetimePosition pos) { |
58 return code->GetInstructionBlock(pos.ToInstructionIndex()); | 58 return code->GetInstructionBlock(pos.ToInstructionIndex()); |
59 } | 59 } |
60 | 60 |
61 | 61 |
62 Instruction* GetLastInstruction(InstructionSequence* code, | 62 Instruction* GetLastInstruction(InstructionSequence* code, |
63 const InstructionBlock* block) { | 63 const InstructionBlock* block) { |
64 return code->InstructionAt(block->last_instruction_index()); | 64 return code->InstructionAt(block->last_instruction_index()); |
65 } | 65 } |
66 | 66 |
67 | 67 bool IsOutputRegisterOf(Instruction* instr, int code) { |
68 bool IsOutputRegisterOf(Instruction* instr, Register reg) { | |
69 for (size_t i = 0; i < instr->OutputCount(); i++) { | 68 for (size_t i = 0; i < instr->OutputCount(); i++) { |
70 InstructionOperand* output = instr->OutputAt(i); | 69 InstructionOperand* output = instr->OutputAt(i); |
71 if (output->IsRegister() && | 70 if (output->IsRegister() && |
72 LocationOperand::cast(output)->GetRegister().is(reg)) { | 71 LocationOperand::cast(output)->register_code() == code) { |
73 return true; | 72 return true; |
74 } | 73 } |
75 } | 74 } |
76 return false; | 75 return false; |
77 } | 76 } |
78 | 77 |
79 | 78 bool IsOutputFPRegisterOf(Instruction* instr, MachineRepresentation rep, |
80 bool IsOutputDoubleRegisterOf(Instruction* instr, DoubleRegister reg) { | 79 int code) { |
81 for (size_t i = 0; i < instr->OutputCount(); i++) { | 80 for (size_t i = 0; i < instr->OutputCount(); i++) { |
82 InstructionOperand* output = instr->OutputAt(i); | 81 InstructionOperand* output = instr->OutputAt(i); |
83 if (output->IsFPRegister() && | 82 if (output->IsFPRegister()) { |
84 LocationOperand::cast(output)->GetDoubleRegister().is(reg)) { | 83 const LocationOperand* op = LocationOperand::cast(output); |
85 return true; | 84 const RegisterConfiguration* config = |
85 RegisterConfiguration::ArchDefault(RegisterConfiguration::TURBOFAN); | |
86 if (config->fp_aliasing_kind() != RegisterConfiguration::COMBINE) { | |
87 if (op->register_code() == code) return true; | |
88 } else { | |
89 if (config->AreAliases(op->representation(), op->register_code(), rep, | |
90 code)) { | |
91 return true; | |
92 } | |
93 } | |
86 } | 94 } |
87 } | 95 } |
88 return false; | 96 return false; |
89 } | 97 } |
90 | 98 |
91 | 99 |
92 // TODO(dcarney): fix frame to allow frame accesses to half size location. | 100 // TODO(dcarney): fix frame to allow frame accesses to half size location. |
93 int GetByteWidth(MachineRepresentation rep) { | 101 int GetByteWidth(MachineRepresentation rep) { |
94 switch (rep) { | 102 switch (rep) { |
95 case MachineRepresentation::kBit: | 103 case MachineRepresentation::kBit: |
(...skipping 1151 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1247 node = new_node; | 1255 node = new_node; |
1248 src = src->next(); | 1256 src = src->next(); |
1249 } | 1257 } |
1250 } | 1258 } |
1251 use_interval_ = result; | 1259 use_interval_ = result; |
1252 live_ranges().push_back(parent); | 1260 live_ranges().push_back(parent); |
1253 end_position_ = node->end(); | 1261 end_position_ = node->end(); |
1254 parent->SetSpillRange(this); | 1262 parent->SetSpillRange(this); |
1255 } | 1263 } |
1256 | 1264 |
1257 | |
1258 int SpillRange::ByteWidth() const { | |
1259 return GetByteWidth(live_ranges_[0]->representation()); | |
1260 } | |
1261 | |
1262 | |
1263 bool SpillRange::IsIntersectingWith(SpillRange* other) const { | 1265 bool SpillRange::IsIntersectingWith(SpillRange* other) const { |
1264 if (this->use_interval_ == nullptr || other->use_interval_ == nullptr || | 1266 if (this->use_interval_ == nullptr || other->use_interval_ == nullptr || |
1265 this->End() <= other->use_interval_->start() || | 1267 this->End() <= other->use_interval_->start() || |
1266 other->End() <= this->use_interval_->start()) { | 1268 other->End() <= this->use_interval_->start()) { |
1267 return false; | 1269 return false; |
1268 } | 1270 } |
1269 return AreUseIntervalsIntersecting(use_interval_, other->use_interval_); | 1271 return AreUseIntervalsIntersecting(use_interval_, other->use_interval_); |
1270 } | 1272 } |
1271 | 1273 |
1272 | 1274 |
(...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1355 } | 1357 } |
1356 | 1358 |
1357 | 1359 |
1358 void RegisterAllocationData::PhiMapValue::CommitAssignment( | 1360 void RegisterAllocationData::PhiMapValue::CommitAssignment( |
1359 const InstructionOperand& assigned) { | 1361 const InstructionOperand& assigned) { |
1360 for (InstructionOperand* operand : incoming_operands_) { | 1362 for (InstructionOperand* operand : incoming_operands_) { |
1361 InstructionOperand::ReplaceWith(operand, &assigned); | 1363 InstructionOperand::ReplaceWith(operand, &assigned); |
1362 } | 1364 } |
1363 } | 1365 } |
1364 | 1366 |
1365 | |
1366 RegisterAllocationData::RegisterAllocationData( | 1367 RegisterAllocationData::RegisterAllocationData( |
1367 const RegisterConfiguration* config, Zone* zone, Frame* frame, | 1368 const RegisterConfiguration* config, Zone* zone, Frame* frame, |
1368 InstructionSequence* code, const char* debug_name) | 1369 InstructionSequence* code, const char* debug_name) |
1369 : allocation_zone_(zone), | 1370 : allocation_zone_(zone), |
1370 frame_(frame), | 1371 frame_(frame), |
1371 code_(code), | 1372 code_(code), |
1372 debug_name_(debug_name), | 1373 debug_name_(debug_name), |
1373 config_(config), | 1374 config_(config), |
1374 phi_map_(allocation_zone()), | 1375 phi_map_(allocation_zone()), |
1375 live_in_sets_(code->InstructionBlockCount(), nullptr, allocation_zone()), | 1376 live_in_sets_(code->InstructionBlockCount(), nullptr, allocation_zone()), |
1376 live_out_sets_(code->InstructionBlockCount(), nullptr, allocation_zone()), | 1377 live_out_sets_(code->InstructionBlockCount(), nullptr, allocation_zone()), |
1377 live_ranges_(code->VirtualRegisterCount() * 2, nullptr, | 1378 live_ranges_(code->VirtualRegisterCount() * 2, nullptr, |
1378 allocation_zone()), | 1379 allocation_zone()), |
1379 fixed_live_ranges_(this->config()->num_general_registers(), nullptr, | 1380 fixed_live_ranges_(this->config()->num_general_registers(), nullptr, |
1380 allocation_zone()), | 1381 allocation_zone()), |
1382 fixed_float_live_ranges_(this->config()->num_float_registers(), nullptr, | |
1383 allocation_zone()), | |
1381 fixed_double_live_ranges_(this->config()->num_double_registers(), nullptr, | 1384 fixed_double_live_ranges_(this->config()->num_double_registers(), nullptr, |
1382 allocation_zone()), | 1385 allocation_zone()), |
1383 spill_ranges_(code->VirtualRegisterCount(), nullptr, allocation_zone()), | 1386 spill_ranges_(code->VirtualRegisterCount(), nullptr, allocation_zone()), |
1384 delayed_references_(allocation_zone()), | 1387 delayed_references_(allocation_zone()), |
1385 assigned_registers_(nullptr), | 1388 assigned_registers_(nullptr), |
1386 assigned_double_registers_(nullptr), | 1389 assigned_double_registers_(nullptr), |
1387 virtual_register_count_(code->VirtualRegisterCount()), | 1390 virtual_register_count_(code->VirtualRegisterCount()), |
1388 preassigned_slot_ranges_(zone) { | 1391 preassigned_slot_ranges_(zone) { |
1389 assigned_registers_ = new (code_zone()) | 1392 assigned_registers_ = new (code_zone()) |
1390 BitVector(this->config()->num_general_registers(), code_zone()); | 1393 BitVector(this->config()->num_general_registers(), code_zone()); |
(...skipping 155 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1546 | 1549 |
1547 SpillRange* RegisterAllocationData::CreateSpillRangeForLiveRange( | 1550 SpillRange* RegisterAllocationData::CreateSpillRangeForLiveRange( |
1548 TopLevelLiveRange* range) { | 1551 TopLevelLiveRange* range) { |
1549 DCHECK(!range->HasSpillOperand()); | 1552 DCHECK(!range->HasSpillOperand()); |
1550 DCHECK(!range->IsSplinter()); | 1553 DCHECK(!range->IsSplinter()); |
1551 SpillRange* spill_range = | 1554 SpillRange* spill_range = |
1552 new (allocation_zone()) SpillRange(range, allocation_zone()); | 1555 new (allocation_zone()) SpillRange(range, allocation_zone()); |
1553 return spill_range; | 1556 return spill_range; |
1554 } | 1557 } |
1555 | 1558 |
1556 | 1559 void RegisterAllocationData::MarkAllocated(MachineRepresentation rep, |
1557 void RegisterAllocationData::MarkAllocated(RegisterKind kind, int index) { | 1560 int index) { |
1558 if (kind == FP_REGISTERS) { | 1561 switch (rep) { |
1559 assigned_double_registers_->Add(index); | 1562 case MachineRepresentation::kFloat32: |
1560 } else { | 1563 if (config()->fp_aliasing_kind() == RegisterConfiguration::COMBINE) { |
1561 DCHECK(kind == GENERAL_REGISTERS); | 1564 int alias_base_index; |
1562 assigned_registers_->Add(index); | 1565 int aliases = config()->GetAliases( |
1566 rep, index, MachineRepresentation::kFloat64, &alias_base_index); | |
1567 while (aliases--) { | |
1568 int aliased_reg = alias_base_index + aliases; | |
1569 assigned_double_registers_->Add(aliased_reg); | |
1570 } | |
1571 } | |
1572 break; | |
1573 case MachineRepresentation::kFloat64: | |
1574 assigned_double_registers_->Add(index); | |
1575 break; | |
1576 default: | |
1577 DCHECK(!IsFloatingPoint(rep)); | |
1578 assigned_registers_->Add(index); | |
1579 break; | |
1563 } | 1580 } |
1564 } | 1581 } |
1565 | 1582 |
1566 | |
1567 bool RegisterAllocationData::IsBlockBoundary(LifetimePosition pos) const { | 1583 bool RegisterAllocationData::IsBlockBoundary(LifetimePosition pos) const { |
1568 return pos.IsFullStart() && | 1584 return pos.IsFullStart() && |
1569 code()->GetInstructionBlock(pos.ToInstructionIndex())->code_start() == | 1585 code()->GetInstructionBlock(pos.ToInstructionIndex())->code_start() == |
1570 pos.ToInstructionIndex(); | 1586 pos.ToInstructionIndex(); |
1571 } | 1587 } |
1572 | 1588 |
1573 | 1589 |
1574 ConstraintBuilder::ConstraintBuilder(RegisterAllocationData* data) | 1590 ConstraintBuilder::ConstraintBuilder(RegisterAllocationData* data) |
1575 : data_(data) {} | 1591 : data_(data) {} |
1576 | 1592 |
(...skipping 293 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1870 .NextStart(); | 1886 .NextStart(); |
1871 BitVector::Iterator iterator(live_out); | 1887 BitVector::Iterator iterator(live_out); |
1872 while (!iterator.Done()) { | 1888 while (!iterator.Done()) { |
1873 int operand_index = iterator.Current(); | 1889 int operand_index = iterator.Current(); |
1874 TopLevelLiveRange* range = data()->GetOrCreateLiveRangeFor(operand_index); | 1890 TopLevelLiveRange* range = data()->GetOrCreateLiveRangeFor(operand_index); |
1875 range->AddUseInterval(start, end, allocation_zone()); | 1891 range->AddUseInterval(start, end, allocation_zone()); |
1876 iterator.Advance(); | 1892 iterator.Advance(); |
1877 } | 1893 } |
1878 } | 1894 } |
1879 | 1895 |
1880 | 1896 int LiveRangeBuilder::FixedFPLiveRangeID(int index, MachineRepresentation rep) { |
1881 int LiveRangeBuilder::FixedDoubleLiveRangeID(int index) { | 1897 switch (rep) { |
1882 return -index - 1 - config()->num_general_registers(); | 1898 case MachineRepresentation::kFloat32: |
1899 return -index - 1 - config()->num_general_registers(); | |
1900 case MachineRepresentation::kFloat64: | |
1901 return -index - 1 - config()->num_general_registers() - | |
1902 config()->num_float_registers(); | |
1903 default: | |
1904 break; | |
1905 } | |
1906 UNREACHABLE(); | |
1907 return 0; | |
1883 } | 1908 } |
1884 | 1909 |
1885 | |
1886 TopLevelLiveRange* LiveRangeBuilder::FixedLiveRangeFor(int index) { | 1910 TopLevelLiveRange* LiveRangeBuilder::FixedLiveRangeFor(int index) { |
1887 DCHECK(index < config()->num_general_registers()); | 1911 DCHECK(index < config()->num_general_registers()); |
1888 TopLevelLiveRange* result = data()->fixed_live_ranges()[index]; | 1912 TopLevelLiveRange* result = data()->fixed_live_ranges()[index]; |
1889 if (result == nullptr) { | 1913 if (result == nullptr) { |
1890 result = data()->NewLiveRange(FixedLiveRangeID(index), | 1914 MachineRepresentation rep = InstructionSequence::DefaultRepresentation(); |
1891 InstructionSequence::DefaultRepresentation()); | 1915 result = data()->NewLiveRange(FixedLiveRangeID(index), rep); |
1892 DCHECK(result->IsFixed()); | 1916 DCHECK(result->IsFixed()); |
1893 result->set_assigned_register(index); | 1917 result->set_assigned_register(index); |
1894 data()->MarkAllocated(GENERAL_REGISTERS, index); | 1918 data()->MarkAllocated(rep, index); |
1895 data()->fixed_live_ranges()[index] = result; | 1919 data()->fixed_live_ranges()[index] = result; |
1896 } | 1920 } |
1897 return result; | 1921 return result; |
1898 } | 1922 } |
1899 | 1923 |
1900 | 1924 TopLevelLiveRange* LiveRangeBuilder::FixedFPLiveRangeFor( |
1901 TopLevelLiveRange* LiveRangeBuilder::FixedDoubleLiveRangeFor(int index) { | 1925 int index, MachineRepresentation rep) { |
1902 DCHECK(index < config()->num_double_registers()); | 1926 TopLevelLiveRange* result = nullptr; |
1903 TopLevelLiveRange* result = data()->fixed_double_live_ranges()[index]; | 1927 if (rep == MachineRepresentation::kFloat64) { |
1904 if (result == nullptr) { | 1928 DCHECK(index < config()->num_double_registers()); |
1905 result = data()->NewLiveRange(FixedDoubleLiveRangeID(index), | 1929 result = data()->fixed_double_live_ranges()[index]; |
1906 MachineRepresentation::kFloat64); | 1930 if (result == nullptr) { |
1907 DCHECK(result->IsFixed()); | 1931 result = data()->NewLiveRange(FixedFPLiveRangeID(index, rep), rep); |
1908 result->set_assigned_register(index); | 1932 DCHECK(result->IsFixed()); |
1909 data()->MarkAllocated(FP_REGISTERS, index); | 1933 result->set_assigned_register(index); |
1910 data()->fixed_double_live_ranges()[index] = result; | 1934 data()->MarkAllocated(rep, index); |
1935 data()->fixed_double_live_ranges()[index] = result; | |
1936 } | |
1937 } else { | |
1938 DCHECK(rep == MachineRepresentation::kFloat32); | |
1939 DCHECK(index < config()->num_float_registers()); | |
1940 result = data()->fixed_float_live_ranges()[index]; | |
1941 if (result == nullptr) { | |
1942 result = data()->NewLiveRange(FixedFPLiveRangeID(index, rep), rep); | |
1943 DCHECK(result->IsFixed()); | |
1944 result->set_assigned_register(index); | |
1945 data()->MarkAllocated(rep, index); | |
1946 data()->fixed_float_live_ranges()[index] = result; | |
1947 } | |
1911 } | 1948 } |
1912 return result; | 1949 return result; |
1913 } | 1950 } |
1914 | 1951 |
1915 | |
1916 TopLevelLiveRange* LiveRangeBuilder::LiveRangeFor(InstructionOperand* operand) { | 1952 TopLevelLiveRange* LiveRangeBuilder::LiveRangeFor(InstructionOperand* operand) { |
1917 if (operand->IsUnallocated()) { | 1953 if (operand->IsUnallocated()) { |
1918 return data()->GetOrCreateLiveRangeFor( | 1954 return data()->GetOrCreateLiveRangeFor( |
1919 UnallocatedOperand::cast(operand)->virtual_register()); | 1955 UnallocatedOperand::cast(operand)->virtual_register()); |
1920 } else if (operand->IsConstant()) { | 1956 } else if (operand->IsConstant()) { |
1921 return data()->GetOrCreateLiveRangeFor( | 1957 return data()->GetOrCreateLiveRangeFor( |
1922 ConstantOperand::cast(operand)->virtual_register()); | 1958 ConstantOperand::cast(operand)->virtual_register()); |
1923 } else if (operand->IsRegister()) { | 1959 } else if (operand->IsRegister()) { |
1924 return FixedLiveRangeFor( | 1960 return FixedLiveRangeFor( |
1925 LocationOperand::cast(operand)->GetRegister().code()); | 1961 LocationOperand::cast(operand)->GetRegister().code()); |
1926 } else if (operand->IsFPRegister()) { | 1962 } else if (operand->IsFPRegister()) { |
1927 return FixedDoubleLiveRangeFor( | 1963 LocationOperand* op = LocationOperand::cast(operand); |
1928 LocationOperand::cast(operand)->GetDoubleRegister().code()); | 1964 return FixedFPLiveRangeFor(op->register_code(), op->representation()); |
1929 } else { | 1965 } else { |
1930 return nullptr; | 1966 return nullptr; |
1931 } | 1967 } |
1932 } | 1968 } |
1933 | 1969 |
1934 | 1970 |
1935 UsePosition* LiveRangeBuilder::NewUsePosition(LifetimePosition pos, | 1971 UsePosition* LiveRangeBuilder::NewUsePosition(LifetimePosition pos, |
1936 InstructionOperand* operand, | 1972 InstructionOperand* operand, |
1937 void* hint, | 1973 void* hint, |
1938 UsePositionHintType hint_type) { | 1974 UsePositionHintType hint_type) { |
(...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2014 // the first instruction in the handler? | 2050 // the first instruction in the handler? |
2015 Define(LifetimePosition::GapFromInstructionIndex(index), output); | 2051 Define(LifetimePosition::GapFromInstructionIndex(index), output); |
2016 } else { | 2052 } else { |
2017 Define(curr_position, output); | 2053 Define(curr_position, output); |
2018 } | 2054 } |
2019 } | 2055 } |
2020 | 2056 |
2021 if (instr->ClobbersRegisters()) { | 2057 if (instr->ClobbersRegisters()) { |
2022 for (int i = 0; i < config()->num_allocatable_general_registers(); ++i) { | 2058 for (int i = 0; i < config()->num_allocatable_general_registers(); ++i) { |
2023 int code = config()->GetAllocatableGeneralCode(i); | 2059 int code = config()->GetAllocatableGeneralCode(i); |
2024 if (!IsOutputRegisterOf(instr, Register::from_code(code))) { | 2060 if (!IsOutputRegisterOf(instr, code)) { |
2025 TopLevelLiveRange* range = FixedLiveRangeFor(code); | 2061 TopLevelLiveRange* range = FixedLiveRangeFor(code); |
2026 range->AddUseInterval(curr_position, curr_position.End(), | 2062 range->AddUseInterval(curr_position, curr_position.End(), |
2027 allocation_zone()); | 2063 allocation_zone()); |
2028 } | 2064 } |
2029 } | 2065 } |
2030 } | 2066 } |
2031 | 2067 |
2032 if (instr->ClobbersDoubleRegisters()) { | 2068 if (instr->ClobbersDoubleRegisters()) { |
2033 for (int i = 0; i < config()->num_allocatable_aliased_double_registers(); | 2069 for (int i = 0; i < config()->num_allocatable_double_registers(); ++i) { |
2034 ++i) { | |
2035 int code = config()->GetAllocatableDoubleCode(i); | 2070 int code = config()->GetAllocatableDoubleCode(i); |
2036 if (!IsOutputDoubleRegisterOf(instr, DoubleRegister::from_code(code))) { | 2071 if (!IsOutputFPRegisterOf(instr, MachineRepresentation::kFloat64, |
2037 TopLevelLiveRange* range = FixedDoubleLiveRangeFor(code); | 2072 code)) { |
2073 TopLevelLiveRange* range = | |
2074 FixedFPLiveRangeFor(code, MachineRepresentation::kFloat64); | |
2038 range->AddUseInterval(curr_position, curr_position.End(), | 2075 range->AddUseInterval(curr_position, curr_position.End(), |
2039 allocation_zone()); | 2076 allocation_zone()); |
2040 } | 2077 } |
2078 } | |
bbudge
2016/06/21 23:09:35
Mircea, I still think I need use positions for fix
Mircea Trofin
2016/06/22 06:07:34
Wouldn't the virtual register that the output gets
bbudge
2016/06/22 20:16:04
In RegisterAllocatorVerifier::VerifyGapMoves, allo
| |
2079 for (int i = 0; i < config()->num_allocatable_float_registers(); ++i) { | |
2080 int code = config()->GetAllocatableFloatCode(i); | |
2081 if (!IsOutputFPRegisterOf(instr, MachineRepresentation::kFloat32, | |
2082 code)) { | |
2083 TopLevelLiveRange* range = | |
2084 FixedFPLiveRangeFor(code, MachineRepresentation::kFloat32); | |
2085 range->AddUseInterval(curr_position, curr_position.End(), | |
2086 allocation_zone()); | |
2087 } | |
2041 } | 2088 } |
2042 } | 2089 } |
2043 | 2090 |
2044 for (size_t i = 0; i < instr->InputCount(); i++) { | 2091 for (size_t i = 0; i < instr->InputCount(); i++) { |
2045 InstructionOperand* input = instr->InputAt(i); | 2092 InstructionOperand* input = instr->InputAt(i); |
2046 if (input->IsImmediate() || input->IsExplicit()) { | 2093 if (input->IsImmediate() || input->IsExplicit()) { |
2047 continue; // Ignore immediates and explicitly reserved registers. | 2094 continue; // Ignore immediates and explicitly reserved registers. |
2048 } | 2095 } |
2049 LifetimePosition use_pos; | 2096 LifetimePosition use_pos; |
2050 if (input->IsUnallocated() && | 2097 if (input->IsUnallocated() && |
(...skipping 323 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2374 } | 2421 } |
2375 | 2422 |
2376 RegisterAllocator::RegisterAllocator(RegisterAllocationData* data, | 2423 RegisterAllocator::RegisterAllocator(RegisterAllocationData* data, |
2377 RegisterKind kind) | 2424 RegisterKind kind) |
2378 : data_(data), | 2425 : data_(data), |
2379 mode_(kind), | 2426 mode_(kind), |
2380 num_registers_(GetRegisterCount(data->config(), kind)), | 2427 num_registers_(GetRegisterCount(data->config(), kind)), |
2381 num_allocatable_registers_( | 2428 num_allocatable_registers_( |
2382 GetAllocatableRegisterCount(data->config(), kind)), | 2429 GetAllocatableRegisterCount(data->config(), kind)), |
2383 allocatable_register_codes_( | 2430 allocatable_register_codes_( |
2384 GetAllocatableRegisterCodes(data->config(), kind)) {} | 2431 GetAllocatableRegisterCodes(data->config(), kind)), |
2385 | 2432 no_combining_(kind != FP_REGISTERS || |
2433 data->config()->fp_aliasing_kind() != | |
2434 RegisterConfiguration::COMBINE) {} | |
2386 | 2435 |
2387 LifetimePosition RegisterAllocator::GetSplitPositionForInstruction( | 2436 LifetimePosition RegisterAllocator::GetSplitPositionForInstruction( |
2388 const LiveRange* range, int instruction_index) { | 2437 const LiveRange* range, int instruction_index) { |
2389 LifetimePosition ret = LifetimePosition::Invalid(); | 2438 LifetimePosition ret = LifetimePosition::Invalid(); |
2390 | 2439 |
2391 ret = LifetimePosition::GapFromInstructionIndex(instruction_index); | 2440 ret = LifetimePosition::GapFromInstructionIndex(instruction_index); |
2392 if (range->Start() >= ret || ret >= range->End()) { | 2441 if (range->Start() >= ret || ret >= range->End()) { |
2393 return LifetimePosition::Invalid(); | 2442 return LifetimePosition::Invalid(); |
2394 } | 2443 } |
2395 return ret; | 2444 return ret; |
(...skipping 149 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2545 DCHECK(!range->spilled()); | 2594 DCHECK(!range->spilled()); |
2546 TopLevelLiveRange* first = range->TopLevel(); | 2595 TopLevelLiveRange* first = range->TopLevel(); |
2547 TRACE("Spilling live range %d:%d\n", first->vreg(), range->relative_id()); | 2596 TRACE("Spilling live range %d:%d\n", first->vreg(), range->relative_id()); |
2548 | 2597 |
2549 if (first->HasNoSpillType()) { | 2598 if (first->HasNoSpillType()) { |
2550 data()->AssignSpillRangeToLiveRange(first); | 2599 data()->AssignSpillRangeToLiveRange(first); |
2551 } | 2600 } |
2552 range->Spill(); | 2601 range->Spill(); |
2553 } | 2602 } |
2554 | 2603 |
2555 | |
2556 const ZoneVector<TopLevelLiveRange*>& RegisterAllocator::GetFixedRegisters() | |
2557 const { | |
2558 return mode() == FP_REGISTERS ? data()->fixed_double_live_ranges() | |
2559 : data()->fixed_live_ranges(); | |
2560 } | |
2561 | |
2562 | |
2563 const char* RegisterAllocator::RegisterName(int register_code) const { | 2604 const char* RegisterAllocator::RegisterName(int register_code) const { |
2564 if (mode() == GENERAL_REGISTERS) { | 2605 if (mode() == GENERAL_REGISTERS) { |
2565 return data()->config()->GetGeneralRegisterName(register_code); | 2606 return data()->config()->GetGeneralRegisterName(register_code); |
2566 } else { | 2607 } else { |
2567 return data()->config()->GetDoubleRegisterName(register_code); | 2608 return data()->config()->GetDoubleRegisterName(register_code); |
2568 } | 2609 } |
2569 } | 2610 } |
2570 | 2611 |
2571 | 2612 |
2572 LinearScanAllocator::LinearScanAllocator(RegisterAllocationData* data, | 2613 LinearScanAllocator::LinearScanAllocator(RegisterAllocationData* data, |
(...skipping 26 matching lines...) Expand all Loading... | |
2599 for (LiveRange* to_add = range; to_add != nullptr; | 2640 for (LiveRange* to_add = range; to_add != nullptr; |
2600 to_add = to_add->next()) { | 2641 to_add = to_add->next()) { |
2601 if (!to_add->spilled()) { | 2642 if (!to_add->spilled()) { |
2602 AddToUnhandledUnsorted(to_add); | 2643 AddToUnhandledUnsorted(to_add); |
2603 } | 2644 } |
2604 } | 2645 } |
2605 } | 2646 } |
2606 SortUnhandled(); | 2647 SortUnhandled(); |
2607 DCHECK(UnhandledIsSorted()); | 2648 DCHECK(UnhandledIsSorted()); |
2608 | 2649 |
2609 auto& fixed_ranges = GetFixedRegisters(); | 2650 if (mode() == GENERAL_REGISTERS) { |
2610 for (TopLevelLiveRange* current : fixed_ranges) { | 2651 for (TopLevelLiveRange* current : data()->fixed_live_ranges()) { |
2611 if (current != nullptr) { | 2652 if (current != nullptr) AddToInactive(current); |
2612 DCHECK_EQ(mode(), current->kind()); | 2653 } |
2613 AddToInactive(current); | 2654 } else { |
2655 for (TopLevelLiveRange* current : data()->fixed_float_live_ranges()) { | |
2656 if (current != nullptr) AddToInactive(current); | |
2657 } | |
2658 for (TopLevelLiveRange* current : data()->fixed_double_live_ranges()) { | |
2659 if (current != nullptr) AddToInactive(current); | |
2614 } | 2660 } |
2615 } | 2661 } |
2616 | 2662 |
2617 while (!unhandled_live_ranges().empty()) { | 2663 while (!unhandled_live_ranges().empty()) { |
2618 DCHECK(UnhandledIsSorted()); | 2664 DCHECK(UnhandledIsSorted()); |
2619 LiveRange* current = unhandled_live_ranges().back(); | 2665 LiveRange* current = unhandled_live_ranges().back(); |
2620 unhandled_live_ranges().pop_back(); | 2666 unhandled_live_ranges().pop_back(); |
2621 DCHECK(UnhandledIsSorted()); | 2667 DCHECK(UnhandledIsSorted()); |
2622 LifetimePosition position = current->Start(); | 2668 LifetimePosition position = current->Start(); |
2623 #ifdef DEBUG | 2669 #ifdef DEBUG |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2657 if (!result) AllocateBlockedReg(current); | 2703 if (!result) AllocateBlockedReg(current); |
2658 if (current->HasRegisterAssigned()) { | 2704 if (current->HasRegisterAssigned()) { |
2659 AddToActive(current); | 2705 AddToActive(current); |
2660 } | 2706 } |
2661 } | 2707 } |
2662 } | 2708 } |
2663 | 2709 |
2664 | 2710 |
2665 void LinearScanAllocator::SetLiveRangeAssignedRegister(LiveRange* range, | 2711 void LinearScanAllocator::SetLiveRangeAssignedRegister(LiveRange* range, |
2666 int reg) { | 2712 int reg) { |
2667 data()->MarkAllocated(range->kind(), reg); | 2713 data()->MarkAllocated(range->representation(), reg); |
2668 range->set_assigned_register(reg); | 2714 range->set_assigned_register(reg); |
2669 range->SetUseHints(reg); | 2715 range->SetUseHints(reg); |
2670 if (range->IsTopLevel() && range->TopLevel()->is_phi()) { | 2716 if (range->IsTopLevel() && range->TopLevel()->is_phi()) { |
2671 data()->GetPhiMapValueFor(range->TopLevel())->set_assigned_register(reg); | 2717 data()->GetPhiMapValueFor(range->TopLevel())->set_assigned_register(reg); |
2672 } | 2718 } |
2673 } | 2719 } |
2674 | 2720 |
2675 | 2721 |
2676 void LinearScanAllocator::AddToActive(LiveRange* range) { | 2722 void LinearScanAllocator::AddToActive(LiveRange* range) { |
2677 TRACE("Add live range %d:%d to active\n", range->TopLevel()->vreg(), | 2723 TRACE("Add live range %d:%d to active\n", range->TopLevel()->vreg(), |
(...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2771 | 2817 |
2772 void LinearScanAllocator::InactiveToActive(LiveRange* range) { | 2818 void LinearScanAllocator::InactiveToActive(LiveRange* range) { |
2773 RemoveElement(&inactive_live_ranges(), range); | 2819 RemoveElement(&inactive_live_ranges(), range); |
2774 active_live_ranges().push_back(range); | 2820 active_live_ranges().push_back(range); |
2775 TRACE("Moving live range %d:%d from inactive to active\n", | 2821 TRACE("Moving live range %d:%d from inactive to active\n", |
2776 range->TopLevel()->vreg(), range->relative_id()); | 2822 range->TopLevel()->vreg(), range->relative_id()); |
2777 } | 2823 } |
2778 | 2824 |
2779 | 2825 |
2780 bool LinearScanAllocator::TryAllocateFreeReg(LiveRange* current) { | 2826 bool LinearScanAllocator::TryAllocateFreeReg(LiveRange* current) { |
2827 int num_regs = num_registers(); | |
2828 int num_codes = num_allocatable_registers(); | |
2829 const int* codes = allocatable_register_codes(); | |
2830 if (!no_combining() && | |
2831 (current->representation() == MachineRepresentation::kFloat32)) { | |
2832 num_regs = data()->config()->num_float_registers(); | |
2833 num_codes = data()->config()->num_allocatable_float_registers(); | |
2834 codes = data()->config()->allocatable_float_codes(); | |
2835 } | |
2781 LifetimePosition free_until_pos[RegisterConfiguration::kMaxFPRegisters]; | 2836 LifetimePosition free_until_pos[RegisterConfiguration::kMaxFPRegisters]; |
2782 | 2837 for (int i = 0; i < num_regs; i++) { |
2783 for (int i = 0; i < num_registers(); i++) { | |
2784 free_until_pos[i] = LifetimePosition::MaxPosition(); | 2838 free_until_pos[i] = LifetimePosition::MaxPosition(); |
2785 } | 2839 } |
2786 | 2840 |
2787 for (LiveRange* cur_active : active_live_ranges()) { | 2841 for (LiveRange* cur_active : active_live_ranges()) { |
2788 free_until_pos[cur_active->assigned_register()] = | 2842 int cur_reg = cur_active->assigned_register(); |
2789 LifetimePosition::GapFromInstructionIndex(0); | 2843 if (no_combining()) { |
2790 TRACE("Register %s is free until pos %d (1)\n", | 2844 free_until_pos[cur_reg] = LifetimePosition::GapFromInstructionIndex(0); |
2791 RegisterName(cur_active->assigned_register()), | 2845 TRACE("Register %s is free until pos %d (1)\n", RegisterName(cur_reg), |
2792 LifetimePosition::GapFromInstructionIndex(0).value()); | 2846 LifetimePosition::GapFromInstructionIndex(0).value()); |
2847 } else { | |
2848 int alias_base_index; | |
2849 int aliases = data()->config()->GetAliases( | |
2850 cur_active->representation(), cur_reg, current->representation(), | |
2851 &alias_base_index); | |
2852 while (aliases--) { | |
2853 int aliased_reg = alias_base_index + aliases; | |
2854 free_until_pos[aliased_reg] = | |
2855 LifetimePosition::GapFromInstructionIndex(0); | |
2856 } | |
2857 } | |
2793 } | 2858 } |
2794 | 2859 |
2795 for (LiveRange* cur_inactive : inactive_live_ranges()) { | 2860 for (LiveRange* cur_inactive : inactive_live_ranges()) { |
2796 DCHECK(cur_inactive->End() > current->Start()); | 2861 DCHECK(cur_inactive->End() > current->Start()); |
2797 LifetimePosition next_intersection = | 2862 LifetimePosition next_intersection = |
2798 cur_inactive->FirstIntersection(current); | 2863 cur_inactive->FirstIntersection(current); |
2799 if (!next_intersection.IsValid()) continue; | 2864 if (!next_intersection.IsValid()) continue; |
2800 int cur_reg = cur_inactive->assigned_register(); | 2865 int cur_reg = cur_inactive->assigned_register(); |
2801 free_until_pos[cur_reg] = Min(free_until_pos[cur_reg], next_intersection); | 2866 if (no_combining()) { |
2802 TRACE("Register %s is free until pos %d (2)\n", RegisterName(cur_reg), | 2867 free_until_pos[cur_reg] = Min(free_until_pos[cur_reg], next_intersection); |
2803 Min(free_until_pos[cur_reg], next_intersection).value()); | 2868 TRACE("Register %s is free until pos %d (2)\n", RegisterName(cur_reg), |
2869 Min(free_until_pos[cur_reg], next_intersection).value()); | |
2870 } else { | |
2871 int alias_base_index; | |
2872 int aliases = data()->config()->GetAliases( | |
2873 cur_inactive->representation(), cur_reg, current->representation(), | |
2874 &alias_base_index); | |
2875 while (aliases--) { | |
2876 int aliased_reg = alias_base_index + aliases; | |
2877 free_until_pos[aliased_reg] = | |
2878 Min(free_until_pos[aliased_reg], next_intersection); | |
2879 } | |
2880 } | |
2804 } | 2881 } |
2805 | 2882 |
2806 int hint_register; | 2883 int hint_register; |
2807 if (current->FirstHintPosition(&hint_register) != nullptr) { | 2884 if (current->FirstHintPosition(&hint_register) != nullptr) { |
2808 TRACE( | 2885 TRACE( |
2809 "Found reg hint %s (free until [%d) for live range %d:%d (end %d[).\n", | 2886 "Found reg hint %s (free until [%d) for live range %d:%d (end %d[).\n", |
2810 RegisterName(hint_register), free_until_pos[hint_register].value(), | 2887 RegisterName(hint_register), free_until_pos[hint_register].value(), |
2811 current->TopLevel()->vreg(), current->relative_id(), | 2888 current->TopLevel()->vreg(), current->relative_id(), |
2812 current->End().value()); | 2889 current->End().value()); |
2813 | 2890 |
2814 // The desired register is free until the end of the current live range. | 2891 // The desired register is free until the end of the current live range. |
2815 if (free_until_pos[hint_register] >= current->End()) { | 2892 if (free_until_pos[hint_register] >= current->End()) { |
2816 TRACE("Assigning preferred reg %s to live range %d:%d\n", | 2893 TRACE("Assigning preferred reg %s to live range %d:%d\n", |
2817 RegisterName(hint_register), current->TopLevel()->vreg(), | 2894 RegisterName(hint_register), current->TopLevel()->vreg(), |
2818 current->relative_id()); | 2895 current->relative_id()); |
2819 SetLiveRangeAssignedRegister(current, hint_register); | 2896 SetLiveRangeAssignedRegister(current, hint_register); |
2820 return true; | 2897 return true; |
2821 } | 2898 } |
2822 } | 2899 } |
2823 | 2900 |
2824 // Find the register which stays free for the longest time. | 2901 // Find the register which stays free for the longest time. |
2825 int reg = allocatable_register_code(0); | 2902 int reg = codes[0]; |
2826 for (int i = 1; i < num_allocatable_registers(); ++i) { | 2903 for (int i = 1; i < num_codes; ++i) { |
2827 int code = allocatable_register_code(i); | 2904 int code = codes[i]; |
2828 if (free_until_pos[code] > free_until_pos[reg]) { | 2905 if (free_until_pos[code] > free_until_pos[reg]) { |
2829 reg = code; | 2906 reg = code; |
2830 } | 2907 } |
2831 } | 2908 } |
2832 | 2909 |
2833 LifetimePosition pos = free_until_pos[reg]; | 2910 LifetimePosition pos = free_until_pos[reg]; |
2834 | 2911 |
2835 if (pos <= current->Start()) { | 2912 if (pos <= current->Start()) { |
2836 // All registers are blocked. | 2913 // All registers are blocked. |
2837 return false; | 2914 return false; |
2838 } | 2915 } |
2839 | 2916 |
2840 if (pos < current->End()) { | 2917 if (pos < current->End()) { |
2841 // Register reg is available at the range start but becomes blocked before | 2918 // Register reg is available at the range start but becomes blocked before |
2842 // the range end. Split current at position where it becomes blocked. | 2919 // the range end. Split current at position where it becomes blocked. |
2843 LiveRange* tail = SplitRangeAt(current, pos); | 2920 LiveRange* tail = SplitRangeAt(current, pos); |
2844 AddToUnhandledSorted(tail); | 2921 AddToUnhandledSorted(tail); |
2845 } | 2922 } |
2846 | 2923 |
2847 // Register reg is available at the range start and is free until | 2924 // Register reg is available at the range start and is free until the range |
2848 // the range end. | 2925 // end. |
2849 DCHECK(pos >= current->End()); | 2926 DCHECK(pos >= current->End()); |
2850 TRACE("Assigning free reg %s to live range %d:%d\n", RegisterName(reg), | 2927 TRACE("Assigning free reg %s to live range %d:%d\n", RegisterName(reg), |
2851 current->TopLevel()->vreg(), current->relative_id()); | 2928 current->TopLevel()->vreg(), current->relative_id()); |
2852 SetLiveRangeAssignedRegister(current, reg); | 2929 SetLiveRangeAssignedRegister(current, reg); |
2853 | 2930 |
2854 return true; | 2931 return true; |
2855 } | 2932 } |
2856 | 2933 |
2857 | 2934 |
2858 void LinearScanAllocator::AllocateBlockedReg(LiveRange* current) { | 2935 void LinearScanAllocator::AllocateBlockedReg(LiveRange* current) { |
2859 UsePosition* register_use = current->NextRegisterPosition(current->Start()); | 2936 UsePosition* register_use = current->NextRegisterPosition(current->Start()); |
2860 if (register_use == nullptr) { | 2937 if (register_use == nullptr) { |
2861 // There is no use in the current live range that requires a register. | 2938 // There is no use in the current live range that requires a register. |
2862 // We can just spill it. | 2939 // We can just spill it. |
2863 Spill(current); | 2940 Spill(current); |
2864 return; | 2941 return; |
2865 } | 2942 } |
2866 | 2943 |
2944 int num_regs = num_registers(); | |
2945 int num_codes = num_allocatable_registers(); | |
2946 const int* codes = allocatable_register_codes(); | |
2947 if (!no_combining() && | |
2948 (current->representation() == MachineRepresentation::kFloat32)) { | |
2949 num_regs = data()->config()->num_float_registers(); | |
2950 num_codes = data()->config()->num_allocatable_float_registers(); | |
2951 codes = data()->config()->allocatable_float_codes(); | |
2952 } | |
2953 | |
2867 LifetimePosition use_pos[RegisterConfiguration::kMaxFPRegisters]; | 2954 LifetimePosition use_pos[RegisterConfiguration::kMaxFPRegisters]; |
2868 LifetimePosition block_pos[RegisterConfiguration::kMaxFPRegisters]; | 2955 LifetimePosition block_pos[RegisterConfiguration::kMaxFPRegisters]; |
2869 | 2956 for (int i = 0; i < num_regs; i++) { |
2870 for (int i = 0; i < num_registers(); i++) { | |
2871 use_pos[i] = block_pos[i] = LifetimePosition::MaxPosition(); | 2957 use_pos[i] = block_pos[i] = LifetimePosition::MaxPosition(); |
2872 } | 2958 } |
2873 | 2959 |
2874 for (LiveRange* range : active_live_ranges()) { | 2960 for (LiveRange* range : active_live_ranges()) { |
2875 int cur_reg = range->assigned_register(); | 2961 int cur_reg = range->assigned_register(); |
2876 if (range->TopLevel()->IsFixed() || | 2962 bool is_fixed_or_cant_spill = |
2877 !range->CanBeSpilled(current->Start())) { | 2963 range->TopLevel()->IsFixed() || !range->CanBeSpilled(current->Start()); |
2878 block_pos[cur_reg] = use_pos[cur_reg] = | 2964 if (no_combining()) { |
2879 LifetimePosition::GapFromInstructionIndex(0); | 2965 if (is_fixed_or_cant_spill) { |
2966 block_pos[cur_reg] = use_pos[cur_reg] = | |
2967 LifetimePosition::GapFromInstructionIndex(0); | |
2968 } else { | |
2969 UsePosition* next_use = | |
2970 range->NextUsePositionRegisterIsBeneficial(current->Start()); | |
2971 if (next_use == nullptr) { | |
2972 use_pos[cur_reg] = range->End(); | |
2973 } else { | |
2974 use_pos[cur_reg] = next_use->pos(); | |
2975 } | |
2976 } | |
2880 } else { | 2977 } else { |
2881 UsePosition* next_use = | 2978 int alias_base_index; |
Mircea Trofin
2016/06/22 06:07:34
Could you initialize this?
bbudge
2016/06/22 20:16:04
Done (at all call sites - there are 6)
| |
2882 range->NextUsePositionRegisterIsBeneficial(current->Start()); | 2979 int aliases = data()->config()->GetAliases( |
2883 if (next_use == nullptr) { | 2980 range->representation(), cur_reg, current->representation(), |
2884 use_pos[cur_reg] = range->End(); | 2981 &alias_base_index); |
2885 } else { | 2982 while (aliases--) { |
2886 use_pos[cur_reg] = next_use->pos(); | 2983 int aliased_reg = alias_base_index + aliases; |
2984 if (is_fixed_or_cant_spill) { | |
2985 block_pos[aliased_reg] = use_pos[aliased_reg] = | |
2986 LifetimePosition::GapFromInstructionIndex(0); | |
2987 } else { | |
2988 UsePosition* next_use = | |
2989 range->NextUsePositionRegisterIsBeneficial(current->Start()); | |
2990 if (next_use == nullptr) { | |
2991 use_pos[aliased_reg] = range->End(); | |
2992 } else { | |
2993 use_pos[aliased_reg] = next_use->pos(); | |
2994 } | |
2995 } | |
2887 } | 2996 } |
2888 } | 2997 } |
2889 } | 2998 } |
2890 | 2999 |
2891 for (LiveRange* range : inactive_live_ranges()) { | 3000 for (LiveRange* range : inactive_live_ranges()) { |
2892 DCHECK(range->End() > current->Start()); | 3001 DCHECK(range->End() > current->Start()); |
2893 LifetimePosition next_intersection = range->FirstIntersection(current); | 3002 LifetimePosition next_intersection = range->FirstIntersection(current); |
2894 if (!next_intersection.IsValid()) continue; | 3003 if (!next_intersection.IsValid()) continue; |
2895 int cur_reg = range->assigned_register(); | 3004 int cur_reg = range->assigned_register(); |
2896 if (range->TopLevel()->IsFixed()) { | 3005 bool is_fixed = range->TopLevel()->IsFixed(); |
2897 block_pos[cur_reg] = Min(block_pos[cur_reg], next_intersection); | 3006 if (no_combining()) { |
2898 use_pos[cur_reg] = Min(block_pos[cur_reg], use_pos[cur_reg]); | 3007 if (is_fixed) { |
3008 block_pos[cur_reg] = Min(block_pos[cur_reg], next_intersection); | |
3009 use_pos[cur_reg] = Min(block_pos[cur_reg], use_pos[cur_reg]); | |
3010 } else { | |
3011 use_pos[cur_reg] = Min(use_pos[cur_reg], next_intersection); | |
3012 } | |
2899 } else { | 3013 } else { |
2900 use_pos[cur_reg] = Min(use_pos[cur_reg], next_intersection); | 3014 int alias_base_index; |
Mircea Trofin
2016/06/22 06:07:34
please initialize
bbudge
2016/06/22 20:16:04
Done.
| |
3015 int aliases = data()->config()->GetAliases( | |
3016 range->representation(), cur_reg, current->representation(), | |
3017 &alias_base_index); | |
3018 while (aliases--) { | |
3019 int aliased_reg = alias_base_index + aliases; | |
3020 if (is_fixed) { | |
3021 block_pos[aliased_reg] = | |
3022 Min(block_pos[aliased_reg], next_intersection); | |
3023 use_pos[aliased_reg] = | |
3024 Min(block_pos[aliased_reg], use_pos[aliased_reg]); | |
3025 } else { | |
3026 use_pos[aliased_reg] = Min(use_pos[aliased_reg], next_intersection); | |
3027 } | |
3028 } | |
2901 } | 3029 } |
2902 } | 3030 } |
2903 | 3031 |
2904 int reg = allocatable_register_code(0); | 3032 int reg = codes[0]; |
2905 for (int i = 1; i < num_allocatable_registers(); ++i) { | 3033 for (int i = 1; i < num_codes; ++i) { |
2906 int code = allocatable_register_code(i); | 3034 int code = codes[i]; |
2907 if (use_pos[code] > use_pos[reg]) { | 3035 if (use_pos[code] > use_pos[reg]) { |
2908 reg = code; | 3036 reg = code; |
2909 } | 3037 } |
2910 } | 3038 } |
2911 | 3039 |
2912 LifetimePosition pos = use_pos[reg]; | 3040 LifetimePosition pos = use_pos[reg]; |
2913 | 3041 |
2914 if (pos < register_use->pos()) { | 3042 if (pos < register_use->pos()) { |
2915 if (LifetimePosition::ExistsGapPositionBetween(current->Start(), | 3043 if (LifetimePosition::ExistsGapPositionBetween(current->Start(), |
2916 register_use->pos())) { | 3044 register_use->pos())) { |
(...skipping 25 matching lines...) Expand all Loading... | |
2942 SplitAndSpillIntersecting(current); | 3070 SplitAndSpillIntersecting(current); |
2943 } | 3071 } |
2944 | 3072 |
2945 | 3073 |
2946 void LinearScanAllocator::SplitAndSpillIntersecting(LiveRange* current) { | 3074 void LinearScanAllocator::SplitAndSpillIntersecting(LiveRange* current) { |
2947 DCHECK(current->HasRegisterAssigned()); | 3075 DCHECK(current->HasRegisterAssigned()); |
2948 int reg = current->assigned_register(); | 3076 int reg = current->assigned_register(); |
2949 LifetimePosition split_pos = current->Start(); | 3077 LifetimePosition split_pos = current->Start(); |
2950 for (size_t i = 0; i < active_live_ranges().size(); ++i) { | 3078 for (size_t i = 0; i < active_live_ranges().size(); ++i) { |
2951 LiveRange* range = active_live_ranges()[i]; | 3079 LiveRange* range = active_live_ranges()[i]; |
2952 if (range->assigned_register() == reg) { | 3080 if (no_combining()) { |
2953 UsePosition* next_pos = range->NextRegisterPosition(current->Start()); | 3081 if (range->assigned_register() != reg) continue; |
2954 LifetimePosition spill_pos = FindOptimalSpillingPos(range, split_pos); | 3082 } else { |
2955 if (next_pos == nullptr) { | 3083 if (!data()->config()->AreAliases(current->representation(), reg, |
2956 SpillAfter(range, spill_pos); | 3084 range->representation(), |
2957 } else { | 3085 range->assigned_register())) { |
2958 // When spilling between spill_pos and next_pos ensure that the range | 3086 continue; |
2959 // remains spilled at least until the start of the current live range. | |
2960 // This guarantees that we will not introduce new unhandled ranges that | |
2961 // start before the current range as this violates allocation invariant | |
2962 // and will lead to an inconsistent state of active and inactive | |
2963 // live-ranges: ranges are allocated in order of their start positions, | |
2964 // ranges are retired from active/inactive when the start of the | |
2965 // current live-range is larger than their end. | |
2966 DCHECK(LifetimePosition::ExistsGapPositionBetween(current->Start(), | |
2967 next_pos->pos())); | |
2968 SpillBetweenUntil(range, spill_pos, current->Start(), next_pos->pos()); | |
2969 } | 3087 } |
2970 ActiveToHandled(range); | |
2971 --i; | |
2972 } | 3088 } |
3089 | |
3090 UsePosition* next_pos = range->NextRegisterPosition(current->Start()); | |
3091 LifetimePosition spill_pos = FindOptimalSpillingPos(range, split_pos); | |
3092 if (next_pos == nullptr) { | |
3093 SpillAfter(range, spill_pos); | |
3094 } else { | |
3095 // When spilling between spill_pos and next_pos ensure that the range | |
3096 // remains spilled at least until the start of the current live range. | |
3097 // This guarantees that we will not introduce new unhandled ranges that | |
3098 // start before the current range as this violates allocation invariants | |
3099 // and will lead to an inconsistent state of active and inactive | |
3100 // live-ranges: ranges are allocated in order of their start positions, | |
3101 // ranges are retired from active/inactive when the start of the | |
3102 // current live-range is larger than their end. | |
3103 DCHECK(LifetimePosition::ExistsGapPositionBetween(current->Start(), | |
3104 next_pos->pos())); | |
3105 SpillBetweenUntil(range, spill_pos, current->Start(), next_pos->pos()); | |
3106 } | |
3107 ActiveToHandled(range); | |
3108 --i; | |
2973 } | 3109 } |
2974 | 3110 |
2975 for (size_t i = 0; i < inactive_live_ranges().size(); ++i) { | 3111 for (size_t i = 0; i < inactive_live_ranges().size(); ++i) { |
2976 LiveRange* range = inactive_live_ranges()[i]; | 3112 LiveRange* range = inactive_live_ranges()[i]; |
2977 DCHECK(range->End() > current->Start()); | 3113 DCHECK(range->End() > current->Start()); |
2978 if (range->assigned_register() == reg && !range->TopLevel()->IsFixed()) { | 3114 if (range->TopLevel()->IsFixed()) continue; |
2979 LifetimePosition next_intersection = range->FirstIntersection(current); | 3115 if (no_combining()) { |
2980 if (next_intersection.IsValid()) { | 3116 if (range->assigned_register() != reg) continue; |
2981 UsePosition* next_pos = range->NextRegisterPosition(current->Start()); | 3117 } else { |
2982 if (next_pos == nullptr) { | 3118 if (!data()->config()->AreAliases(current->representation(), reg, |
2983 SpillAfter(range, split_pos); | 3119 range->representation(), |
2984 } else { | 3120 range->assigned_register())) |
2985 next_intersection = Min(next_intersection, next_pos->pos()); | 3121 continue; |
2986 SpillBetween(range, split_pos, next_intersection); | 3122 } |
2987 } | 3123 |
2988 InactiveToHandled(range); | 3124 LifetimePosition next_intersection = range->FirstIntersection(current); |
2989 --i; | 3125 if (next_intersection.IsValid()) { |
3126 UsePosition* next_pos = range->NextRegisterPosition(current->Start()); | |
3127 if (next_pos == nullptr) { | |
3128 SpillAfter(range, split_pos); | |
3129 } else { | |
3130 next_intersection = Min(next_intersection, next_pos->pos()); | |
3131 SpillBetween(range, split_pos, next_intersection); | |
2990 } | 3132 } |
3133 InactiveToHandled(range); | |
3134 --i; | |
2991 } | 3135 } |
2992 } | 3136 } |
2993 } | 3137 } |
2994 | 3138 |
2995 | 3139 |
2996 bool LinearScanAllocator::TryReuseSpillForPhi(TopLevelLiveRange* range) { | 3140 bool LinearScanAllocator::TryReuseSpillForPhi(TopLevelLiveRange* range) { |
2997 if (!range->is_phi()) return false; | 3141 if (!range->is_phi()) return false; |
2998 | 3142 |
2999 DCHECK(!range->HasSpillOperand()); | 3143 DCHECK(!range->HasSpillOperand()); |
3000 RegisterAllocationData::PhiMapValue* phi_map_value = | 3144 RegisterAllocationData::PhiMapValue* phi_map_value = |
(...skipping 159 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
3160 if (other != nullptr && !other->IsEmpty()) { | 3304 if (other != nullptr && !other->IsEmpty()) { |
3161 range->TryMerge(other); | 3305 range->TryMerge(other); |
3162 } | 3306 } |
3163 } | 3307 } |
3164 } | 3308 } |
3165 // Allocate slots for the merged spill ranges. | 3309 // Allocate slots for the merged spill ranges. |
3166 for (SpillRange* range : spill_ranges) { | 3310 for (SpillRange* range : spill_ranges) { |
3167 if (range == nullptr || range->IsEmpty()) continue; | 3311 if (range == nullptr || range->IsEmpty()) continue; |
3168 // Allocate a new operand referring to the spill slot. | 3312 // Allocate a new operand referring to the spill slot. |
3169 if (!range->HasSlot()) { | 3313 if (!range->HasSlot()) { |
3170 int byte_width = range->ByteWidth(); | 3314 int index = data()->frame()->AllocateSpillSlot(range->byte_width()); |
3171 int index = data()->frame()->AllocateSpillSlot(byte_width); | |
3172 range->set_assigned_slot(index); | 3315 range->set_assigned_slot(index); |
3173 } | 3316 } |
3174 } | 3317 } |
3175 } | 3318 } |
3176 | 3319 |
3177 | 3320 |
3178 void OperandAssigner::CommitAssignment() { | 3321 void OperandAssigner::CommitAssignment() { |
3179 for (TopLevelLiveRange* top_range : data()->live_ranges()) { | 3322 for (TopLevelLiveRange* top_range : data()->live_ranges()) { |
3180 if (top_range == nullptr || top_range->IsEmpty()) continue; | 3323 if (top_range == nullptr || top_range->IsEmpty()) continue; |
3181 InstructionOperand spill_operand; | 3324 InstructionOperand spill_operand; |
(...skipping 450 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
3632 } | 3775 } |
3633 } | 3776 } |
3634 } | 3777 } |
3635 } | 3778 } |
3636 } | 3779 } |
3637 | 3780 |
3638 | 3781 |
3639 } // namespace compiler | 3782 } // namespace compiler |
3640 } // namespace internal | 3783 } // namespace internal |
3641 } // namespace v8 | 3784 } // namespace v8 |
OLD | NEW |