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