| 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 756 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 767 if (move_op->IsEliminated()) continue; | 767 if (move_op->IsEliminated()) continue; |
| 768 if (move_op->source().Equals(*to_spill->operand) && | 768 if (move_op->source().Equals(*to_spill->operand) && |
| 769 move_op->destination().Equals(op)) { | 769 move_op->destination().Equals(op)) { |
| 770 found = true; | 770 found = true; |
| 771 if (has_preassigned_slot()) move_op->Eliminate(); | 771 if (has_preassigned_slot()) move_op->Eliminate(); |
| 772 break; | 772 break; |
| 773 } | 773 } |
| 774 } | 774 } |
| 775 if (found) continue; | 775 if (found) continue; |
| 776 } | 776 } |
| 777 move->AddMove(*to_spill->operand, op); | 777 if (!has_preassigned_slot()) { |
| 778 move->AddMove(*to_spill->operand, op); |
| 779 } |
| 778 } | 780 } |
| 779 } | 781 } |
| 780 | 782 |
| 781 | 783 |
| 782 void TopLevelLiveRange::SetSpillOperand(InstructionOperand* operand) { | 784 void TopLevelLiveRange::SetSpillOperand(InstructionOperand* operand) { |
| 783 DCHECK(HasNoSpillType()); | 785 DCHECK(HasNoSpillType()); |
| 784 DCHECK(!operand->IsUnallocated() && !operand->IsImmediate()); | 786 DCHECK(!operand->IsUnallocated() && !operand->IsImmediate()); |
| 785 set_spill_type(SpillType::kSpillOperand); | 787 set_spill_type(SpillType::kSpillOperand); |
| 786 spill_operand_ = operand; | 788 spill_operand_ = operand; |
| 787 } | 789 } |
| (...skipping 338 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1126 if (this->use_interval_ == nullptr || other->use_interval_ == nullptr || | 1128 if (this->use_interval_ == nullptr || other->use_interval_ == nullptr || |
| 1127 this->End() <= other->use_interval_->start() || | 1129 this->End() <= other->use_interval_->start() || |
| 1128 other->End() <= this->use_interval_->start()) { | 1130 other->End() <= this->use_interval_->start()) { |
| 1129 return false; | 1131 return false; |
| 1130 } | 1132 } |
| 1131 return AreUseIntervalsIntersecting(use_interval_, other->use_interval_); | 1133 return AreUseIntervalsIntersecting(use_interval_, other->use_interval_); |
| 1132 } | 1134 } |
| 1133 | 1135 |
| 1134 | 1136 |
| 1135 bool SpillRange::TryMerge(SpillRange* other) { | 1137 bool SpillRange::TryMerge(SpillRange* other) { |
| 1138 if (HasSlot() || other->HasSlot()) return false; |
| 1136 // TODO(dcarney): byte widths should be compared here not kinds. | 1139 // TODO(dcarney): byte widths should be compared here not kinds. |
| 1137 if (live_ranges_[0]->kind() != other->live_ranges_[0]->kind() || | 1140 if (live_ranges_[0]->kind() != other->live_ranges_[0]->kind() || |
| 1138 IsIntersectingWith(other)) { | 1141 IsIntersectingWith(other)) { |
| 1139 return false; | 1142 return false; |
| 1140 } | 1143 } |
| 1141 | 1144 |
| 1142 auto max = LifetimePosition::MaxPosition(); | 1145 auto max = LifetimePosition::MaxPosition(); |
| 1143 if (End() < other->End() && other->End() != max) { | 1146 if (End() < other->End() && other->End() != max) { |
| 1144 end_position_ = other->End(); | 1147 end_position_ = other->End(); |
| 1145 } | 1148 } |
| (...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1227 live_ranges_(code->VirtualRegisterCount() * 2, nullptr, | 1230 live_ranges_(code->VirtualRegisterCount() * 2, nullptr, |
| 1228 allocation_zone()), | 1231 allocation_zone()), |
| 1229 fixed_live_ranges_(this->config()->num_general_registers(), nullptr, | 1232 fixed_live_ranges_(this->config()->num_general_registers(), nullptr, |
| 1230 allocation_zone()), | 1233 allocation_zone()), |
| 1231 fixed_double_live_ranges_(this->config()->num_double_registers(), nullptr, | 1234 fixed_double_live_ranges_(this->config()->num_double_registers(), nullptr, |
| 1232 allocation_zone()), | 1235 allocation_zone()), |
| 1233 spill_ranges_(code->VirtualRegisterCount(), nullptr, allocation_zone()), | 1236 spill_ranges_(code->VirtualRegisterCount(), nullptr, allocation_zone()), |
| 1234 delayed_references_(allocation_zone()), | 1237 delayed_references_(allocation_zone()), |
| 1235 assigned_registers_(nullptr), | 1238 assigned_registers_(nullptr), |
| 1236 assigned_double_registers_(nullptr), | 1239 assigned_double_registers_(nullptr), |
| 1237 virtual_register_count_(code->VirtualRegisterCount()) { | 1240 virtual_register_count_(code->VirtualRegisterCount()), |
| 1241 preassigned_slot_ranges_(allocation_zone()) { |
| 1238 DCHECK(this->config()->num_general_registers() <= | 1242 DCHECK(this->config()->num_general_registers() <= |
| 1239 RegisterConfiguration::kMaxGeneralRegisters); | 1243 RegisterConfiguration::kMaxGeneralRegisters); |
| 1240 DCHECK(this->config()->num_double_registers() <= | 1244 DCHECK(this->config()->num_double_registers() <= |
| 1241 RegisterConfiguration::kMaxDoubleRegisters); | 1245 RegisterConfiguration::kMaxDoubleRegisters); |
| 1242 assigned_registers_ = new (code_zone()) | 1246 assigned_registers_ = new (code_zone()) |
| 1243 BitVector(this->config()->num_general_registers(), code_zone()); | 1247 BitVector(this->config()->num_general_registers(), code_zone()); |
| 1244 assigned_double_registers_ = new (code_zone()) | 1248 assigned_double_registers_ = new (code_zone()) |
| 1245 BitVector(this->config()->num_double_registers(), code_zone()); | 1249 BitVector(this->config()->num_double_registers(), code_zone()); |
| 1246 this->frame()->SetAllocatedRegisters(assigned_registers_); | 1250 this->frame()->SetAllocatedRegisters(assigned_registers_); |
| 1247 this->frame()->SetAllocatedDoubleRegisters(assigned_double_registers_); | 1251 this->frame()->SetAllocatedDoubleRegisters(assigned_double_registers_); |
| (...skipping 371 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1619 auto first_output = UnallocatedOperand::cast(output); | 1623 auto first_output = UnallocatedOperand::cast(output); |
| 1620 auto range = | 1624 auto range = |
| 1621 data()->GetOrCreateLiveRangeFor(first_output->virtual_register()); | 1625 data()->GetOrCreateLiveRangeFor(first_output->virtual_register()); |
| 1622 bool assigned = false; | 1626 bool assigned = false; |
| 1623 if (first_output->HasFixedPolicy()) { | 1627 if (first_output->HasFixedPolicy()) { |
| 1624 int output_vreg = first_output->virtual_register(); | 1628 int output_vreg = first_output->virtual_register(); |
| 1625 UnallocatedOperand output_copy(UnallocatedOperand::ANY, output_vreg); | 1629 UnallocatedOperand output_copy(UnallocatedOperand::ANY, output_vreg); |
| 1626 bool is_tagged = code()->IsReference(output_vreg); | 1630 bool is_tagged = code()->IsReference(output_vreg); |
| 1627 if (first_output->HasSecondaryStorage()) { | 1631 if (first_output->HasSecondaryStorage()) { |
| 1628 range->MarkHasPreassignedSlot(); | 1632 range->MarkHasPreassignedSlot(); |
| 1629 InstructionOperand* spill_op = AllocatedOperand::New( | 1633 data()->preassigned_slot_ranges()[range] = |
| 1630 data()->code_zone(), LocationOperand::LocationKind::STACK_SLOT, | 1634 first_output->GetSecondaryStorage(); |
| 1631 range->machine_type(), first_output->GetSecondaryStorage()); | |
| 1632 range->RecordSpillLocation(allocation_zone(), instr_index + 1, | |
| 1633 first_output); | |
| 1634 range->SetSpillOperand(spill_op); | |
| 1635 range->SetSpillStartIndex(instr_index + 1); | |
| 1636 assigned = true; | |
| 1637 } | 1635 } |
| 1638 AllocateFixed(first_output, instr_index, is_tagged); | 1636 AllocateFixed(first_output, instr_index, is_tagged); |
| 1639 | 1637 |
| 1640 // This value is produced on the stack, we never need to spill it. | 1638 // This value is produced on the stack, we never need to spill it. |
| 1641 if (first_output->IsStackSlot()) { | 1639 if (first_output->IsStackSlot()) { |
| 1642 DCHECK(LocationOperand::cast(first_output)->index() < | 1640 DCHECK(LocationOperand::cast(first_output)->index() < |
| 1643 data()->frame()->GetTotalFrameSlotCount()); | 1641 data()->frame()->GetTotalFrameSlotCount()); |
| 1644 range->SetSpillOperand(LocationOperand::cast(first_output)); | 1642 range->SetSpillOperand(LocationOperand::cast(first_output)); |
| 1645 range->SetSpillStartIndex(instr_index + 1); | 1643 range->SetSpillStartIndex(instr_index + 1); |
| 1646 assigned = true; | 1644 assigned = true; |
| (...skipping 510 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2157 if (pos->type() == UsePositionType::kRequiresSlot) continue; | 2155 if (pos->type() == UsePositionType::kRequiresSlot) continue; |
| 2158 UsePositionType new_type = UsePositionType::kAny; | 2156 UsePositionType new_type = UsePositionType::kAny; |
| 2159 // Can't mark phis as needing a register. | 2157 // Can't mark phis as needing a register. |
| 2160 if (!pos->pos().IsGapPosition()) { | 2158 if (!pos->pos().IsGapPosition()) { |
| 2161 new_type = UsePositionType::kRequiresRegister; | 2159 new_type = UsePositionType::kRequiresRegister; |
| 2162 } | 2160 } |
| 2163 pos->set_type(new_type, true); | 2161 pos->set_type(new_type, true); |
| 2164 } | 2162 } |
| 2165 } | 2163 } |
| 2166 } | 2164 } |
| 2165 for (auto preassigned : data()->preassigned_slot_ranges()) { |
| 2166 TopLevelLiveRange* range = preassigned.first; |
| 2167 int slot_id = preassigned.second; |
| 2168 SpillRange* spill = range->HasSpillRange() |
| 2169 ? range->GetSpillRange() |
| 2170 : data()->AssignSpillRangeToLiveRange(range); |
| 2171 spill->set_assigned_slot(slot_id); |
| 2172 } |
| 2167 #ifdef DEBUG | 2173 #ifdef DEBUG |
| 2168 Verify(); | 2174 Verify(); |
| 2169 #endif | 2175 #endif |
| 2170 } | 2176 } |
| 2171 | 2177 |
| 2172 | 2178 |
| 2173 void LiveRangeBuilder::MapPhiHint(InstructionOperand* operand, | 2179 void LiveRangeBuilder::MapPhiHint(InstructionOperand* operand, |
| 2174 UsePosition* use_pos) { | 2180 UsePosition* use_pos) { |
| 2175 DCHECK(!use_pos->IsResolved()); | 2181 DCHECK(!use_pos->IsResolved()); |
| 2176 auto res = phi_hints_.insert(std::make_pair(operand, use_pos)); | 2182 auto res = phi_hints_.insert(std::make_pair(operand, use_pos)); |
| (...skipping 799 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2976 SpillRange* other = spill_ranges[j]; | 2982 SpillRange* other = spill_ranges[j]; |
| 2977 if (other != nullptr && !other->IsEmpty()) { | 2983 if (other != nullptr && !other->IsEmpty()) { |
| 2978 range->TryMerge(other); | 2984 range->TryMerge(other); |
| 2979 } | 2985 } |
| 2980 } | 2986 } |
| 2981 } | 2987 } |
| 2982 // Allocate slots for the merged spill ranges. | 2988 // Allocate slots for the merged spill ranges. |
| 2983 for (SpillRange* range : spill_ranges) { | 2989 for (SpillRange* range : spill_ranges) { |
| 2984 if (range == nullptr || range->IsEmpty()) continue; | 2990 if (range == nullptr || range->IsEmpty()) continue; |
| 2985 // Allocate a new operand referring to the spill slot. | 2991 // Allocate a new operand referring to the spill slot. |
| 2986 int byte_width = range->ByteWidth(); | 2992 if (!range->HasSlot()) { |
| 2987 int index = data()->frame()->AllocateSpillSlot(byte_width); | 2993 int byte_width = range->ByteWidth(); |
| 2988 range->set_assigned_slot(index); | 2994 int index = data()->frame()->AllocateSpillSlot(byte_width); |
| 2995 range->set_assigned_slot(index); |
| 2996 } |
| 2989 } | 2997 } |
| 2990 } | 2998 } |
| 2991 | 2999 |
| 2992 | 3000 |
| 2993 void OperandAssigner::CommitAssignment() { | 3001 void OperandAssigner::CommitAssignment() { |
| 2994 for (TopLevelLiveRange* top_range : data()->live_ranges()) { | 3002 for (TopLevelLiveRange* top_range : data()->live_ranges()) { |
| 2995 if (top_range == nullptr || top_range->IsEmpty()) continue; | 3003 if (top_range == nullptr || top_range->IsEmpty()) continue; |
| 2996 InstructionOperand spill_operand; | 3004 InstructionOperand spill_operand; |
| 2997 if (top_range->HasSpillOperand()) { | 3005 if (top_range->HasSpillOperand()) { |
| 2998 spill_operand = *top_range->TopLevel()->GetSpillOperand(); | 3006 spill_operand = *top_range->TopLevel()->GetSpillOperand(); |
| (...skipping 446 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3445 auto eliminate = moves->PrepareInsertAfter(move); | 3453 auto eliminate = moves->PrepareInsertAfter(move); |
| 3446 to_insert.push_back(move); | 3454 to_insert.push_back(move); |
| 3447 if (eliminate != nullptr) to_eliminate.push_back(eliminate); | 3455 if (eliminate != nullptr) to_eliminate.push_back(eliminate); |
| 3448 } | 3456 } |
| 3449 } | 3457 } |
| 3450 | 3458 |
| 3451 | 3459 |
| 3452 } // namespace compiler | 3460 } // namespace compiler |
| 3453 } // namespace internal | 3461 } // namespace internal |
| 3454 } // namespace v8 | 3462 } // namespace v8 |
| OLD | NEW |