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 |