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 235 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
246 | 246 |
247 LiveRange::LiveRange(int id, MachineType machine_type) | 247 LiveRange::LiveRange(int id, MachineType machine_type) |
248 : id_(id), | 248 : id_(id), |
249 spill_start_index_(kMaxInt), | 249 spill_start_index_(kMaxInt), |
250 bits_(0), | 250 bits_(0), |
251 last_interval_(nullptr), | 251 last_interval_(nullptr), |
252 first_interval_(nullptr), | 252 first_interval_(nullptr), |
253 first_pos_(nullptr), | 253 first_pos_(nullptr), |
254 parent_(nullptr), | 254 parent_(nullptr), |
255 next_(nullptr), | 255 next_(nullptr), |
256 splintered_from_(nullptr), | |
256 spill_operand_(nullptr), | 257 spill_operand_(nullptr), |
257 spills_at_definition_(nullptr), | 258 spills_at_definition_(nullptr), |
258 current_interval_(nullptr), | 259 current_interval_(nullptr), |
259 last_processed_use_(nullptr), | 260 last_processed_use_(nullptr), |
260 current_hint_position_(nullptr), | 261 current_hint_position_(nullptr), |
261 size_(kInvalidSize), | 262 size_(kInvalidSize), |
262 weight_(kInvalidWeight), | 263 weight_(kInvalidWeight), |
263 spilled_in_deferred_block_(false) { | 264 spilled_in_deferred_block_(false) { |
264 DCHECK(AllocatedOperand::IsSupportedMachineType(machine_type)); | 265 DCHECK(AllocatedOperand::IsSupportedMachineType(machine_type)); |
265 bits_ = SpillTypeField::encode(SpillType::kNoSpillType) | | 266 bits_ = SpillTypeField::encode(SpillType::kNoSpillType) | |
(...skipping 174 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
440 | 441 |
441 void LiveRange::SetSpillOperand(InstructionOperand* operand) { | 442 void LiveRange::SetSpillOperand(InstructionOperand* operand) { |
442 DCHECK(HasNoSpillType()); | 443 DCHECK(HasNoSpillType()); |
443 DCHECK(!operand->IsUnallocated() && !operand->IsImmediate()); | 444 DCHECK(!operand->IsUnallocated() && !operand->IsImmediate()); |
444 set_spill_type(SpillType::kSpillOperand); | 445 set_spill_type(SpillType::kSpillOperand); |
445 spill_operand_ = operand; | 446 spill_operand_ = operand; |
446 } | 447 } |
447 | 448 |
448 | 449 |
449 void LiveRange::SetSpillRange(SpillRange* spill_range) { | 450 void LiveRange::SetSpillRange(SpillRange* spill_range) { |
450 DCHECK(HasNoSpillType() || HasSpillRange()); | 451 DCHECK(!HasSpillOperand()); |
451 DCHECK(spill_range); | 452 DCHECK(spill_range); |
452 set_spill_type(SpillType::kSpillRange); | 453 DCHECK(!IsChild()); |
453 spill_range_ = spill_range; | 454 spill_range_ = spill_range; |
454 } | 455 } |
455 | 456 |
456 | 457 |
457 UsePosition* LiveRange::NextUsePosition(LifetimePosition start) const { | 458 UsePosition* LiveRange::NextUsePosition(LifetimePosition start) const { |
458 UsePosition* use_pos = last_processed_use_; | 459 UsePosition* use_pos = last_processed_use_; |
459 if (use_pos == nullptr || use_pos->pos() > start) { | 460 if (use_pos == nullptr || use_pos->pos() > start) { |
460 use_pos = first_pos(); | 461 use_pos = first_pos(); |
461 } | 462 } |
462 while (use_pos != nullptr && use_pos->pos() < start) { | 463 while (use_pos != nullptr && use_pos->pos() < start) { |
(...skipping 198 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
661 // invalid at construction. | 662 // invalid at construction. |
662 size_ = kInvalidSize; | 663 size_ = kInvalidSize; |
663 weight_ = kInvalidWeight; | 664 weight_ = kInvalidWeight; |
664 #ifdef DEBUG | 665 #ifdef DEBUG |
665 Verify(); | 666 Verify(); |
666 result->Verify(); | 667 result->Verify(); |
667 #endif | 668 #endif |
668 } | 669 } |
669 | 670 |
670 | 671 |
672 void LiveRange::Splinter(LifetimePosition start, LifetimePosition end, | |
673 LiveRange* result, Zone* zone) { | |
674 DCHECK(start != Start() || end != End()); | |
675 DCHECK(start < end); | |
676 | |
677 result->set_spill_type(spill_type()); | |
678 | |
679 if (start <= Start()) { | |
680 DCHECK(end < End()); | |
681 SplitAt(end, result, zone); | |
682 next_ = nullptr; | |
683 } else if (end >= End()) { | |
684 DCHECK(start > Start()); | |
685 SplitAt(start, result, zone); | |
686 next_ = nullptr; | |
687 } else { | |
688 DCHECK(start < End() && Start() < end); | |
689 | |
690 const int kInvalidId = std::numeric_limits<int>::max(); | |
691 | |
692 SplitAt(start, result, zone); | |
693 | |
694 LiveRange end_part(kInvalidId, this->machine_type()); | |
695 result->SplitAt(end, &end_part, zone); | |
696 | |
697 next_ = end_part.next_; | |
698 last_interval_->set_next(end_part.first_interval_); | |
699 last_interval_ = end_part.last_interval_; | |
700 | |
701 | |
702 if (first_pos_ == nullptr) { | |
703 first_pos_ = end_part.first_pos_; | |
704 } else { | |
705 UsePosition* pos = first_pos_; | |
706 for (; pos->next() != nullptr; pos = pos->next()) { | |
707 } | |
708 pos->set_next(end_part.first_pos_); | |
709 } | |
710 } | |
711 result->next_ = nullptr; | |
712 result->parent_ = nullptr; | |
713 | |
714 result->SetSplinteredFrom(this); | |
715 } | |
716 | |
717 | |
718 void LiveRange::SetSplinteredFrom(LiveRange* splinter_parent) { | |
719 // The splinter parent is always the original "Top". | |
720 DCHECK(splinter_parent->Start() < Start() && !splinter_parent->IsChild()); | |
Benedikt Meurer
2015/08/24 04:33:26
Use separate DCHECKs here instead of &&.
Mircea Trofin
2015/08/24 20:55:10
Done.
| |
721 | |
722 splintered_from_ = splinter_parent; | |
723 if (!HasSpillOperand()) { | |
724 SetSpillRange(splinter_parent->spill_range_); | |
725 } | |
726 } | |
727 | |
728 | |
729 void LiveRange::AppendChild(LiveRange* other) { | |
730 DCHECK(!other->IsChild()); | |
731 next_ = other; | |
732 | |
733 other->UpdateParentForAllChildren(TopLevel()); | |
734 TopLevel()->UpdateSpillRangePostMerge(other); | |
735 } | |
736 | |
737 | |
738 void LiveRange::UpdateSpillRangePostMerge(LiveRange* merged) { | |
739 DCHECK(!IsChild()); | |
740 DCHECK(merged->TopLevel() == this); | |
741 | |
742 if (HasNoSpillType() && merged->HasSpillRange()) { | |
743 set_spill_type(merged->spill_type()); | |
744 DCHECK(GetSpillRange()->live_ranges().size() > 0); | |
745 merged->spill_range_ = nullptr; | |
746 merged->bits_ = SpillTypeField::update(merged->bits_, | |
747 LiveRange::SpillType::kNoSpillType); | |
748 } | |
749 } | |
750 | |
751 | |
752 void LiveRange::UpdateParentForAllChildren(LiveRange* new_parent) { | |
753 LiveRange* child = this; | |
754 for (; child != nullptr; child = child->next()) { | |
755 child->parent_ = new_parent; | |
756 } | |
757 } | |
758 | |
759 | |
760 LiveRange* LiveRange::GetLastChild() { | |
761 LiveRange* ret = this; | |
762 for (; ret->next() != nullptr; ret = ret->next()) { | |
763 } | |
764 return ret; | |
765 } | |
766 | |
767 | |
768 void LiveRange::Merge(LiveRange* other, RegisterAllocationData* data) { | |
769 DCHECK(!IsChild()); | |
770 DCHECK(!other->IsChild()); | |
771 DCHECK(Start() < other->Start()); | |
772 | |
773 LiveRange* last_other = other->GetLastChild(); | |
774 LiveRange* last_me = GetLastChild(); | |
775 | |
776 // Simple case: we just append at the end. | |
777 if (last_me->End() <= other->Start()) return last_me->AppendChild(other); | |
778 | |
779 DCHECK(last_me->End() > last_other->End()); | |
780 | |
781 // In the more general case, we need to find the ranges between which to | |
782 // insert. | |
783 LiveRange* insertion_point = this; | |
784 for (; insertion_point->next() != nullptr && | |
785 insertion_point->next()->Start() <= other->Start(); | |
786 insertion_point = insertion_point->next()) { | |
787 } | |
788 | |
789 // When we splintered the original range, we reconstituted the original range | |
790 // into one range without children, but with discontinuities. To merge the | |
791 // splinter back in, we need to split the range - or a child obtained after | |
792 // register allocation splitting. | |
793 LiveRange* after = insertion_point->next(); | |
794 if (insertion_point->End() > other->Start()) { | |
795 LiveRange* new_after = data->NewChildRangeFor(insertion_point); | |
796 insertion_point->SplitAt(other->Start(), new_after, | |
797 data->allocation_zone()); | |
798 new_after->set_spilled(insertion_point->spilled()); | |
799 if (!new_after->spilled()) | |
800 new_after->set_assigned_register(insertion_point->assigned_register()); | |
801 after = new_after; | |
802 } | |
803 | |
804 last_other->next_ = after; | |
805 insertion_point->next_ = other; | |
806 other->UpdateParentForAllChildren(TopLevel()); | |
807 TopLevel()->UpdateSpillRangePostMerge(other); | |
808 } | |
809 | |
810 | |
671 // This implements an ordering on live ranges so that they are ordered by their | 811 // This implements an ordering on live ranges so that they are ordered by their |
672 // start positions. This is needed for the correctness of the register | 812 // start positions. This is needed for the correctness of the register |
673 // allocation algorithm. If two live ranges start at the same offset then there | 813 // allocation algorithm. If two live ranges start at the same offset then there |
674 // is a tie breaker based on where the value is first used. This part of the | 814 // is a tie breaker based on where the value is first used. This part of the |
675 // ordering is merely a heuristic. | 815 // ordering is merely a heuristic. |
676 bool LiveRange::ShouldBeAllocatedBefore(const LiveRange* other) const { | 816 bool LiveRange::ShouldBeAllocatedBefore(const LiveRange* other) const { |
677 LifetimePosition start = Start(); | 817 LifetimePosition start = Start(); |
678 LifetimePosition other_start = other->Start(); | 818 LifetimePosition other_start = other->Start(); |
679 if (start == other_start) { | 819 if (start == other_start) { |
680 UsePosition* pos = first_pos(); | 820 UsePosition* pos = first_pos(); |
(...skipping 225 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
906 os << '[' << interval->start() << ", " << interval->end() << ')' | 1046 os << '[' << interval->start() << ", " << interval->end() << ')' |
907 << std::endl; | 1047 << std::endl; |
908 interval = interval->next(); | 1048 interval = interval->next(); |
909 } | 1049 } |
910 os << "}"; | 1050 os << "}"; |
911 return os; | 1051 return os; |
912 } | 1052 } |
913 | 1053 |
914 | 1054 |
915 SpillRange::SpillRange(LiveRange* parent, Zone* zone) | 1055 SpillRange::SpillRange(LiveRange* parent, Zone* zone) |
916 : live_ranges_(zone), assigned_slot_(kUnassignedSlot) { | 1056 : live_ranges_(zone), |
1057 assigned_slot_(kUnassignedSlot), | |
1058 byte_width_(GetByteWidth(parent->machine_type())), | |
1059 kind_(parent->kind()) { | |
1060 // Spill ranges are created for top level, non-splintered ranges. This is so | |
1061 // that, when merging decisions are made, we consider the full extent of the | |
1062 // virtual register, and avoid clobbering it. | |
917 DCHECK(!parent->IsChild()); | 1063 DCHECK(!parent->IsChild()); |
1064 DCHECK(!parent->IsSplinter()); | |
918 UseInterval* result = nullptr; | 1065 UseInterval* result = nullptr; |
919 UseInterval* node = nullptr; | 1066 UseInterval* node = nullptr; |
920 // Copy the intervals for all ranges. | 1067 // Copy the intervals for all ranges. |
921 for (auto range = parent; range != nullptr; range = range->next()) { | 1068 for (auto range = parent; range != nullptr; range = range->next()) { |
922 auto src = range->first_interval(); | 1069 auto src = range->first_interval(); |
923 while (src != nullptr) { | 1070 while (src != nullptr) { |
924 auto new_node = new (zone) UseInterval(src->start(), src->end()); | 1071 auto new_node = new (zone) UseInterval(src->start(), src->end()); |
925 if (result == nullptr) { | 1072 if (result == nullptr) { |
926 result = new_node; | 1073 result = new_node; |
927 } else { | 1074 } else { |
928 node->set_next(new_node); | 1075 node->set_next(new_node); |
929 } | 1076 } |
930 node = new_node; | 1077 node = new_node; |
931 src = src->next(); | 1078 src = src->next(); |
932 } | 1079 } |
933 } | 1080 } |
934 use_interval_ = result; | 1081 use_interval_ = result; |
935 live_ranges().push_back(parent); | 1082 live_ranges().push_back(parent); |
936 end_position_ = node->end(); | 1083 end_position_ = node->end(); |
937 DCHECK(!parent->HasSpillRange()); | |
938 parent->SetSpillRange(this); | 1084 parent->SetSpillRange(this); |
939 } | 1085 } |
940 | 1086 |
941 | 1087 |
942 int SpillRange::ByteWidth() const { | 1088 int SpillRange::ByteWidth() const { |
943 return GetByteWidth(live_ranges_[0]->machine_type()); | 1089 return GetByteWidth(live_ranges_[0]->machine_type()); |
944 } | 1090 } |
945 | 1091 |
946 | 1092 |
947 bool SpillRange::IsIntersectingWith(SpillRange* other) const { | 1093 bool SpillRange::IsIntersectingWith(SpillRange* other) const { |
(...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1049 allocation_zone()), | 1195 allocation_zone()), |
1050 spill_ranges_(allocation_zone()), | 1196 spill_ranges_(allocation_zone()), |
1051 delayed_references_(allocation_zone()), | 1197 delayed_references_(allocation_zone()), |
1052 assigned_registers_(nullptr), | 1198 assigned_registers_(nullptr), |
1053 assigned_double_registers_(nullptr), | 1199 assigned_double_registers_(nullptr), |
1054 virtual_register_count_(code->VirtualRegisterCount()) { | 1200 virtual_register_count_(code->VirtualRegisterCount()) { |
1055 DCHECK(this->config()->num_general_registers() <= | 1201 DCHECK(this->config()->num_general_registers() <= |
1056 RegisterConfiguration::kMaxGeneralRegisters); | 1202 RegisterConfiguration::kMaxGeneralRegisters); |
1057 DCHECK(this->config()->num_double_registers() <= | 1203 DCHECK(this->config()->num_double_registers() <= |
1058 RegisterConfiguration::kMaxDoubleRegisters); | 1204 RegisterConfiguration::kMaxDoubleRegisters); |
1059 spill_ranges().reserve(8); | |
1060 assigned_registers_ = new (code_zone()) | 1205 assigned_registers_ = new (code_zone()) |
1061 BitVector(this->config()->num_general_registers(), code_zone()); | 1206 BitVector(this->config()->num_general_registers(), code_zone()); |
1062 assigned_double_registers_ = new (code_zone()) | 1207 assigned_double_registers_ = new (code_zone()) |
1063 BitVector(this->config()->num_aliased_double_registers(), code_zone()); | 1208 BitVector(this->config()->num_aliased_double_registers(), code_zone()); |
1064 this->frame()->SetAllocatedRegisters(assigned_registers_); | 1209 this->frame()->SetAllocatedRegisters(assigned_registers_); |
1065 this->frame()->SetAllocatedDoubleRegisters(assigned_double_registers_); | 1210 this->frame()->SetAllocatedDoubleRegisters(assigned_double_registers_); |
1066 } | 1211 } |
1067 | 1212 |
1068 | 1213 |
1069 MoveOperands* RegisterAllocationData::AddGapMove( | 1214 MoveOperands* RegisterAllocationData::AddGapMove( |
(...skipping 23 matching lines...) Expand all Loading... | |
1093 return result; | 1238 return result; |
1094 } | 1239 } |
1095 | 1240 |
1096 | 1241 |
1097 LiveRange* RegisterAllocationData::NewLiveRange(int index, | 1242 LiveRange* RegisterAllocationData::NewLiveRange(int index, |
1098 MachineType machine_type) { | 1243 MachineType machine_type) { |
1099 return new (allocation_zone()) LiveRange(index, machine_type); | 1244 return new (allocation_zone()) LiveRange(index, machine_type); |
1100 } | 1245 } |
1101 | 1246 |
1102 | 1247 |
1248 LiveRange* RegisterAllocationData::NextLiveRange(MachineType machine_type) { | |
1249 int vreg = virtual_register_count_++; | |
1250 if (vreg >= static_cast<int>(live_ranges().size())) { | |
1251 live_ranges().resize(vreg + 1, nullptr); | |
1252 } | |
1253 LiveRange* ret = NewLiveRange(vreg, machine_type); | |
1254 return ret; | |
1255 } | |
1256 | |
1257 | |
1103 LiveRange* RegisterAllocationData::NewChildRangeFor(LiveRange* range) { | 1258 LiveRange* RegisterAllocationData::NewChildRangeFor(LiveRange* range) { |
1104 int vreg = virtual_register_count_++; | 1259 auto child = NextLiveRange(range->machine_type()); |
1105 if (vreg >= static_cast<int>(live_ranges().size())) { | 1260 DCHECK_NULL(live_ranges()[child->id()]); |
1106 live_ranges().resize(vreg + 1, nullptr); | 1261 live_ranges()[child->id()] = child; |
1107 } | |
1108 auto child = new (allocation_zone()) LiveRange(vreg, range->machine_type()); | |
1109 DCHECK_NULL(live_ranges()[vreg]); | |
1110 live_ranges()[vreg] = child; | |
1111 return child; | 1262 return child; |
1112 } | 1263 } |
1113 | 1264 |
1114 | 1265 |
1115 RegisterAllocationData::PhiMapValue* RegisterAllocationData::InitializePhiMap( | 1266 RegisterAllocationData::PhiMapValue* RegisterAllocationData::InitializePhiMap( |
1116 const InstructionBlock* block, PhiInstruction* phi) { | 1267 const InstructionBlock* block, PhiInstruction* phi) { |
1117 auto map_value = new (allocation_zone()) | 1268 auto map_value = new (allocation_zone()) |
1118 RegisterAllocationData::PhiMapValue(phi, block, allocation_zone()); | 1269 RegisterAllocationData::PhiMapValue(phi, block, allocation_zone()); |
1119 auto res = | 1270 auto res = |
1120 phi_map_.insert(std::make_pair(phi->virtual_register(), map_value)); | 1271 phi_map_.insert(std::make_pair(phi->virtual_register(), map_value)); |
(...skipping 27 matching lines...) Expand all Loading... | |
1148 PrintF(" (function: %s)\n", debug_name()); | 1299 PrintF(" (function: %s)\n", debug_name()); |
1149 } | 1300 } |
1150 iterator.Advance(); | 1301 iterator.Advance(); |
1151 } | 1302 } |
1152 return found; | 1303 return found; |
1153 } | 1304 } |
1154 | 1305 |
1155 | 1306 |
1156 SpillRange* RegisterAllocationData::AssignSpillRangeToLiveRange( | 1307 SpillRange* RegisterAllocationData::AssignSpillRangeToLiveRange( |
1157 LiveRange* range) { | 1308 LiveRange* range) { |
1158 auto spill_range = | 1309 DCHECK(!range->IsChild()); |
1159 new (allocation_zone()) SpillRange(range, allocation_zone()); | 1310 DCHECK(!range->HasSpillOperand()); |
1160 spill_ranges().push_back(spill_range); | 1311 |
1312 SpillRange* spill_range = range->GetAllocatedSpillRange(); | |
1313 if (spill_range == nullptr) { | |
1314 DCHECK(!range->IsSplinter()); | |
1315 spill_range = new (allocation_zone()) SpillRange(range, allocation_zone()); | |
1316 } | |
1317 range->set_spill_type(LiveRange::SpillType::kSpillRange); | |
1318 | |
1319 spill_ranges().insert(spill_range); | |
1161 return spill_range; | 1320 return spill_range; |
1162 } | 1321 } |
1163 | 1322 |
1323 | |
1324 SpillRange* RegisterAllocationData::CreateSpillRangeForLiveRange( | |
1325 LiveRange* range) { | |
1326 DCHECK(!range->HasSpillOperand()); | |
1327 DCHECK(!range->IsChild()); | |
1328 DCHECK(!range->IsSplinter()); | |
1329 auto spill_range = | |
1330 new (allocation_zone()) SpillRange(range, allocation_zone()); | |
1331 return spill_range; | |
1332 } | |
1333 | |
1164 | 1334 |
1165 void RegisterAllocationData::MarkAllocated(RegisterKind kind, int index) { | 1335 void RegisterAllocationData::MarkAllocated(RegisterKind kind, int index) { |
1166 if (kind == DOUBLE_REGISTERS) { | 1336 if (kind == DOUBLE_REGISTERS) { |
1167 assigned_double_registers_->Add(index); | 1337 assigned_double_registers_->Add(index); |
1168 } else { | 1338 } else { |
1169 DCHECK(kind == GENERAL_REGISTERS); | 1339 DCHECK(kind == GENERAL_REGISTERS); |
1170 assigned_registers_->Add(index); | 1340 assigned_registers_->Add(index); |
1171 } | 1341 } |
1172 } | 1342 } |
1173 | 1343 |
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1223 OFStream os(stdout); | 1393 OFStream os(stdout); |
1224 PrintableInstructionOperand wrapper; | 1394 PrintableInstructionOperand wrapper; |
1225 wrapper.register_configuration_ = config(); | 1395 wrapper.register_configuration_ = config(); |
1226 wrapper.op_ = move->destination(); | 1396 wrapper.op_ = move->destination(); |
1227 os << wrapper << " = "; | 1397 os << wrapper << " = "; |
1228 wrapper.op_ = move->source(); | 1398 wrapper.op_ = move->source(); |
1229 os << wrapper << std::endl; | 1399 os << wrapper << std::endl; |
1230 } | 1400 } |
1231 | 1401 |
1232 | 1402 |
1403 void RegisterAllocationData::Print(const SpillRange* spill_range) { | |
1404 OFStream os(stdout); | |
1405 os << "{" << std::endl; | |
1406 for (LiveRange* range : spill_range->live_ranges()) { | |
1407 os << range->id() << " "; | |
1408 } | |
1409 os << std::endl; | |
1410 | |
1411 for (UseInterval* interval = spill_range->interval(); interval != nullptr; | |
1412 interval = interval->next()) { | |
1413 os << '[' << interval->start() << ", " << interval->end() << ')' | |
1414 << std::endl; | |
1415 } | |
1416 os << "}" << std::endl; | |
1417 } | |
1418 | |
1419 | |
1233 ConstraintBuilder::ConstraintBuilder(RegisterAllocationData* data) | 1420 ConstraintBuilder::ConstraintBuilder(RegisterAllocationData* data) |
1234 : data_(data) {} | 1421 : data_(data) {} |
1235 | 1422 |
1236 | 1423 |
1237 InstructionOperand* ConstraintBuilder::AllocateFixed( | 1424 InstructionOperand* ConstraintBuilder::AllocateFixed( |
1238 UnallocatedOperand* operand, int pos, bool is_tagged) { | 1425 UnallocatedOperand* operand, int pos, bool is_tagged) { |
1239 TRACE("Allocating fixed reg for op %d\n", operand->virtual_register()); | 1426 TRACE("Allocating fixed reg for op %d\n", operand->virtual_register()); |
1240 DCHECK(operand->HasFixedPolicy()); | 1427 DCHECK(operand->HasFixedPolicy()); |
1241 InstructionOperand allocated; | 1428 InstructionOperand allocated; |
1242 MachineType machine_type = InstructionSequence::DefaultRepresentation(); | 1429 MachineType machine_type = InstructionSequence::DefaultRepresentation(); |
(...skipping 224 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1467 live_range->set_is_non_loop_phi(!block->IsLoopHeader()); | 1654 live_range->set_is_non_loop_phi(!block->IsLoopHeader()); |
1468 } | 1655 } |
1469 } | 1656 } |
1470 | 1657 |
1471 | 1658 |
1472 LiveRangeBuilder::LiveRangeBuilder(RegisterAllocationData* data, | 1659 LiveRangeBuilder::LiveRangeBuilder(RegisterAllocationData* data, |
1473 Zone* local_zone) | 1660 Zone* local_zone) |
1474 : data_(data), phi_hints_(local_zone) {} | 1661 : data_(data), phi_hints_(local_zone) {} |
1475 | 1662 |
1476 | 1663 |
1477 BitVector* LiveRangeBuilder::ComputeLiveOut(const InstructionBlock* block) { | 1664 BitVector* LiveRangeBuilder::ComputeLiveOut(const InstructionBlock* block, |
1665 RegisterAllocationData* data) { | |
1478 // Compute live out for the given block, except not including backward | 1666 // Compute live out for the given block, except not including backward |
1479 // successor edges. | 1667 // successor edges. |
1480 auto live_out = new (allocation_zone()) | 1668 Zone* zone = data->allocation_zone(); |
1481 BitVector(code()->VirtualRegisterCount(), allocation_zone()); | 1669 const InstructionSequence* code = data->code(); |
1670 | |
1671 auto live_out = new (zone) BitVector(code->VirtualRegisterCount(), zone); | |
1482 | 1672 |
1483 // Process all successor blocks. | 1673 // Process all successor blocks. |
1484 for (auto succ : block->successors()) { | 1674 for (auto succ : block->successors()) { |
1485 // Add values live on entry to the successor. Note the successor's | 1675 // Add values live on entry to the successor. |
1486 // live_in will not be computed yet for backwards edges. | 1676 if (succ <= block->rpo_number()) continue; |
1487 auto live_in = live_in_sets()[succ.ToSize()]; | 1677 auto live_in = data->live_in_sets()[succ.ToSize()]; |
1488 if (live_in != nullptr) live_out->Union(*live_in); | 1678 if (live_in != nullptr) live_out->Union(*live_in); |
1489 | 1679 |
1490 // All phi input operands corresponding to this successor edge are live | 1680 // All phi input operands corresponding to this successor edge are live |
1491 // out from this block. | 1681 // out from this block. |
1492 auto successor = code()->InstructionBlockAt(succ); | 1682 auto successor = code->InstructionBlockAt(succ); |
1493 size_t index = successor->PredecessorIndexOf(block->rpo_number()); | 1683 size_t index = successor->PredecessorIndexOf(block->rpo_number()); |
1494 DCHECK(index < successor->PredecessorCount()); | 1684 DCHECK(index < successor->PredecessorCount()); |
1495 for (auto phi : successor->phis()) { | 1685 for (auto phi : successor->phis()) { |
1496 live_out->Add(phi->operands()[index]); | 1686 live_out->Add(phi->operands()[index]); |
1497 } | 1687 } |
1498 } | 1688 } |
1499 return live_out; | 1689 return live_out; |
1500 } | 1690 } |
1501 | 1691 |
1502 | 1692 |
(...skipping 324 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1827 live_in_sets()[i]->Union(*live); | 2017 live_in_sets()[i]->Union(*live); |
1828 } | 2018 } |
1829 } | 2019 } |
1830 | 2020 |
1831 | 2021 |
1832 void LiveRangeBuilder::BuildLiveRanges() { | 2022 void LiveRangeBuilder::BuildLiveRanges() { |
1833 // Process the blocks in reverse order. | 2023 // Process the blocks in reverse order. |
1834 for (int block_id = code()->InstructionBlockCount() - 1; block_id >= 0; | 2024 for (int block_id = code()->InstructionBlockCount() - 1; block_id >= 0; |
1835 --block_id) { | 2025 --block_id) { |
1836 auto block = code()->InstructionBlockAt(RpoNumber::FromInt(block_id)); | 2026 auto block = code()->InstructionBlockAt(RpoNumber::FromInt(block_id)); |
1837 auto live = ComputeLiveOut(block); | 2027 auto live = ComputeLiveOut(block, data()); |
1838 // Initially consider all live_out values live for the entire block. We | 2028 // Initially consider all live_out values live for the entire block. We |
1839 // will shorten these intervals if necessary. | 2029 // will shorten these intervals if necessary. |
1840 AddInitialIntervals(block, live); | 2030 AddInitialIntervals(block, live); |
1841 // Process the instructions in reverse order, generating and killing | 2031 // Process the instructions in reverse order, generating and killing |
1842 // live values. | 2032 // live values. |
1843 ProcessInstructions(block, live); | 2033 ProcessInstructions(block, live); |
1844 // All phi output operands are killed by this block. | 2034 // All phi output operands are killed by this block. |
1845 ProcessPhis(block, live); | 2035 ProcessPhis(block, live); |
1846 // Now live is live_in for this block except not including values live | 2036 // Now live is live_in for this block except not including values live |
1847 // out on backward successor edges. | 2037 // out on backward successor edges. |
(...skipping 744 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2592 } | 2782 } |
2593 } | 2783 } |
2594 | 2784 |
2595 | 2785 |
2596 OperandAssigner::OperandAssigner(RegisterAllocationData* data) : data_(data) {} | 2786 OperandAssigner::OperandAssigner(RegisterAllocationData* data) : data_(data) {} |
2597 | 2787 |
2598 | 2788 |
2599 void OperandAssigner::AssignSpillSlots() { | 2789 void OperandAssigner::AssignSpillSlots() { |
2600 auto& spill_ranges = data()->spill_ranges(); | 2790 auto& spill_ranges = data()->spill_ranges(); |
2601 // Merge disjoint spill ranges | 2791 // Merge disjoint spill ranges |
2602 for (size_t i = 0; i < spill_ranges.size(); i++) { | 2792 for (auto i = spill_ranges.begin(), end = spill_ranges.end(); i != end; ++i) { |
2603 auto range = spill_ranges[i]; | 2793 auto range = *i; |
Benedikt Meurer
2015/08/24 04:33:26
Nit: Use LiveRange* instead of auto
Mircea Trofin
2015/08/24 20:55:10
Done.
| |
2604 if (range->IsEmpty()) continue; | 2794 if (range->IsEmpty()) continue; |
2605 for (size_t j = i + 1; j < spill_ranges.size(); j++) { | 2795 auto j = i; |
2606 auto other = spill_ranges[j]; | 2796 j++; |
2797 for (; j != end; ++j) { | |
2798 auto other = *j; | |
Benedikt Meurer
2015/08/24 04:33:26
Same here.
Mircea Trofin
2015/08/24 20:55:10
Done.
| |
2607 if (!other->IsEmpty()) { | 2799 if (!other->IsEmpty()) { |
2608 range->TryMerge(other); | 2800 range->TryMerge(other); |
2609 } | 2801 } |
2610 } | 2802 } |
2611 } | 2803 } |
2612 // Allocate slots for the merged spill ranges. | 2804 // Allocate slots for the merged spill ranges. |
2613 for (auto range : spill_ranges) { | 2805 for (auto range : spill_ranges) { |
2614 if (range->IsEmpty()) continue; | 2806 if (range->IsEmpty()) continue; |
2615 // Allocate a new operand referring to the spill slot. | 2807 // Allocate a new operand referring to the spill slot. |
2616 int byte_width = range->ByteWidth(); | 2808 int byte_width = range->ByteWidth(); |
(...skipping 442 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
3059 auto eliminate = moves->PrepareInsertAfter(move); | 3251 auto eliminate = moves->PrepareInsertAfter(move); |
3060 to_insert.push_back(move); | 3252 to_insert.push_back(move); |
3061 if (eliminate != nullptr) to_eliminate.push_back(eliminate); | 3253 if (eliminate != nullptr) to_eliminate.push_back(eliminate); |
3062 } | 3254 } |
3063 } | 3255 } |
3064 | 3256 |
3065 | 3257 |
3066 } // namespace compiler | 3258 } // namespace compiler |
3067 } // namespace internal | 3259 } // namespace internal |
3068 } // namespace v8 | 3260 } // namespace v8 |
OLD | NEW |