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

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

Issue 1103533002: [turbofan] remove hint aliasing (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Created 5 years, 8 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') | no next file » | 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 47 matching lines...) Expand 10 before | Expand all | Expand 10 after
58 code->GetInstructionBlock(pos.ToInstructionIndex())->code_start() == 58 code->GetInstructionBlock(pos.ToInstructionIndex())->code_start() ==
59 pos.ToInstructionIndex(); 59 pos.ToInstructionIndex();
60 } 60 }
61 61
62 62
63 Instruction* GetLastInstruction(InstructionSequence* code, 63 Instruction* GetLastInstruction(InstructionSequence* code,
64 const InstructionBlock* block) { 64 const InstructionBlock* block) {
65 return code->InstructionAt(block->last_instruction_index()); 65 return code->InstructionAt(block->last_instruction_index());
66 } 66 }
67 67
68
69 bool IsOutputRegisterOf(Instruction* instr, int index) {
70 for (size_t i = 0; i < instr->OutputCount(); i++) {
71 auto output = instr->OutputAt(i);
72 if (output->IsRegister() &&
73 RegisterOperand::cast(output)->index() == index) {
74 return true;
75 }
76 }
77 return false;
78 }
79
80
81 bool IsOutputDoubleRegisterOf(Instruction* instr, int index) {
82 for (size_t i = 0; i < instr->OutputCount(); i++) {
83 auto output = instr->OutputAt(i);
84 if (output->IsDoubleRegister() &&
85 DoubleRegisterOperand::cast(output)->index() == index) {
86 return true;
87 }
88 }
89 return false;
90 }
91
68 } // namespace 92 } // namespace
69 93
70 94
71 UsePosition::UsePosition(LifetimePosition pos, InstructionOperand* operand, 95 UsePosition::UsePosition(LifetimePosition pos, InstructionOperand* operand,
72 InstructionOperand* hint) 96 void* hint, UsePositionHintType hint_type)
73 : operand_(operand), hint_(hint), pos_(pos), next_(nullptr), flags_(0) { 97 : operand_(operand), hint_(hint), next_(nullptr), pos_(pos), flags_(0) {
98 DCHECK_IMPLIES(hint == nullptr, hint_type == UsePositionHintType::kNone);
74 bool register_beneficial = true; 99 bool register_beneficial = true;
75 UsePositionType type = UsePositionType::kAny; 100 UsePositionType type = UsePositionType::kAny;
76 if (operand_ != nullptr && operand_->IsUnallocated()) { 101 if (operand_ != nullptr && operand_->IsUnallocated()) {
77 const UnallocatedOperand* unalloc = UnallocatedOperand::cast(operand_); 102 const UnallocatedOperand* unalloc = UnallocatedOperand::cast(operand_);
78 if (unalloc->HasRegisterPolicy()) { 103 if (unalloc->HasRegisterPolicy()) {
79 type = UsePositionType::kRequiresRegister; 104 type = UsePositionType::kRequiresRegister;
80 } else if (unalloc->HasSlotPolicy()) { 105 } else if (unalloc->HasSlotPolicy()) {
81 type = UsePositionType::kRequiresSlot; 106 type = UsePositionType::kRequiresSlot;
82 register_beneficial = false; 107 register_beneficial = false;
83 } else { 108 } else {
84 register_beneficial = !unalloc->HasAnyPolicy(); 109 register_beneficial = !unalloc->HasAnyPolicy();
85 } 110 }
86 } 111 }
87 flags_ = TypeField::encode(type) | 112 flags_ = TypeField::encode(type) | HintTypeField::encode(hint_type) |
88 RegisterBeneficialField::encode(register_beneficial); 113 RegisterBeneficialField::encode(register_beneficial) |
114 AssignedRegisterField::encode(kUnassignedRegister);
89 DCHECK(pos_.IsValid()); 115 DCHECK(pos_.IsValid());
90 } 116 }
91 117
92 118
93 bool UsePosition::HasHint() const { 119 bool UsePosition::HasHint() const {
94 return hint_ != nullptr && !hint_->IsUnallocated(); 120 int hint_register;
121 return HintRegister(&hint_register);
95 } 122 }
96 123
97 124
125 bool UsePosition::HintRegister(int* register_index) const {
126 if (hint_ == nullptr) return false;
127 switch (HintTypeField::decode(flags_)) {
128 case UsePositionHintType::kNone:
129 case UsePositionHintType::kUnresolved:
130 return false;
131 case UsePositionHintType::kUsePos: {
132 auto use_pos = reinterpret_cast<UsePosition*>(hint_);
133 int assigned_register = AssignedRegisterField::decode(use_pos->flags_);
134 if (assigned_register == kUnassignedRegister) return false;
135 *register_index = assigned_register;
136 return true;
137 }
138 case UsePositionHintType::kOperand: {
139 auto operand = reinterpret_cast<InstructionOperand*>(hint_);
140 int assigned_register = AllocatedOperand::cast(operand)->index();
141 *register_index = assigned_register;
142 return true;
143 }
144 case UsePositionHintType::kPhi: {
145 auto phi = reinterpret_cast<RegisterAllocationData::PhiMapValue*>(hint_);
146 int assigned_register = phi->assigned_register();
147 if (assigned_register == kUnassignedRegister) return false;
148 *register_index = assigned_register;
149 return true;
150 }
151 }
152 UNREACHABLE();
153 return false;
154 }
155
156
157 UsePositionHintType UsePosition::HintTypeForOperand(
158 const InstructionOperand& op) {
159 switch (op.kind()) {
160 case InstructionOperand::CONSTANT:
161 case InstructionOperand::IMMEDIATE:
162 return UsePositionHintType::kNone;
163 case InstructionOperand::UNALLOCATED:
164 return UsePositionHintType::kUnresolved;
165 case InstructionOperand::ALLOCATED:
166 switch (AllocatedOperand::cast(op).allocated_kind()) {
167 case AllocatedOperand::REGISTER:
168 case AllocatedOperand::DOUBLE_REGISTER:
169 return UsePositionHintType::kOperand;
170 case AllocatedOperand::STACK_SLOT:
171 case AllocatedOperand::DOUBLE_STACK_SLOT:
172 return UsePositionHintType::kNone;
173 }
174 case InstructionOperand::INVALID:
175 break;
176 }
177 UNREACHABLE();
178 return UsePositionHintType::kNone;
179 }
180
181
182 void UsePosition::ResolveHint(UsePosition* use_pos) {
183 DCHECK_NOT_NULL(use_pos);
184 if (HintTypeField::decode(flags_) != UsePositionHintType::kUnresolved) return;
185 hint_ = use_pos;
186 flags_ = HintTypeField::update(flags_, UsePositionHintType::kUsePos);
187 }
188
189
98 void UsePosition::set_type(UsePositionType type, bool register_beneficial) { 190 void UsePosition::set_type(UsePositionType type, bool register_beneficial) {
99 DCHECK_IMPLIES(type == UsePositionType::kRequiresSlot, !register_beneficial); 191 DCHECK_IMPLIES(type == UsePositionType::kRequiresSlot, !register_beneficial);
100 flags_ = TypeField::encode(type) | 192 flags_ = TypeField::encode(type) |
101 RegisterBeneficialField::encode(register_beneficial); 193 RegisterBeneficialField::encode(register_beneficial);
102 } 194 }
103 195
104 196
105 UseInterval* UseInterval::SplitAt(LifetimePosition pos, Zone* zone) { 197 UseInterval* UseInterval::SplitAt(LifetimePosition pos, Zone* zone) {
106 DCHECK(Contains(pos) && pos != start()); 198 DCHECK(Contains(pos) && pos != start());
107 auto after = new (zone) UseInterval(pos, end_); 199 auto after = new (zone) UseInterval(pos, end_);
(...skipping 14 matching lines...) Expand all
122 }; 214 };
123 215
124 216
125 LiveRange::LiveRange(int id) 217 LiveRange::LiveRange(int id)
126 : id_(id), 218 : id_(id),
127 spilled_(false), 219 spilled_(false),
128 has_slot_use_(false), 220 has_slot_use_(false),
129 is_phi_(false), 221 is_phi_(false),
130 is_non_loop_phi_(false), 222 is_non_loop_phi_(false),
131 kind_(UNALLOCATED_REGISTERS), 223 kind_(UNALLOCATED_REGISTERS),
132 assigned_register_(kInvalidAssignment), 224 assigned_register_(kUnassignedRegister),
133 last_interval_(nullptr), 225 last_interval_(nullptr),
134 first_interval_(nullptr), 226 first_interval_(nullptr),
135 first_pos_(nullptr), 227 first_pos_(nullptr),
136 parent_(nullptr), 228 parent_(nullptr),
137 next_(nullptr), 229 next_(nullptr),
138 current_interval_(nullptr), 230 current_interval_(nullptr),
139 last_processed_use_(nullptr), 231 last_processed_use_(nullptr),
140 current_hint_operand_(nullptr), 232 current_hint_position_(nullptr),
141 spill_start_index_(kMaxInt), 233 spill_start_index_(kMaxInt),
142 spill_type_(SpillType::kNoSpillType), 234 spill_type_(SpillType::kNoSpillType),
143 spill_operand_(nullptr), 235 spill_operand_(nullptr),
144 spills_at_definition_(nullptr) {} 236 spills_at_definition_(nullptr) {}
145 237
146 238
147 void LiveRange::Verify() const { 239 void LiveRange::Verify() const {
148 // Walk the positions, verifying that each is in an interval. 240 // Walk the positions, verifying that each is in an interval.
149 auto interval = first_interval_; 241 auto interval = first_interval_;
150 for (auto pos = first_pos_; pos != nullptr; pos = pos->next()) { 242 for (auto pos = first_pos_; pos != nullptr; pos = pos->next()) {
151 CHECK(Start() <= pos->pos()); 243 CHECK(Start() <= pos->pos());
152 CHECK(pos->pos() <= End()); 244 CHECK(pos->pos() <= End());
153 CHECK(interval != nullptr); 245 CHECK(interval != nullptr);
154 while (!interval->Contains(pos->pos()) && interval->end() != pos->pos()) { 246 while (!interval->Contains(pos->pos()) && interval->end() != pos->pos()) {
155 interval = interval->next(); 247 interval = interval->next();
156 CHECK(interval != nullptr); 248 CHECK(interval != nullptr);
157 } 249 }
158 } 250 }
159 } 251 }
160 252
161 253
162 void LiveRange::set_assigned_register(int reg) { 254 void LiveRange::set_assigned_register(int reg) {
163 DCHECK(!HasRegisterAssigned() && !IsSpilled()); 255 DCHECK(!HasRegisterAssigned() && !IsSpilled());
164 assigned_register_ = reg; 256 assigned_register_ = reg;
165 } 257 }
166 258
167 259
260 void LiveRange::UnsetAssignedRegister() {
261 DCHECK(HasRegisterAssigned() && !IsSpilled());
262 assigned_register_ = kUnassignedRegister;
263 }
264
265
168 void LiveRange::MakeSpilled() { 266 void LiveRange::MakeSpilled() {
169 DCHECK(!IsSpilled()); 267 DCHECK(!IsSpilled());
170 DCHECK(!TopLevel()->HasNoSpillType()); 268 DCHECK(!TopLevel()->HasNoSpillType());
171 spilled_ = true; 269 spilled_ = true;
172 assigned_register_ = kInvalidAssignment; 270 assigned_register_ = kUnassignedRegister;
173 } 271 }
174 272
175 273
176 void LiveRange::SpillAtDefinition(Zone* zone, int gap_index, 274 void LiveRange::SpillAtDefinition(Zone* zone, int gap_index,
177 InstructionOperand* operand) { 275 InstructionOperand* operand) {
178 DCHECK(HasNoSpillType()); 276 DCHECK(HasNoSpillType());
179 spills_at_definition_ = new (zone) 277 spills_at_definition_ = new (zone)
180 SpillAtDefinitionList(gap_index, operand, spills_at_definition_); 278 SpillAtDefinitionList(gap_index, operand, spills_at_definition_);
181 } 279 }
182 280
(...skipping 20 matching lines...) Expand all
203 break; 301 break;
204 } 302 }
205 } 303 }
206 if (found) continue; 304 if (found) continue;
207 } 305 }
208 move->AddMove(*to_spill->operand, *op); 306 move->AddMove(*to_spill->operand, *op);
209 } 307 }
210 } 308 }
211 309
212 310
311 UsePosition* LiveRange::FirstHintPosition(int* register_index) const {
312 for (auto pos = first_pos_; pos != nullptr; pos = pos->next()) {
313 if (pos->HintRegister(register_index)) return pos;
314 }
315 return nullptr;
316 }
317
318
213 void LiveRange::SetSpillOperand(InstructionOperand* operand) { 319 void LiveRange::SetSpillOperand(InstructionOperand* operand) {
214 DCHECK(HasNoSpillType()); 320 DCHECK(HasNoSpillType());
215 DCHECK(!operand->IsUnallocated() && !operand->IsImmediate()); 321 DCHECK(!operand->IsUnallocated() && !operand->IsImmediate());
216 spill_type_ = SpillType::kSpillOperand; 322 spill_type_ = SpillType::kSpillOperand;
217 spill_operand_ = operand; 323 spill_operand_ = operand;
218 } 324 }
219 325
220 326
221 void LiveRange::SetSpillRange(SpillRange* spill_range) { 327 void LiveRange::SetSpillRange(SpillRange* spill_range) {
222 DCHECK(HasNoSpillType() || HasSpillRange()); 328 DCHECK(HasNoSpillType() || HasSpillRange());
(...skipping 264 matching lines...) Expand 10 before | Expand all | Expand 10 after
487 // that each new use interval either precedes or intersects with 593 // that each new use interval either precedes or intersects with
488 // last added interval. 594 // last added interval.
489 DCHECK(start < first_interval_->end()); 595 DCHECK(start < first_interval_->end());
490 first_interval_->set_start(Min(start, first_interval_->start())); 596 first_interval_->set_start(Min(start, first_interval_->start()));
491 first_interval_->set_end(Max(end, first_interval_->end())); 597 first_interval_->set_end(Max(end, first_interval_->end()));
492 } 598 }
493 } 599 }
494 } 600 }
495 601
496 602
497 void LiveRange::AddUsePosition(LifetimePosition pos, 603 void LiveRange::AddUsePosition(UsePosition* use_pos) {
498 InstructionOperand* operand, 604 auto pos = use_pos->pos();
499 InstructionOperand* hint, Zone* zone) {
500 TRACE("Add to live range %d use position %d\n", id_, pos.value()); 605 TRACE("Add to live range %d use position %d\n", id_, pos.value());
501 auto use_pos = new (zone) UsePosition(pos, operand, hint);
502 UsePosition* prev_hint = nullptr; 606 UsePosition* prev_hint = nullptr;
503 UsePosition* prev = nullptr; 607 UsePosition* prev = nullptr;
504 auto current = first_pos_; 608 auto current = first_pos_;
505 while (current != nullptr && current->pos() < pos) { 609 while (current != nullptr && current->pos() < pos) {
506 prev_hint = current->HasHint() ? current : prev_hint; 610 prev_hint = current->HasHint() ? current : prev_hint;
507 prev = current; 611 prev = current;
508 current = current->next(); 612 current = current->next();
509 } 613 }
510 614
511 if (prev == nullptr) { 615 if (prev == nullptr) {
512 use_pos->set_next(first_pos_); 616 use_pos->set_next(first_pos_);
513 first_pos_ = use_pos; 617 first_pos_ = use_pos;
514 } else { 618 } else {
515 use_pos->set_next(prev->next()); 619 use_pos->set_next(prev->next());
516 prev->set_next(use_pos); 620 prev->set_next(use_pos);
517 } 621 }
518 622
519 if (prev_hint == nullptr && use_pos->HasHint()) { 623 if (prev_hint == nullptr && use_pos->HasHint()) {
520 current_hint_operand_ = hint; 624 current_hint_position_ = use_pos;
521 } 625 }
522 } 626 }
523 627
524 628
525 void LiveRange::ConvertUsesToOperand(const InstructionOperand& op, 629 void LiveRange::ConvertUsesToOperand(const InstructionOperand& op,
526 InstructionOperand* spill_op) { 630 InstructionOperand* spill_op) {
527 for (auto pos = first_pos(); pos != nullptr; pos = pos->next()) { 631 for (auto pos = first_pos(); pos != nullptr; pos = pos->next()) {
528 DCHECK(Start() <= pos->pos() && pos->pos() <= End()); 632 DCHECK(Start() <= pos->pos() && pos->pos() <= End());
529 if (!pos->HasOperand()) { 633 if (!pos->HasOperand()) continue;
530 continue;
531 }
532 switch (pos->type()) { 634 switch (pos->type()) {
533 case UsePositionType::kRequiresSlot: 635 case UsePositionType::kRequiresSlot:
534 if (spill_op != nullptr) { 636 if (spill_op != nullptr) {
535 InstructionOperand::ReplaceWith(pos->operand(), spill_op); 637 InstructionOperand::ReplaceWith(pos->operand(), spill_op);
536 } 638 }
537 break; 639 break;
538 case UsePositionType::kRequiresRegister: 640 case UsePositionType::kRequiresRegister:
539 DCHECK(op.IsRegister() || op.IsDoubleRegister()); 641 DCHECK(op.IsRegister() || op.IsDoubleRegister());
540 // Fall through. 642 // Fall through.
541 case UsePositionType::kAny: 643 case UsePositionType::kAny:
542 InstructionOperand::ReplaceWith(pos->operand(), &op); 644 InstructionOperand::ReplaceWith(pos->operand(), &op);
543 break; 645 break;
544 } 646 }
545 } 647 }
546 } 648 }
547 649
548 650
651 void LiveRange::SetUseHints(int register_index) {
652 for (auto pos = first_pos(); pos != nullptr; pos = pos->next()) {
653 if (!pos->HasOperand()) continue;
654 switch (pos->type()) {
655 case UsePositionType::kRequiresSlot:
656 break;
657 case UsePositionType::kRequiresRegister:
658 case UsePositionType::kAny:
659 pos->set_assigned_register(register_index);
660 break;
661 }
662 }
663 }
664
665
549 bool LiveRange::CanCover(LifetimePosition position) const { 666 bool LiveRange::CanCover(LifetimePosition position) const {
550 if (IsEmpty()) return false; 667 if (IsEmpty()) return false;
551 return Start() <= position && position < End(); 668 return Start() <= position && position < End();
552 } 669 }
553 670
554 671
555 bool LiveRange::Covers(LifetimePosition position) const { 672 bool LiveRange::Covers(LifetimePosition position) const {
556 if (!CanCover(position)) return false; 673 if (!CanCover(position)) return false;
557 auto start_search = FirstSearchIntervalForPosition(position); 674 auto start_search = FirstSearchIntervalForPosition(position);
558 for (auto interval = start_search; interval != nullptr; 675 for (auto interval = start_search; interval != nullptr;
(...skipping 136 matching lines...) Expand 10 before | Expand all | Expand 10 after
695 } else { 812 } else {
696 tail->set_next(current); 813 tail->set_next(current);
697 } 814 }
698 tail = current; 815 tail = current;
699 current = current->next(); 816 current = current->next();
700 } 817 }
701 // Other list is empty => we are done 818 // Other list is empty => we are done
702 } 819 }
703 820
704 821
822 RegisterAllocationData::PhiMapValue::PhiMapValue(PhiInstruction* phi,
823 const InstructionBlock* block,
824 Zone* zone)
825 : phi_(phi),
826 block_(block),
827 incoming_operands_(zone),
828 assigned_register_(kUnassignedRegister) {
829 incoming_operands_.reserve(phi->operands().size());
830 }
831
832
833 void RegisterAllocationData::PhiMapValue::AddOperand(
834 InstructionOperand* operand) {
835 incoming_operands_.push_back(operand);
836 }
837
838
839 void RegisterAllocationData::PhiMapValue::CommitAssignment(
840 const InstructionOperand& assigned) {
841 for (auto operand : incoming_operands_) {
842 InstructionOperand::ReplaceWith(operand, &assigned);
843 }
844 }
845
846
705 RegisterAllocationData::RegisterAllocationData( 847 RegisterAllocationData::RegisterAllocationData(
706 const RegisterConfiguration* config, Zone* zone, Frame* frame, 848 const RegisterConfiguration* config, Zone* zone, Frame* frame,
707 InstructionSequence* code, const char* debug_name) 849 InstructionSequence* code, const char* debug_name)
708 : allocation_zone_(zone), 850 : allocation_zone_(zone),
709 frame_(frame), 851 frame_(frame),
710 code_(code), 852 code_(code),
711 debug_name_(debug_name), 853 debug_name_(debug_name),
712 config_(config), 854 config_(config),
713 phi_map_(allocation_zone()), 855 phi_map_(allocation_zone()),
714 live_in_sets_(code->InstructionBlockCount(), nullptr, allocation_zone()), 856 live_in_sets_(code->InstructionBlockCount(), nullptr, allocation_zone()),
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
750 892
751 MoveOperands* RegisterAllocationData::AddGapMove( 893 MoveOperands* RegisterAllocationData::AddGapMove(
752 int index, Instruction::GapPosition position, 894 int index, Instruction::GapPosition position,
753 const InstructionOperand& from, const InstructionOperand& to) { 895 const InstructionOperand& from, const InstructionOperand& to) {
754 auto instr = code()->InstructionAt(index); 896 auto instr = code()->InstructionAt(index);
755 auto moves = instr->GetOrCreateParallelMove(position, code_zone()); 897 auto moves = instr->GetOrCreateParallelMove(position, code_zone());
756 return moves->AddMove(from, to); 898 return moves->AddMove(from, to);
757 } 899 }
758 900
759 901
760 void RegisterAllocationData::AssignPhiInput(
761 LiveRange* range, const InstructionOperand& assignment) {
762 DCHECK(range->is_phi());
763 auto it = phi_map().find(range->id());
764 DCHECK(it != phi_map().end());
765 for (auto move : it->second->incoming_moves) {
766 move->set_destination(assignment);
767 }
768 }
769
770
771 LiveRange* RegisterAllocationData::NewLiveRange(int index) { 902 LiveRange* RegisterAllocationData::NewLiveRange(int index) {
772 return new (allocation_zone()) LiveRange(index); 903 return new (allocation_zone()) LiveRange(index);
773 } 904 }
774 905
775 906
907 RegisterAllocationData::PhiMapValue* RegisterAllocationData::InitializePhiMap(
908 const InstructionBlock* block, PhiInstruction* phi) {
909 auto map_value = new (allocation_zone())
910 RegisterAllocationData::PhiMapValue(phi, block, allocation_zone());
911 auto res =
912 phi_map_.insert(std::make_pair(phi->virtual_register(), map_value));
913 DCHECK(res.second);
914 USE(res);
915 return map_value;
916 }
917
918
919 RegisterAllocationData::PhiMapValue* RegisterAllocationData::GetPhiMapValueFor(
920 int virtual_register) {
921 auto it = phi_map_.find(virtual_register);
922 DCHECK(it != phi_map_.end());
923 return it->second;
924 }
925
926
776 bool RegisterAllocationData::ExistsUseWithoutDefinition() { 927 bool RegisterAllocationData::ExistsUseWithoutDefinition() {
777 bool found = false; 928 bool found = false;
778 BitVector::Iterator iterator(live_in_sets()[0]); 929 BitVector::Iterator iterator(live_in_sets()[0]);
779 while (!iterator.Done()) { 930 while (!iterator.Done()) {
780 found = true; 931 found = true;
781 int operand_index = iterator.Current(); 932 int operand_index = iterator.Current();
782 PrintF("Register allocator error: live v%d reached first block.\n", 933 PrintF("Register allocator error: live v%d reached first block.\n",
783 operand_index); 934 operand_index);
784 LiveRange* range = LiveRangeFor(operand_index); 935 LiveRange* range = LiveRangeFor(operand_index);
785 PrintF(" (first use is at %d)\n", range->first_pos()->pos().value()); 936 PrintF(" (first use is at %d)\n", range->first_pos()->pos().value());
(...skipping 10 matching lines...) Expand all
796 947
797 SpillRange* RegisterAllocationData::AssignSpillRangeToLiveRange( 948 SpillRange* RegisterAllocationData::AssignSpillRangeToLiveRange(
798 LiveRange* range) { 949 LiveRange* range) {
799 auto spill_range = 950 auto spill_range =
800 new (allocation_zone()) SpillRange(range, allocation_zone()); 951 new (allocation_zone()) SpillRange(range, allocation_zone());
801 spill_ranges().push_back(spill_range); 952 spill_ranges().push_back(spill_range);
802 return spill_range; 953 return spill_range;
803 } 954 }
804 955
805 956
806 void RegisterAllocationData::SetLiveRangeAssignedRegister(LiveRange* range, 957 void RegisterAllocationData::MarkAllocated(RegisterKind kind, int index) {
807 int reg) { 958 if (kind == DOUBLE_REGISTERS) {
808 if (range->Kind() == DOUBLE_REGISTERS) { 959 assigned_double_registers_->Add(index);
809 assigned_double_registers_->Add(reg);
810 } else { 960 } else {
811 DCHECK(range->Kind() == GENERAL_REGISTERS); 961 DCHECK(kind == GENERAL_REGISTERS);
812 assigned_registers_->Add(reg); 962 assigned_registers_->Add(index);
813 } 963 }
814 range->set_assigned_register(reg);
815 auto assignment = range->GetAssignedOperand();
816 // TODO(dcarney): stop aliasing hint operands.
817 range->ConvertUsesToOperand(assignment, nullptr);
818 if (range->is_phi()) AssignPhiInput(range, assignment);
819 } 964 }
820 965
821 966
822 ConstraintBuilder::ConstraintBuilder(RegisterAllocationData* data) 967 ConstraintBuilder::ConstraintBuilder(RegisterAllocationData* data)
823 : data_(data) {} 968 : data_(data) {}
824 969
825 970
826 InstructionOperand* ConstraintBuilder::AllocateFixed( 971 InstructionOperand* ConstraintBuilder::AllocateFixed(
827 UnallocatedOperand* operand, int pos, bool is_tagged) { 972 UnallocatedOperand* operand, int pos, bool is_tagged) {
828 TRACE("Allocating fixed reg for op %d\n", operand->virtual_register()); 973 TRACE("Allocating fixed reg for op %d\n", operand->virtual_register());
(...skipping 186 matching lines...) Expand 10 before | Expand all | Expand 10 after
1015 // Process the blocks in reverse order. 1160 // Process the blocks in reverse order.
1016 for (InstructionBlock* block : base::Reversed(code()->instruction_blocks())) { 1161 for (InstructionBlock* block : base::Reversed(code()->instruction_blocks())) {
1017 ResolvePhis(block); 1162 ResolvePhis(block);
1018 } 1163 }
1019 } 1164 }
1020 1165
1021 1166
1022 void ConstraintBuilder::ResolvePhis(const InstructionBlock* block) { 1167 void ConstraintBuilder::ResolvePhis(const InstructionBlock* block) {
1023 for (auto phi : block->phis()) { 1168 for (auto phi : block->phis()) {
1024 int phi_vreg = phi->virtual_register(); 1169 int phi_vreg = phi->virtual_register();
1025 auto map_value = new (allocation_zone()) 1170 auto map_value = data()->InitializePhiMap(block, phi);
1026 RegisterAllocationData::PhiMapValue(phi, block, allocation_zone());
1027 auto res = data()->phi_map().insert(std::make_pair(phi_vreg, map_value));
1028 DCHECK(res.second);
1029 USE(res);
1030 auto& output = phi->output(); 1171 auto& output = phi->output();
1172 // Map the destination operands, so the commitment phase can find them.
1031 for (size_t i = 0; i < phi->operands().size(); ++i) { 1173 for (size_t i = 0; i < phi->operands().size(); ++i) {
1032 InstructionBlock* cur_block = 1174 InstructionBlock* cur_block =
1033 code()->InstructionBlockAt(block->predecessors()[i]); 1175 code()->InstructionBlockAt(block->predecessors()[i]);
1034 UnallocatedOperand input(UnallocatedOperand::ANY, phi->operands()[i]); 1176 UnallocatedOperand input(UnallocatedOperand::ANY, phi->operands()[i]);
1035 auto move = data()->AddGapMove(cur_block->last_instruction_index(), 1177 auto move = data()->AddGapMove(cur_block->last_instruction_index(),
1036 Instruction::END, input, output); 1178 Instruction::END, input, output);
1037 map_value->incoming_moves.push_back(move); 1179 map_value->AddOperand(&move->destination());
1038 DCHECK(!InstructionAt(cur_block->last_instruction_index()) 1180 DCHECK(!InstructionAt(cur_block->last_instruction_index())
1039 ->HasReferenceMap()); 1181 ->HasReferenceMap());
1040 } 1182 }
1041 auto live_range = LiveRangeFor(phi_vreg); 1183 auto live_range = LiveRangeFor(phi_vreg);
1042 int gap_index = block->first_instruction_index(); 1184 int gap_index = block->first_instruction_index();
1043 live_range->SpillAtDefinition(allocation_zone(), gap_index, &output); 1185 live_range->SpillAtDefinition(allocation_zone(), gap_index, &output);
1044 live_range->SetSpillStartIndex(gap_index); 1186 live_range->SetSpillStartIndex(gap_index);
1045 // We use the phi-ness of some nodes in some later heuristics. 1187 // We use the phi-ness of some nodes in some later heuristics.
1046 live_range->set_is_phi(true); 1188 live_range->set_is_phi(true);
1047 live_range->set_is_non_loop_phi(!block->IsLoopHeader()); 1189 live_range->set_is_non_loop_phi(!block->IsLoopHeader());
1048 } 1190 }
1049 } 1191 }
1050 1192
1051 1193
1052 LiveRangeBuilder::LiveRangeBuilder(RegisterAllocationData* data) 1194 LiveRangeBuilder::LiveRangeBuilder(RegisterAllocationData* data,
1053 : data_(data) {} 1195 Zone* local_zone)
1196 : data_(data), phi_hints_(local_zone) {}
1054 1197
1055 1198
1056 BitVector* LiveRangeBuilder::ComputeLiveOut(const InstructionBlock* block) { 1199 BitVector* LiveRangeBuilder::ComputeLiveOut(const InstructionBlock* block) {
1057 // Compute live out for the given block, except not including backward 1200 // Compute live out for the given block, except not including backward
1058 // successor edges. 1201 // successor edges.
1059 auto live_out = new (allocation_zone()) 1202 auto live_out = new (allocation_zone())
1060 BitVector(code()->VirtualRegisterCount(), allocation_zone()); 1203 BitVector(code()->VirtualRegisterCount(), allocation_zone());
1061 1204
1062 // Process all successor blocks. 1205 // Process all successor blocks.
1063 for (auto succ : block->successors()) { 1206 for (auto succ : block->successors()) {
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
1102 } 1245 }
1103 1246
1104 1247
1105 LiveRange* LiveRangeBuilder::FixedLiveRangeFor(int index) { 1248 LiveRange* LiveRangeBuilder::FixedLiveRangeFor(int index) {
1106 DCHECK(index < config()->num_general_registers()); 1249 DCHECK(index < config()->num_general_registers());
1107 auto result = data()->fixed_live_ranges()[index]; 1250 auto result = data()->fixed_live_ranges()[index];
1108 if (result == nullptr) { 1251 if (result == nullptr) {
1109 result = data()->NewLiveRange(FixedLiveRangeID(index)); 1252 result = data()->NewLiveRange(FixedLiveRangeID(index));
1110 DCHECK(result->IsFixed()); 1253 DCHECK(result->IsFixed());
1111 result->set_kind(GENERAL_REGISTERS); 1254 result->set_kind(GENERAL_REGISTERS);
1112 data()->SetLiveRangeAssignedRegister(result, index); 1255 result->set_assigned_register(index);
1256 data()->MarkAllocated(GENERAL_REGISTERS, index);
1113 data()->fixed_live_ranges()[index] = result; 1257 data()->fixed_live_ranges()[index] = result;
1114 } 1258 }
1115 return result; 1259 return result;
1116 } 1260 }
1117 1261
1118 1262
1119 LiveRange* LiveRangeBuilder::FixedDoubleLiveRangeFor(int index) { 1263 LiveRange* LiveRangeBuilder::FixedDoubleLiveRangeFor(int index) {
1120 DCHECK(index < config()->num_aliased_double_registers()); 1264 DCHECK(index < config()->num_aliased_double_registers());
1121 auto result = data()->fixed_double_live_ranges()[index]; 1265 auto result = data()->fixed_double_live_ranges()[index];
1122 if (result == nullptr) { 1266 if (result == nullptr) {
1123 result = data()->NewLiveRange(FixedDoubleLiveRangeID(index)); 1267 result = data()->NewLiveRange(FixedDoubleLiveRangeID(index));
1124 DCHECK(result->IsFixed()); 1268 DCHECK(result->IsFixed());
1125 result->set_kind(DOUBLE_REGISTERS); 1269 result->set_kind(DOUBLE_REGISTERS);
1126 data()->SetLiveRangeAssignedRegister(result, index); 1270 result->set_assigned_register(index);
1271 data()->MarkAllocated(DOUBLE_REGISTERS, index);
1127 data()->fixed_double_live_ranges()[index] = result; 1272 data()->fixed_double_live_ranges()[index] = result;
1128 } 1273 }
1129 return result; 1274 return result;
1130 } 1275 }
1131 1276
1132 1277
1133 LiveRange* LiveRangeBuilder::LiveRangeFor(InstructionOperand* operand) { 1278 LiveRange* LiveRangeBuilder::LiveRangeFor(InstructionOperand* operand) {
1134 if (operand->IsUnallocated()) { 1279 if (operand->IsUnallocated()) {
1135 return LiveRangeFor(UnallocatedOperand::cast(operand)->virtual_register()); 1280 return LiveRangeFor(UnallocatedOperand::cast(operand)->virtual_register());
1136 } else if (operand->IsConstant()) { 1281 } else if (operand->IsConstant()) {
1137 return LiveRangeFor(ConstantOperand::cast(operand)->virtual_register()); 1282 return LiveRangeFor(ConstantOperand::cast(operand)->virtual_register());
1138 } else if (operand->IsRegister()) { 1283 } else if (operand->IsRegister()) {
1139 return FixedLiveRangeFor(RegisterOperand::cast(operand)->index()); 1284 return FixedLiveRangeFor(RegisterOperand::cast(operand)->index());
1140 } else if (operand->IsDoubleRegister()) { 1285 } else if (operand->IsDoubleRegister()) {
1141 return FixedDoubleLiveRangeFor( 1286 return FixedDoubleLiveRangeFor(
1142 DoubleRegisterOperand::cast(operand)->index()); 1287 DoubleRegisterOperand::cast(operand)->index());
1143 } else { 1288 } else {
1144 return nullptr; 1289 return nullptr;
1145 } 1290 }
1146 } 1291 }
1147 1292
1148 1293
1149 void LiveRangeBuilder::Define(LifetimePosition position, 1294 UsePosition* LiveRangeBuilder::NewUsePosition(LifetimePosition pos,
1150 InstructionOperand* operand, 1295 InstructionOperand* operand,
1151 InstructionOperand* hint) { 1296 void* hint,
1297 UsePositionHintType hint_type) {
1298 return new (allocation_zone()) UsePosition(pos, operand, hint, hint_type);
1299 }
1300
1301
1302 UsePosition* LiveRangeBuilder::Define(LifetimePosition position,
1303 InstructionOperand* operand, void* hint,
1304 UsePositionHintType hint_type) {
1152 auto range = LiveRangeFor(operand); 1305 auto range = LiveRangeFor(operand);
1153 if (range == nullptr) return; 1306 if (range == nullptr) return nullptr;
1154 1307
1155 if (range->IsEmpty() || range->Start() > position) { 1308 if (range->IsEmpty() || range->Start() > position) {
1156 // Can happen if there is a definition without use. 1309 // Can happen if there is a definition without use.
1157 range->AddUseInterval(position, position.NextStart(), allocation_zone()); 1310 range->AddUseInterval(position, position.NextStart(), allocation_zone());
1158 range->AddUsePosition(position.NextStart(), nullptr, nullptr, 1311 range->AddUsePosition(NewUsePosition(position.NextStart()));
1159 allocation_zone());
1160 } else { 1312 } else {
1161 range->ShortenTo(position); 1313 range->ShortenTo(position);
1162 } 1314 }
1163 1315 if (!operand->IsUnallocated()) return nullptr;
1164 if (operand->IsUnallocated()) { 1316 auto unalloc_operand = UnallocatedOperand::cast(operand);
1165 auto unalloc_operand = UnallocatedOperand::cast(operand); 1317 auto use_pos = NewUsePosition(position, unalloc_operand, hint, hint_type);
1166 range->AddUsePosition(position, unalloc_operand, hint, allocation_zone()); 1318 range->AddUsePosition(use_pos);
1167 } 1319 return use_pos;
1168 } 1320 }
1169 1321
1170 1322
1171 void LiveRangeBuilder::Use(LifetimePosition block_start, 1323 UsePosition* LiveRangeBuilder::Use(LifetimePosition block_start,
1172 LifetimePosition position, 1324 LifetimePosition position,
1173 InstructionOperand* operand, 1325 InstructionOperand* operand, void* hint,
1174 InstructionOperand* hint) { 1326 UsePositionHintType hint_type) {
1175 auto range = LiveRangeFor(operand); 1327 auto range = LiveRangeFor(operand);
1176 if (range == nullptr) return; 1328 if (range == nullptr) return nullptr;
1329 UsePosition* use_pos = nullptr;
1177 if (operand->IsUnallocated()) { 1330 if (operand->IsUnallocated()) {
1178 UnallocatedOperand* unalloc_operand = UnallocatedOperand::cast(operand); 1331 UnallocatedOperand* unalloc_operand = UnallocatedOperand::cast(operand);
1179 range->AddUsePosition(position, unalloc_operand, hint, allocation_zone()); 1332 use_pos = NewUsePosition(position, unalloc_operand, hint, hint_type);
1333 range->AddUsePosition(use_pos);
1180 } 1334 }
1181 range->AddUseInterval(block_start, position, allocation_zone()); 1335 range->AddUseInterval(block_start, position, allocation_zone());
1336 return use_pos;
1182 } 1337 }
1183 1338
1184 1339
1185 bool LiveRangeBuilder::IsOutputRegisterOf(Instruction* instr, int index) {
1186 for (size_t i = 0; i < instr->OutputCount(); i++) {
1187 auto output = instr->OutputAt(i);
1188 if (output->IsRegister() && RegisterOperand::cast(output)->index() == index)
1189 return true;
1190 }
1191 return false;
1192 }
1193
1194
1195 bool LiveRangeBuilder::IsOutputDoubleRegisterOf(Instruction* instr, int index) {
1196 for (size_t i = 0; i < instr->OutputCount(); i++) {
1197 auto output = instr->OutputAt(i);
1198 if (output->IsDoubleRegister() &&
1199 DoubleRegisterOperand::cast(output)->index() == index)
1200 return true;
1201 }
1202 return false;
1203 }
1204
1205
1206 void LiveRangeBuilder::ProcessInstructions(const InstructionBlock* block, 1340 void LiveRangeBuilder::ProcessInstructions(const InstructionBlock* block,
1207 BitVector* live) { 1341 BitVector* live) {
1208 int block_start = block->first_instruction_index(); 1342 int block_start = block->first_instruction_index();
1209 auto block_start_position = 1343 auto block_start_position =
1210 LifetimePosition::GapFromInstructionIndex(block_start); 1344 LifetimePosition::GapFromInstructionIndex(block_start);
1211 1345
1212 for (int index = block->last_instruction_index(); index >= block_start; 1346 for (int index = block->last_instruction_index(); index >= block_start;
1213 index--) { 1347 index--) {
1214 auto curr_position = 1348 auto curr_position =
1215 LifetimePosition::InstructionFromInstructionIndex(index); 1349 LifetimePosition::InstructionFromInstructionIndex(index);
1216 auto instr = code()->InstructionAt(index); 1350 auto instr = code()->InstructionAt(index);
1217 DCHECK(instr != nullptr); 1351 DCHECK(instr != nullptr);
1218 DCHECK(curr_position.IsInstructionPosition()); 1352 DCHECK(curr_position.IsInstructionPosition());
1219 // Process output, inputs, and temps of this instruction. 1353 // Process output, inputs, and temps of this instruction.
1220 for (size_t i = 0; i < instr->OutputCount(); i++) { 1354 for (size_t i = 0; i < instr->OutputCount(); i++) {
1221 auto output = instr->OutputAt(i); 1355 auto output = instr->OutputAt(i);
1222 if (output->IsUnallocated()) { 1356 if (output->IsUnallocated()) {
1223 // Unsupported. 1357 // Unsupported.
1224 DCHECK(!UnallocatedOperand::cast(output)->HasSlotPolicy()); 1358 DCHECK(!UnallocatedOperand::cast(output)->HasSlotPolicy());
1225 int out_vreg = UnallocatedOperand::cast(output)->virtual_register(); 1359 int out_vreg = UnallocatedOperand::cast(output)->virtual_register();
1226 live->Remove(out_vreg); 1360 live->Remove(out_vreg);
1227 } else if (output->IsConstant()) { 1361 } else if (output->IsConstant()) {
1228 int out_vreg = ConstantOperand::cast(output)->virtual_register(); 1362 int out_vreg = ConstantOperand::cast(output)->virtual_register();
1229 live->Remove(out_vreg); 1363 live->Remove(out_vreg);
1230 } 1364 }
1231 Define(curr_position, output, nullptr); 1365 Define(curr_position, output);
1232 } 1366 }
1233 1367
1234 if (instr->ClobbersRegisters()) { 1368 if (instr->ClobbersRegisters()) {
1235 for (int i = 0; i < config()->num_general_registers(); ++i) { 1369 for (int i = 0; i < config()->num_general_registers(); ++i) {
1236 if (!IsOutputRegisterOf(instr, i)) { 1370 if (!IsOutputRegisterOf(instr, i)) {
1237 auto range = FixedLiveRangeFor(i); 1371 auto range = FixedLiveRangeFor(i);
1238 range->AddUseInterval(curr_position, curr_position.End(), 1372 range->AddUseInterval(curr_position, curr_position.End(),
1239 allocation_zone()); 1373 allocation_zone());
1240 } 1374 }
1241 } 1375 }
(...skipping 21 matching lines...) Expand all
1263 } 1397 }
1264 1398
1265 if (input->IsUnallocated()) { 1399 if (input->IsUnallocated()) {
1266 UnallocatedOperand* unalloc = UnallocatedOperand::cast(input); 1400 UnallocatedOperand* unalloc = UnallocatedOperand::cast(input);
1267 int vreg = unalloc->virtual_register(); 1401 int vreg = unalloc->virtual_register();
1268 live->Add(vreg); 1402 live->Add(vreg);
1269 if (unalloc->HasSlotPolicy()) { 1403 if (unalloc->HasSlotPolicy()) {
1270 LiveRangeFor(vreg)->set_has_slot_use(true); 1404 LiveRangeFor(vreg)->set_has_slot_use(true);
1271 } 1405 }
1272 } 1406 }
1273 Use(block_start_position, use_pos, input, nullptr); 1407 Use(block_start_position, use_pos, input);
1274 } 1408 }
1275 1409
1276 for (size_t i = 0; i < instr->TempCount(); i++) { 1410 for (size_t i = 0; i < instr->TempCount(); i++) {
1277 auto temp = instr->TempAt(i); 1411 auto temp = instr->TempAt(i);
1278 // Unsupported. 1412 // Unsupported.
1279 DCHECK_IMPLIES(temp->IsUnallocated(), 1413 DCHECK_IMPLIES(temp->IsUnallocated(),
1280 !UnallocatedOperand::cast(temp)->HasSlotPolicy()); 1414 !UnallocatedOperand::cast(temp)->HasSlotPolicy());
1281 if (instr->ClobbersTemps()) { 1415 if (instr->ClobbersTemps()) {
1282 if (temp->IsRegister()) continue; 1416 if (temp->IsRegister()) continue;
1283 if (temp->IsUnallocated()) { 1417 if (temp->IsUnallocated()) {
1284 UnallocatedOperand* temp_unalloc = UnallocatedOperand::cast(temp); 1418 UnallocatedOperand* temp_unalloc = UnallocatedOperand::cast(temp);
1285 if (temp_unalloc->HasFixedPolicy()) { 1419 if (temp_unalloc->HasFixedPolicy()) {
1286 continue; 1420 continue;
1287 } 1421 }
1288 } 1422 }
1289 } 1423 }
1290 Use(block_start_position, curr_position.End(), temp, nullptr); 1424 Use(block_start_position, curr_position.End(), temp);
1291 Define(curr_position, temp, nullptr); 1425 Define(curr_position, temp);
1292 } 1426 }
1293 1427
1294 // Process the moves of the instruction's gaps, making their sources live. 1428 // Process the moves of the instruction's gaps, making their sources live.
1295 const Instruction::GapPosition kPositions[] = {Instruction::END, 1429 const Instruction::GapPosition kPositions[] = {Instruction::END,
1296 Instruction::START}; 1430 Instruction::START};
1297 curr_position = curr_position.PrevStart(); 1431 curr_position = curr_position.PrevStart();
1298 DCHECK(curr_position.IsGapPosition()); 1432 DCHECK(curr_position.IsGapPosition());
1299 for (auto position : kPositions) { 1433 for (auto position : kPositions) {
1300 auto move = instr->GetParallelMove(position); 1434 auto move = instr->GetParallelMove(position);
1301 if (move == nullptr) continue; 1435 if (move == nullptr) continue;
1302 if (position == Instruction::END) { 1436 if (position == Instruction::END) {
1303 curr_position = curr_position.End(); 1437 curr_position = curr_position.End();
1304 } else { 1438 } else {
1305 curr_position = curr_position.Start(); 1439 curr_position = curr_position.Start();
1306 } 1440 }
1307 for (auto cur : *move) { 1441 for (auto cur : *move) {
1308 auto& from = cur->source(); 1442 auto& from = cur->source();
1309 auto& to = cur->destination(); 1443 auto& to = cur->destination();
1310 auto hint = &to; 1444 void* hint = &to;
1445 UsePositionHintType hint_type = UsePosition::HintTypeForOperand(to);
1446 UsePosition* to_use = nullptr;
1447 int phi_vreg = -1;
1311 if (to.IsUnallocated()) { 1448 if (to.IsUnallocated()) {
1312 int to_vreg = UnallocatedOperand::cast(to).virtual_register(); 1449 int to_vreg = UnallocatedOperand::cast(to).virtual_register();
1313 auto to_range = LiveRangeFor(to_vreg); 1450 auto to_range = LiveRangeFor(to_vreg);
1314 if (to_range->is_phi()) { 1451 if (to_range->is_phi()) {
1452 phi_vreg = to_vreg;
1315 if (to_range->is_non_loop_phi()) { 1453 if (to_range->is_non_loop_phi()) {
1316 hint = to_range->current_hint_operand(); 1454 hint = to_range->current_hint_position();
1455 hint_type = hint == nullptr ? UsePositionHintType::kNone
1456 : UsePositionHintType::kUsePos;
1457 } else {
1458 hint_type = UsePositionHintType::kPhi;
1459 hint = data()->GetPhiMapValueFor(to_vreg);
1317 } 1460 }
1318 } else { 1461 } else {
1319 if (live->Contains(to_vreg)) { 1462 if (live->Contains(to_vreg)) {
1320 Define(curr_position, &to, &from); 1463 to_use = Define(curr_position, &to, &from,
1464 UsePosition::HintTypeForOperand(from));
1321 live->Remove(to_vreg); 1465 live->Remove(to_vreg);
1322 } else { 1466 } else {
1323 cur->Eliminate(); 1467 cur->Eliminate();
1324 continue; 1468 continue;
1325 } 1469 }
1326 } 1470 }
1327 } else { 1471 } else {
1328 Define(curr_position, &to, &from); 1472 Define(curr_position, &to);
1329 } 1473 }
1330 Use(block_start_position, curr_position, &from, hint); 1474 auto from_use =
1475 Use(block_start_position, curr_position, &from, hint, hint_type);
1476 // Mark range live.
1331 if (from.IsUnallocated()) { 1477 if (from.IsUnallocated()) {
1332 live->Add(UnallocatedOperand::cast(from).virtual_register()); 1478 live->Add(UnallocatedOperand::cast(from).virtual_register());
1333 } 1479 }
1480 // Resolve use position hints just created.
1481 if (to_use != nullptr && from_use != nullptr) {
1482 to_use->ResolveHint(from_use);
1483 from_use->ResolveHint(to_use);
1484 }
1485 DCHECK_IMPLIES(to_use != nullptr, to_use->IsResolved());
1486 DCHECK_IMPLIES(from_use != nullptr, from_use->IsResolved());
1487 // Potentially resolve phi hint.
1488 if (phi_vreg != -1) ResolvePhiHint(&from, from_use);
1334 } 1489 }
1335 } 1490 }
1336 } 1491 }
1337 } 1492 }
1338 1493
1339 1494
1495 void LiveRangeBuilder::ProcessPhis(const InstructionBlock* block,
1496 BitVector* live) {
1497 for (auto phi : block->phis()) {
1498 // The live range interval already ends at the first instruction of the
1499 // block.
1500 int phi_vreg = phi->virtual_register();
1501 live->Remove(phi_vreg);
1502 InstructionOperand* hint = nullptr;
1503 auto instr = GetLastInstruction(
1504 code(), code()->InstructionBlockAt(block->predecessors()[0]));
1505 for (auto move : *instr->GetParallelMove(Instruction::END)) {
1506 auto& to = move->destination();
1507 if (to.IsUnallocated() &&
1508 UnallocatedOperand::cast(to).virtual_register() == phi_vreg) {
1509 hint = &move->source();
1510 break;
1511 }
1512 }
1513 DCHECK(hint != nullptr);
1514 auto block_start = LifetimePosition::GapFromInstructionIndex(
1515 block->first_instruction_index());
1516 auto use_pos = Define(block_start, &phi->output(), hint,
1517 UsePosition::HintTypeForOperand(*hint));
1518 MapPhiHint(hint, use_pos);
1519 }
1520 }
1521
1522
1523 void LiveRangeBuilder::ProcessLoopHeader(const InstructionBlock* block,
1524 BitVector* live) {
1525 DCHECK(block->IsLoopHeader());
1526 // Add a live range stretching from the first loop instruction to the last
1527 // for each value live on entry to the header.
1528 BitVector::Iterator iterator(live);
1529 auto start = LifetimePosition::GapFromInstructionIndex(
1530 block->first_instruction_index());
1531 auto end = LifetimePosition::GapFromInstructionIndex(
1532 code()->LastLoopInstructionIndex(block)).NextFullStart();
1533 while (!iterator.Done()) {
1534 int operand_index = iterator.Current();
1535 auto range = LiveRangeFor(operand_index);
1536 range->EnsureInterval(start, end, allocation_zone());
1537 iterator.Advance();
1538 }
1539 // Insert all values into the live in sets of all blocks in the loop.
1540 for (int i = block->rpo_number().ToInt() + 1; i < block->loop_end().ToInt();
1541 ++i) {
1542 live_in_sets()[i]->Union(*live);
1543 }
1544 }
1545
1546
1340 void LiveRangeBuilder::BuildLiveRanges() { 1547 void LiveRangeBuilder::BuildLiveRanges() {
1341 // Process the blocks in reverse order. 1548 // Process the blocks in reverse order.
1342 for (int block_id = code()->InstructionBlockCount() - 1; block_id >= 0; 1549 for (int block_id = code()->InstructionBlockCount() - 1; block_id >= 0;
1343 --block_id) { 1550 --block_id) {
1344 auto block = code()->InstructionBlockAt(RpoNumber::FromInt(block_id)); 1551 auto block = code()->InstructionBlockAt(RpoNumber::FromInt(block_id));
1345 auto live = ComputeLiveOut(block); 1552 auto live = ComputeLiveOut(block);
1346 // Initially consider all live_out values live for the entire block. We 1553 // Initially consider all live_out values live for the entire block. We
1347 // will shorten these intervals if necessary. 1554 // will shorten these intervals if necessary.
1348 AddInitialIntervals(block, live); 1555 AddInitialIntervals(block, live);
1349
1350 // Process the instructions in reverse order, generating and killing 1556 // Process the instructions in reverse order, generating and killing
1351 // live values. 1557 // live values.
1352 ProcessInstructions(block, live); 1558 ProcessInstructions(block, live);
1353 // All phi output operands are killed by this block. 1559 // All phi output operands are killed by this block.
1354 for (auto phi : block->phis()) { 1560 ProcessPhis(block, live);
1355 // The live range interval already ends at the first instruction of the
1356 // block.
1357 int phi_vreg = phi->virtual_register();
1358 live->Remove(phi_vreg);
1359 InstructionOperand* hint = nullptr;
1360 auto instr = GetLastInstruction(
1361 code(), code()->InstructionBlockAt(block->predecessors()[0]));
1362 for (auto move : *instr->GetParallelMove(Instruction::END)) {
1363 auto& to = move->destination();
1364 if (to.IsUnallocated() &&
1365 UnallocatedOperand::cast(to).virtual_register() == phi_vreg) {
1366 hint = &move->source();
1367 break;
1368 }
1369 }
1370 DCHECK(hint != nullptr);
1371 auto block_start = LifetimePosition::GapFromInstructionIndex(
1372 block->first_instruction_index());
1373 Define(block_start, &phi->output(), hint);
1374 }
1375
1376 // Now live is live_in for this block except not including values live 1561 // Now live is live_in for this block except not including values live
1377 // out on backward successor edges. 1562 // out on backward successor edges.
1563 if (block->IsLoopHeader()) ProcessLoopHeader(block, live);
1378 live_in_sets()[block_id] = live; 1564 live_in_sets()[block_id] = live;
1379
1380 if (block->IsLoopHeader()) {
1381 // Add a live range stretching from the first loop instruction to the last
1382 // for each value live on entry to the header.
1383 BitVector::Iterator iterator(live);
1384 auto start = LifetimePosition::GapFromInstructionIndex(
1385 block->first_instruction_index());
1386 auto end = LifetimePosition::GapFromInstructionIndex(
1387 code()->LastLoopInstructionIndex(block)).NextFullStart();
1388 while (!iterator.Done()) {
1389 int operand_index = iterator.Current();
1390 auto range = LiveRangeFor(operand_index);
1391 range->EnsureInterval(start, end, allocation_zone());
1392 iterator.Advance();
1393 }
1394 // Insert all values into the live in sets of all blocks in the loop.
1395 for (int i = block->rpo_number().ToInt() + 1;
1396 i < block->loop_end().ToInt(); ++i) {
1397 live_in_sets()[i]->Union(*live);
1398 }
1399 }
1400 } 1565 }
1401 1566 // Postprocess the ranges.
1402 for (auto range : data()->live_ranges()) { 1567 for (auto range : data()->live_ranges()) {
1403 if (range == nullptr) continue; 1568 if (range == nullptr) continue;
1404 range->set_kind(RequiredRegisterKind(range->id())); 1569 range->set_kind(RequiredRegisterKind(range->id()));
1405 // Give slots to all ranges with a non fixed slot use. 1570 // Give slots to all ranges with a non fixed slot use.
1406 if (range->has_slot_use() && range->HasNoSpillType()) { 1571 if (range->has_slot_use() && range->HasNoSpillType()) {
1407 data()->AssignSpillRangeToLiveRange(range); 1572 data()->AssignSpillRangeToLiveRange(range);
1408 } 1573 }
1409 // TODO(bmeurer): This is a horrible hack to make sure that for constant 1574 // TODO(bmeurer): This is a horrible hack to make sure that for constant
1410 // live ranges, every use requires the constant to be in a register. 1575 // live ranges, every use requires the constant to be in a register.
1411 // Without this hack, all uses with "any" policy would get the constant 1576 // Without this hack, all uses with "any" policy would get the constant
1412 // operand assigned. 1577 // operand assigned.
1413 if (range->HasSpillOperand() && range->GetSpillOperand()->IsConstant()) { 1578 if (range->HasSpillOperand() && range->GetSpillOperand()->IsConstant()) {
1414 for (auto pos = range->first_pos(); pos != nullptr; pos = pos->next()) { 1579 for (auto pos = range->first_pos(); pos != nullptr; pos = pos->next()) {
1415 if (pos->type() == UsePositionType::kRequiresSlot) continue; 1580 if (pos->type() == UsePositionType::kRequiresSlot) continue;
1416 UsePositionType new_type = UsePositionType::kAny; 1581 UsePositionType new_type = UsePositionType::kAny;
1417 // Can't mark phis as needing a register. 1582 // Can't mark phis as needing a register.
1418 if (!pos->pos().IsGapPosition()) { 1583 if (!pos->pos().IsGapPosition()) {
1419 new_type = UsePositionType::kRequiresRegister; 1584 new_type = UsePositionType::kRequiresRegister;
1420 } 1585 }
1421 pos->set_type(new_type, true); 1586 pos->set_type(new_type, true);
1422 } 1587 }
1423 } 1588 }
1424 } 1589 }
1425
1426 #ifdef DEBUG 1590 #ifdef DEBUG
1427 Verify(); 1591 Verify();
1428 #endif 1592 #endif
1429 } 1593 }
1430 1594
1431 1595
1596 void LiveRangeBuilder::MapPhiHint(InstructionOperand* operand,
1597 UsePosition* use_pos) {
1598 DCHECK(!use_pos->IsResolved());
1599 auto res = phi_hints_.insert(std::make_pair(operand, use_pos));
1600 DCHECK(res.second);
1601 USE(res);
1602 }
1603
1604
1605 void LiveRangeBuilder::ResolvePhiHint(InstructionOperand* operand,
1606 UsePosition* use_pos) {
1607 auto it = phi_hints_.find(operand);
1608 if (it == phi_hints_.end()) return;
1609 DCHECK(!it->second->IsResolved());
1610 it->second->ResolveHint(use_pos);
1611 }
1612
1613
1432 RegisterKind LiveRangeBuilder::RequiredRegisterKind( 1614 RegisterKind LiveRangeBuilder::RequiredRegisterKind(
1433 int virtual_register) const { 1615 int virtual_register) const {
1434 return (code()->IsDouble(virtual_register)) ? DOUBLE_REGISTERS 1616 return (code()->IsDouble(virtual_register)) ? DOUBLE_REGISTERS
1435 : GENERAL_REGISTERS; 1617 : GENERAL_REGISTERS;
1436 } 1618 }
1437 1619
1438 1620
1439 void LiveRangeBuilder::Verify() const { 1621 void LiveRangeBuilder::Verify() const {
1622 for (auto& hint : phi_hints_) {
1623 CHECK(hint.second->IsResolved());
1624 }
1440 for (auto current : data()->live_ranges()) { 1625 for (auto current : data()->live_ranges()) {
1441 if (current != nullptr) current->Verify(); 1626 if (current != nullptr) current->Verify();
1442 } 1627 }
1443 } 1628 }
1444 1629
1445 1630
1446 RegisterAllocator::RegisterAllocator(RegisterAllocationData* data, 1631 RegisterAllocator::RegisterAllocator(RegisterAllocationData* data,
1447 RegisterKind kind) 1632 RegisterKind kind)
1448 : data_(data), 1633 : data_(data),
1449 mode_(kind), 1634 mode_(kind),
(...skipping 220 matching lines...) Expand 10 before | Expand all | Expand 10 after
1670 1855
1671 const char* LinearScanAllocator::RegisterName(int allocation_index) const { 1856 const char* LinearScanAllocator::RegisterName(int allocation_index) const {
1672 if (mode() == GENERAL_REGISTERS) { 1857 if (mode() == GENERAL_REGISTERS) {
1673 return data()->config()->general_register_name(allocation_index); 1858 return data()->config()->general_register_name(allocation_index);
1674 } else { 1859 } else {
1675 return data()->config()->double_register_name(allocation_index); 1860 return data()->config()->double_register_name(allocation_index);
1676 } 1861 }
1677 } 1862 }
1678 1863
1679 1864
1865 void LinearScanAllocator::SetLiveRangeAssignedRegister(LiveRange* range,
1866 int reg) {
1867 data()->MarkAllocated(range->Kind(), reg);
1868 range->set_assigned_register(reg);
1869 range->SetUseHints(reg);
1870 if (range->is_phi()) {
1871 data()->GetPhiMapValueFor(range->id())->set_assigned_register(reg);
1872 }
1873 }
1874
1875
1680 void LinearScanAllocator::AddToActive(LiveRange* range) { 1876 void LinearScanAllocator::AddToActive(LiveRange* range) {
1681 TRACE("Add live range %d to active\n", range->id()); 1877 TRACE("Add live range %d to active\n", range->id());
1682 active_live_ranges().push_back(range); 1878 active_live_ranges().push_back(range);
1683 } 1879 }
1684 1880
1685 1881
1686 void LinearScanAllocator::AddToInactive(LiveRange* range) { 1882 void LinearScanAllocator::AddToInactive(LiveRange* range) {
1687 TRACE("Add live range %d to inactive\n", range->id()); 1883 TRACE("Add live range %d to inactive\n", range->id());
1688 inactive_live_ranges().push_back(range); 1884 inactive_live_ranges().push_back(range);
1689 } 1885 }
(...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after
1785 } 1981 }
1786 1982
1787 for (auto cur_inactive : inactive_live_ranges()) { 1983 for (auto cur_inactive : inactive_live_ranges()) {
1788 DCHECK(cur_inactive->End() > current->Start()); 1984 DCHECK(cur_inactive->End() > current->Start());
1789 auto next_intersection = cur_inactive->FirstIntersection(current); 1985 auto next_intersection = cur_inactive->FirstIntersection(current);
1790 if (!next_intersection.IsValid()) continue; 1986 if (!next_intersection.IsValid()) continue;
1791 int cur_reg = cur_inactive->assigned_register(); 1987 int cur_reg = cur_inactive->assigned_register();
1792 free_until_pos[cur_reg] = Min(free_until_pos[cur_reg], next_intersection); 1988 free_until_pos[cur_reg] = Min(free_until_pos[cur_reg], next_intersection);
1793 } 1989 }
1794 1990
1795 auto hint = current->FirstHint(); 1991 int hint_register;
1796 if (hint != nullptr && (hint->IsRegister() || hint->IsDoubleRegister())) { 1992 if (current->FirstHintPosition(&hint_register) != nullptr) {
1797 int register_index = AllocatedOperand::cast(hint)->index();
1798 TRACE("Found reg hint %s (free until [%d) for live range %d (end %d[).\n", 1993 TRACE("Found reg hint %s (free until [%d) for live range %d (end %d[).\n",
1799 RegisterName(register_index), free_until_pos[register_index].value(), 1994 RegisterName(hint_register), free_until_pos[hint_register].value(),
1800 current->id(), current->End().value()); 1995 current->id(), current->End().value());
1801 1996
1802 // The desired register is free until the end of the current live range. 1997 // The desired register is free until the end of the current live range.
1803 if (free_until_pos[register_index] >= current->End()) { 1998 if (free_until_pos[hint_register] >= current->End()) {
1804 TRACE("Assigning preferred reg %s to live range %d\n", 1999 TRACE("Assigning preferred reg %s to live range %d\n",
1805 RegisterName(register_index), current->id()); 2000 RegisterName(hint_register), current->id());
1806 data()->SetLiveRangeAssignedRegister(current, register_index); 2001 SetLiveRangeAssignedRegister(current, hint_register);
1807 return true; 2002 return true;
1808 } 2003 }
1809 } 2004 }
1810 2005
1811 // Find the register which stays free for the longest time. 2006 // Find the register which stays free for the longest time.
1812 int reg = 0; 2007 int reg = 0;
1813 for (int i = 1; i < num_registers(); ++i) { 2008 for (int i = 1; i < num_registers(); ++i) {
1814 if (free_until_pos[i] > free_until_pos[reg]) { 2009 if (free_until_pos[i] > free_until_pos[reg]) {
1815 reg = i; 2010 reg = i;
1816 } 2011 }
(...skipping 11 matching lines...) Expand all
1828 // the range end. Split current at position where it becomes blocked. 2023 // the range end. Split current at position where it becomes blocked.
1829 auto tail = SplitRangeAt(current, pos); 2024 auto tail = SplitRangeAt(current, pos);
1830 AddToUnhandledSorted(tail); 2025 AddToUnhandledSorted(tail);
1831 } 2026 }
1832 2027
1833 // Register reg is available at the range start and is free until 2028 // Register reg is available at the range start and is free until
1834 // the range end. 2029 // the range end.
1835 DCHECK(pos >= current->End()); 2030 DCHECK(pos >= current->End());
1836 TRACE("Assigning free reg %s to live range %d\n", RegisterName(reg), 2031 TRACE("Assigning free reg %s to live range %d\n", RegisterName(reg),
1837 current->id()); 2032 current->id());
1838 data()->SetLiveRangeAssignedRegister(current, reg); 2033 SetLiveRangeAssignedRegister(current, reg);
1839 2034
1840 return true; 2035 return true;
1841 } 2036 }
1842 2037
1843 2038
1844 void LinearScanAllocator::AllocateBlockedReg(LiveRange* current) { 2039 void LinearScanAllocator::AllocateBlockedReg(LiveRange* current) {
1845 auto register_use = current->NextRegisterPosition(current->Start()); 2040 auto register_use = current->NextRegisterPosition(current->Start());
1846 if (register_use == nullptr) { 2041 if (register_use == nullptr) {
1847 // There is no use in the current live range that requires a register. 2042 // There is no use in the current live range that requires a register.
1848 // We can just spill it. 2043 // We can just spill it.
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after
1907 // position. 2102 // position.
1908 LiveRange* tail = 2103 LiveRange* tail =
1909 SplitBetween(current, current->Start(), block_pos[reg].Start()); 2104 SplitBetween(current, current->Start(), block_pos[reg].Start());
1910 AddToUnhandledSorted(tail); 2105 AddToUnhandledSorted(tail);
1911 } 2106 }
1912 2107
1913 // Register reg is not blocked for the whole range. 2108 // Register reg is not blocked for the whole range.
1914 DCHECK(block_pos[reg] >= current->End()); 2109 DCHECK(block_pos[reg] >= current->End());
1915 TRACE("Assigning blocked reg %s to live range %d\n", RegisterName(reg), 2110 TRACE("Assigning blocked reg %s to live range %d\n", RegisterName(reg),
1916 current->id()); 2111 current->id());
1917 data()->SetLiveRangeAssignedRegister(current, reg); 2112 SetLiveRangeAssignedRegister(current, reg);
1918 2113
1919 // This register was not free. Thus we need to find and spill 2114 // This register was not free. Thus we need to find and spill
1920 // parts of active and inactive live regions that use the same register 2115 // parts of active and inactive live regions that use the same register
1921 // at the same lifetime positions as current. 2116 // at the same lifetime positions as current.
1922 SplitAndSpillIntersecting(current); 2117 SplitAndSpillIntersecting(current);
1923 } 2118 }
1924 2119
1925 2120
1926 void LinearScanAllocator::SplitAndSpillIntersecting(LiveRange* current) { 2121 void LinearScanAllocator::SplitAndSpillIntersecting(LiveRange* current) {
1927 DCHECK(current->HasRegisterAssigned()); 2122 DCHECK(current->HasRegisterAssigned());
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after
1967 --i; 2162 --i;
1968 } 2163 }
1969 } 2164 }
1970 } 2165 }
1971 } 2166 }
1972 2167
1973 2168
1974 bool LinearScanAllocator::TryReuseSpillForPhi(LiveRange* range) { 2169 bool LinearScanAllocator::TryReuseSpillForPhi(LiveRange* range) {
1975 if (range->IsChild() || !range->is_phi()) return false; 2170 if (range->IsChild() || !range->is_phi()) return false;
1976 DCHECK(!range->HasSpillOperand()); 2171 DCHECK(!range->HasSpillOperand());
1977 2172 auto phi_map_value = data()->GetPhiMapValueFor(range->id());
1978 auto lookup = data()->phi_map().find(range->id()); 2173 auto phi = phi_map_value->phi();
1979 DCHECK(lookup != data()->phi_map().end()); 2174 auto block = phi_map_value->block();
1980 auto phi = lookup->second->phi;
1981 auto block = lookup->second->block;
1982 // Count the number of spilled operands. 2175 // Count the number of spilled operands.
1983 size_t spilled_count = 0; 2176 size_t spilled_count = 0;
1984 LiveRange* first_op = nullptr; 2177 LiveRange* first_op = nullptr;
1985 for (size_t i = 0; i < phi->operands().size(); i++) { 2178 for (size_t i = 0; i < phi->operands().size(); i++) {
1986 int op = phi->operands()[i]; 2179 int op = phi->operands()[i];
1987 LiveRange* op_range = LiveRangeFor(op); 2180 LiveRange* op_range = LiveRangeFor(op);
1988 if (!op_range->HasSpillRange()) continue; 2181 if (!op_range->HasSpillRange()) continue;
1989 auto pred = code()->InstructionBlockAt(block->predecessors()[i]); 2182 auto pred = code()->InstructionBlockAt(block->predecessors()[i]);
1990 auto pred_end = LifetimePosition::InstructionFromInstructionIndex( 2183 auto pred_end = LifetimePosition::InstructionFromInstructionIndex(
1991 pred->last_instruction_index()); 2184 pred->last_instruction_index());
(...skipping 200 matching lines...) Expand 10 before | Expand all | Expand 10 after
2192 } 2385 }
2193 2386
2194 2387
2195 void GreedyAllocator::AssignRangeToRegister(int reg_id, LiveRange* range) { 2388 void GreedyAllocator::AssignRangeToRegister(int reg_id, LiveRange* range) {
2196 allocations_[reg_id]->Insert(range); 2389 allocations_[reg_id]->Insert(range);
2197 if (range->HasRegisterAssigned()) { 2390 if (range->HasRegisterAssigned()) {
2198 DCHECK_EQ(reg_id, range->assigned_register()); 2391 DCHECK_EQ(reg_id, range->assigned_register());
2199 return; 2392 return;
2200 } 2393 }
2201 range->set_assigned_register(reg_id); 2394 range->set_assigned_register(reg_id);
2395 range->SetUseHints(reg_id);
2396 if (range->is_phi()) {
2397 data()->GetPhiMapValueFor(range->id())->set_assigned_register(reg_id);
2398 }
2202 } 2399 }
2203 2400
2204 2401
2205 float GreedyAllocator::CalculateSpillWeight(LiveRange* range) { 2402 float GreedyAllocator::CalculateSpillWeight(LiveRange* range) {
2206 if (range->IsFixed()) return std::numeric_limits<float>::max(); 2403 if (range->IsFixed()) return std::numeric_limits<float>::max();
2207 2404
2208 if (range->FirstHint() != nullptr && range->FirstHint()->IsRegister()) { 2405 int hint_register;
2406 if (range->FirstHintPosition(&hint_register) != nullptr) {
2209 return std::numeric_limits<float>::max(); 2407 return std::numeric_limits<float>::max();
2210 } 2408 }
2211 2409
2212 unsigned use_count = 0; 2410 unsigned use_count = 0;
2213 auto* pos = range->first_pos(); 2411 auto* pos = range->first_pos();
2214 while (pos != nullptr) { 2412 while (pos != nullptr) {
2215 use_count++; 2413 use_count++;
2216 pos = pos->next(); 2414 pos = pos->next();
2217 } 2415 }
2218 2416
(...skipping 11 matching lines...) Expand all
2230 for (auto* r : ranges) { 2428 for (auto* r : ranges) {
2231 max = std::max(max, CalculateSpillWeight(r)); 2429 max = std::max(max, CalculateSpillWeight(r));
2232 } 2430 }
2233 return max; 2431 return max;
2234 } 2432 }
2235 2433
2236 2434
2237 void GreedyAllocator::Evict(LiveRange* range) { 2435 void GreedyAllocator::Evict(LiveRange* range) {
2238 bool removed = allocations_[range->assigned_register()]->Remove(range); 2436 bool removed = allocations_[range->assigned_register()]->Remove(range);
2239 CHECK(removed); 2437 CHECK(removed);
2438 range->UnsetUseHints();
2439 range->UnsetAssignedRegister();
2440 if (range->is_phi()) {
2441 data()->GetPhiMapValueFor(range->id())->UnsetAssignedRegister();
2442 }
2240 } 2443 }
2241 2444
2242 2445
2243 bool GreedyAllocator::TryAllocatePhysicalRegister( 2446 bool GreedyAllocator::TryAllocatePhysicalRegister(
2244 unsigned reg_id, LiveRange* range, ZoneSet<LiveRange*>* conflicting) { 2447 unsigned reg_id, LiveRange* range, ZoneSet<LiveRange*>* conflicting) {
2245 auto* segment = range->first_interval(); 2448 auto* segment = range->first_interval();
2246 2449
2247 auto* alloc_info = allocations_[reg_id]; 2450 auto* alloc_info = allocations_[reg_id];
2248 while (segment != nullptr) { 2451 while (segment != nullptr) {
2249 if (auto* existing = alloc_info->Find(segment)) { 2452 if (auto* existing = alloc_info->Find(segment)) {
(...skipping 148 matching lines...) Expand 10 before | Expand all | Expand 10 after
2398 CHECK(allocated); 2601 CHECK(allocated);
2399 DCHECK(conflicting.empty()); 2602 DCHECK(conflicting.empty());
2400 } else { 2603 } else {
2401 DCHECK(!current->IsFixed() || current->CanBeSpilled(current->Start())); 2604 DCHECK(!current->IsFixed() || current->CanBeSpilled(current->Start()));
2402 bool allocated = AllocateBlockedRange(current, conflicting); 2605 bool allocated = AllocateBlockedRange(current, conflicting);
2403 CHECK(allocated); 2606 CHECK(allocated);
2404 } 2607 }
2405 } 2608 }
2406 } 2609 }
2407 2610
2408 BitVector* assigned_registers = new (zone) BitVector(num_registers(), zone);
2409 for (size_t i = 0; i < allocations_.size(); ++i) { 2611 for (size_t i = 0; i < allocations_.size(); ++i) {
2410 if (!allocations_[i]->IsEmpty()) { 2612 if (!allocations_[i]->IsEmpty()) {
2411 assigned_registers->Add(static_cast<int>(i)); 2613 data()->MarkAllocated(mode(), static_cast<int>(i));
2412 } 2614 }
2413 } 2615 }
2414 data()->frame()->SetAllocatedRegisters(assigned_registers);
2415 } 2616 }
2416 2617
2417 2618
2418 bool GreedyAllocator::AllocateBlockedRange( 2619 bool GreedyAllocator::AllocateBlockedRange(
2419 LiveRange* current, const ZoneSet<LiveRange*>& conflicts) { 2620 LiveRange* current, const ZoneSet<LiveRange*>& conflicts) {
2420 auto register_use = current->NextRegisterPosition(current->Start()); 2621 auto register_use = current->NextRegisterPosition(current->Start());
2421 if (register_use == nullptr) { 2622 if (register_use == nullptr) {
2422 // There is no use in the current live range that requires a register. 2623 // There is no use in the current live range that requires a register.
2423 // We can just spill it. 2624 // We can just spill it.
2424 Spill(current); 2625 Spill(current);
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
2465 2666
2466 void OperandAssigner::CommitAssignment() { 2667 void OperandAssigner::CommitAssignment() {
2467 for (auto range : data()->live_ranges()) { 2668 for (auto range : data()->live_ranges()) {
2468 if (range == nullptr || range->IsEmpty()) continue; 2669 if (range == nullptr || range->IsEmpty()) continue;
2469 InstructionOperand* spill_operand = nullptr; 2670 InstructionOperand* spill_operand = nullptr;
2470 if (!range->TopLevel()->HasNoSpillType()) { 2671 if (!range->TopLevel()->HasNoSpillType()) {
2471 spill_operand = range->TopLevel()->GetSpillOperand(); 2672 spill_operand = range->TopLevel()->GetSpillOperand();
2472 } 2673 }
2473 auto assigned = range->GetAssignedOperand(); 2674 auto assigned = range->GetAssignedOperand();
2474 range->ConvertUsesToOperand(assigned, spill_operand); 2675 range->ConvertUsesToOperand(assigned, spill_operand);
2475 if (range->is_phi()) data()->AssignPhiInput(range, assigned); 2676 if (range->is_phi()) {
2677 data()->GetPhiMapValueFor(range->id())->CommitAssignment(assigned);
2678 }
2476 if (!range->IsChild() && spill_operand != nullptr) { 2679 if (!range->IsChild() && spill_operand != nullptr) {
2477 range->CommitSpillsAtDefinition(data()->code(), spill_operand, 2680 range->CommitSpillsAtDefinition(data()->code(), spill_operand,
2478 range->has_slot_use()); 2681 range->has_slot_use());
2479 } 2682 }
2480 } 2683 }
2481 } 2684 }
2482 2685
2483 2686
2484 ReferenceMapPopulator::ReferenceMapPopulator(RegisterAllocationData* data) 2687 ReferenceMapPopulator::ReferenceMapPopulator(RegisterAllocationData* data)
2485 : data_(data) {} 2688 : data_(data) {}
(...skipping 355 matching lines...) Expand 10 before | Expand all | Expand 10 after
2841 auto eliminate = moves->PrepareInsertAfter(move); 3044 auto eliminate = moves->PrepareInsertAfter(move);
2842 to_insert.push_back(move); 3045 to_insert.push_back(move);
2843 if (eliminate != nullptr) to_eliminate.push_back(eliminate); 3046 if (eliminate != nullptr) to_eliminate.push_back(eliminate);
2844 } 3047 }
2845 } 3048 }
2846 3049
2847 3050
2848 } // namespace compiler 3051 } // namespace compiler
2849 } // namespace internal 3052 } // namespace internal
2850 } // namespace v8 3053 } // namespace v8
OLDNEW
« no previous file with comments | « src/compiler/register-allocator.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698