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

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

Issue 1050803002: [turbofan] cleanup InstructionOperand a little (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: rebase 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') | 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/compiler/linkage.h" 5 #include "src/compiler/linkage.h"
6 #include "src/compiler/register-allocator.h" 6 #include "src/compiler/register-allocator.h"
7 #include "src/string-stream.h" 7 #include "src/string-stream.h"
8 8
9 namespace v8 { 9 namespace v8 {
10 namespace internal { 10 namespace internal {
(...skipping 147 matching lines...) Expand 10 before | Expand all | Expand 10 after
158 InstructionOperand* operand) { 158 InstructionOperand* operand) {
159 DCHECK(HasNoSpillType()); 159 DCHECK(HasNoSpillType());
160 spills_at_definition_ = new (zone) 160 spills_at_definition_ = new (zone)
161 SpillAtDefinitionList(gap_index, operand, spills_at_definition_); 161 SpillAtDefinitionList(gap_index, operand, spills_at_definition_);
162 } 162 }
163 163
164 164
165 void LiveRange::CommitSpillsAtDefinition(InstructionSequence* sequence, 165 void LiveRange::CommitSpillsAtDefinition(InstructionSequence* sequence,
166 InstructionOperand* op, 166 InstructionOperand* op,
167 bool might_be_duplicated) { 167 bool might_be_duplicated) {
168 DCHECK_IMPLIES(op->IsConstant(), spills_at_definition_ == nullptr);
168 DCHECK(!IsChild()); 169 DCHECK(!IsChild());
169 auto zone = sequence->zone(); 170 auto zone = sequence->zone();
170 for (auto to_spill = spills_at_definition_; to_spill != nullptr; 171 for (auto to_spill = spills_at_definition_; to_spill != nullptr;
171 to_spill = to_spill->next) { 172 to_spill = to_spill->next) {
172 auto instr = sequence->InstructionAt(to_spill->gap_index); 173 auto instr = sequence->InstructionAt(to_spill->gap_index);
173 auto move = instr->GetOrCreateParallelMove(Instruction::START, zone); 174 auto move = instr->GetOrCreateParallelMove(Instruction::START, zone);
174 // Skip insertion if it's possible that the move exists already as a 175 // Skip insertion if it's possible that the move exists already as a
175 // constraint move from a fixed output register to a slot. 176 // constraint move from a fixed output register to a slot.
176 if (might_be_duplicated) { 177 if (might_be_duplicated) {
177 bool found = false; 178 bool found = false;
178 auto move_ops = move->move_operands(); 179 auto move_ops = move->move_operands();
179 for (auto move_op = move_ops->begin(); move_op != move_ops->end(); 180 for (auto move_op = move_ops->begin(); move_op != move_ops->end();
180 ++move_op) { 181 ++move_op) {
181 if (move_op->IsEliminated()) continue; 182 if (move_op->IsEliminated()) continue;
182 if (move_op->source()->Equals(to_spill->operand) && 183 if (move_op->source()->Equals(to_spill->operand) &&
183 move_op->destination()->Equals(op)) { 184 move_op->destination()->Equals(op)) {
184 found = true; 185 found = true;
185 break; 186 break;
186 } 187 }
187 } 188 }
188 if (found) continue; 189 if (found) continue;
189 } 190 }
190 move->AddMove(to_spill->operand, op, zone); 191 move->AddMove(to_spill->operand, op, zone);
191 } 192 }
192 } 193 }
193 194
194 195
195 void LiveRange::SetSpillOperand(InstructionOperand* operand) { 196 void LiveRange::SetSpillOperand(InstructionOperand* operand) {
196 DCHECK(HasNoSpillType()); 197 DCHECK(HasNoSpillType());
197 DCHECK(!operand->IsUnallocated()); 198 DCHECK(!operand->IsUnallocated() && !operand->IsImmediate());
198 spill_type_ = SpillType::kSpillOperand; 199 spill_type_ = SpillType::kSpillOperand;
199 spill_operand_ = operand; 200 spill_operand_ = operand;
200 } 201 }
201 202
202 203
203 void LiveRange::SetSpillRange(SpillRange* spill_range) { 204 void LiveRange::SetSpillRange(SpillRange* spill_range) {
204 DCHECK(HasNoSpillType() || HasSpillRange()); 205 DCHECK(HasNoSpillType() || HasSpillRange());
205 DCHECK(spill_range); 206 DCHECK(spill_range);
206 spill_type_ = SpillType::kSpillRange; 207 spill_type_ = SpillType::kSpillRange;
207 spill_range_ = spill_range; 208 spill_range_ = spill_range;
208 } 209 }
209 210
210 211
211 void LiveRange::CommitSpillOperand(InstructionOperand* operand) { 212 void LiveRange::CommitSpillOperand(AllocatedOperand* operand) {
212 DCHECK(HasSpillRange()); 213 DCHECK(HasSpillRange());
213 DCHECK(!operand->IsUnallocated());
214 DCHECK(!IsChild()); 214 DCHECK(!IsChild());
215 spill_type_ = SpillType::kSpillOperand; 215 spill_type_ = SpillType::kSpillOperand;
216 spill_operand_ = operand; 216 spill_operand_ = operand;
217 } 217 }
218 218
219 219
220 UsePosition* LiveRange::NextUsePosition(LifetimePosition start) { 220 UsePosition* LiveRange::NextUsePosition(LifetimePosition start) {
221 UsePosition* use_pos = last_processed_use_; 221 UsePosition* use_pos = last_processed_use_;
222 if (use_pos == nullptr) use_pos = first_pos(); 222 if (use_pos == nullptr) use_pos = first_pos();
223 while (use_pos != nullptr && use_pos->pos().Value() < start.Value()) { 223 while (use_pos != nullptr && use_pos->pos().Value() < start.Value()) {
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after
267 return use_pos->pos().Value() > pos.NextStart().End().Value(); 267 return use_pos->pos().Value() > pos.NextStart().End().Value();
268 } 268 }
269 269
270 270
271 InstructionOperand* LiveRange::GetAssignedOperand( 271 InstructionOperand* LiveRange::GetAssignedOperand(
272 InstructionOperandCache* cache) const { 272 InstructionOperandCache* cache) const {
273 if (HasRegisterAssigned()) { 273 if (HasRegisterAssigned()) {
274 DCHECK(!IsSpilled()); 274 DCHECK(!IsSpilled());
275 switch (Kind()) { 275 switch (Kind()) {
276 case GENERAL_REGISTERS: 276 case GENERAL_REGISTERS:
277 return cache->RegisterOperand(assigned_register()); 277 return cache->GetRegisterOperand(assigned_register());
278 case DOUBLE_REGISTERS: 278 case DOUBLE_REGISTERS:
279 return cache->DoubleRegisterOperand(assigned_register()); 279 return cache->GetDoubleRegisterOperand(assigned_register());
280 default: 280 default:
281 UNREACHABLE(); 281 UNREACHABLE();
282 } 282 }
283 } 283 }
284 DCHECK(IsSpilled()); 284 DCHECK(IsSpilled());
285 DCHECK(!HasRegisterAssigned()); 285 DCHECK(!HasRegisterAssigned());
286 auto op = TopLevel()->GetSpillOperand(); 286 auto op = TopLevel()->GetSpillOperand();
287 DCHECK(!op->IsUnallocated()); 287 DCHECK(!op->IsUnallocated());
288 return op; 288 return op;
289 } 289 }
(...skipping 240 matching lines...) Expand 10 before | Expand all | Expand 10 after
530 InstructionOperand* spill_op) { 530 InstructionOperand* spill_op) {
531 for (auto pos = first_pos(); pos != nullptr; pos = pos->next()) { 531 for (auto pos = first_pos(); pos != nullptr; pos = pos->next()) {
532 DCHECK(Start().Value() <= pos->pos().Value() && 532 DCHECK(Start().Value() <= pos->pos().Value() &&
533 pos->pos().Value() <= End().Value()); 533 pos->pos().Value() <= End().Value());
534 if (!pos->HasOperand()) { 534 if (!pos->HasOperand()) {
535 continue; 535 continue;
536 } 536 }
537 switch (pos->type()) { 537 switch (pos->type()) {
538 case UsePositionType::kRequiresSlot: 538 case UsePositionType::kRequiresSlot:
539 if (spill_op != nullptr) { 539 if (spill_op != nullptr) {
540 pos->operand()->ConvertTo(spill_op->kind(), spill_op->index()); 540 InstructionOperand::ReplaceWith(pos->operand(), spill_op);
541 } 541 }
542 break; 542 break;
543 case UsePositionType::kRequiresRegister: 543 case UsePositionType::kRequiresRegister:
544 DCHECK(op->IsRegister() || op->IsDoubleRegister()); 544 DCHECK(op->IsRegister() || op->IsDoubleRegister());
545 // Fall through. 545 // Fall through.
546 case UsePositionType::kAny: 546 case UsePositionType::kAny:
547 pos->operand()->ConvertTo(op->kind(), op->index()); 547 InstructionOperand::ReplaceWith(pos->operand(), op);
548 break; 548 break;
549 } 549 }
550 } 550 }
551 } 551 }
552 552
553 553
554 bool LiveRange::CanCover(LifetimePosition position) const { 554 bool LiveRange::CanCover(LifetimePosition position) const {
555 if (IsEmpty()) return false; 555 if (IsEmpty()) return false;
556 return Start().Value() <= position.Value() && 556 return Start().Value() <= position.Value() &&
557 position.Value() < End().Value(); 557 position.Value() < End().Value();
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
592 } else { 592 } else {
593 b = b->next(); 593 b = b->next();
594 } 594 }
595 } 595 }
596 return LifetimePosition::Invalid(); 596 return LifetimePosition::Invalid();
597 } 597 }
598 598
599 599
600 InstructionOperandCache::InstructionOperandCache() { 600 InstructionOperandCache::InstructionOperandCache() {
601 for (size_t i = 0; i < arraysize(general_register_operands_); ++i) { 601 for (size_t i = 0; i < arraysize(general_register_operands_); ++i) {
602 general_register_operands_[i] = 602 general_register_operands_[i] = RegisterOperand(static_cast<int>(i));
603 i::compiler::RegisterOperand(static_cast<int>(i));
604 } 603 }
605 for (size_t i = 0; i < arraysize(double_register_operands_); ++i) { 604 for (size_t i = 0; i < arraysize(double_register_operands_); ++i) {
606 double_register_operands_[i] = 605 double_register_operands_[i] = DoubleRegisterOperand(static_cast<int>(i));
607 i::compiler::DoubleRegisterOperand(static_cast<int>(i));
608 } 606 }
609 } 607 }
610 608
611 609
612 RegisterAllocator::RegisterAllocator(const RegisterConfiguration* config, 610 RegisterAllocator::RegisterAllocator(const RegisterConfiguration* config,
613 Zone* zone, Frame* frame, 611 Zone* zone, Frame* frame,
614 InstructionSequence* code, 612 InstructionSequence* code,
615 const char* debug_name) 613 const char* debug_name)
616 : local_zone_(zone), 614 : local_zone_(zone),
617 frame_(frame), 615 frame_(frame),
(...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after
700 698
701 int RegisterAllocator::FixedDoubleLiveRangeID(int index) { 699 int RegisterAllocator::FixedDoubleLiveRangeID(int index) {
702 return -index - 1 - config()->num_general_registers(); 700 return -index - 1 - config()->num_general_registers();
703 } 701 }
704 702
705 703
706 InstructionOperand* RegisterAllocator::AllocateFixed( 704 InstructionOperand* RegisterAllocator::AllocateFixed(
707 UnallocatedOperand* operand, int pos, bool is_tagged) { 705 UnallocatedOperand* operand, int pos, bool is_tagged) {
708 TRACE("Allocating fixed reg for op %d\n", operand->virtual_register()); 706 TRACE("Allocating fixed reg for op %d\n", operand->virtual_register());
709 DCHECK(operand->HasFixedPolicy()); 707 DCHECK(operand->HasFixedPolicy());
708 InstructionOperand allocated;
710 if (operand->HasFixedSlotPolicy()) { 709 if (operand->HasFixedSlotPolicy()) {
711 operand->ConvertTo(InstructionOperand::STACK_SLOT, 710 allocated = AllocatedOperand(InstructionOperand::STACK_SLOT,
712 operand->fixed_slot_index()); 711 operand->fixed_slot_index());
713 } else if (operand->HasFixedRegisterPolicy()) { 712 } else if (operand->HasFixedRegisterPolicy()) {
714 int reg_index = operand->fixed_register_index(); 713 allocated = AllocatedOperand(InstructionOperand::REGISTER,
715 operand->ConvertTo(InstructionOperand::REGISTER, reg_index); 714 operand->fixed_register_index());
716 } else if (operand->HasFixedDoubleRegisterPolicy()) { 715 } else if (operand->HasFixedDoubleRegisterPolicy()) {
717 int reg_index = operand->fixed_register_index(); 716 allocated = AllocatedOperand(InstructionOperand::DOUBLE_REGISTER,
718 operand->ConvertTo(InstructionOperand::DOUBLE_REGISTER, reg_index); 717 operand->fixed_register_index());
719 } else { 718 } else {
720 UNREACHABLE(); 719 UNREACHABLE();
721 } 720 }
721 InstructionOperand::ReplaceWith(operand, &allocated);
722 if (is_tagged) { 722 if (is_tagged) {
723 TRACE("Fixed reg is tagged at %d\n", pos); 723 TRACE("Fixed reg is tagged at %d\n", pos);
724 auto instr = InstructionAt(pos); 724 auto instr = InstructionAt(pos);
725 if (instr->HasPointerMap()) { 725 if (instr->HasPointerMap()) {
726 instr->pointer_map()->RecordPointer(operand, code_zone()); 726 instr->pointer_map()->RecordPointer(operand, code_zone());
727 } 727 }
728 } 728 }
729 return operand; 729 return operand;
730 } 730 }
731 731
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after
782 Instruction* RegisterAllocator::GetLastInstruction( 782 Instruction* RegisterAllocator::GetLastInstruction(
783 const InstructionBlock* block) { 783 const InstructionBlock* block) {
784 return code()->InstructionAt(block->last_instruction_index()); 784 return code()->InstructionAt(block->last_instruction_index());
785 } 785 }
786 786
787 787
788 LiveRange* RegisterAllocator::LiveRangeFor(InstructionOperand* operand) { 788 LiveRange* RegisterAllocator::LiveRangeFor(InstructionOperand* operand) {
789 if (operand->IsUnallocated()) { 789 if (operand->IsUnallocated()) {
790 return LiveRangeFor(UnallocatedOperand::cast(operand)->virtual_register()); 790 return LiveRangeFor(UnallocatedOperand::cast(operand)->virtual_register());
791 } else if (operand->IsConstant()) { 791 } else if (operand->IsConstant()) {
792 return LiveRangeFor(ConstantOperand::cast(operand)->index()); 792 return LiveRangeFor(ConstantOperand::cast(operand)->virtual_register());
793 } else if (operand->IsRegister()) { 793 } else if (operand->IsRegister()) {
794 return FixedLiveRangeFor(operand->index()); 794 return FixedLiveRangeFor(RegisterOperand::cast(operand)->index());
795 } else if (operand->IsDoubleRegister()) { 795 } else if (operand->IsDoubleRegister()) {
796 return FixedDoubleLiveRangeFor(operand->index()); 796 return FixedDoubleLiveRangeFor(
797 DoubleRegisterOperand::cast(operand)->index());
797 } else { 798 } else {
798 return nullptr; 799 return nullptr;
799 } 800 }
800 } 801 }
801 802
802 803
803 void RegisterAllocator::Define(LifetimePosition position, 804 void RegisterAllocator::Define(LifetimePosition position,
804 InstructionOperand* operand, 805 InstructionOperand* operand,
805 InstructionOperand* hint) { 806 InstructionOperand* hint) {
806 auto range = LiveRangeFor(operand); 807 auto range = LiveRangeFor(operand);
(...skipping 108 matching lines...) Expand 10 before | Expand all | Expand 10 after
915 } 916 }
916 917
917 live_ranges().insert(live_ranges().end(), other->live_ranges().begin(), 918 live_ranges().insert(live_ranges().end(), other->live_ranges().begin(),
918 other->live_ranges().end()); 919 other->live_ranges().end());
919 other->live_ranges().clear(); 920 other->live_ranges().clear();
920 921
921 return true; 922 return true;
922 } 923 }
923 924
924 925
925 void SpillRange::SetOperand(InstructionOperand* op) { 926 void SpillRange::SetOperand(AllocatedOperand* op) {
926 for (auto range : live_ranges()) { 927 for (auto range : live_ranges()) {
927 DCHECK(range->GetSpillRange() == this); 928 DCHECK(range->GetSpillRange() == this);
928 range->CommitSpillOperand(op); 929 range->CommitSpillOperand(op);
929 } 930 }
930 } 931 }
931 932
932 933
933 void SpillRange::MergeDisjointIntervals(UseInterval* other) { 934 void SpillRange::MergeDisjointIntervals(UseInterval* other) {
934 UseInterval* tail = nullptr; 935 UseInterval* tail = nullptr;
935 auto current = use_interval_; 936 auto current = use_interval_;
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
970 971
971 // Allocate slots for the merged spill ranges. 972 // Allocate slots for the merged spill ranges.
972 for (auto range : spill_ranges()) { 973 for (auto range : spill_ranges()) {
973 if (range->IsEmpty()) continue; 974 if (range->IsEmpty()) continue;
974 // Allocate a new operand referring to the spill slot. 975 // Allocate a new operand referring to the spill slot.
975 auto kind = range->Kind(); 976 auto kind = range->Kind();
976 int index = frame()->AllocateSpillSlot(kind == DOUBLE_REGISTERS); 977 int index = frame()->AllocateSpillSlot(kind == DOUBLE_REGISTERS);
977 auto op_kind = kind == DOUBLE_REGISTERS 978 auto op_kind = kind == DOUBLE_REGISTERS
978 ? InstructionOperand::DOUBLE_STACK_SLOT 979 ? InstructionOperand::DOUBLE_STACK_SLOT
979 : InstructionOperand::STACK_SLOT; 980 : InstructionOperand::STACK_SLOT;
980 auto op = InstructionOperand::New(code_zone(), op_kind, index); 981 auto op = AllocatedOperand::New(code_zone(), op_kind, index);
981 range->SetOperand(op); 982 range->SetOperand(op);
982 } 983 }
983 } 984 }
984 985
985 986
986 void RegisterAllocator::CommitAssignment() { 987 void RegisterAllocator::CommitAssignment() {
987 for (auto range : live_ranges()) { 988 for (auto range : live_ranges()) {
988 if (range == nullptr || range->IsEmpty()) continue; 989 if (range == nullptr || range->IsEmpty()) continue;
989 auto assigned = range->GetAssignedOperand(operand_cache()); 990 auto assigned = range->GetAssignedOperand(operand_cache());
990 InstructionOperand* spill_operand = nullptr; 991 InstructionOperand* spill_operand = nullptr;
(...skipping 119 matching lines...) Expand 10 before | Expand all | Expand 10 after
1110 auto output_operand = last_instruction->OutputAt(i); 1111 auto output_operand = last_instruction->OutputAt(i);
1111 DCHECK(!output_operand->IsConstant()); 1112 DCHECK(!output_operand->IsConstant());
1112 auto output = UnallocatedOperand::cast(output_operand); 1113 auto output = UnallocatedOperand::cast(output_operand);
1113 int output_vreg = output->virtual_register(); 1114 int output_vreg = output->virtual_register();
1114 auto range = LiveRangeFor(output_vreg); 1115 auto range = LiveRangeFor(output_vreg);
1115 bool assigned = false; 1116 bool assigned = false;
1116 if (output->HasFixedPolicy()) { 1117 if (output->HasFixedPolicy()) {
1117 AllocateFixed(output, -1, false); 1118 AllocateFixed(output, -1, false);
1118 // This value is produced on the stack, we never need to spill it. 1119 // This value is produced on the stack, we never need to spill it.
1119 if (output->IsStackSlot()) { 1120 if (output->IsStackSlot()) {
1120 DCHECK(output->index() < frame_->GetSpillSlotCount()); 1121 DCHECK(StackSlotOperand::cast(output)->index() <
1121 range->SetSpillOperand(output); 1122 frame_->GetSpillSlotCount());
1123 range->SetSpillOperand(StackSlotOperand::cast(output));
1122 range->SetSpillStartIndex(end); 1124 range->SetSpillStartIndex(end);
1123 assigned = true; 1125 assigned = true;
1124 } 1126 }
1125 1127
1126 for (auto succ : block->successors()) { 1128 for (auto succ : block->successors()) {
1127 const InstructionBlock* successor = code()->InstructionBlockAt(succ); 1129 const InstructionBlock* successor = code()->InstructionBlockAt(succ);
1128 DCHECK(successor->PredecessorCount() == 1); 1130 DCHECK(successor->PredecessorCount() == 1);
1129 int gap_index = successor->first_instruction_index(); 1131 int gap_index = successor->first_instruction_index();
1130 // Create an unconstrained operand for the same virtual register 1132 // Create an unconstrained operand for the same virtual register
1131 // and insert a gap move from the fixed output to the operand. 1133 // and insert a gap move from the fixed output to the operand.
(...skipping 21 matching lines...) Expand all
1153 auto first = InstructionAt(instr_index); 1155 auto first = InstructionAt(instr_index);
1154 // Handle fixed temporaries. 1156 // Handle fixed temporaries.
1155 for (size_t i = 0; i < first->TempCount(); i++) { 1157 for (size_t i = 0; i < first->TempCount(); i++) {
1156 auto temp = UnallocatedOperand::cast(first->TempAt(i)); 1158 auto temp = UnallocatedOperand::cast(first->TempAt(i));
1157 if (temp->HasFixedPolicy()) AllocateFixed(temp, instr_index, false); 1159 if (temp->HasFixedPolicy()) AllocateFixed(temp, instr_index, false);
1158 } 1160 }
1159 // Handle constant/fixed output operands. 1161 // Handle constant/fixed output operands.
1160 for (size_t i = 0; i < first->OutputCount(); i++) { 1162 for (size_t i = 0; i < first->OutputCount(); i++) {
1161 InstructionOperand* output = first->OutputAt(i); 1163 InstructionOperand* output = first->OutputAt(i);
1162 if (output->IsConstant()) { 1164 if (output->IsConstant()) {
1163 int output_vreg = output->index(); 1165 int output_vreg = ConstantOperand::cast(output)->virtual_register();
1164 auto range = LiveRangeFor(output_vreg); 1166 auto range = LiveRangeFor(output_vreg);
1165 range->SetSpillStartIndex(instr_index + 1); 1167 range->SetSpillStartIndex(instr_index + 1);
1166 range->SetSpillOperand(output); 1168 range->SetSpillOperand(output);
1167 continue; 1169 continue;
1168 } 1170 }
1169 auto first_output = UnallocatedOperand::cast(output); 1171 auto first_output = UnallocatedOperand::cast(output);
1170 auto range = LiveRangeFor(first_output->virtual_register()); 1172 auto range = LiveRangeFor(first_output->virtual_register());
1171 bool assigned = false; 1173 bool assigned = false;
1172 if (first_output->HasFixedPolicy()) { 1174 if (first_output->HasFixedPolicy()) {
1173 auto output_copy = first_output->CopyUnconstrained(code_zone()); 1175 auto output_copy = first_output->CopyUnconstrained(code_zone());
1174 bool is_tagged = HasTaggedValue(first_output->virtual_register()); 1176 bool is_tagged = HasTaggedValue(first_output->virtual_register());
1175 AllocateFixed(first_output, instr_index, is_tagged); 1177 AllocateFixed(first_output, instr_index, is_tagged);
1176 1178
1177 // This value is produced on the stack, we never need to spill it. 1179 // This value is produced on the stack, we never need to spill it.
1178 if (first_output->IsStackSlot()) { 1180 if (first_output->IsStackSlot()) {
1179 DCHECK(first_output->index() < frame_->GetSpillSlotCount()); 1181 DCHECK(StackSlotOperand::cast(first_output)->index() <
1180 range->SetSpillOperand(first_output); 1182 frame_->GetSpillSlotCount());
1183 range->SetSpillOperand(StackSlotOperand::cast(first_output));
1181 range->SetSpillStartIndex(instr_index + 1); 1184 range->SetSpillStartIndex(instr_index + 1);
1182 assigned = true; 1185 assigned = true;
1183 } 1186 }
1184 AddGapMove(instr_index + 1, Instruction::START, first_output, 1187 AddGapMove(instr_index + 1, Instruction::START, first_output,
1185 output_copy); 1188 output_copy);
1186 } 1189 }
1187 // Make sure we add a gap move for spilling (if we have not done 1190 // Make sure we add a gap move for spilling (if we have not done
1188 // so already). 1191 // so already).
1189 if (!assigned) { 1192 if (!assigned) {
1190 range->SpillAtDefinition(local_zone(), instr_index + 1, first_output); 1193 range->SpillAtDefinition(local_zone(), instr_index + 1, first_output);
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after
1234 // this is not desired, then the pointer map at this instruction needs 1237 // this is not desired, then the pointer map at this instruction needs
1235 // to be adjusted manually. 1238 // to be adjusted manually.
1236 } 1239 }
1237 } 1240 }
1238 } 1241 }
1239 1242
1240 1243
1241 bool RegisterAllocator::IsOutputRegisterOf(Instruction* instr, int index) { 1244 bool RegisterAllocator::IsOutputRegisterOf(Instruction* instr, int index) {
1242 for (size_t i = 0; i < instr->OutputCount(); i++) { 1245 for (size_t i = 0; i < instr->OutputCount(); i++) {
1243 auto output = instr->OutputAt(i); 1246 auto output = instr->OutputAt(i);
1244 if (output->IsRegister() && output->index() == index) return true; 1247 if (output->IsRegister() && RegisterOperand::cast(output)->index() == index)
1248 return true;
1245 } 1249 }
1246 return false; 1250 return false;
1247 } 1251 }
1248 1252
1249 1253
1250 bool RegisterAllocator::IsOutputDoubleRegisterOf(Instruction* instr, 1254 bool RegisterAllocator::IsOutputDoubleRegisterOf(Instruction* instr,
1251 int index) { 1255 int index) {
1252 for (size_t i = 0; i < instr->OutputCount(); i++) { 1256 for (size_t i = 0; i < instr->OutputCount(); i++) {
1253 auto output = instr->OutputAt(i); 1257 auto output = instr->OutputAt(i);
1254 if (output->IsDoubleRegister() && output->index() == index) return true; 1258 if (output->IsDoubleRegister() &&
1259 DoubleRegisterOperand::cast(output)->index() == index)
1260 return true;
1255 } 1261 }
1256 return false; 1262 return false;
1257 } 1263 }
1258 1264
1259 1265
1260 void RegisterAllocator::ProcessInstructions(const InstructionBlock* block, 1266 void RegisterAllocator::ProcessInstructions(const InstructionBlock* block,
1261 BitVector* live) { 1267 BitVector* live) {
1262 int block_start = block->first_instruction_index(); 1268 int block_start = block->first_instruction_index();
1263 auto block_start_position = 1269 auto block_start_position =
1264 LifetimePosition::GapFromInstructionIndex(block_start); 1270 LifetimePosition::GapFromInstructionIndex(block_start);
1265 1271
1266 for (int index = block->last_instruction_index(); index >= block_start; 1272 for (int index = block->last_instruction_index(); index >= block_start;
1267 index--) { 1273 index--) {
1268 auto curr_position = 1274 auto curr_position =
1269 LifetimePosition::InstructionFromInstructionIndex(index); 1275 LifetimePosition::InstructionFromInstructionIndex(index);
1270 auto instr = InstructionAt(index); 1276 auto instr = InstructionAt(index);
1271 DCHECK(instr != nullptr); 1277 DCHECK(instr != nullptr);
1272 DCHECK(curr_position.IsInstructionPosition()); 1278 DCHECK(curr_position.IsInstructionPosition());
1273 // Process output, inputs, and temps of this instruction. 1279 // Process output, inputs, and temps of this instruction.
1274 for (size_t i = 0; i < instr->OutputCount(); i++) { 1280 for (size_t i = 0; i < instr->OutputCount(); i++) {
1275 auto output = instr->OutputAt(i); 1281 auto output = instr->OutputAt(i);
1276 if (output->IsUnallocated()) { 1282 if (output->IsUnallocated()) {
1277 // Unsupported. 1283 // Unsupported.
1278 DCHECK(!UnallocatedOperand::cast(output)->HasSlotPolicy()); 1284 DCHECK(!UnallocatedOperand::cast(output)->HasSlotPolicy());
1279 int out_vreg = UnallocatedOperand::cast(output)->virtual_register(); 1285 int out_vreg = UnallocatedOperand::cast(output)->virtual_register();
1280 live->Remove(out_vreg); 1286 live->Remove(out_vreg);
1281 } else if (output->IsConstant()) { 1287 } else if (output->IsConstant()) {
1282 int out_vreg = output->index(); 1288 int out_vreg = ConstantOperand::cast(output)->virtual_register();
1283 live->Remove(out_vreg); 1289 live->Remove(out_vreg);
1284 } 1290 }
1285 Define(curr_position, output, nullptr); 1291 Define(curr_position, output, nullptr);
1286 } 1292 }
1287 1293
1288 if (instr->ClobbersRegisters()) { 1294 if (instr->ClobbersRegisters()) {
1289 for (int i = 0; i < config()->num_general_registers(); ++i) { 1295 for (int i = 0; i < config()->num_general_registers(); ++i) {
1290 if (!IsOutputRegisterOf(instr, i)) { 1296 if (!IsOutputRegisterOf(instr, i)) {
1291 auto range = FixedLiveRangeFor(i); 1297 auto range = FixedLiveRangeFor(i);
1292 range->AddUseInterval(curr_position, curr_position.End(), 1298 range->AddUseInterval(curr_position, curr_position.End(),
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after
1360 } 1366 }
1361 auto move_ops = move->move_operands(); 1367 auto move_ops = move->move_operands();
1362 for (auto cur = move_ops->begin(); cur != move_ops->end(); ++cur) { 1368 for (auto cur = move_ops->begin(); cur != move_ops->end(); ++cur) {
1363 auto from = cur->source(); 1369 auto from = cur->source();
1364 auto to = cur->destination(); 1370 auto to = cur->destination();
1365 auto hint = to; 1371 auto hint = to;
1366 if (to->IsUnallocated()) { 1372 if (to->IsUnallocated()) {
1367 int to_vreg = UnallocatedOperand::cast(to)->virtual_register(); 1373 int to_vreg = UnallocatedOperand::cast(to)->virtual_register();
1368 auto to_range = LiveRangeFor(to_vreg); 1374 auto to_range = LiveRangeFor(to_vreg);
1369 if (to_range->is_phi()) { 1375 if (to_range->is_phi()) {
1370 DCHECK(!FLAG_turbo_delay_ssa_decon);
1371 if (to_range->is_non_loop_phi()) { 1376 if (to_range->is_non_loop_phi()) {
1372 hint = to_range->current_hint_operand(); 1377 hint = to_range->current_hint_operand();
1373 } 1378 }
1374 } else { 1379 } else {
1375 if (live->Contains(to_vreg)) { 1380 if (live->Contains(to_vreg)) {
1376 Define(curr_position, to, from); 1381 Define(curr_position, to, from);
1377 live->Remove(to_vreg); 1382 live->Remove(to_vreg);
1378 } else { 1383 } else {
1379 cur->Eliminate(); 1384 cur->Eliminate();
1380 continue; 1385 continue;
(...skipping 13 matching lines...) Expand all
1394 1399
1395 1400
1396 void RegisterAllocator::ResolvePhis(const InstructionBlock* block) { 1401 void RegisterAllocator::ResolvePhis(const InstructionBlock* block) {
1397 for (auto phi : block->phis()) { 1402 for (auto phi : block->phis()) {
1398 int phi_vreg = phi->virtual_register(); 1403 int phi_vreg = phi->virtual_register();
1399 auto res = 1404 auto res =
1400 phi_map_.insert(std::make_pair(phi_vreg, PhiMapValue(phi, block))); 1405 phi_map_.insert(std::make_pair(phi_vreg, PhiMapValue(phi, block)));
1401 DCHECK(res.second); 1406 DCHECK(res.second);
1402 USE(res); 1407 USE(res);
1403 auto& output = phi->output(); 1408 auto& output = phi->output();
1404 if (!FLAG_turbo_delay_ssa_decon) { 1409 for (size_t i = 0; i < phi->operands().size(); ++i) {
1405 for (size_t i = 0; i < phi->operands().size(); ++i) { 1410 InstructionBlock* cur_block =
1406 InstructionBlock* cur_block = 1411 code()->InstructionBlockAt(block->predecessors()[i]);
1407 code()->InstructionBlockAt(block->predecessors()[i]); 1412 AddGapMove(cur_block->last_instruction_index(), Instruction::END,
1408 AddGapMove(cur_block->last_instruction_index(), Instruction::END, 1413 &phi->inputs()[i], &output);
1409 &phi->inputs()[i], &output); 1414 DCHECK(
1410 DCHECK(!InstructionAt(cur_block->last_instruction_index()) 1415 !InstructionAt(cur_block->last_instruction_index())->HasPointerMap());
1411 ->HasPointerMap());
1412 }
1413 } 1416 }
1414 auto live_range = LiveRangeFor(phi_vreg); 1417 auto live_range = LiveRangeFor(phi_vreg);
1415 int gap_index = block->first_instruction_index(); 1418 int gap_index = block->first_instruction_index();
1416 live_range->SpillAtDefinition(local_zone(), gap_index, &output); 1419 live_range->SpillAtDefinition(local_zone(), gap_index, &output);
1417 live_range->SetSpillStartIndex(gap_index); 1420 live_range->SetSpillStartIndex(gap_index);
1418 // We use the phi-ness of some nodes in some later heuristics. 1421 // We use the phi-ness of some nodes in some later heuristics.
1419 live_range->set_is_phi(true); 1422 live_range->set_is_phi(true);
1420 live_range->set_is_non_loop_phi(!block->IsLoopHeader()); 1423 live_range->set_is_non_loop_phi(!block->IsLoopHeader());
1421 } 1424 }
1422 } 1425 }
(...skipping 234 matching lines...) Expand 10 before | Expand all | Expand 10 after
1657 }; 1660 };
1658 1661
1659 } // namespace 1662 } // namespace
1660 1663
1661 1664
1662 void RegisterAllocator::ResolveControlFlow() { 1665 void RegisterAllocator::ResolveControlFlow() {
1663 // Lazily linearize live ranges in memory for fast lookup. 1666 // Lazily linearize live ranges in memory for fast lookup.
1664 LiveRangeFinder finder(*this); 1667 LiveRangeFinder finder(*this);
1665 for (auto block : code()->instruction_blocks()) { 1668 for (auto block : code()->instruction_blocks()) {
1666 if (CanEagerlyResolveControlFlow(block)) continue; 1669 if (CanEagerlyResolveControlFlow(block)) continue;
1667 if (FLAG_turbo_delay_ssa_decon) {
1668 // resolve phis
1669 for (auto phi : block->phis()) {
1670 auto* block_bound =
1671 finder.ArrayFor(phi->virtual_register())->FindSucc(block);
1672 auto phi_output =
1673 block_bound->range_->GetAssignedOperand(operand_cache());
1674 phi->output().ConvertTo(phi_output->kind(), phi_output->index());
1675 size_t pred_index = 0;
1676 for (auto pred : block->predecessors()) {
1677 const InstructionBlock* pred_block = code()->InstructionBlockAt(pred);
1678 auto* pred_bound = finder.ArrayFor(phi->operands()[pred_index])
1679 ->FindPred(pred_block);
1680 auto pred_op =
1681 pred_bound->range_->GetAssignedOperand(operand_cache());
1682 phi->inputs()[pred_index] = *pred_op;
1683 ResolveControlFlow(block, phi_output, pred_block, pred_op);
1684 pred_index++;
1685 }
1686 }
1687 }
1688 auto live = live_in_sets_[block->rpo_number().ToInt()]; 1670 auto live = live_in_sets_[block->rpo_number().ToInt()];
1689 BitVector::Iterator iterator(live); 1671 BitVector::Iterator iterator(live);
1690 while (!iterator.Done()) { 1672 while (!iterator.Done()) {
1691 auto* array = finder.ArrayFor(iterator.Current()); 1673 auto* array = finder.ArrayFor(iterator.Current());
1692 for (auto pred : block->predecessors()) { 1674 for (auto pred : block->predecessors()) {
1693 FindResult result; 1675 FindResult result;
1694 const auto* pred_block = code()->InstructionBlockAt(pred); 1676 const auto* pred_block = code()->InstructionBlockAt(pred);
1695 array->Find(block, pred_block, &result); 1677 array->Find(block, pred_block, &result);
1696 if (result.cur_cover_ == result.pred_cover_ || 1678 if (result.cur_cover_ == result.pred_cover_ ||
1697 result.cur_cover_->IsSpilled()) 1679 result.cur_cover_->IsSpilled())
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
1738 1720
1739 // Process the instructions in reverse order, generating and killing 1721 // Process the instructions in reverse order, generating and killing
1740 // live values. 1722 // live values.
1741 ProcessInstructions(block, live); 1723 ProcessInstructions(block, live);
1742 // All phi output operands are killed by this block. 1724 // All phi output operands are killed by this block.
1743 for (auto phi : block->phis()) { 1725 for (auto phi : block->phis()) {
1744 // The live range interval already ends at the first instruction of the 1726 // The live range interval already ends at the first instruction of the
1745 // block. 1727 // block.
1746 int phi_vreg = phi->virtual_register(); 1728 int phi_vreg = phi->virtual_register();
1747 live->Remove(phi_vreg); 1729 live->Remove(phi_vreg);
1748 if (!FLAG_turbo_delay_ssa_decon) { 1730 InstructionOperand* hint = nullptr;
1749 InstructionOperand* hint = nullptr; 1731 InstructionOperand* phi_operand = nullptr;
1750 InstructionOperand* phi_operand = nullptr; 1732 auto instr = GetLastInstruction(
1751 auto instr = GetLastInstruction( 1733 code()->InstructionBlockAt(block->predecessors()[0]));
1752 code()->InstructionBlockAt(block->predecessors()[0])); 1734 auto move = instr->GetParallelMove(Instruction::END);
1753 auto move = instr->GetParallelMove(Instruction::END); 1735 for (int j = 0; j < move->move_operands()->length(); ++j) {
1754 for (int j = 0; j < move->move_operands()->length(); ++j) { 1736 auto to = move->move_operands()->at(j).destination();
1755 auto to = move->move_operands()->at(j).destination(); 1737 if (to->IsUnallocated() &&
1756 if (to->IsUnallocated() && 1738 UnallocatedOperand::cast(to)->virtual_register() == phi_vreg) {
1757 UnallocatedOperand::cast(to)->virtual_register() == phi_vreg) { 1739 hint = move->move_operands()->at(j).source();
1758 hint = move->move_operands()->at(j).source(); 1740 phi_operand = to;
1759 phi_operand = to; 1741 break;
1760 break;
1761 }
1762 } 1742 }
1763 DCHECK(hint != nullptr);
1764 auto block_start = LifetimePosition::GapFromInstructionIndex(
1765 block->first_instruction_index());
1766 Define(block_start, phi_operand, hint);
1767 } 1743 }
1744 DCHECK(hint != nullptr);
1745 auto block_start = LifetimePosition::GapFromInstructionIndex(
1746 block->first_instruction_index());
1747 Define(block_start, phi_operand, hint);
1768 } 1748 }
1769 1749
1770 // Now live is live_in for this block except not including values live 1750 // Now live is live_in for this block except not including values live
1771 // out on backward successor edges. 1751 // out on backward successor edges.
1772 live_in_sets_[block_id] = live; 1752 live_in_sets_[block_id] = live;
1773 1753
1774 if (block->IsLoopHeader()) { 1754 if (block->IsLoopHeader()) {
1775 // Add a live range stretching from the first loop instruction to the last 1755 // Add a live range stretching from the first loop instruction to the last
1776 // for each value live on entry to the header. 1756 // for each value live on entry to the header.
1777 BitVector::Iterator iterator(live); 1757 BitVector::Iterator iterator(live);
(...skipping 399 matching lines...) Expand 10 before | Expand all | Expand 10 after
2177 for (auto cur_inactive : inactive_live_ranges()) { 2157 for (auto cur_inactive : inactive_live_ranges()) {
2178 DCHECK(cur_inactive->End().Value() > current->Start().Value()); 2158 DCHECK(cur_inactive->End().Value() > current->Start().Value());
2179 auto next_intersection = cur_inactive->FirstIntersection(current); 2159 auto next_intersection = cur_inactive->FirstIntersection(current);
2180 if (!next_intersection.IsValid()) continue; 2160 if (!next_intersection.IsValid()) continue;
2181 int cur_reg = cur_inactive->assigned_register(); 2161 int cur_reg = cur_inactive->assigned_register();
2182 free_until_pos[cur_reg] = Min(free_until_pos[cur_reg], next_intersection); 2162 free_until_pos[cur_reg] = Min(free_until_pos[cur_reg], next_intersection);
2183 } 2163 }
2184 2164
2185 auto hint = current->FirstHint(); 2165 auto hint = current->FirstHint();
2186 if (hint != nullptr && (hint->IsRegister() || hint->IsDoubleRegister())) { 2166 if (hint != nullptr && (hint->IsRegister() || hint->IsDoubleRegister())) {
2187 int register_index = hint->index(); 2167 int register_index = AllocatedOperand::cast(hint)->index();
2188 TRACE("Found reg hint %s (free until [%d) for live range %d (end %d[).\n", 2168 TRACE("Found reg hint %s (free until [%d) for live range %d (end %d[).\n",
2189 RegisterName(register_index), free_until_pos[register_index].Value(), 2169 RegisterName(register_index), free_until_pos[register_index].Value(),
2190 current->id(), current->End().Value()); 2170 current->id(), current->End().Value());
2191 2171
2192 // The desired register is free until the end of the current live range. 2172 // The desired register is free until the end of the current live range.
2193 if (free_until_pos[register_index].Value() >= current->End().Value()) { 2173 if (free_until_pos[register_index].Value() >= current->End().Value()) {
2194 TRACE("Assigning preferred reg %s to live range %d\n", 2174 TRACE("Assigning preferred reg %s to live range %d\n",
2195 RegisterName(register_index), current->id()); 2175 RegisterName(register_index), current->id());
2196 SetLiveRangeAssignedRegister(current, register_index); 2176 SetLiveRangeAssignedRegister(current, register_index);
2197 return true; 2177 return true;
(...skipping 355 matching lines...) Expand 10 before | Expand all | Expand 10 after
2553 } else { 2533 } else {
2554 DCHECK(range->Kind() == GENERAL_REGISTERS); 2534 DCHECK(range->Kind() == GENERAL_REGISTERS);
2555 assigned_registers_->Add(reg); 2535 assigned_registers_->Add(reg);
2556 } 2536 }
2557 range->set_assigned_register(reg, operand_cache()); 2537 range->set_assigned_register(reg, operand_cache());
2558 } 2538 }
2559 2539
2560 } // namespace compiler 2540 } // namespace compiler
2561 } // namespace internal 2541 } // namespace internal
2562 } // namespace v8 2542 } // 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