Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(494)

Side by Side Diff: src/compiler/register-allocator.cc

Issue 1305393003: [turbofan] Deferred blocks splintering. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Created 5 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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
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
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
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
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
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
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
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
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
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
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
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
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698