Chromium Code Reviews| 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 |