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

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

Issue 1119483003: Revert of [turbofan] add MachineType to AllocatedOperand (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Created 5 years, 7 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
« no previous file with comments | « src/compiler/register-allocator.h ('k') | src/compiler/register-allocator-verifier.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 71 matching lines...) Expand 10 before | Expand all | Expand 10 after
82 for (size_t i = 0; i < instr->OutputCount(); i++) { 82 for (size_t i = 0; i < instr->OutputCount(); i++) {
83 auto output = instr->OutputAt(i); 83 auto output = instr->OutputAt(i);
84 if (output->IsDoubleRegister() && 84 if (output->IsDoubleRegister() &&
85 DoubleRegisterOperand::cast(output)->index() == index) { 85 DoubleRegisterOperand::cast(output)->index() == index) {
86 return true; 86 return true;
87 } 87 }
88 } 88 }
89 return false; 89 return false;
90 } 90 }
91 91
92
93 // TODO(dcarney): fix frame to allow frame accesses to half size location.
94 int GetByteWidth(MachineType machine_type) {
95 DCHECK_EQ(RepresentationOf(machine_type), machine_type);
96 switch (machine_type) {
97 case kRepBit:
98 case kRepWord8:
99 case kRepWord16:
100 case kRepWord32:
101 case kRepTagged:
102 return kPointerSize;
103 case kRepFloat32:
104 case kRepWord64:
105 case kRepFloat64:
106 return 8;
107 default:
108 UNREACHABLE();
109 return 0;
110 }
111 }
112
113 } // namespace 92 } // namespace
114 93
115 94
116 UsePosition::UsePosition(LifetimePosition pos, InstructionOperand* operand, 95 UsePosition::UsePosition(LifetimePosition pos, InstructionOperand* operand,
117 void* hint, UsePositionHintType hint_type) 96 void* hint, UsePositionHintType hint_type)
118 : operand_(operand), hint_(hint), next_(nullptr), pos_(pos), flags_(0) { 97 : operand_(operand), hint_(hint), next_(nullptr), pos_(pos), flags_(0) {
119 DCHECK_IMPLIES(hint == nullptr, hint_type == UsePositionHintType::kNone); 98 DCHECK_IMPLIES(hint == nullptr, hint_type == UsePositionHintType::kNone);
120 bool register_beneficial = true; 99 bool register_beneficial = true;
121 UsePositionType type = UsePositionType::kAny; 100 UsePositionType type = UsePositionType::kAny;
122 if (operand_ != nullptr && operand_->IsUnallocated()) { 101 if (operand_ != nullptr && operand_->IsUnallocated()) {
(...skipping 105 matching lines...) Expand 10 before | Expand all | Expand 10 after
228 struct LiveRange::SpillAtDefinitionList : ZoneObject { 207 struct LiveRange::SpillAtDefinitionList : ZoneObject {
229 SpillAtDefinitionList(int gap_index, InstructionOperand* operand, 208 SpillAtDefinitionList(int gap_index, InstructionOperand* operand,
230 SpillAtDefinitionList* next) 209 SpillAtDefinitionList* next)
231 : gap_index(gap_index), operand(operand), next(next) {} 210 : gap_index(gap_index), operand(operand), next(next) {}
232 const int gap_index; 211 const int gap_index;
233 InstructionOperand* const operand; 212 InstructionOperand* const operand;
234 SpillAtDefinitionList* const next; 213 SpillAtDefinitionList* const next;
235 }; 214 };
236 215
237 216
238 LiveRange::LiveRange(int id, MachineType machine_type) 217 LiveRange::LiveRange(int id)
239 : id_(id), 218 : id_(id),
240 spill_start_index_(kMaxInt), 219 spill_start_index_(kMaxInt),
241 bits_(0), 220 bits_(0),
242 last_interval_(nullptr), 221 last_interval_(nullptr),
243 first_interval_(nullptr), 222 first_interval_(nullptr),
244 first_pos_(nullptr), 223 first_pos_(nullptr),
245 parent_(nullptr), 224 parent_(nullptr),
246 next_(nullptr), 225 next_(nullptr),
247 spill_operand_(nullptr), 226 spill_operand_(nullptr),
248 spills_at_definition_(nullptr), 227 spills_at_definition_(nullptr),
249 current_interval_(nullptr), 228 current_interval_(nullptr),
250 last_processed_use_(nullptr), 229 last_processed_use_(nullptr),
251 current_hint_position_(nullptr) { 230 current_hint_position_(nullptr) {
252 DCHECK(AllocatedOperand::IsSupportedMachineType(machine_type));
253 bits_ = SpillTypeField::encode(SpillType::kNoSpillType) | 231 bits_ = SpillTypeField::encode(SpillType::kNoSpillType) |
254 AssignedRegisterField::encode(kUnassignedRegister) | 232 AssignedRegisterField::encode(kUnassignedRegister);
255 MachineTypeField::encode(machine_type);
256 } 233 }
257 234
258 235
259 void LiveRange::Verify() const { 236 void LiveRange::Verify() const {
260 // Walk the positions, verifying that each is in an interval. 237 // Walk the positions, verifying that each is in an interval.
261 auto interval = first_interval_; 238 auto interval = first_interval_;
262 for (auto pos = first_pos_; pos != nullptr; pos = pos->next()) { 239 for (auto pos = first_pos_; pos != nullptr; pos = pos->next()) {
263 CHECK(Start() <= pos->pos()); 240 CHECK(Start() <= pos->pos());
264 CHECK(pos->pos() <= End()); 241 CHECK(pos->pos() <= End());
265 CHECK(interval != nullptr); 242 CHECK(interval != nullptr);
(...skipping 18 matching lines...) Expand all
284 261
285 262
286 void LiveRange::Spill() { 263 void LiveRange::Spill() {
287 DCHECK(!spilled()); 264 DCHECK(!spilled());
288 DCHECK(!TopLevel()->HasNoSpillType()); 265 DCHECK(!TopLevel()->HasNoSpillType());
289 set_spilled(true); 266 set_spilled(true);
290 bits_ = AssignedRegisterField::update(bits_, kUnassignedRegister); 267 bits_ = AssignedRegisterField::update(bits_, kUnassignedRegister);
291 } 268 }
292 269
293 270
294 RegisterKind LiveRange::kind() const {
295 switch (RepresentationOf(machine_type())) {
296 case kRepFloat32:
297 case kRepFloat64:
298 return DOUBLE_REGISTERS;
299 default:
300 break;
301 }
302 return GENERAL_REGISTERS;
303 }
304
305
306 void LiveRange::SpillAtDefinition(Zone* zone, int gap_index, 271 void LiveRange::SpillAtDefinition(Zone* zone, int gap_index,
307 InstructionOperand* operand) { 272 InstructionOperand* operand) {
308 DCHECK(HasNoSpillType()); 273 DCHECK(HasNoSpillType());
309 spills_at_definition_ = new (zone) 274 spills_at_definition_ = new (zone)
310 SpillAtDefinitionList(gap_index, operand, spills_at_definition_); 275 SpillAtDefinitionList(gap_index, operand, spills_at_definition_);
311 } 276 }
312 277
313 278
314 void LiveRange::CommitSpillsAtDefinition(InstructionSequence* sequence, 279 void LiveRange::CommitSpillsAtDefinition(InstructionSequence* sequence,
315 const InstructionOperand& op, 280 InstructionOperand* op,
316 bool might_be_duplicated) { 281 bool might_be_duplicated) {
317 DCHECK_IMPLIES(op.IsConstant(), spills_at_definition_ == nullptr); 282 DCHECK_IMPLIES(op->IsConstant(), spills_at_definition_ == nullptr);
318 DCHECK(!IsChild()); 283 DCHECK(!IsChild());
319 auto zone = sequence->zone(); 284 auto zone = sequence->zone();
320 for (auto to_spill = spills_at_definition_; to_spill != nullptr; 285 for (auto to_spill = spills_at_definition_; to_spill != nullptr;
321 to_spill = to_spill->next) { 286 to_spill = to_spill->next) {
322 auto instr = sequence->InstructionAt(to_spill->gap_index); 287 auto instr = sequence->InstructionAt(to_spill->gap_index);
323 auto move = instr->GetOrCreateParallelMove(Instruction::START, zone); 288 auto move = instr->GetOrCreateParallelMove(Instruction::START, zone);
324 // Skip insertion if it's possible that the move exists already as a 289 // Skip insertion if it's possible that the move exists already as a
325 // constraint move from a fixed output register to a slot. 290 // constraint move from a fixed output register to a slot.
326 if (might_be_duplicated) { 291 if (might_be_duplicated) {
327 bool found = false; 292 bool found = false;
328 for (auto move_op : *move) { 293 for (auto move_op : *move) {
329 if (move_op->IsEliminated()) continue; 294 if (move_op->IsEliminated()) continue;
330 if (move_op->source().Equals(*to_spill->operand) && 295 if (move_op->source() == *to_spill->operand &&
331 move_op->destination().Equals(op)) { 296 move_op->destination() == *op) {
332 found = true; 297 found = true;
333 break; 298 break;
334 } 299 }
335 } 300 }
336 if (found) continue; 301 if (found) continue;
337 } 302 }
338 move->AddMove(*to_spill->operand, op); 303 move->AddMove(*to_spill->operand, *op);
339 } 304 }
340 } 305 }
341 306
342 307
343 UsePosition* LiveRange::FirstHintPosition(int* register_index) const { 308 UsePosition* LiveRange::FirstHintPosition(int* register_index) const {
344 for (auto pos = first_pos_; pos != nullptr; pos = pos->next()) { 309 for (auto pos = first_pos_; pos != nullptr; pos = pos->next()) {
345 if (pos->HintRegister(register_index)) return pos; 310 if (pos->HintRegister(register_index)) return pos;
346 } 311 }
347 return nullptr; 312 return nullptr;
348 } 313 }
349 314
350 315
351 void LiveRange::SetSpillOperand(InstructionOperand* operand) { 316 void LiveRange::SetSpillOperand(InstructionOperand* operand) {
352 DCHECK(HasNoSpillType()); 317 DCHECK(HasNoSpillType());
353 DCHECK(!operand->IsUnallocated() && !operand->IsImmediate()); 318 DCHECK(!operand->IsUnallocated() && !operand->IsImmediate());
354 set_spill_type(SpillType::kSpillOperand); 319 set_spill_type(SpillType::kSpillOperand);
355 spill_operand_ = operand; 320 spill_operand_ = operand;
356 } 321 }
357 322
358 323
359 void LiveRange::SetSpillRange(SpillRange* spill_range) { 324 void LiveRange::SetSpillRange(SpillRange* spill_range) {
360 DCHECK(HasNoSpillType() || HasSpillRange()); 325 DCHECK(HasNoSpillType() || HasSpillRange());
361 DCHECK(spill_range); 326 DCHECK(spill_range);
362 set_spill_type(SpillType::kSpillRange); 327 set_spill_type(SpillType::kSpillRange);
363 spill_range_ = spill_range; 328 spill_range_ = spill_range;
364 } 329 }
365 330
366 331
332 void LiveRange::CommitSpillOperand(AllocatedOperand* operand) {
333 DCHECK(HasSpillRange());
334 DCHECK(!IsChild());
335 set_spill_type(SpillType::kSpillOperand);
336 spill_operand_ = operand;
337 }
338
339
367 UsePosition* LiveRange::NextUsePosition(LifetimePosition start) const { 340 UsePosition* LiveRange::NextUsePosition(LifetimePosition start) const {
368 UsePosition* use_pos = last_processed_use_; 341 UsePosition* use_pos = last_processed_use_;
369 if (use_pos == nullptr || use_pos->pos() > start) { 342 if (use_pos == nullptr || use_pos->pos() > start) {
370 use_pos = first_pos(); 343 use_pos = first_pos();
371 } 344 }
372 while (use_pos != nullptr && use_pos->pos() < start) { 345 while (use_pos != nullptr && use_pos->pos() < start) {
373 use_pos = use_pos->next(); 346 use_pos = use_pos->next();
374 } 347 }
375 last_processed_use_ = use_pos; 348 last_processed_use_ = use_pos;
376 return use_pos; 349 return use_pos;
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
415 if (use_pos == nullptr) return true; 388 if (use_pos == nullptr) return true;
416 return use_pos->pos() > pos.NextStart().End(); 389 return use_pos->pos() > pos.NextStart().End();
417 } 390 }
418 391
419 392
420 InstructionOperand LiveRange::GetAssignedOperand() const { 393 InstructionOperand LiveRange::GetAssignedOperand() const {
421 if (HasRegisterAssigned()) { 394 if (HasRegisterAssigned()) {
422 DCHECK(!spilled()); 395 DCHECK(!spilled());
423 switch (kind()) { 396 switch (kind()) {
424 case GENERAL_REGISTERS: 397 case GENERAL_REGISTERS:
425 return RegisterOperand(machine_type(), assigned_register()); 398 return RegisterOperand(assigned_register());
426 case DOUBLE_REGISTERS: 399 case DOUBLE_REGISTERS:
427 return DoubleRegisterOperand(machine_type(), assigned_register()); 400 return DoubleRegisterOperand(assigned_register());
401 default:
402 UNREACHABLE();
428 } 403 }
429 } 404 }
430 DCHECK(spilled()); 405 DCHECK(spilled());
431 DCHECK(!HasRegisterAssigned()); 406 DCHECK(!HasRegisterAssigned());
432 if (TopLevel()->HasSpillOperand()) { 407 auto op = TopLevel()->GetSpillOperand();
433 auto op = TopLevel()->GetSpillOperand(); 408 DCHECK(!op->IsUnallocated());
434 DCHECK(!op->IsUnallocated()); 409 return *op;
435 return *op;
436 }
437 return TopLevel()->GetSpillRangeOperand();
438 } 410 }
439 411
440 412
441 AllocatedOperand LiveRange::GetSpillRangeOperand() const {
442 auto spill_range = GetSpillRange();
443 int index = spill_range->assigned_slot();
444 switch (kind()) {
445 case GENERAL_REGISTERS:
446 return StackSlotOperand(machine_type(), index);
447 case DOUBLE_REGISTERS:
448 return DoubleStackSlotOperand(machine_type(), index);
449 }
450 UNREACHABLE();
451 return StackSlotOperand(kMachNone, 0);
452 }
453
454
455 UseInterval* LiveRange::FirstSearchIntervalForPosition( 413 UseInterval* LiveRange::FirstSearchIntervalForPosition(
456 LifetimePosition position) const { 414 LifetimePosition position) const {
457 if (current_interval_ == nullptr) return first_interval_; 415 if (current_interval_ == nullptr) return first_interval_;
458 if (current_interval_->start() > position) { 416 if (current_interval_->start() > position) {
459 current_interval_ = nullptr; 417 current_interval_ = nullptr;
460 return first_interval_; 418 return first_interval_;
461 } 419 }
462 return current_interval_; 420 return current_interval_;
463 } 421 }
464 422
(...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after
547 result->first_pos_ = use_after; 505 result->first_pos_ = use_after;
548 506
549 // Discard cached iteration state. It might be pointing 507 // Discard cached iteration state. It might be pointing
550 // to the use that no longer belongs to this live range. 508 // to the use that no longer belongs to this live range.
551 last_processed_use_ = nullptr; 509 last_processed_use_ = nullptr;
552 current_interval_ = nullptr; 510 current_interval_ = nullptr;
553 511
554 // Link the new live range in the chain before any of the other 512 // Link the new live range in the chain before any of the other
555 // ranges linked from the range before the split. 513 // ranges linked from the range before the split.
556 result->parent_ = (parent_ == nullptr) ? this : parent_; 514 result->parent_ = (parent_ == nullptr) ? this : parent_;
515 result->set_kind(result->parent_->kind());
557 result->next_ = next_; 516 result->next_ = next_;
558 next_ = result; 517 next_ = result;
559 518
560 #ifdef DEBUG 519 #ifdef DEBUG
561 Verify(); 520 Verify();
562 result->Verify(); 521 result->Verify();
563 #endif 522 #endif
564 } 523 }
565 524
566 525
(...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after
660 prev->set_next(use_pos); 619 prev->set_next(use_pos);
661 } 620 }
662 621
663 if (prev_hint == nullptr && use_pos->HasHint()) { 622 if (prev_hint == nullptr && use_pos->HasHint()) {
664 current_hint_position_ = use_pos; 623 current_hint_position_ = use_pos;
665 } 624 }
666 } 625 }
667 626
668 627
669 void LiveRange::ConvertUsesToOperand(const InstructionOperand& op, 628 void LiveRange::ConvertUsesToOperand(const InstructionOperand& op,
670 const InstructionOperand& spill_op) { 629 InstructionOperand* spill_op) {
671 for (auto pos = first_pos(); pos != nullptr; pos = pos->next()) { 630 for (auto pos = first_pos(); pos != nullptr; pos = pos->next()) {
672 DCHECK(Start() <= pos->pos() && pos->pos() <= End()); 631 DCHECK(Start() <= pos->pos() && pos->pos() <= End());
673 if (!pos->HasOperand()) continue; 632 if (!pos->HasOperand()) continue;
674 switch (pos->type()) { 633 switch (pos->type()) {
675 case UsePositionType::kRequiresSlot: 634 case UsePositionType::kRequiresSlot:
676 DCHECK(spill_op.IsStackSlot() || spill_op.IsDoubleStackSlot()); 635 if (spill_op != nullptr) {
677 InstructionOperand::ReplaceWith(pos->operand(), &spill_op); 636 InstructionOperand::ReplaceWith(pos->operand(), spill_op);
637 }
678 break; 638 break;
679 case UsePositionType::kRequiresRegister: 639 case UsePositionType::kRequiresRegister:
680 DCHECK(op.IsRegister() || op.IsDoubleRegister()); 640 DCHECK(op.IsRegister() || op.IsDoubleRegister());
681 // Fall through. 641 // Fall through.
682 case UsePositionType::kAny: 642 case UsePositionType::kAny:
683 InstructionOperand::ReplaceWith(pos->operand(), &op); 643 InstructionOperand::ReplaceWith(pos->operand(), &op);
684 break; 644 break;
685 } 645 }
686 } 646 }
687 } 647 }
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after
759 if (interval2->end() > interval1->start()) { 719 if (interval2->end() > interval1->start()) {
760 return true; 720 return true;
761 } 721 }
762 interval2 = interval2->next(); 722 interval2 = interval2->next();
763 } 723 }
764 } 724 }
765 return false; 725 return false;
766 } 726 }
767 727
768 728
769 SpillRange::SpillRange(LiveRange* parent, Zone* zone) 729 SpillRange::SpillRange(LiveRange* parent, Zone* zone) : live_ranges_(zone) {
770 : live_ranges_(zone), assigned_slot_(kUnassignedSlot) {
771 DCHECK(!parent->IsChild()); 730 DCHECK(!parent->IsChild());
772 UseInterval* result = nullptr; 731 UseInterval* result = nullptr;
773 UseInterval* node = nullptr; 732 UseInterval* node = nullptr;
774 // Copy the intervals for all ranges. 733 // Copy the intervals for all ranges.
775 for (auto range = parent; range != nullptr; range = range->next()) { 734 for (auto range = parent; range != nullptr; range = range->next()) {
776 auto src = range->first_interval(); 735 auto src = range->first_interval();
777 while (src != nullptr) { 736 while (src != nullptr) {
778 auto new_node = new (zone) UseInterval(src->start(), src->end()); 737 auto new_node = new (zone) UseInterval(src->start(), src->end());
779 if (result == nullptr) { 738 if (result == nullptr) {
780 result = new_node; 739 result = new_node;
781 } else { 740 } else {
782 node->set_next(new_node); 741 node->set_next(new_node);
783 } 742 }
784 node = new_node; 743 node = new_node;
785 src = src->next(); 744 src = src->next();
786 } 745 }
787 } 746 }
788 use_interval_ = result; 747 use_interval_ = result;
789 live_ranges().push_back(parent); 748 live_ranges().push_back(parent);
790 end_position_ = node->end(); 749 end_position_ = node->end();
791 DCHECK(!parent->HasSpillRange()); 750 DCHECK(!parent->HasSpillRange());
792 parent->SetSpillRange(this); 751 parent->SetSpillRange(this);
793 } 752 }
794 753
795 754
796 int SpillRange::ByteWidth() const {
797 return GetByteWidth(live_ranges_[0]->machine_type());
798 }
799
800
801 bool SpillRange::IsIntersectingWith(SpillRange* other) const { 755 bool SpillRange::IsIntersectingWith(SpillRange* other) const {
802 if (this->use_interval_ == nullptr || other->use_interval_ == nullptr || 756 if (this->use_interval_ == nullptr || other->use_interval_ == nullptr ||
803 this->End() <= other->use_interval_->start() || 757 this->End() <= other->use_interval_->start() ||
804 other->End() <= this->use_interval_->start()) { 758 other->End() <= this->use_interval_->start()) {
805 return false; 759 return false;
806 } 760 }
807 return AreUseIntervalsIntersecting(use_interval_, other->use_interval_); 761 return AreUseIntervalsIntersecting(use_interval_, other->use_interval_);
808 } 762 }
809 763
810 764
811 bool SpillRange::TryMerge(SpillRange* other) { 765 bool SpillRange::TryMerge(SpillRange* other) {
812 // TODO(dcarney): byte widths should be compared here not kinds. 766 if (kind() != other->kind() || IsIntersectingWith(other)) return false;
813 if (live_ranges_[0]->kind() != other->live_ranges_[0]->kind() ||
814 IsIntersectingWith(other)) {
815 return false;
816 }
817 767
818 auto max = LifetimePosition::MaxPosition(); 768 auto max = LifetimePosition::MaxPosition();
819 if (End() < other->End() && other->End() != max) { 769 if (End() < other->End() && other->End() != max) {
820 end_position_ = other->End(); 770 end_position_ = other->End();
821 } 771 }
822 other->end_position_ = max; 772 other->end_position_ = max;
823 773
824 MergeDisjointIntervals(other->use_interval_); 774 MergeDisjointIntervals(other->use_interval_);
825 other->use_interval_ = nullptr; 775 other->use_interval_ = nullptr;
826 776
827 for (auto range : other->live_ranges()) { 777 for (auto range : other->live_ranges()) {
828 DCHECK(range->GetSpillRange() == other); 778 DCHECK(range->GetSpillRange() == other);
829 range->SetSpillRange(this); 779 range->SetSpillRange(this);
830 } 780 }
831 781
832 live_ranges().insert(live_ranges().end(), other->live_ranges().begin(), 782 live_ranges().insert(live_ranges().end(), other->live_ranges().begin(),
833 other->live_ranges().end()); 783 other->live_ranges().end());
834 other->live_ranges().clear(); 784 other->live_ranges().clear();
835 785
836 return true; 786 return true;
837 } 787 }
838 788
839 789
790 void SpillRange::SetOperand(AllocatedOperand* op) {
791 for (auto range : live_ranges()) {
792 DCHECK(range->GetSpillRange() == this);
793 range->CommitSpillOperand(op);
794 }
795 }
796
797
840 void SpillRange::MergeDisjointIntervals(UseInterval* other) { 798 void SpillRange::MergeDisjointIntervals(UseInterval* other) {
841 UseInterval* tail = nullptr; 799 UseInterval* tail = nullptr;
842 auto current = use_interval_; 800 auto current = use_interval_;
843 while (other != nullptr) { 801 while (other != nullptr) {
844 // Make sure the 'current' list starts first 802 // Make sure the 'current' list starts first
845 if (current == nullptr || current->start() > other->start()) { 803 if (current == nullptr || current->start() > other->start()) {
846 std::swap(current, other); 804 std::swap(current, other);
847 } 805 }
848 // Check disjointness 806 // Check disjointness
849 DCHECK(other == nullptr || current->end() <= other->start()); 807 DCHECK(other == nullptr || current->end() <= other->start());
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after
896 phi_map_(allocation_zone()), 854 phi_map_(allocation_zone()),
897 live_in_sets_(code->InstructionBlockCount(), nullptr, allocation_zone()), 855 live_in_sets_(code->InstructionBlockCount(), nullptr, allocation_zone()),
898 live_ranges_(code->VirtualRegisterCount() * 2, nullptr, 856 live_ranges_(code->VirtualRegisterCount() * 2, nullptr,
899 allocation_zone()), 857 allocation_zone()),
900 fixed_live_ranges_(this->config()->num_general_registers(), nullptr, 858 fixed_live_ranges_(this->config()->num_general_registers(), nullptr,
901 allocation_zone()), 859 allocation_zone()),
902 fixed_double_live_ranges_(this->config()->num_double_registers(), nullptr, 860 fixed_double_live_ranges_(this->config()->num_double_registers(), nullptr,
903 allocation_zone()), 861 allocation_zone()),
904 spill_ranges_(allocation_zone()), 862 spill_ranges_(allocation_zone()),
905 assigned_registers_(nullptr), 863 assigned_registers_(nullptr),
906 assigned_double_registers_(nullptr), 864 assigned_double_registers_(nullptr) {
907 virtual_register_count_(code->VirtualRegisterCount()) {
908 DCHECK(this->config()->num_general_registers() <= 865 DCHECK(this->config()->num_general_registers() <=
909 RegisterConfiguration::kMaxGeneralRegisters); 866 RegisterConfiguration::kMaxGeneralRegisters);
910 DCHECK(this->config()->num_double_registers() <= 867 DCHECK(this->config()->num_double_registers() <=
911 RegisterConfiguration::kMaxDoubleRegisters); 868 RegisterConfiguration::kMaxDoubleRegisters);
912 spill_ranges().reserve(8); 869 spill_ranges().reserve(8);
913 assigned_registers_ = new (code_zone()) 870 assigned_registers_ = new (code_zone())
914 BitVector(this->config()->num_general_registers(), code_zone()); 871 BitVector(this->config()->num_general_registers(), code_zone());
915 assigned_double_registers_ = new (code_zone()) 872 assigned_double_registers_ = new (code_zone())
916 BitVector(this->config()->num_aliased_double_registers(), code_zone()); 873 BitVector(this->config()->num_aliased_double_registers(), code_zone());
917 this->frame()->SetAllocatedRegisters(assigned_registers_); 874 this->frame()->SetAllocatedRegisters(assigned_registers_);
918 this->frame()->SetAllocatedDoubleRegisters(assigned_double_registers_); 875 this->frame()->SetAllocatedDoubleRegisters(assigned_double_registers_);
919 } 876 }
920 877
921 878
879 LiveRange* RegisterAllocationData::LiveRangeFor(int index) {
880 if (index >= static_cast<int>(live_ranges().size())) {
881 live_ranges().resize(index + 1, nullptr);
882 }
883 auto result = live_ranges()[index];
884 if (result == nullptr) {
885 result = NewLiveRange(index);
886 live_ranges()[index] = result;
887 }
888 return result;
889 }
890
891
922 MoveOperands* RegisterAllocationData::AddGapMove( 892 MoveOperands* RegisterAllocationData::AddGapMove(
923 int index, Instruction::GapPosition position, 893 int index, Instruction::GapPosition position,
924 const InstructionOperand& from, const InstructionOperand& to) { 894 const InstructionOperand& from, const InstructionOperand& to) {
925 auto instr = code()->InstructionAt(index); 895 auto instr = code()->InstructionAt(index);
926 auto moves = instr->GetOrCreateParallelMove(position, code_zone()); 896 auto moves = instr->GetOrCreateParallelMove(position, code_zone());
927 return moves->AddMove(from, to); 897 return moves->AddMove(from, to);
928 } 898 }
929 899
930 900
931 MachineType RegisterAllocationData::MachineTypeFor(int virtual_register) { 901 LiveRange* RegisterAllocationData::NewLiveRange(int index) {
932 DCHECK_LT(virtual_register, code()->VirtualRegisterCount()); 902 return new (allocation_zone()) LiveRange(index);
933 return code()->GetRepresentation(virtual_register);
934 } 903 }
935 904
936 905
937 LiveRange* RegisterAllocationData::LiveRangeFor(int index) {
938 if (index >= static_cast<int>(live_ranges().size())) {
939 live_ranges().resize(index + 1, nullptr);
940 }
941 auto result = live_ranges()[index];
942 if (result == nullptr) {
943 result = NewLiveRange(index, MachineTypeFor(index));
944 live_ranges()[index] = result;
945 }
946 return result;
947 }
948
949
950 LiveRange* RegisterAllocationData::NewLiveRange(int index,
951 MachineType machine_type) {
952 return new (allocation_zone()) LiveRange(index, machine_type);
953 }
954
955
956 LiveRange* RegisterAllocationData::NewChildRangeFor(LiveRange* range) {
957 int vreg = virtual_register_count_++;
958 if (vreg >= static_cast<int>(live_ranges().size())) {
959 live_ranges().resize(vreg + 1, nullptr);
960 }
961 auto child = new (allocation_zone()) LiveRange(vreg, range->machine_type());
962 DCHECK_NULL(live_ranges()[vreg]);
963 live_ranges()[vreg] = child;
964 return child;
965 }
966
967
968 RegisterAllocationData::PhiMapValue* RegisterAllocationData::InitializePhiMap( 906 RegisterAllocationData::PhiMapValue* RegisterAllocationData::InitializePhiMap(
969 const InstructionBlock* block, PhiInstruction* phi) { 907 const InstructionBlock* block, PhiInstruction* phi) {
970 auto map_value = new (allocation_zone()) 908 auto map_value = new (allocation_zone())
971 RegisterAllocationData::PhiMapValue(phi, block, allocation_zone()); 909 RegisterAllocationData::PhiMapValue(phi, block, allocation_zone());
972 auto res = 910 auto res =
973 phi_map_.insert(std::make_pair(phi->virtual_register(), map_value)); 911 phi_map_.insert(std::make_pair(phi->virtual_register(), map_value));
974 DCHECK(res.second); 912 DCHECK(res.second);
975 USE(res); 913 USE(res);
976 return map_value; 914 return map_value;
977 } 915 }
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after
1027 965
1028 ConstraintBuilder::ConstraintBuilder(RegisterAllocationData* data) 966 ConstraintBuilder::ConstraintBuilder(RegisterAllocationData* data)
1029 : data_(data) {} 967 : data_(data) {}
1030 968
1031 969
1032 InstructionOperand* ConstraintBuilder::AllocateFixed( 970 InstructionOperand* ConstraintBuilder::AllocateFixed(
1033 UnallocatedOperand* operand, int pos, bool is_tagged) { 971 UnallocatedOperand* operand, int pos, bool is_tagged) {
1034 TRACE("Allocating fixed reg for op %d\n", operand->virtual_register()); 972 TRACE("Allocating fixed reg for op %d\n", operand->virtual_register());
1035 DCHECK(operand->HasFixedPolicy()); 973 DCHECK(operand->HasFixedPolicy());
1036 InstructionOperand allocated; 974 InstructionOperand allocated;
1037 MachineType machine_type = InstructionSequence::DefaultRepresentation();
1038 int virtual_register = operand->virtual_register();
1039 if (virtual_register != InstructionOperand::kInvalidVirtualRegister) {
1040 machine_type = data()->MachineTypeFor(virtual_register);
1041 }
1042 if (operand->HasFixedSlotPolicy()) { 975 if (operand->HasFixedSlotPolicy()) {
1043 allocated = AllocatedOperand(AllocatedOperand::STACK_SLOT, machine_type, 976 allocated = AllocatedOperand(AllocatedOperand::STACK_SLOT,
1044 operand->fixed_slot_index()); 977 operand->fixed_slot_index());
1045 } else if (operand->HasFixedRegisterPolicy()) { 978 } else if (operand->HasFixedRegisterPolicy()) {
1046 allocated = AllocatedOperand(AllocatedOperand::REGISTER, machine_type, 979 allocated = AllocatedOperand(AllocatedOperand::REGISTER,
1047 operand->fixed_register_index()); 980 operand->fixed_register_index());
1048 } else if (operand->HasFixedDoubleRegisterPolicy()) { 981 } else if (operand->HasFixedDoubleRegisterPolicy()) {
1049 DCHECK_NE(InstructionOperand::kInvalidVirtualRegister, virtual_register);
1050 allocated = AllocatedOperand(AllocatedOperand::DOUBLE_REGISTER, 982 allocated = AllocatedOperand(AllocatedOperand::DOUBLE_REGISTER,
1051 machine_type, operand->fixed_register_index()); 983 operand->fixed_register_index());
1052 } else { 984 } else {
1053 UNREACHABLE(); 985 UNREACHABLE();
1054 } 986 }
1055 InstructionOperand::ReplaceWith(operand, &allocated); 987 InstructionOperand::ReplaceWith(operand, &allocated);
1056 if (is_tagged) { 988 if (is_tagged) {
1057 TRACE("Fixed reg is tagged at %d\n", pos); 989 TRACE("Fixed reg is tagged at %d\n", pos);
1058 auto instr = InstructionAt(pos); 990 auto instr = InstructionAt(pos);
1059 if (instr->HasReferenceMap()) { 991 if (instr->HasReferenceMap()) {
1060 instr->reference_map()->RecordReference(*operand); 992 instr->reference_map()->RecordReference(*operand);
1061 } 993 }
(...skipping 247 matching lines...) Expand 10 before | Expand all | Expand 10 after
1309 1241
1310 int LiveRangeBuilder::FixedDoubleLiveRangeID(int index) { 1242 int LiveRangeBuilder::FixedDoubleLiveRangeID(int index) {
1311 return -index - 1 - config()->num_general_registers(); 1243 return -index - 1 - config()->num_general_registers();
1312 } 1244 }
1313 1245
1314 1246
1315 LiveRange* LiveRangeBuilder::FixedLiveRangeFor(int index) { 1247 LiveRange* LiveRangeBuilder::FixedLiveRangeFor(int index) {
1316 DCHECK(index < config()->num_general_registers()); 1248 DCHECK(index < config()->num_general_registers());
1317 auto result = data()->fixed_live_ranges()[index]; 1249 auto result = data()->fixed_live_ranges()[index];
1318 if (result == nullptr) { 1250 if (result == nullptr) {
1319 result = data()->NewLiveRange(FixedLiveRangeID(index), 1251 result = data()->NewLiveRange(FixedLiveRangeID(index));
1320 InstructionSequence::DefaultRepresentation());
1321 DCHECK(result->IsFixed()); 1252 DCHECK(result->IsFixed());
1253 result->set_kind(GENERAL_REGISTERS);
1322 result->set_assigned_register(index); 1254 result->set_assigned_register(index);
1323 data()->MarkAllocated(GENERAL_REGISTERS, index); 1255 data()->MarkAllocated(GENERAL_REGISTERS, index);
1324 data()->fixed_live_ranges()[index] = result; 1256 data()->fixed_live_ranges()[index] = result;
1325 } 1257 }
1326 return result; 1258 return result;
1327 } 1259 }
1328 1260
1329 1261
1330 LiveRange* LiveRangeBuilder::FixedDoubleLiveRangeFor(int index) { 1262 LiveRange* LiveRangeBuilder::FixedDoubleLiveRangeFor(int index) {
1331 DCHECK(index < config()->num_aliased_double_registers()); 1263 DCHECK(index < config()->num_aliased_double_registers());
1332 auto result = data()->fixed_double_live_ranges()[index]; 1264 auto result = data()->fixed_double_live_ranges()[index];
1333 if (result == nullptr) { 1265 if (result == nullptr) {
1334 result = data()->NewLiveRange(FixedDoubleLiveRangeID(index), kRepFloat64); 1266 result = data()->NewLiveRange(FixedDoubleLiveRangeID(index));
1335 DCHECK(result->IsFixed()); 1267 DCHECK(result->IsFixed());
1268 result->set_kind(DOUBLE_REGISTERS);
1336 result->set_assigned_register(index); 1269 result->set_assigned_register(index);
1337 data()->MarkAllocated(DOUBLE_REGISTERS, index); 1270 data()->MarkAllocated(DOUBLE_REGISTERS, index);
1338 data()->fixed_double_live_ranges()[index] = result; 1271 data()->fixed_double_live_ranges()[index] = result;
1339 } 1272 }
1340 return result; 1273 return result;
1341 } 1274 }
1342 1275
1343 1276
1344 LiveRange* LiveRangeBuilder::LiveRangeFor(InstructionOperand* operand) { 1277 LiveRange* LiveRangeBuilder::LiveRangeFor(InstructionOperand* operand) {
1345 if (operand->IsUnallocated()) { 1278 if (operand->IsUnallocated()) {
(...skipping 279 matching lines...) Expand 10 before | Expand all | Expand 10 after
1625 // All phi output operands are killed by this block. 1558 // All phi output operands are killed by this block.
1626 ProcessPhis(block, live); 1559 ProcessPhis(block, live);
1627 // Now live is live_in for this block except not including values live 1560 // Now live is live_in for this block except not including values live
1628 // out on backward successor edges. 1561 // out on backward successor edges.
1629 if (block->IsLoopHeader()) ProcessLoopHeader(block, live); 1562 if (block->IsLoopHeader()) ProcessLoopHeader(block, live);
1630 live_in_sets()[block_id] = live; 1563 live_in_sets()[block_id] = live;
1631 } 1564 }
1632 // Postprocess the ranges. 1565 // Postprocess the ranges.
1633 for (auto range : data()->live_ranges()) { 1566 for (auto range : data()->live_ranges()) {
1634 if (range == nullptr) continue; 1567 if (range == nullptr) continue;
1568 range->set_kind(RequiredRegisterKind(range->id()));
1635 // Give slots to all ranges with a non fixed slot use. 1569 // Give slots to all ranges with a non fixed slot use.
1636 if (range->has_slot_use() && range->HasNoSpillType()) { 1570 if (range->has_slot_use() && range->HasNoSpillType()) {
1637 data()->AssignSpillRangeToLiveRange(range); 1571 data()->AssignSpillRangeToLiveRange(range);
1638 } 1572 }
1639 // TODO(bmeurer): This is a horrible hack to make sure that for constant 1573 // TODO(bmeurer): This is a horrible hack to make sure that for constant
1640 // live ranges, every use requires the constant to be in a register. 1574 // live ranges, every use requires the constant to be in a register.
1641 // Without this hack, all uses with "any" policy would get the constant 1575 // Without this hack, all uses with "any" policy would get the constant
1642 // operand assigned. 1576 // operand assigned.
1643 if (range->HasSpillOperand() && range->GetSpillOperand()->IsConstant()) { 1577 if (range->HasSpillOperand() && range->GetSpillOperand()->IsConstant()) {
1644 for (auto pos = range->first_pos(); pos != nullptr; pos = pos->next()) { 1578 for (auto pos = range->first_pos(); pos != nullptr; pos = pos->next()) {
(...skipping 24 matching lines...) Expand all
1669 1603
1670 void LiveRangeBuilder::ResolvePhiHint(InstructionOperand* operand, 1604 void LiveRangeBuilder::ResolvePhiHint(InstructionOperand* operand,
1671 UsePosition* use_pos) { 1605 UsePosition* use_pos) {
1672 auto it = phi_hints_.find(operand); 1606 auto it = phi_hints_.find(operand);
1673 if (it == phi_hints_.end()) return; 1607 if (it == phi_hints_.end()) return;
1674 DCHECK(!it->second->IsResolved()); 1608 DCHECK(!it->second->IsResolved());
1675 it->second->ResolveHint(use_pos); 1609 it->second->ResolveHint(use_pos);
1676 } 1610 }
1677 1611
1678 1612
1613 RegisterKind LiveRangeBuilder::RequiredRegisterKind(
1614 int virtual_register) const {
1615 return (code()->IsDouble(virtual_register)) ? DOUBLE_REGISTERS
1616 : GENERAL_REGISTERS;
1617 }
1618
1619
1679 void LiveRangeBuilder::Verify() const { 1620 void LiveRangeBuilder::Verify() const {
1680 for (auto& hint : phi_hints_) { 1621 for (auto& hint : phi_hints_) {
1681 CHECK(hint.second->IsResolved()); 1622 CHECK(hint.second->IsResolved());
1682 } 1623 }
1683 for (auto current : data()->live_ranges()) { 1624 for (auto current : data()->live_ranges()) {
1684 if (current != nullptr) current->Verify(); 1625 if (current != nullptr) current->Verify();
1685 } 1626 }
1686 } 1627 }
1687 1628
1688 1629
(...skipping 10 matching lines...) Expand all
1699 TRACE("Splitting live range %d at %d\n", range->id(), pos.value()); 1640 TRACE("Splitting live range %d at %d\n", range->id(), pos.value());
1700 1641
1701 if (pos <= range->Start()) return range; 1642 if (pos <= range->Start()) return range;
1702 1643
1703 // We can't properly connect liveranges if splitting occurred at the end 1644 // We can't properly connect liveranges if splitting occurred at the end
1704 // a block. 1645 // a block.
1705 DCHECK(pos.IsStart() || pos.IsGapPosition() || 1646 DCHECK(pos.IsStart() || pos.IsGapPosition() ||
1706 (GetInstructionBlock(code(), pos)->last_instruction_index() != 1647 (GetInstructionBlock(code(), pos)->last_instruction_index() !=
1707 pos.ToInstructionIndex())); 1648 pos.ToInstructionIndex()));
1708 1649
1709 auto result = data()->NewChildRangeFor(range); 1650 int vreg = code()->NextVirtualRegister();
1651 auto result = LiveRangeFor(vreg);
1710 range->SplitAt(pos, result, allocation_zone()); 1652 range->SplitAt(pos, result, allocation_zone());
1711 return result; 1653 return result;
1712 } 1654 }
1713 1655
1714 1656
1715 LiveRange* RegisterAllocator::SplitBetween(LiveRange* range, 1657 LiveRange* RegisterAllocator::SplitBetween(LiveRange* range,
1716 LifetimePosition start, 1658 LifetimePosition start,
1717 LifetimePosition end) { 1659 LifetimePosition end) {
1718 DCHECK(!range->IsFixed()); 1660 DCHECK(!range->IsFixed());
1719 TRACE("Splitting live range %d in position between [%d, %d]\n", range->id(), 1661 TRACE("Splitting live range %d in position between [%d, %d]\n", range->id(),
(...skipping 983 matching lines...) Expand 10 before | Expand all | Expand 10 after
2703 auto other = spill_ranges[j]; 2645 auto other = spill_ranges[j];
2704 if (!other->IsEmpty()) { 2646 if (!other->IsEmpty()) {
2705 range->TryMerge(other); 2647 range->TryMerge(other);
2706 } 2648 }
2707 } 2649 }
2708 } 2650 }
2709 // Allocate slots for the merged spill ranges. 2651 // Allocate slots for the merged spill ranges.
2710 for (auto range : spill_ranges) { 2652 for (auto range : spill_ranges) {
2711 if (range->IsEmpty()) continue; 2653 if (range->IsEmpty()) continue;
2712 // Allocate a new operand referring to the spill slot. 2654 // Allocate a new operand referring to the spill slot.
2713 int byte_width = range->ByteWidth(); 2655 auto kind = range->kind();
2714 int index = data()->frame()->AllocateSpillSlot(byte_width); 2656 int index = data()->frame()->AllocateSpillSlot(kind == DOUBLE_REGISTERS);
2715 range->set_assigned_slot(index); 2657 auto op_kind = kind == DOUBLE_REGISTERS
2658 ? AllocatedOperand::DOUBLE_STACK_SLOT
2659 : AllocatedOperand::STACK_SLOT;
2660 auto op = AllocatedOperand::New(data()->code_zone(), op_kind, index);
2661 range->SetOperand(op);
2716 } 2662 }
2717 } 2663 }
2718 2664
2719 2665
2720 void OperandAssigner::CommitAssignment() { 2666 void OperandAssigner::CommitAssignment() {
2721 for (auto range : data()->live_ranges()) { 2667 for (auto range : data()->live_ranges()) {
2722 if (range == nullptr || range->IsEmpty()) continue; 2668 if (range == nullptr || range->IsEmpty()) continue;
2723 InstructionOperand spill_operand; 2669 InstructionOperand* spill_operand = nullptr;
2724 if (range->TopLevel()->HasSpillOperand()) { 2670 if (!range->TopLevel()->HasNoSpillType()) {
2725 spill_operand = *range->TopLevel()->GetSpillOperand(); 2671 spill_operand = range->TopLevel()->GetSpillOperand();
2726 } else if (range->TopLevel()->HasSpillRange()) {
2727 spill_operand = range->TopLevel()->GetSpillRangeOperand();
2728 } 2672 }
2729 auto assigned = range->GetAssignedOperand(); 2673 auto assigned = range->GetAssignedOperand();
2730 range->ConvertUsesToOperand(assigned, spill_operand); 2674 range->ConvertUsesToOperand(assigned, spill_operand);
2731 if (range->is_phi()) { 2675 if (range->is_phi()) {
2732 data()->GetPhiMapValueFor(range->id())->CommitAssignment(assigned); 2676 data()->GetPhiMapValueFor(range->id())->CommitAssignment(assigned);
2733 } 2677 }
2734 if (!range->IsChild() && !spill_operand.IsInvalid()) { 2678 if (!range->IsChild() && spill_operand != nullptr) {
2735 range->CommitSpillsAtDefinition(data()->code(), spill_operand, 2679 range->CommitSpillsAtDefinition(data()->code(), spill_operand,
2736 range->has_slot_use()); 2680 range->has_slot_use());
2737 } 2681 }
2738 } 2682 }
2739 } 2683 }
2740 2684
2741 2685
2742 ReferenceMapPopulator::ReferenceMapPopulator(RegisterAllocationData* data) 2686 ReferenceMapPopulator::ReferenceMapPopulator(RegisterAllocationData* data)
2743 : data_(data) {} 2687 : data_(data) {}
2744 2688
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after
2805 auto safe_point_pos = 2749 auto safe_point_pos =
2806 LifetimePosition::InstructionFromInstructionIndex(safe_point); 2750 LifetimePosition::InstructionFromInstructionIndex(safe_point);
2807 auto cur = range; 2751 auto cur = range;
2808 while (cur != nullptr && !cur->Covers(safe_point_pos)) { 2752 while (cur != nullptr && !cur->Covers(safe_point_pos)) {
2809 cur = cur->next(); 2753 cur = cur->next();
2810 } 2754 }
2811 if (cur == nullptr) continue; 2755 if (cur == nullptr) continue;
2812 2756
2813 // Check if the live range is spilled and the safe point is after 2757 // Check if the live range is spilled and the safe point is after
2814 // the spill position. 2758 // the spill position.
2815 if (((range->HasSpillOperand() && 2759 if (range->HasSpillOperand() &&
2816 !range->GetSpillOperand()->IsConstant()) || 2760 safe_point >= range->spill_start_index() &&
2817 range->HasSpillRange()) && 2761 !range->GetSpillOperand()->IsConstant()) {
2818 safe_point >= range->spill_start_index()) {
2819 TRACE("Pointer for range %d (spilled at %d) at safe point %d\n", 2762 TRACE("Pointer for range %d (spilled at %d) at safe point %d\n",
2820 range->id(), range->spill_start_index(), safe_point); 2763 range->id(), range->spill_start_index(), safe_point);
2821 InstructionOperand operand; 2764 map->RecordReference(*range->GetSpillOperand());
2822 if (range->HasSpillOperand()) {
2823 operand = *range->GetSpillOperand();
2824 } else {
2825 operand = range->GetSpillRangeOperand();
2826 }
2827 DCHECK(operand.IsStackSlot());
2828 DCHECK_EQ(kRepTagged, AllocatedOperand::cast(operand).machine_type());
2829 map->RecordReference(operand);
2830 } 2765 }
2831 2766
2832 if (!cur->spilled()) { 2767 if (!cur->spilled()) {
2833 TRACE( 2768 TRACE(
2834 "Pointer in register for range %d (start at %d) " 2769 "Pointer in register for range %d (start at %d) "
2835 "at safe point %d\n", 2770 "at safe point %d\n",
2836 cur->id(), cur->Start().value(), safe_point); 2771 cur->id(), cur->Start().value(), safe_point);
2837 auto operand = cur->GetAssignedOperand(); 2772 auto operand = cur->GetAssignedOperand();
2838 DCHECK(!operand.IsStackSlot()); 2773 DCHECK(!operand.IsStackSlot());
2839 DCHECK_EQ(kRepTagged, AllocatedOperand::cast(operand).machine_type());
2840 map->RecordReference(operand); 2774 map->RecordReference(operand);
2841 } 2775 }
2842 } 2776 }
2843 } 2777 }
2844 } 2778 }
2845 2779
2846 2780
2847 namespace { 2781 namespace {
2848 2782
2849 class LiveRangeBound { 2783 class LiveRangeBound {
(...skipping 118 matching lines...) Expand 10 before | Expand all | Expand 10 after
2968 2902
2969 private: 2903 private:
2970 const RegisterAllocationData* const data_; 2904 const RegisterAllocationData* const data_;
2971 const int bounds_length_; 2905 const int bounds_length_;
2972 LiveRangeBoundArray* const bounds_; 2906 LiveRangeBoundArray* const bounds_;
2973 Zone* const zone_; 2907 Zone* const zone_;
2974 2908
2975 DISALLOW_COPY_AND_ASSIGN(LiveRangeFinder); 2909 DISALLOW_COPY_AND_ASSIGN(LiveRangeFinder);
2976 }; 2910 };
2977 2911
2978
2979 typedef std::pair<ParallelMove*, InstructionOperand> DelayedInsertionMapKey;
2980
2981
2982 struct DelayedInsertionMapCompare {
2983 bool operator()(const DelayedInsertionMapKey& a,
2984 const DelayedInsertionMapKey& b) {
2985 if (a.first == b.first) {
2986 return a.second.Compare(b.second);
2987 }
2988 return a.first < b.first;
2989 }
2990 };
2991
2992
2993 typedef ZoneMap<DelayedInsertionMapKey, InstructionOperand,
2994 DelayedInsertionMapCompare> DelayedInsertionMap;
2995
2996 } // namespace 2912 } // namespace
2997 2913
2998 2914
2999 LiveRangeConnector::LiveRangeConnector(RegisterAllocationData* data) 2915 LiveRangeConnector::LiveRangeConnector(RegisterAllocationData* data)
3000 : data_(data) {} 2916 : data_(data) {}
3001 2917
3002 2918
3003 bool LiveRangeConnector::CanEagerlyResolveControlFlow( 2919 bool LiveRangeConnector::CanEagerlyResolveControlFlow(
3004 const InstructionBlock* block) const { 2920 const InstructionBlock* block) const {
3005 if (block->PredecessorCount() != 1) return false; 2921 if (block->PredecessorCount() != 1) return false;
(...skipping 13 matching lines...) Expand all
3019 auto* array = finder.ArrayFor(iterator.Current()); 2935 auto* array = finder.ArrayFor(iterator.Current());
3020 for (auto pred : block->predecessors()) { 2936 for (auto pred : block->predecessors()) {
3021 FindResult result; 2937 FindResult result;
3022 const auto* pred_block = code()->InstructionBlockAt(pred); 2938 const auto* pred_block = code()->InstructionBlockAt(pred);
3023 array->Find(block, pred_block, &result); 2939 array->Find(block, pred_block, &result);
3024 if (result.cur_cover_ == result.pred_cover_ || 2940 if (result.cur_cover_ == result.pred_cover_ ||
3025 result.cur_cover_->spilled()) 2941 result.cur_cover_->spilled())
3026 continue; 2942 continue;
3027 auto pred_op = result.pred_cover_->GetAssignedOperand(); 2943 auto pred_op = result.pred_cover_->GetAssignedOperand();
3028 auto cur_op = result.cur_cover_->GetAssignedOperand(); 2944 auto cur_op = result.cur_cover_->GetAssignedOperand();
3029 if (pred_op.Equals(cur_op)) continue; 2945 if (pred_op == cur_op) continue;
3030 ResolveControlFlow(block, cur_op, pred_block, pred_op); 2946 ResolveControlFlow(block, cur_op, pred_block, pred_op);
3031 } 2947 }
3032 iterator.Advance(); 2948 iterator.Advance();
3033 } 2949 }
3034 } 2950 }
3035 } 2951 }
3036 2952
3037 2953
3038 void LiveRangeConnector::ResolveControlFlow(const InstructionBlock* block, 2954 void LiveRangeConnector::ResolveControlFlow(const InstructionBlock* block,
3039 const InstructionOperand& cur_op, 2955 const InstructionOperand& cur_op,
3040 const InstructionBlock* pred, 2956 const InstructionBlock* pred,
3041 const InstructionOperand& pred_op) { 2957 const InstructionOperand& pred_op) {
3042 DCHECK(!pred_op.Equals(cur_op)); 2958 DCHECK(pred_op != cur_op);
3043 int gap_index; 2959 int gap_index;
3044 Instruction::GapPosition position; 2960 Instruction::GapPosition position;
3045 if (block->PredecessorCount() == 1) { 2961 if (block->PredecessorCount() == 1) {
3046 gap_index = block->first_instruction_index(); 2962 gap_index = block->first_instruction_index();
3047 position = Instruction::START; 2963 position = Instruction::START;
3048 } else { 2964 } else {
3049 DCHECK(pred->SuccessorCount() == 1); 2965 DCHECK(pred->SuccessorCount() == 1);
3050 DCHECK(!code() 2966 DCHECK(!code()
3051 ->InstructionAt(pred->last_instruction_index()) 2967 ->InstructionAt(pred->last_instruction_index())
3052 ->HasReferenceMap()); 2968 ->HasReferenceMap());
3053 gap_index = pred->last_instruction_index(); 2969 gap_index = pred->last_instruction_index();
3054 position = Instruction::END; 2970 position = Instruction::END;
3055 } 2971 }
3056 data()->AddGapMove(gap_index, position, pred_op, cur_op); 2972 data()->AddGapMove(gap_index, position, pred_op, cur_op);
3057 } 2973 }
3058 2974
3059 2975
3060 void LiveRangeConnector::ConnectRanges(Zone* local_zone) { 2976 void LiveRangeConnector::ConnectRanges(Zone* local_zone) {
3061 DelayedInsertionMap delayed_insertion_map(local_zone); 2977 ZoneMap<std::pair<ParallelMove*, InstructionOperand>, InstructionOperand>
2978 delayed_insertion_map(local_zone);
3062 for (auto first_range : data()->live_ranges()) { 2979 for (auto first_range : data()->live_ranges()) {
3063 if (first_range == nullptr || first_range->IsChild()) continue; 2980 if (first_range == nullptr || first_range->IsChild()) continue;
3064 for (auto second_range = first_range->next(); second_range != nullptr; 2981 for (auto second_range = first_range->next(); second_range != nullptr;
3065 first_range = second_range, second_range = second_range->next()) { 2982 first_range = second_range, second_range = second_range->next()) {
3066 auto pos = second_range->Start(); 2983 auto pos = second_range->Start();
3067 // Add gap move if the two live ranges touch and there is no block 2984 // Add gap move if the two live ranges touch and there is no block
3068 // boundary. 2985 // boundary.
3069 if (second_range->spilled()) continue; 2986 if (second_range->spilled()) continue;
3070 if (first_range->End() != pos) continue; 2987 if (first_range->End() != pos) continue;
3071 if (IsBlockBoundary(code(), pos) && 2988 if (IsBlockBoundary(code(), pos) &&
3072 !CanEagerlyResolveControlFlow(GetInstructionBlock(code(), pos))) { 2989 !CanEagerlyResolveControlFlow(GetInstructionBlock(code(), pos))) {
3073 continue; 2990 continue;
3074 } 2991 }
3075 auto prev_operand = first_range->GetAssignedOperand(); 2992 auto prev_operand = first_range->GetAssignedOperand();
3076 auto cur_operand = second_range->GetAssignedOperand(); 2993 auto cur_operand = second_range->GetAssignedOperand();
3077 if (prev_operand.Equals(cur_operand)) continue; 2994 if (prev_operand == cur_operand) continue;
3078 bool delay_insertion = false; 2995 bool delay_insertion = false;
3079 Instruction::GapPosition gap_pos; 2996 Instruction::GapPosition gap_pos;
3080 int gap_index = pos.ToInstructionIndex(); 2997 int gap_index = pos.ToInstructionIndex();
3081 if (pos.IsGapPosition()) { 2998 if (pos.IsGapPosition()) {
3082 gap_pos = pos.IsStart() ? Instruction::START : Instruction::END; 2999 gap_pos = pos.IsStart() ? Instruction::START : Instruction::END;
3083 } else { 3000 } else {
3084 if (pos.IsStart()) { 3001 if (pos.IsStart()) {
3085 delay_insertion = true; 3002 delay_insertion = true;
3086 } else { 3003 } else {
3087 gap_index++; 3004 gap_index++;
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
3126 auto eliminate = moves->PrepareInsertAfter(move); 3043 auto eliminate = moves->PrepareInsertAfter(move);
3127 to_insert.push_back(move); 3044 to_insert.push_back(move);
3128 if (eliminate != nullptr) to_eliminate.push_back(eliminate); 3045 if (eliminate != nullptr) to_eliminate.push_back(eliminate);
3129 } 3046 }
3130 } 3047 }
3131 3048
3132 3049
3133 } // namespace compiler 3050 } // namespace compiler
3134 } // namespace internal 3051 } // namespace internal
3135 } // namespace v8 3052 } // namespace v8
OLDNEW
« no previous file with comments | « src/compiler/register-allocator.h ('k') | src/compiler/register-allocator-verifier.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698