| 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 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 85 if (output->IsDoubleRegister() && | 85 if (output->IsDoubleRegister() && |
| 86 LocationOperand::cast(output)->GetDoubleRegister().is(reg)) { | 86 LocationOperand::cast(output)->GetDoubleRegister().is(reg)) { |
| 87 return true; | 87 return true; |
| 88 } | 88 } |
| 89 } | 89 } |
| 90 return false; | 90 return false; |
| 91 } | 91 } |
| 92 | 92 |
| 93 | 93 |
| 94 // TODO(dcarney): fix frame to allow frame accesses to half size location. | 94 // TODO(dcarney): fix frame to allow frame accesses to half size location. |
| 95 int GetByteWidth(MachineType machine_type) { | 95 int GetByteWidth(MachineRepresentation rep) { |
| 96 DCHECK_EQ(RepresentationOf(machine_type), machine_type); | 96 switch (rep) { |
| 97 switch (machine_type) { | 97 case MachineRepresentation::kBit: |
| 98 case kRepBit: | 98 case MachineRepresentation::kWord8: |
| 99 case kRepWord8: | 99 case MachineRepresentation::kWord16: |
| 100 case kRepWord16: | 100 case MachineRepresentation::kWord32: |
| 101 case kRepWord32: | 101 case MachineRepresentation::kTagged: |
| 102 case kRepTagged: | |
| 103 return kPointerSize; | 102 return kPointerSize; |
| 104 case kRepFloat32: | 103 case MachineRepresentation::kFloat32: |
| 105 case kRepWord64: | 104 case MachineRepresentation::kWord64: |
| 106 case kRepFloat64: | 105 case MachineRepresentation::kFloat64: |
| 107 return 8; | 106 return 8; |
| 108 default: | 107 default: |
| 109 UNREACHABLE(); | 108 UNREACHABLE(); |
| 110 return 0; | 109 return 0; |
| 111 } | 110 } |
| 112 } | 111 } |
| 113 | 112 |
| 114 } // namespace | 113 } // namespace |
| 115 | 114 |
| 116 | 115 |
| (...skipping 127 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 244 os << 'e'; | 243 os << 'e'; |
| 245 } | 244 } |
| 246 return os; | 245 return os; |
| 247 } | 246 } |
| 248 | 247 |
| 249 | 248 |
| 250 const float LiveRange::kInvalidWeight = -1; | 249 const float LiveRange::kInvalidWeight = -1; |
| 251 const float LiveRange::kMaxWeight = std::numeric_limits<float>::max(); | 250 const float LiveRange::kMaxWeight = std::numeric_limits<float>::max(); |
| 252 | 251 |
| 253 | 252 |
| 254 LiveRange::LiveRange(int relative_id, MachineType machine_type, | 253 LiveRange::LiveRange(int relative_id, MachineRepresentation rep, |
| 255 TopLevelLiveRange* top_level) | 254 TopLevelLiveRange* top_level) |
| 256 : relative_id_(relative_id), | 255 : relative_id_(relative_id), |
| 257 bits_(0), | 256 bits_(0), |
| 258 last_interval_(nullptr), | 257 last_interval_(nullptr), |
| 259 first_interval_(nullptr), | 258 first_interval_(nullptr), |
| 260 first_pos_(nullptr), | 259 first_pos_(nullptr), |
| 261 top_level_(top_level), | 260 top_level_(top_level), |
| 262 next_(nullptr), | 261 next_(nullptr), |
| 263 current_interval_(nullptr), | 262 current_interval_(nullptr), |
| 264 last_processed_use_(nullptr), | 263 last_processed_use_(nullptr), |
| 265 current_hint_position_(nullptr), | 264 current_hint_position_(nullptr), |
| 266 splitting_pointer_(nullptr), | 265 splitting_pointer_(nullptr), |
| 267 size_(kInvalidSize), | 266 size_(kInvalidSize), |
| 268 weight_(kInvalidWeight), | 267 weight_(kInvalidWeight), |
| 269 group_(nullptr) { | 268 group_(nullptr) { |
| 270 DCHECK(AllocatedOperand::IsSupportedMachineType(machine_type)); | 269 DCHECK(AllocatedOperand::IsSupportedRepresentation(rep)); |
| 271 bits_ = AssignedRegisterField::encode(kUnassignedRegister) | | 270 bits_ = AssignedRegisterField::encode(kUnassignedRegister) | |
| 272 MachineTypeField::encode(machine_type); | 271 RepresentationField::encode(rep); |
| 273 } | 272 } |
| 274 | 273 |
| 275 | 274 |
| 276 void LiveRange::Verify() const { | 275 void LiveRange::Verify() const { |
| 277 // Walk the positions, verifying that each is in an interval. | 276 // Walk the positions, verifying that each is in an interval. |
| 278 auto interval = first_interval_; | 277 auto interval = first_interval_; |
| 279 for (auto pos = first_pos_; pos != nullptr; pos = pos->next()) { | 278 for (auto pos = first_pos_; pos != nullptr; pos = pos->next()) { |
| 280 CHECK(Start() <= pos->pos()); | 279 CHECK(Start() <= pos->pos()); |
| 281 CHECK(pos->pos() <= End()); | 280 CHECK(pos->pos() <= End()); |
| 282 CHECK(interval != nullptr); | 281 CHECK(interval != nullptr); |
| (...skipping 19 matching lines...) Expand all Loading... |
| 302 | 301 |
| 303 void LiveRange::Spill() { | 302 void LiveRange::Spill() { |
| 304 DCHECK(!spilled()); | 303 DCHECK(!spilled()); |
| 305 DCHECK(!TopLevel()->HasNoSpillType()); | 304 DCHECK(!TopLevel()->HasNoSpillType()); |
| 306 set_spilled(true); | 305 set_spilled(true); |
| 307 bits_ = AssignedRegisterField::update(bits_, kUnassignedRegister); | 306 bits_ = AssignedRegisterField::update(bits_, kUnassignedRegister); |
| 308 } | 307 } |
| 309 | 308 |
| 310 | 309 |
| 311 RegisterKind LiveRange::kind() const { | 310 RegisterKind LiveRange::kind() const { |
| 312 switch (RepresentationOf(machine_type())) { | 311 return IsFloatingPoint(representation()) ? DOUBLE_REGISTERS |
| 313 case kRepFloat32: | 312 : GENERAL_REGISTERS; |
| 314 case kRepFloat64: | |
| 315 return DOUBLE_REGISTERS; | |
| 316 default: | |
| 317 break; | |
| 318 } | |
| 319 return GENERAL_REGISTERS; | |
| 320 } | 313 } |
| 321 | 314 |
| 322 | 315 |
| 323 UsePosition* LiveRange::FirstHintPosition(int* register_index) const { | 316 UsePosition* LiveRange::FirstHintPosition(int* register_index) const { |
| 324 for (auto pos = first_pos_; pos != nullptr; pos = pos->next()) { | 317 for (auto pos = first_pos_; pos != nullptr; pos = pos->next()) { |
| 325 if (pos->HintRegister(register_index)) return pos; | 318 if (pos->HintRegister(register_index)) return pos; |
| 326 } | 319 } |
| 327 return nullptr; | 320 return nullptr; |
| 328 } | 321 } |
| 329 | 322 |
| (...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 390 return use_pos->pos() > pos.NextStart().End(); | 383 return use_pos->pos() > pos.NextStart().End(); |
| 391 } | 384 } |
| 392 | 385 |
| 393 | 386 |
| 394 bool LiveRange::IsTopLevel() const { return top_level_ == this; } | 387 bool LiveRange::IsTopLevel() const { return top_level_ == this; } |
| 395 | 388 |
| 396 | 389 |
| 397 InstructionOperand LiveRange::GetAssignedOperand() const { | 390 InstructionOperand LiveRange::GetAssignedOperand() const { |
| 398 if (HasRegisterAssigned()) { | 391 if (HasRegisterAssigned()) { |
| 399 DCHECK(!spilled()); | 392 DCHECK(!spilled()); |
| 400 return AllocatedOperand(LocationOperand::REGISTER, machine_type(), | 393 return AllocatedOperand(LocationOperand::REGISTER, representation(), |
| 401 assigned_register()); | 394 assigned_register()); |
| 402 } | 395 } |
| 403 DCHECK(spilled()); | 396 DCHECK(spilled()); |
| 404 DCHECK(!HasRegisterAssigned()); | 397 DCHECK(!HasRegisterAssigned()); |
| 405 if (TopLevel()->HasSpillOperand()) { | 398 if (TopLevel()->HasSpillOperand()) { |
| 406 auto op = TopLevel()->GetSpillOperand(); | 399 auto op = TopLevel()->GetSpillOperand(); |
| 407 DCHECK(!op->IsUnallocated()); | 400 DCHECK(!op->IsUnallocated()); |
| 408 return *op; | 401 return *op; |
| 409 } | 402 } |
| 410 return TopLevel()->GetSpillRangeOperand(); | 403 return TopLevel()->GetSpillRangeOperand(); |
| (...skipping 18 matching lines...) Expand all Loading... |
| 429 auto start = current_interval_ == nullptr ? LifetimePosition::Invalid() | 422 auto start = current_interval_ == nullptr ? LifetimePosition::Invalid() |
| 430 : current_interval_->start(); | 423 : current_interval_->start(); |
| 431 if (to_start_of->start() > start) { | 424 if (to_start_of->start() > start) { |
| 432 current_interval_ = to_start_of; | 425 current_interval_ = to_start_of; |
| 433 } | 426 } |
| 434 } | 427 } |
| 435 | 428 |
| 436 | 429 |
| 437 LiveRange* LiveRange::SplitAt(LifetimePosition position, Zone* zone) { | 430 LiveRange* LiveRange::SplitAt(LifetimePosition position, Zone* zone) { |
| 438 int new_id = TopLevel()->GetNextChildId(); | 431 int new_id = TopLevel()->GetNextChildId(); |
| 439 LiveRange* child = new (zone) LiveRange(new_id, machine_type(), TopLevel()); | 432 LiveRange* child = new (zone) LiveRange(new_id, representation(), TopLevel()); |
| 440 DetachAt(position, child, zone); | 433 DetachAt(position, child, zone); |
| 441 | 434 |
| 442 child->top_level_ = TopLevel(); | 435 child->top_level_ = TopLevel(); |
| 443 child->next_ = next_; | 436 child->next_ = next_; |
| 444 next_ = child; | 437 next_ = child; |
| 445 if (child->next() == nullptr) { | 438 if (child->next() == nullptr) { |
| 446 TopLevel()->set_last_child(child); | 439 TopLevel()->set_last_child(child); |
| 447 } | 440 } |
| 448 return child; | 441 return child; |
| 449 } | 442 } |
| (...skipping 224 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 674 struct TopLevelLiveRange::SpillMoveInsertionList : ZoneObject { | 667 struct TopLevelLiveRange::SpillMoveInsertionList : ZoneObject { |
| 675 SpillMoveInsertionList(int gap_index, InstructionOperand* operand, | 668 SpillMoveInsertionList(int gap_index, InstructionOperand* operand, |
| 676 SpillMoveInsertionList* next) | 669 SpillMoveInsertionList* next) |
| 677 : gap_index(gap_index), operand(operand), next(next) {} | 670 : gap_index(gap_index), operand(operand), next(next) {} |
| 678 const int gap_index; | 671 const int gap_index; |
| 679 InstructionOperand* const operand; | 672 InstructionOperand* const operand; |
| 680 SpillMoveInsertionList* const next; | 673 SpillMoveInsertionList* const next; |
| 681 }; | 674 }; |
| 682 | 675 |
| 683 | 676 |
| 684 TopLevelLiveRange::TopLevelLiveRange(int vreg, MachineType machine_type) | 677 TopLevelLiveRange::TopLevelLiveRange(int vreg, MachineRepresentation rep) |
| 685 : LiveRange(0, machine_type, this), | 678 : LiveRange(0, rep, this), |
| 686 vreg_(vreg), | 679 vreg_(vreg), |
| 687 last_child_id_(0), | 680 last_child_id_(0), |
| 688 splintered_from_(nullptr), | 681 splintered_from_(nullptr), |
| 689 spill_operand_(nullptr), | 682 spill_operand_(nullptr), |
| 690 spill_move_insertion_locations_(nullptr), | 683 spill_move_insertion_locations_(nullptr), |
| 691 spilled_in_deferred_blocks_(false), | 684 spilled_in_deferred_blocks_(false), |
| 692 spill_start_index_(kMaxInt), | 685 spill_start_index_(kMaxInt), |
| 693 last_child_(this), | 686 last_child_(this), |
| 694 last_pos_(nullptr), | 687 last_pos_(nullptr), |
| 695 splinter_(nullptr), | 688 splinter_(nullptr), |
| (...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 790 void TopLevelLiveRange::SetSpillRange(SpillRange* spill_range) { | 783 void TopLevelLiveRange::SetSpillRange(SpillRange* spill_range) { |
| 791 DCHECK(!HasSpillOperand()); | 784 DCHECK(!HasSpillOperand()); |
| 792 DCHECK(spill_range); | 785 DCHECK(spill_range); |
| 793 spill_range_ = spill_range; | 786 spill_range_ = spill_range; |
| 794 } | 787 } |
| 795 | 788 |
| 796 | 789 |
| 797 AllocatedOperand TopLevelLiveRange::GetSpillRangeOperand() const { | 790 AllocatedOperand TopLevelLiveRange::GetSpillRangeOperand() const { |
| 798 auto spill_range = GetSpillRange(); | 791 auto spill_range = GetSpillRange(); |
| 799 int index = spill_range->assigned_slot(); | 792 int index = spill_range->assigned_slot(); |
| 800 return AllocatedOperand(LocationOperand::STACK_SLOT, machine_type(), index); | 793 return AllocatedOperand(LocationOperand::STACK_SLOT, representation(), index); |
| 801 } | 794 } |
| 802 | 795 |
| 803 | 796 |
| 804 void TopLevelLiveRange::Splinter(LifetimePosition start, LifetimePosition end, | 797 void TopLevelLiveRange::Splinter(LifetimePosition start, LifetimePosition end, |
| 805 Zone* zone) { | 798 Zone* zone) { |
| 806 DCHECK(start != Start() || end != End()); | 799 DCHECK(start != Start() || end != End()); |
| 807 DCHECK(start < end); | 800 DCHECK(start < end); |
| 808 | 801 |
| 809 TopLevelLiveRange splinter_temp(-1, machine_type()); | 802 TopLevelLiveRange splinter_temp(-1, representation()); |
| 810 UsePosition* last_in_splinter = nullptr; | 803 UsePosition* last_in_splinter = nullptr; |
| 811 // Live ranges defined in deferred blocks stay in deferred blocks, so we | 804 // Live ranges defined in deferred blocks stay in deferred blocks, so we |
| 812 // don't need to splinter them. That means that start should always be | 805 // don't need to splinter them. That means that start should always be |
| 813 // after the beginning of the range. | 806 // after the beginning of the range. |
| 814 DCHECK(start > Start()); | 807 DCHECK(start > Start()); |
| 815 | 808 |
| 816 if (end >= End()) { | 809 if (end >= End()) { |
| 817 DCHECK(start > Start()); | 810 DCHECK(start > Start()); |
| 818 DetachAt(start, &splinter_temp, zone); | 811 DetachAt(start, &splinter_temp, zone); |
| 819 next_ = nullptr; | 812 next_ = nullptr; |
| 820 } else { | 813 } else { |
| 821 DCHECK(start < End() && Start() < end); | 814 DCHECK(start < End() && Start() < end); |
| 822 | 815 |
| 823 const int kInvalidId = std::numeric_limits<int>::max(); | 816 const int kInvalidId = std::numeric_limits<int>::max(); |
| 824 | 817 |
| 825 UsePosition* last = DetachAt(start, &splinter_temp, zone); | 818 UsePosition* last = DetachAt(start, &splinter_temp, zone); |
| 826 | 819 |
| 827 LiveRange end_part(kInvalidId, this->machine_type(), nullptr); | 820 LiveRange end_part(kInvalidId, this->representation(), nullptr); |
| 828 last_in_splinter = splinter_temp.DetachAt(end, &end_part, zone); | 821 last_in_splinter = splinter_temp.DetachAt(end, &end_part, zone); |
| 829 | 822 |
| 830 next_ = end_part.next_; | 823 next_ = end_part.next_; |
| 831 last_interval_->set_next(end_part.first_interval_); | 824 last_interval_->set_next(end_part.first_interval_); |
| 832 // The next splinter will happen either at or after the current interval. | 825 // The next splinter will happen either at or after the current interval. |
| 833 // We can optimize DetachAt by setting current_interval_ accordingly, | 826 // We can optimize DetachAt by setting current_interval_ accordingly, |
| 834 // which will then be picked up by FirstSearchIntervalForPosition. | 827 // which will then be picked up by FirstSearchIntervalForPosition. |
| 835 current_interval_ = last_interval_; | 828 current_interval_ = last_interval_; |
| 836 last_interval_ = end_part.last_interval_; | 829 last_interval_ = end_part.last_interval_; |
| 837 | 830 |
| (...skipping 243 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1081 interval = interval->next(); | 1074 interval = interval->next(); |
| 1082 } | 1075 } |
| 1083 os << "}"; | 1076 os << "}"; |
| 1084 return os; | 1077 return os; |
| 1085 } | 1078 } |
| 1086 | 1079 |
| 1087 | 1080 |
| 1088 SpillRange::SpillRange(TopLevelLiveRange* parent, Zone* zone) | 1081 SpillRange::SpillRange(TopLevelLiveRange* parent, Zone* zone) |
| 1089 : live_ranges_(zone), | 1082 : live_ranges_(zone), |
| 1090 assigned_slot_(kUnassignedSlot), | 1083 assigned_slot_(kUnassignedSlot), |
| 1091 byte_width_(GetByteWidth(parent->machine_type())), | 1084 byte_width_(GetByteWidth(parent->representation())), |
| 1092 kind_(parent->kind()) { | 1085 kind_(parent->kind()) { |
| 1093 // Spill ranges are created for top level, non-splintered ranges. This is so | 1086 // Spill ranges are created for top level, non-splintered ranges. This is so |
| 1094 // that, when merging decisions are made, we consider the full extent of the | 1087 // that, when merging decisions are made, we consider the full extent of the |
| 1095 // virtual register, and avoid clobbering it. | 1088 // virtual register, and avoid clobbering it. |
| 1096 DCHECK(!parent->IsSplinter()); | 1089 DCHECK(!parent->IsSplinter()); |
| 1097 UseInterval* result = nullptr; | 1090 UseInterval* result = nullptr; |
| 1098 UseInterval* node = nullptr; | 1091 UseInterval* node = nullptr; |
| 1099 // Copy the intervals for all ranges. | 1092 // Copy the intervals for all ranges. |
| 1100 for (LiveRange* range = parent; range != nullptr; range = range->next()) { | 1093 for (LiveRange* range = parent; range != nullptr; range = range->next()) { |
| 1101 auto src = range->first_interval(); | 1094 auto src = range->first_interval(); |
| 1102 while (src != nullptr) { | 1095 while (src != nullptr) { |
| 1103 auto new_node = new (zone) UseInterval(src->start(), src->end()); | 1096 auto new_node = new (zone) UseInterval(src->start(), src->end()); |
| 1104 if (result == nullptr) { | 1097 if (result == nullptr) { |
| 1105 result = new_node; | 1098 result = new_node; |
| 1106 } else { | 1099 } else { |
| 1107 node->set_next(new_node); | 1100 node->set_next(new_node); |
| 1108 } | 1101 } |
| 1109 node = new_node; | 1102 node = new_node; |
| 1110 src = src->next(); | 1103 src = src->next(); |
| 1111 } | 1104 } |
| 1112 } | 1105 } |
| 1113 use_interval_ = result; | 1106 use_interval_ = result; |
| 1114 live_ranges().push_back(parent); | 1107 live_ranges().push_back(parent); |
| 1115 end_position_ = node->end(); | 1108 end_position_ = node->end(); |
| 1116 parent->SetSpillRange(this); | 1109 parent->SetSpillRange(this); |
| 1117 } | 1110 } |
| 1118 | 1111 |
| 1119 | 1112 |
| 1120 int SpillRange::ByteWidth() const { | 1113 int SpillRange::ByteWidth() const { |
| 1121 return GetByteWidth(live_ranges_[0]->machine_type()); | 1114 return GetByteWidth(live_ranges_[0]->representation()); |
| 1122 } | 1115 } |
| 1123 | 1116 |
| 1124 | 1117 |
| 1125 bool SpillRange::IsIntersectingWith(SpillRange* other) const { | 1118 bool SpillRange::IsIntersectingWith(SpillRange* other) const { |
| 1126 if (this->use_interval_ == nullptr || other->use_interval_ == nullptr || | 1119 if (this->use_interval_ == nullptr || other->use_interval_ == nullptr || |
| 1127 this->End() <= other->use_interval_->start() || | 1120 this->End() <= other->use_interval_->start() || |
| 1128 other->End() <= this->use_interval_->start()) { | 1121 other->End() <= this->use_interval_->start()) { |
| 1129 return false; | 1122 return false; |
| 1130 } | 1123 } |
| 1131 return AreUseIntervalsIntersecting(use_interval_, other->use_interval_); | 1124 return AreUseIntervalsIntersecting(use_interval_, other->use_interval_); |
| (...skipping 118 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1250 | 1243 |
| 1251 MoveOperands* RegisterAllocationData::AddGapMove( | 1244 MoveOperands* RegisterAllocationData::AddGapMove( |
| 1252 int index, Instruction::GapPosition position, | 1245 int index, Instruction::GapPosition position, |
| 1253 const InstructionOperand& from, const InstructionOperand& to) { | 1246 const InstructionOperand& from, const InstructionOperand& to) { |
| 1254 auto instr = code()->InstructionAt(index); | 1247 auto instr = code()->InstructionAt(index); |
| 1255 auto moves = instr->GetOrCreateParallelMove(position, code_zone()); | 1248 auto moves = instr->GetOrCreateParallelMove(position, code_zone()); |
| 1256 return moves->AddMove(from, to); | 1249 return moves->AddMove(from, to); |
| 1257 } | 1250 } |
| 1258 | 1251 |
| 1259 | 1252 |
| 1260 MachineType RegisterAllocationData::MachineTypeFor(int virtual_register) { | 1253 MachineRepresentation RegisterAllocationData::RepresentationFor( |
| 1254 int virtual_register) { |
| 1261 DCHECK_LT(virtual_register, code()->VirtualRegisterCount()); | 1255 DCHECK_LT(virtual_register, code()->VirtualRegisterCount()); |
| 1262 return code()->GetRepresentation(virtual_register); | 1256 return code()->GetRepresentation(virtual_register); |
| 1263 } | 1257 } |
| 1264 | 1258 |
| 1265 | 1259 |
| 1266 TopLevelLiveRange* RegisterAllocationData::GetOrCreateLiveRangeFor(int index) { | 1260 TopLevelLiveRange* RegisterAllocationData::GetOrCreateLiveRangeFor(int index) { |
| 1267 if (index >= static_cast<int>(live_ranges().size())) { | 1261 if (index >= static_cast<int>(live_ranges().size())) { |
| 1268 live_ranges().resize(index + 1, nullptr); | 1262 live_ranges().resize(index + 1, nullptr); |
| 1269 } | 1263 } |
| 1270 auto result = live_ranges()[index]; | 1264 auto result = live_ranges()[index]; |
| 1271 if (result == nullptr) { | 1265 if (result == nullptr) { |
| 1272 result = NewLiveRange(index, MachineTypeFor(index)); | 1266 result = NewLiveRange(index, RepresentationFor(index)); |
| 1273 live_ranges()[index] = result; | 1267 live_ranges()[index] = result; |
| 1274 } | 1268 } |
| 1275 return result; | 1269 return result; |
| 1276 } | 1270 } |
| 1277 | 1271 |
| 1278 | 1272 |
| 1279 TopLevelLiveRange* RegisterAllocationData::NewLiveRange( | 1273 TopLevelLiveRange* RegisterAllocationData::NewLiveRange( |
| 1280 int index, MachineType machine_type) { | 1274 int index, MachineRepresentation rep) { |
| 1281 return new (allocation_zone()) TopLevelLiveRange(index, machine_type); | 1275 return new (allocation_zone()) TopLevelLiveRange(index, rep); |
| 1282 } | 1276 } |
| 1283 | 1277 |
| 1284 | 1278 |
| 1285 int RegisterAllocationData::GetNextLiveRangeId() { | 1279 int RegisterAllocationData::GetNextLiveRangeId() { |
| 1286 int vreg = virtual_register_count_++; | 1280 int vreg = virtual_register_count_++; |
| 1287 if (vreg >= static_cast<int>(live_ranges().size())) { | 1281 if (vreg >= static_cast<int>(live_ranges().size())) { |
| 1288 live_ranges().resize(vreg + 1, nullptr); | 1282 live_ranges().resize(vreg + 1, nullptr); |
| 1289 } | 1283 } |
| 1290 return vreg; | 1284 return vreg; |
| 1291 } | 1285 } |
| 1292 | 1286 |
| 1293 | 1287 |
| 1294 TopLevelLiveRange* RegisterAllocationData::NextLiveRange( | 1288 TopLevelLiveRange* RegisterAllocationData::NextLiveRange( |
| 1295 MachineType machine_type) { | 1289 MachineRepresentation rep) { |
| 1296 int vreg = GetNextLiveRangeId(); | 1290 int vreg = GetNextLiveRangeId(); |
| 1297 TopLevelLiveRange* ret = NewLiveRange(vreg, machine_type); | 1291 TopLevelLiveRange* ret = NewLiveRange(vreg, rep); |
| 1298 return ret; | 1292 return ret; |
| 1299 } | 1293 } |
| 1300 | 1294 |
| 1301 | 1295 |
| 1302 RegisterAllocationData::PhiMapValue* RegisterAllocationData::InitializePhiMap( | 1296 RegisterAllocationData::PhiMapValue* RegisterAllocationData::InitializePhiMap( |
| 1303 const InstructionBlock* block, PhiInstruction* phi) { | 1297 const InstructionBlock* block, PhiInstruction* phi) { |
| 1304 auto map_value = new (allocation_zone()) | 1298 auto map_value = new (allocation_zone()) |
| 1305 RegisterAllocationData::PhiMapValue(phi, block, allocation_zone()); | 1299 RegisterAllocationData::PhiMapValue(phi, block, allocation_zone()); |
| 1306 auto res = | 1300 auto res = |
| 1307 phi_map_.insert(std::make_pair(phi->virtual_register(), map_value)); | 1301 phi_map_.insert(std::make_pair(phi->virtual_register(), map_value)); |
| (...skipping 186 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1494 | 1488 |
| 1495 ConstraintBuilder::ConstraintBuilder(RegisterAllocationData* data) | 1489 ConstraintBuilder::ConstraintBuilder(RegisterAllocationData* data) |
| 1496 : data_(data) {} | 1490 : data_(data) {} |
| 1497 | 1491 |
| 1498 | 1492 |
| 1499 InstructionOperand* ConstraintBuilder::AllocateFixed( | 1493 InstructionOperand* ConstraintBuilder::AllocateFixed( |
| 1500 UnallocatedOperand* operand, int pos, bool is_tagged) { | 1494 UnallocatedOperand* operand, int pos, bool is_tagged) { |
| 1501 TRACE("Allocating fixed reg for op %d\n", operand->virtual_register()); | 1495 TRACE("Allocating fixed reg for op %d\n", operand->virtual_register()); |
| 1502 DCHECK(operand->HasFixedPolicy()); | 1496 DCHECK(operand->HasFixedPolicy()); |
| 1503 InstructionOperand allocated; | 1497 InstructionOperand allocated; |
| 1504 MachineType machine_type = InstructionSequence::DefaultRepresentation(); | 1498 MachineRepresentation rep = InstructionSequence::DefaultRepresentation(); |
| 1505 int virtual_register = operand->virtual_register(); | 1499 int virtual_register = operand->virtual_register(); |
| 1506 if (virtual_register != InstructionOperand::kInvalidVirtualRegister) { | 1500 if (virtual_register != InstructionOperand::kInvalidVirtualRegister) { |
| 1507 machine_type = data()->MachineTypeFor(virtual_register); | 1501 rep = data()->RepresentationFor(virtual_register); |
| 1508 } | 1502 } |
| 1509 if (operand->HasFixedSlotPolicy()) { | 1503 if (operand->HasFixedSlotPolicy()) { |
| 1510 allocated = AllocatedOperand(AllocatedOperand::STACK_SLOT, machine_type, | 1504 allocated = AllocatedOperand(AllocatedOperand::STACK_SLOT, rep, |
| 1511 operand->fixed_slot_index()); | 1505 operand->fixed_slot_index()); |
| 1512 } else if (operand->HasFixedRegisterPolicy()) { | 1506 } else if (operand->HasFixedRegisterPolicy()) { |
| 1513 DCHECK(!IsFloatingPoint(machine_type)); | 1507 DCHECK(!IsFloatingPoint(rep)); |
| 1514 allocated = AllocatedOperand(AllocatedOperand::REGISTER, machine_type, | 1508 allocated = AllocatedOperand(AllocatedOperand::REGISTER, rep, |
| 1515 operand->fixed_register_index()); | 1509 operand->fixed_register_index()); |
| 1516 } else if (operand->HasFixedDoubleRegisterPolicy()) { | 1510 } else if (operand->HasFixedDoubleRegisterPolicy()) { |
| 1517 DCHECK(IsFloatingPoint(machine_type)); | 1511 DCHECK(IsFloatingPoint(rep)); |
| 1518 DCHECK_NE(InstructionOperand::kInvalidVirtualRegister, virtual_register); | 1512 DCHECK_NE(InstructionOperand::kInvalidVirtualRegister, virtual_register); |
| 1519 allocated = AllocatedOperand(AllocatedOperand::REGISTER, machine_type, | 1513 allocated = AllocatedOperand(AllocatedOperand::REGISTER, rep, |
| 1520 operand->fixed_register_index()); | 1514 operand->fixed_register_index()); |
| 1521 } else { | 1515 } else { |
| 1522 UNREACHABLE(); | 1516 UNREACHABLE(); |
| 1523 } | 1517 } |
| 1524 InstructionOperand::ReplaceWith(operand, &allocated); | 1518 InstructionOperand::ReplaceWith(operand, &allocated); |
| 1525 if (is_tagged) { | 1519 if (is_tagged) { |
| 1526 TRACE("Fixed reg is tagged at %d\n", pos); | 1520 TRACE("Fixed reg is tagged at %d\n", pos); |
| 1527 auto instr = code()->InstructionAt(pos); | 1521 auto instr = code()->InstructionAt(pos); |
| 1528 if (instr->HasReferenceMap()) { | 1522 if (instr->HasReferenceMap()) { |
| 1529 instr->reference_map()->RecordReference(*AllocatedOperand::cast(operand)); | 1523 instr->reference_map()->RecordReference(*AllocatedOperand::cast(operand)); |
| (...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1621 data()->GetOrCreateLiveRangeFor(first_output->virtual_register()); | 1615 data()->GetOrCreateLiveRangeFor(first_output->virtual_register()); |
| 1622 bool assigned = false; | 1616 bool assigned = false; |
| 1623 if (first_output->HasFixedPolicy()) { | 1617 if (first_output->HasFixedPolicy()) { |
| 1624 int output_vreg = first_output->virtual_register(); | 1618 int output_vreg = first_output->virtual_register(); |
| 1625 UnallocatedOperand output_copy(UnallocatedOperand::ANY, output_vreg); | 1619 UnallocatedOperand output_copy(UnallocatedOperand::ANY, output_vreg); |
| 1626 bool is_tagged = code()->IsReference(output_vreg); | 1620 bool is_tagged = code()->IsReference(output_vreg); |
| 1627 if (first_output->HasSecondaryStorage()) { | 1621 if (first_output->HasSecondaryStorage()) { |
| 1628 range->MarkHasPreassignedSlot(); | 1622 range->MarkHasPreassignedSlot(); |
| 1629 InstructionOperand* spill_op = AllocatedOperand::New( | 1623 InstructionOperand* spill_op = AllocatedOperand::New( |
| 1630 data()->code_zone(), LocationOperand::LocationKind::STACK_SLOT, | 1624 data()->code_zone(), LocationOperand::LocationKind::STACK_SLOT, |
| 1631 range->machine_type(), first_output->GetSecondaryStorage()); | 1625 range->representation(), first_output->GetSecondaryStorage()); |
| 1632 range->RecordSpillLocation(allocation_zone(), instr_index + 1, | 1626 range->RecordSpillLocation(allocation_zone(), instr_index + 1, |
| 1633 first_output); | 1627 first_output); |
| 1634 range->SetSpillOperand(spill_op); | 1628 range->SetSpillOperand(spill_op); |
| 1635 range->SetSpillStartIndex(instr_index + 1); | 1629 range->SetSpillStartIndex(instr_index + 1); |
| 1636 assigned = true; | 1630 assigned = true; |
| 1637 } | 1631 } |
| 1638 AllocateFixed(first_output, instr_index, is_tagged); | 1632 AllocateFixed(first_output, instr_index, is_tagged); |
| 1639 | 1633 |
| 1640 // This value is produced on the stack, we never need to spill it. | 1634 // This value is produced on the stack, we never need to spill it. |
| 1641 if (first_output->IsStackSlot()) { | 1635 if (first_output->IsStackSlot()) { |
| (...skipping 178 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1820 data()->fixed_live_ranges()[index] = result; | 1814 data()->fixed_live_ranges()[index] = result; |
| 1821 } | 1815 } |
| 1822 return result; | 1816 return result; |
| 1823 } | 1817 } |
| 1824 | 1818 |
| 1825 | 1819 |
| 1826 TopLevelLiveRange* LiveRangeBuilder::FixedDoubleLiveRangeFor(int index) { | 1820 TopLevelLiveRange* LiveRangeBuilder::FixedDoubleLiveRangeFor(int index) { |
| 1827 DCHECK(index < config()->num_double_registers()); | 1821 DCHECK(index < config()->num_double_registers()); |
| 1828 auto result = data()->fixed_double_live_ranges()[index]; | 1822 auto result = data()->fixed_double_live_ranges()[index]; |
| 1829 if (result == nullptr) { | 1823 if (result == nullptr) { |
| 1830 result = data()->NewLiveRange(FixedDoubleLiveRangeID(index), kRepFloat64); | 1824 result = data()->NewLiveRange(FixedDoubleLiveRangeID(index), |
| 1825 MachineRepresentation::kFloat64); |
| 1831 DCHECK(result->IsFixed()); | 1826 DCHECK(result->IsFixed()); |
| 1832 result->set_assigned_register(index); | 1827 result->set_assigned_register(index); |
| 1833 data()->MarkAllocated(DOUBLE_REGISTERS, index); | 1828 data()->MarkAllocated(DOUBLE_REGISTERS, index); |
| 1834 data()->fixed_double_live_ranges()[index] = result; | 1829 data()->fixed_double_live_ranges()[index] = result; |
| 1835 } | 1830 } |
| 1836 return result; | 1831 return result; |
| 1837 } | 1832 } |
| 1838 | 1833 |
| 1839 | 1834 |
| 1840 TopLevelLiveRange* LiveRangeBuilder::LiveRangeFor(InstructionOperand* operand) { | 1835 TopLevelLiveRange* LiveRangeBuilder::LiveRangeFor(InstructionOperand* operand) { |
| (...skipping 1252 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3093 InstructionOperand spill_operand; | 3088 InstructionOperand spill_operand; |
| 3094 if (((range->HasSpillOperand() && | 3089 if (((range->HasSpillOperand() && |
| 3095 !range->GetSpillOperand()->IsConstant()) || | 3090 !range->GetSpillOperand()->IsConstant()) || |
| 3096 range->HasSpillRange())) { | 3091 range->HasSpillRange())) { |
| 3097 if (range->HasSpillOperand()) { | 3092 if (range->HasSpillOperand()) { |
| 3098 spill_operand = *range->GetSpillOperand(); | 3093 spill_operand = *range->GetSpillOperand(); |
| 3099 } else { | 3094 } else { |
| 3100 spill_operand = range->GetSpillRangeOperand(); | 3095 spill_operand = range->GetSpillRangeOperand(); |
| 3101 } | 3096 } |
| 3102 DCHECK(spill_operand.IsStackSlot()); | 3097 DCHECK(spill_operand.IsStackSlot()); |
| 3103 DCHECK_EQ(kRepTagged, | 3098 DCHECK_EQ(MachineRepresentation::kTagged, |
| 3104 AllocatedOperand::cast(spill_operand).machine_type()); | 3099 AllocatedOperand::cast(spill_operand).representation()); |
| 3105 } | 3100 } |
| 3106 | 3101 |
| 3107 // Step through the safe points to see whether they are in the range. | 3102 // Step through the safe points to see whether they are in the range. |
| 3108 for (auto it = first_it; it != reference_maps->end(); ++it) { | 3103 for (auto it = first_it; it != reference_maps->end(); ++it) { |
| 3109 auto map = *it; | 3104 auto map = *it; |
| 3110 int safe_point = map->instruction_position(); | 3105 int safe_point = map->instruction_position(); |
| 3111 | 3106 |
| 3112 // The safe points are sorted so we can stop searching here. | 3107 // The safe points are sorted so we can stop searching here. |
| 3113 if (safe_point - 1 > end) break; | 3108 if (safe_point - 1 > end) break; |
| 3114 | 3109 |
| (...skipping 20 matching lines...) Expand all Loading... |
| 3135 } | 3130 } |
| 3136 | 3131 |
| 3137 if (!cur->spilled()) { | 3132 if (!cur->spilled()) { |
| 3138 TRACE( | 3133 TRACE( |
| 3139 "Pointer in register for range %d:%d (start at %d) " | 3134 "Pointer in register for range %d:%d (start at %d) " |
| 3140 "at safe point %d\n", | 3135 "at safe point %d\n", |
| 3141 range->vreg(), cur->relative_id(), cur->Start().value(), | 3136 range->vreg(), cur->relative_id(), cur->Start().value(), |
| 3142 safe_point); | 3137 safe_point); |
| 3143 auto operand = cur->GetAssignedOperand(); | 3138 auto operand = cur->GetAssignedOperand(); |
| 3144 DCHECK(!operand.IsStackSlot()); | 3139 DCHECK(!operand.IsStackSlot()); |
| 3145 DCHECK_EQ(kRepTagged, AllocatedOperand::cast(operand).machine_type()); | 3140 DCHECK_EQ(MachineRepresentation::kTagged, |
| 3141 AllocatedOperand::cast(operand).representation()); |
| 3146 map->RecordReference(AllocatedOperand::cast(operand)); | 3142 map->RecordReference(AllocatedOperand::cast(operand)); |
| 3147 } | 3143 } |
| 3148 } | 3144 } |
| 3149 } | 3145 } |
| 3150 } | 3146 } |
| 3151 | 3147 |
| 3152 | 3148 |
| 3153 namespace { | 3149 namespace { |
| 3154 | 3150 |
| 3155 class LiveRangeBound { | 3151 class LiveRangeBound { |
| (...skipping 289 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3445 auto eliminate = moves->PrepareInsertAfter(move); | 3441 auto eliminate = moves->PrepareInsertAfter(move); |
| 3446 to_insert.push_back(move); | 3442 to_insert.push_back(move); |
| 3447 if (eliminate != nullptr) to_eliminate.push_back(eliminate); | 3443 if (eliminate != nullptr) to_eliminate.push_back(eliminate); |
| 3448 } | 3444 } |
| 3449 } | 3445 } |
| 3450 | 3446 |
| 3451 | 3447 |
| 3452 } // namespace compiler | 3448 } // namespace compiler |
| 3453 } // namespace internal | 3449 } // namespace internal |
| 3454 } // namespace v8 | 3450 } // namespace v8 |
| OLD | NEW |