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