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

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

Issue 785993002: [turbofan] delay inserting spill slots for parent ranges. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Created 6 years 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 49 matching lines...) Expand 10 before | Expand all | Expand 10 after
60 60
61 void UseInterval::SplitAt(LifetimePosition pos, Zone* zone) { 61 void UseInterval::SplitAt(LifetimePosition pos, Zone* zone) {
62 DCHECK(Contains(pos) && pos.Value() != start().Value()); 62 DCHECK(Contains(pos) && pos.Value() != start().Value());
63 UseInterval* after = new (zone) UseInterval(pos, end_); 63 UseInterval* after = new (zone) UseInterval(pos, end_);
64 after->next_ = next_; 64 after->next_ = next_;
65 next_ = after; 65 next_ = after;
66 end_ = pos; 66 end_ = pos;
67 } 67 }
68 68
69 69
70 struct LiveRange::SpillAtDefinitionList : ZoneObject {
71 SpillAtDefinitionList(int gap_index, InstructionOperand* operand,
72 SpillAtDefinitionList* next)
73 : gap_index(gap_index), operand(operand), next(next) {}
74 const int gap_index;
75 InstructionOperand* const operand;
76 SpillAtDefinitionList* const next;
77 };
78
79
70 #ifdef DEBUG 80 #ifdef DEBUG
71 81
72 82
73 void LiveRange::Verify() const { 83 void LiveRange::Verify() const {
74 UsePosition* cur = first_pos_; 84 UsePosition* cur = first_pos_;
75 while (cur != NULL) { 85 while (cur != NULL) {
76 DCHECK(Start().Value() <= cur->pos().Value() && 86 DCHECK(Start().Value() <= cur->pos().Value() &&
77 cur->pos().Value() <= End().Value()); 87 cur->pos().Value() <= End().Value());
78 cur = cur->next(); 88 cur = cur->next();
79 } 89 }
(...skipping 17 matching lines...) Expand all
97 #endif 107 #endif
98 108
99 109
100 LiveRange::LiveRange(int id, Zone* zone) 110 LiveRange::LiveRange(int id, Zone* zone)
101 : id_(id), 111 : id_(id),
102 spilled_(false), 112 spilled_(false),
103 is_phi_(false), 113 is_phi_(false),
104 is_non_loop_phi_(false), 114 is_non_loop_phi_(false),
105 kind_(UNALLOCATED_REGISTERS), 115 kind_(UNALLOCATED_REGISTERS),
106 assigned_register_(kInvalidAssignment), 116 assigned_register_(kInvalidAssignment),
107 last_interval_(NULL), 117 last_interval_(nullptr),
108 first_interval_(NULL), 118 first_interval_(nullptr),
109 first_pos_(NULL), 119 first_pos_(nullptr),
110 parent_(NULL), 120 parent_(nullptr),
111 next_(NULL), 121 next_(nullptr),
112 current_interval_(NULL), 122 current_interval_(nullptr),
113 last_processed_use_(NULL), 123 last_processed_use_(nullptr),
114 current_hint_operand_(NULL), 124 current_hint_operand_(nullptr),
115 spill_operand_(new (zone) InstructionOperand()),
116 spill_start_index_(kMaxInt), 125 spill_start_index_(kMaxInt),
117 spill_range_(NULL) {} 126 spill_type_(SpillType::kNoSpillType),
127 spill_operand_(nullptr),
128 spills_at_definition_(nullptr) {}
118 129
119 130
120 void LiveRange::set_assigned_register(int reg, Zone* zone) { 131 void LiveRange::set_assigned_register(int reg) {
121 DCHECK(!HasRegisterAssigned() && !IsSpilled()); 132 DCHECK(!HasRegisterAssigned() && !IsSpilled());
122 assigned_register_ = reg; 133 assigned_register_ = reg;
123 if (spill_range_ == nullptr) {
124 ConvertOperands(zone);
125 }
126 } 134 }
127 135
128 136
129 void LiveRange::MakeSpilled(Zone* zone) { 137 void LiveRange::MakeSpilled() {
130 DCHECK(!IsSpilled()); 138 DCHECK(!IsSpilled());
131 DCHECK(TopLevel()->HasAllocatedSpillOperand()); 139 DCHECK(!TopLevel()->HasNoSpillType());
132 spilled_ = true; 140 spilled_ = true;
133 assigned_register_ = kInvalidAssignment; 141 assigned_register_ = kInvalidAssignment;
134 ConvertOperands(zone);
135 } 142 }
136 143
137 144
138 bool LiveRange::HasAllocatedSpillOperand() const { 145 void LiveRange::SpillAtDefinition(Zone* zone, int gap_index,
139 DCHECK(spill_operand_ != NULL); 146 InstructionOperand* operand) {
140 return !spill_operand_->IsIgnored() || spill_range_ != NULL; 147 DCHECK(HasNoSpillType());
148 spills_at_definition_ = new (zone)
149 SpillAtDefinitionList(gap_index, operand, spills_at_definition_);
150 }
151
152
153 void LiveRange::CommitSpillsAtDefinition(InstructionSequence* sequence,
154 InstructionOperand* op) {
155 auto to_spill = TopLevel()->spills_at_definition_;
156 if (to_spill == nullptr) return;
157 Zone* zone = sequence->zone();
158 for (; to_spill != nullptr; to_spill = to_spill->next) {
159 auto gap = sequence->GapAt(to_spill->gap_index);
160 auto move = gap->GetOrCreateParallelMove(GapInstruction::START, zone);
161 move->AddMove(to_spill->operand, op, zone);
162 }
163 TopLevel()->spills_at_definition_ = nullptr;
141 } 164 }
142 165
143 166
144 void LiveRange::SetSpillOperand(InstructionOperand* operand) { 167 void LiveRange::SetSpillOperand(InstructionOperand* operand) {
168 DCHECK(HasNoSpillType());
145 DCHECK(!operand->IsUnallocated()); 169 DCHECK(!operand->IsUnallocated());
146 DCHECK(spill_operand_ != NULL); 170 spill_type_ = SpillType::kSpillOperand;
147 DCHECK(spill_operand_->IsIgnored()); 171 spill_operand_ = operand;
148 spill_operand_->ConvertTo(operand->kind(), operand->index()); 172 }
173
174
175 void LiveRange::SetSpillRange(SpillRange* spill_range) {
176 DCHECK(HasNoSpillType() || HasSpillRange());
177 DCHECK_NE(spill_range, nullptr);
178 spill_type_ = SpillType::kSpillRange;
179 spill_range_ = spill_range;
149 } 180 }
150 181
151 182
152 void LiveRange::CommitSpillOperand(InstructionOperand* operand) { 183 void LiveRange::CommitSpillOperand(InstructionOperand* operand) {
153 DCHECK(spill_range_ != NULL); 184 DCHECK(HasSpillRange());
185 DCHECK(!operand->IsUnallocated());
154 DCHECK(!IsChild()); 186 DCHECK(!IsChild());
155 spill_range_ = NULL; 187 spill_type_ = SpillType::kSpillOperand;
156 SetSpillOperand(operand); 188 spill_operand_ = operand;
157 for (LiveRange* range = this; range != NULL; range = range->next()) {
158 if (range->IsSpilled()) {
159 range->ConvertUsesToOperand(operand);
160 }
161 }
162 } 189 }
163 190
164 191
165 UsePosition* LiveRange::NextUsePosition(LifetimePosition start) { 192 UsePosition* LiveRange::NextUsePosition(LifetimePosition start) {
166 UsePosition* use_pos = last_processed_use_; 193 UsePosition* use_pos = last_processed_use_;
167 if (use_pos == NULL) use_pos = first_pos(); 194 if (use_pos == NULL) use_pos = first_pos();
168 while (use_pos != NULL && use_pos->pos().Value() < start.Value()) { 195 while (use_pos != NULL && use_pos->pos().Value() < start.Value()) {
169 use_pos = use_pos->next(); 196 use_pos = use_pos->next();
170 } 197 }
171 last_processed_use_ = use_pos; 198 last_processed_use_ = use_pos;
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
208 // We cannot spill a live range that has a use requiring a register 235 // We cannot spill a live range that has a use requiring a register
209 // at the current or the immediate next position. 236 // at the current or the immediate next position.
210 UsePosition* use_pos = NextRegisterPosition(pos); 237 UsePosition* use_pos = NextRegisterPosition(pos);
211 if (use_pos == NULL) return true; 238 if (use_pos == NULL) return true;
212 return use_pos->pos().Value() > 239 return use_pos->pos().Value() >
213 pos.NextInstruction().InstructionEnd().Value(); 240 pos.NextInstruction().InstructionEnd().Value();
214 } 241 }
215 242
216 243
217 InstructionOperand* LiveRange::CreateAssignedOperand(Zone* zone) const { 244 InstructionOperand* LiveRange::CreateAssignedOperand(Zone* zone) const {
218 InstructionOperand* op = NULL; 245 InstructionOperand* op = nullptr;
219 if (HasRegisterAssigned()) { 246 if (HasRegisterAssigned()) {
220 DCHECK(!IsSpilled()); 247 DCHECK(!IsSpilled());
221 switch (Kind()) { 248 switch (Kind()) {
222 case GENERAL_REGISTERS: 249 case GENERAL_REGISTERS:
223 op = RegisterOperand::Create(assigned_register(), zone); 250 op = RegisterOperand::Create(assigned_register(), zone);
224 break; 251 break;
225 case DOUBLE_REGISTERS: 252 case DOUBLE_REGISTERS:
226 op = DoubleRegisterOperand::Create(assigned_register(), zone); 253 op = DoubleRegisterOperand::Create(assigned_register(), zone);
227 break; 254 break;
228 default: 255 default:
229 UNREACHABLE(); 256 UNREACHABLE();
230 } 257 }
231 } else if (IsSpilled()) { 258 } else {
259 DCHECK(IsSpilled());
232 DCHECK(!HasRegisterAssigned()); 260 DCHECK(!HasRegisterAssigned());
233 op = TopLevel()->GetSpillOperand(); 261 op = TopLevel()->GetSpillOperand();
234 DCHECK(!op->IsUnallocated()); 262 DCHECK(!op->IsUnallocated());
235 } else {
236 UnallocatedOperand* unalloc =
237 new (zone) UnallocatedOperand(UnallocatedOperand::NONE);
238 unalloc->set_virtual_register(id_);
239 op = unalloc;
240 } 263 }
241 return op; 264 return op;
242 } 265 }
243 266
244 267
245 UseInterval* LiveRange::FirstSearchIntervalForPosition( 268 UseInterval* LiveRange::FirstSearchIntervalForPosition(
246 LifetimePosition position) const { 269 LifetimePosition position) const {
247 if (current_interval_ == NULL) return first_interval_; 270 if (current_interval_ == NULL) return first_interval_;
248 if (current_interval_->start().Value() > position.Value()) { 271 if (current_interval_->start().Value() > position.Value()) {
249 current_interval_ = NULL; 272 current_interval_ = NULL;
(...skipping 217 matching lines...) Expand 10 before | Expand all | Expand 10 after
467 if (use_pos->HasOperand()) { 490 if (use_pos->HasOperand()) {
468 DCHECK(op->IsRegister() || op->IsDoubleRegister() || 491 DCHECK(op->IsRegister() || op->IsDoubleRegister() ||
469 !use_pos->RequiresRegister()); 492 !use_pos->RequiresRegister());
470 use_pos->operand()->ConvertTo(op->kind(), op->index()); 493 use_pos->operand()->ConvertTo(op->kind(), op->index());
471 } 494 }
472 use_pos = use_pos->next(); 495 use_pos = use_pos->next();
473 } 496 }
474 } 497 }
475 498
476 499
477 void LiveRange::ConvertOperands(Zone* zone) {
478 ConvertUsesToOperand(CreateAssignedOperand(zone));
479 }
480
481
482 bool LiveRange::CanCover(LifetimePosition position) const { 500 bool LiveRange::CanCover(LifetimePosition position) const {
483 if (IsEmpty()) return false; 501 if (IsEmpty()) return false;
484 return Start().Value() <= position.Value() && 502 return Start().Value() <= position.Value() &&
485 position.Value() < End().Value(); 503 position.Value() < End().Value();
486 } 504 }
487 505
488 506
489 bool LiveRange::Covers(LifetimePosition position) { 507 bool LiveRange::Covers(LifetimePosition position) {
490 if (!CanCover(position)) return false; 508 if (!CanCover(position)) return false;
491 UseInterval* start_search = FirstSearchIntervalForPosition(position); 509 UseInterval* start_search = FirstSearchIntervalForPosition(position);
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after
548 spill_ranges_(8, local_zone()), 566 spill_ranges_(8, local_zone()),
549 mode_(UNALLOCATED_REGISTERS), 567 mode_(UNALLOCATED_REGISTERS),
550 num_registers_(-1), 568 num_registers_(-1),
551 allocation_ok_(true) { 569 allocation_ok_(true) {
552 DCHECK(this->config()->num_general_registers() <= 570 DCHECK(this->config()->num_general_registers() <=
553 RegisterConfiguration::kMaxGeneralRegisters); 571 RegisterConfiguration::kMaxGeneralRegisters);
554 DCHECK(this->config()->num_double_registers() <= 572 DCHECK(this->config()->num_double_registers() <=
555 RegisterConfiguration::kMaxDoubleRegisters); 573 RegisterConfiguration::kMaxDoubleRegisters);
556 // TryAllocateFreeReg and AllocateBlockedReg assume this 574 // TryAllocateFreeReg and AllocateBlockedReg assume this
557 // when allocating local arrays. 575 // when allocating local arrays.
558 DCHECK(this->config()->num_double_registers() >= 576 DCHECK(RegisterConfiguration::kMaxDoubleRegisters >=
559 this->config()->num_general_registers()); 577 this->config()->num_general_registers());
560 assigned_registers_ = 578 assigned_registers_ =
561 new (code_zone()) BitVector(config->num_general_registers(), code_zone()); 579 new (code_zone()) BitVector(config->num_general_registers(), code_zone());
562 assigned_double_registers_ = new (code_zone()) 580 assigned_double_registers_ = new (code_zone())
563 BitVector(config->num_aliased_double_registers(), code_zone()); 581 BitVector(config->num_aliased_double_registers(), code_zone());
564 frame->SetAllocatedRegisters(assigned_registers_); 582 frame->SetAllocatedRegisters(assigned_registers_);
565 frame->SetAllocatedDoubleRegisters(assigned_double_registers_); 583 frame->SetAllocatedDoubleRegisters(assigned_double_registers_);
566 } 584 }
567 585
568 586
(...skipping 200 matching lines...) Expand 10 before | Expand all | Expand 10 after
769 } 787 }
770 } 788 }
771 move->AddMove(from, to, code_zone()); 789 move->AddMove(from, to, code_zone());
772 } 790 }
773 791
774 792
775 static bool AreUseIntervalsIntersecting(UseInterval* interval1, 793 static bool AreUseIntervalsIntersecting(UseInterval* interval1,
776 UseInterval* interval2) { 794 UseInterval* interval2) {
777 while (interval1 != NULL && interval2 != NULL) { 795 while (interval1 != NULL && interval2 != NULL) {
778 if (interval1->start().Value() < interval2->start().Value()) { 796 if (interval1->start().Value() < interval2->start().Value()) {
779 if (interval1->end().Value() >= interval2->start().Value()) { 797 if (interval1->end().Value() > interval2->start().Value()) {
780 return true; 798 return true;
781 } 799 }
782 interval1 = interval1->next(); 800 interval1 = interval1->next();
783 } else { 801 } else {
784 if (interval2->end().Value() >= interval1->start().Value()) { 802 if (interval2->end().Value() > interval1->start().Value()) {
785 return true; 803 return true;
786 } 804 }
787 interval2 = interval2->next(); 805 interval2 = interval2->next();
788 } 806 }
789 } 807 }
790 return false; 808 return false;
791 } 809 }
792 810
793 811
794 SpillRange::SpillRange(LiveRange* range, int id, Zone* zone) 812 SpillRange::SpillRange(LiveRange* range, int id, Zone* zone)
795 : id_(id), live_ranges_(1, zone), end_position_(range->End()) { 813 : id_(id), live_ranges_(1, zone), end_position_(range->End()) {
796 UseInterval* src = range->first_interval(); 814 UseInterval* src = range->first_interval();
797 UseInterval* result = NULL; 815 UseInterval* result = NULL;
798 UseInterval* node = NULL; 816 UseInterval* node = NULL;
799 // Copy the nodes 817 // Copy the nodes
800 while (src != NULL) { 818 while (src != NULL) {
801 UseInterval* new_node = new (zone) UseInterval(src->start(), src->end()); 819 UseInterval* new_node = new (zone) UseInterval(src->start(), src->end());
802 if (result == NULL) { 820 if (result == NULL) {
803 result = new_node; 821 result = new_node;
804 } else { 822 } else {
805 node->set_next(new_node); 823 node->set_next(new_node);
806 } 824 }
807 node = new_node; 825 node = new_node;
808 src = src->next(); 826 src = src->next();
809 } 827 }
810 use_interval_ = result; 828 use_interval_ = result;
811 live_ranges_.Add(range, zone); 829 live_ranges_.Add(range, zone);
812 DCHECK(range->GetSpillRange() == NULL); 830 DCHECK(!range->HasSpillRange());
813 range->SetSpillRange(this); 831 range->SetSpillRange(this);
814 } 832 }
815 833
816 834
817 bool SpillRange::IsIntersectingWith(SpillRange* other) { 835 bool SpillRange::IsIntersectingWith(SpillRange* other) {
818 if (End().Value() <= other->use_interval_->start().Value() || 836 if (End().Value() <= other->use_interval_->start().Value() ||
819 other->End().Value() <= use_interval_->start().Value()) { 837 other->End().Value() <= use_interval_->start().Value()) {
820 return false; 838 return false;
821 } 839 }
822 return AreUseIntervalsIntersecting(use_interval_, other->use_interval_); 840 return AreUseIntervalsIntersecting(use_interval_, other->use_interval_);
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after
891 SpillRange* other = spill_ranges_.at(j); 909 SpillRange* other = spill_ranges_.at(j);
892 if (!other->IsEmpty()) { 910 if (!other->IsEmpty()) {
893 range->TryMerge(spill_ranges_.at(j), local_zone()); 911 range->TryMerge(spill_ranges_.at(j), local_zone());
894 } 912 }
895 } 913 }
896 } 914 }
897 } 915 }
898 916
899 // Allocate slots for the merged spill ranges. 917 // Allocate slots for the merged spill ranges.
900 for (int i = 0; i < spill_ranges_.length(); i++) { 918 for (int i = 0; i < spill_ranges_.length(); i++) {
901 SpillRange* range = spill_ranges_.at(i); 919 auto range = spill_ranges_.at(i);
902 if (!range->IsEmpty()) { 920 if (range->IsEmpty()) continue;
903 // Allocate a new operand referring to the spill slot. 921 // Allocate a new operand referring to the spill slot.
904 RegisterKind kind = range->Kind(); 922 auto kind = range->Kind();
905 int index = frame()->AllocateSpillSlot(kind == DOUBLE_REGISTERS); 923 int index = frame()->AllocateSpillSlot(kind == DOUBLE_REGISTERS);
906 InstructionOperand* op = nullptr; 924 auto op_kind = kind == DOUBLE_REGISTERS
907 if (kind == DOUBLE_REGISTERS) { 925 ? InstructionOperand::DOUBLE_STACK_SLOT
908 op = DoubleStackSlotOperand::Create(index, local_zone()); 926 : InstructionOperand::STACK_SLOT;
909 } else { 927 auto op = new (code_zone()) InstructionOperand(op_kind, index);
910 DCHECK(kind == GENERAL_REGISTERS); 928 range->SetOperand(op);
911 op = StackSlotOperand::Create(index, local_zone()); 929 }
912 } 930 }
913 range->SetOperand(op); 931
932
933 void RegisterAllocator::CommitAssignment() {
934 for (auto range : live_ranges()) {
935 if (range == nullptr || range->IsEmpty()) continue;
936 auto assigned = range->CreateAssignedOperand(code_zone());
937 range->ConvertUsesToOperand(assigned);
938 if (range->IsSpilled()) {
939 range->CommitSpillsAtDefinition(code(), assigned);
914 } 940 }
915 } 941 }
916 } 942 }
917 943
918 944
919 SpillRange* RegisterAllocator::AssignSpillRangeToLiveRange(LiveRange* range) { 945 SpillRange* RegisterAllocator::AssignSpillRangeToLiveRange(LiveRange* range) {
920 DCHECK(FLAG_turbo_reuse_spill_slots); 946 DCHECK(FLAG_turbo_reuse_spill_slots);
921 int spill_id = spill_ranges_.length(); 947 int spill_id = spill_ranges_.length();
922 SpillRange* spill_range = 948 SpillRange* spill_range =
923 new (local_zone()) SpillRange(range, spill_id, local_zone()); 949 new (local_zone()) SpillRange(range, spill_id, local_zone());
924 spill_ranges_.Add(spill_range, local_zone()); 950 spill_ranges_.Add(spill_range, local_zone());
925 return spill_range; 951 return spill_range;
926 } 952 }
927 953
928 954
929 bool RegisterAllocator::TryReuseSpillForPhi(LiveRange* range) { 955 bool RegisterAllocator::TryReuseSpillForPhi(LiveRange* range) {
930 DCHECK(FLAG_turbo_reuse_spill_slots); 956 DCHECK(FLAG_turbo_reuse_spill_slots);
931 DCHECK(!range->HasAllocatedSpillOperand()); 957 DCHECK(range->HasNoSpillType());
932 if (range->IsChild() || !range->is_phi()) return false; 958 if (range->IsChild() || !range->is_phi()) return false;
933 959
934 auto lookup = phi_map_.find(range->id()); 960 auto lookup = phi_map_.find(range->id());
935 DCHECK(lookup != phi_map_.end()); 961 DCHECK(lookup != phi_map_.end());
936 auto phi = lookup->second.phi; 962 auto phi = lookup->second.phi;
937 auto block = lookup->second.block; 963 auto block = lookup->second.block;
938 // Count the number of spilled operands. 964 // Count the number of spilled operands.
939 size_t spilled_count = 0; 965 size_t spilled_count = 0;
940 LiveRange* first_op = nullptr; 966 LiveRange* first_op = nullptr;
941 for (size_t i = 0; i < phi->operands().size(); i++) { 967 for (size_t i = 0; i < phi->operands().size(); i++) {
(...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after
1040 InstructionOperand* output_operand = last_instruction->OutputAt(i); 1066 InstructionOperand* output_operand = last_instruction->OutputAt(i);
1041 DCHECK(!output_operand->IsConstant()); 1067 DCHECK(!output_operand->IsConstant());
1042 UnallocatedOperand* output = UnallocatedOperand::cast(output_operand); 1068 UnallocatedOperand* output = UnallocatedOperand::cast(output_operand);
1043 int output_vreg = output->virtual_register(); 1069 int output_vreg = output->virtual_register();
1044 LiveRange* range = LiveRangeFor(output_vreg); 1070 LiveRange* range = LiveRangeFor(output_vreg);
1045 bool assigned = false; 1071 bool assigned = false;
1046 if (output->HasFixedPolicy()) { 1072 if (output->HasFixedPolicy()) {
1047 AllocateFixed(output, -1, false); 1073 AllocateFixed(output, -1, false);
1048 // This value is produced on the stack, we never need to spill it. 1074 // This value is produced on the stack, we never need to spill it.
1049 if (output->IsStackSlot()) { 1075 if (output->IsStackSlot()) {
1076 DCHECK(output->index() < 0);
1050 range->SetSpillOperand(output); 1077 range->SetSpillOperand(output);
1051 range->SetSpillStartIndex(end); 1078 range->SetSpillStartIndex(end);
1052 assigned = true; 1079 assigned = true;
1053 } 1080 }
1054 1081
1055 for (auto succ : block->successors()) { 1082 for (auto succ : block->successors()) {
1056 const InstructionBlock* successor = code()->InstructionBlockAt(succ); 1083 const InstructionBlock* successor = code()->InstructionBlockAt(succ);
1057 DCHECK(successor->PredecessorCount() == 1); 1084 DCHECK(successor->PredecessorCount() == 1);
1058 int gap_index = successor->first_instruction_index() + 1; 1085 int gap_index = successor->first_instruction_index() + 1;
1059 DCHECK(code()->IsGapAt(gap_index)); 1086 DCHECK(code()->IsGapAt(gap_index));
1060 1087
1061 // Create an unconstrained operand for the same virtual register 1088 // Create an unconstrained operand for the same virtual register
1062 // and insert a gap move from the fixed output to the operand. 1089 // and insert a gap move from the fixed output to the operand.
1063 UnallocatedOperand* output_copy = 1090 UnallocatedOperand* output_copy =
1064 new (code_zone()) UnallocatedOperand(UnallocatedOperand::ANY); 1091 new (code_zone()) UnallocatedOperand(UnallocatedOperand::ANY);
1065 output_copy->set_virtual_register(output_vreg); 1092 output_copy->set_virtual_register(output_vreg);
1066 1093
1067 code()->AddGapMove(gap_index, output, output_copy); 1094 code()->AddGapMove(gap_index, output, output_copy);
1068 } 1095 }
1069 } 1096 }
1070 1097
1071 if (!assigned) { 1098 if (!assigned) {
1072 for (auto succ : block->successors()) { 1099 for (auto succ : block->successors()) {
1073 const InstructionBlock* successor = code()->InstructionBlockAt(succ); 1100 const InstructionBlock* successor = code()->InstructionBlockAt(succ);
1074 DCHECK(successor->PredecessorCount() == 1); 1101 DCHECK(successor->PredecessorCount() == 1);
1075 int gap_index = successor->first_instruction_index() + 1; 1102 int gap_index = successor->first_instruction_index() + 1;
1103 range->SpillAtDefinition(local_zone(), gap_index, output);
1076 range->SetSpillStartIndex(gap_index); 1104 range->SetSpillStartIndex(gap_index);
1077
1078 // This move to spill operand is not a real use. Liveness analysis
1079 // and splitting of live ranges do not account for it.
1080 // Thus it should be inserted to a lifetime position corresponding to
1081 // the instruction end.
1082 GapInstruction* gap = code()->GapAt(gap_index);
1083 ParallelMove* move =
1084 gap->GetOrCreateParallelMove(GapInstruction::BEFORE, code_zone());
1085 move->AddMove(output, range->GetSpillOperand(), code_zone());
1086 } 1105 }
1087 } 1106 }
1088 } 1107 }
1089 } 1108 }
1090 1109
1091 1110
1092 void RegisterAllocator::MeetConstraintsBetween(Instruction* first, 1111 void RegisterAllocator::MeetConstraintsBetween(Instruction* first,
1093 Instruction* second, 1112 Instruction* second,
1094 int gap_index) { 1113 int gap_index) {
1095 if (first != NULL) { 1114 if (first != NULL) {
(...skipping 18 matching lines...) Expand all
1114 LiveRange* range = LiveRangeFor(first_output->virtual_register()); 1133 LiveRange* range = LiveRangeFor(first_output->virtual_register());
1115 bool assigned = false; 1134 bool assigned = false;
1116 if (first_output->HasFixedPolicy()) { 1135 if (first_output->HasFixedPolicy()) {
1117 UnallocatedOperand* output_copy = 1136 UnallocatedOperand* output_copy =
1118 first_output->CopyUnconstrained(code_zone()); 1137 first_output->CopyUnconstrained(code_zone());
1119 bool is_tagged = HasTaggedValue(first_output->virtual_register()); 1138 bool is_tagged = HasTaggedValue(first_output->virtual_register());
1120 AllocateFixed(first_output, gap_index, is_tagged); 1139 AllocateFixed(first_output, gap_index, is_tagged);
1121 1140
1122 // This value is produced on the stack, we never need to spill it. 1141 // This value is produced on the stack, we never need to spill it.
1123 if (first_output->IsStackSlot()) { 1142 if (first_output->IsStackSlot()) {
1143 DCHECK(first_output->index() < 0);
1124 range->SetSpillOperand(first_output); 1144 range->SetSpillOperand(first_output);
1125 range->SetSpillStartIndex(gap_index - 1); 1145 range->SetSpillStartIndex(gap_index - 1);
1126 assigned = true; 1146 assigned = true;
1127 } 1147 }
1128 code()->AddGapMove(gap_index, first_output, output_copy); 1148 code()->AddGapMove(gap_index, first_output, output_copy);
1129 } 1149 }
1130 1150
1131 // Make sure we add a gap move for spilling (if we have not done 1151 // Make sure we add a gap move for spilling (if we have not done
1132 // so already). 1152 // so already).
1133 if (!assigned) { 1153 if (!assigned) {
1154 range->SpillAtDefinition(local_zone(), gap_index, first_output);
1134 range->SetSpillStartIndex(gap_index); 1155 range->SetSpillStartIndex(gap_index);
1135
1136 // This move to spill operand is not a real use. Liveness analysis
1137 // and splitting of live ranges do not account for it.
1138 // Thus it should be inserted to a lifetime position corresponding to
1139 // the instruction end.
1140 GapInstruction* gap = code()->GapAt(gap_index);
1141 ParallelMove* move =
1142 gap->GetOrCreateParallelMove(GapInstruction::BEFORE, code_zone());
1143 move->AddMove(first_output, range->GetSpillOperand(), code_zone());
1144 } 1156 }
1145 } 1157 }
1146 } 1158 }
1147 } 1159 }
1148 1160
1149 if (second != NULL) { 1161 if (second != NULL) {
1150 // Handle fixed input operands of second instruction. 1162 // Handle fixed input operands of second instruction.
1151 for (size_t i = 0; i < second->InputCount(); i++) { 1163 for (size_t i = 0; i < second->InputCount(); i++) {
1152 InstructionOperand* input = second->InputAt(i); 1164 InstructionOperand* input = second->InputAt(i);
1153 if (input->IsImmediate()) continue; // Ignore immediates. 1165 if (input->IsImmediate()) continue; // Ignore immediates.
(...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after
1234 if (instr->IsGapMoves()) { 1246 if (instr->IsGapMoves()) {
1235 // Process the moves of the gap instruction, making their sources live. 1247 // Process the moves of the gap instruction, making their sources live.
1236 GapInstruction* gap = code()->GapAt(index); 1248 GapInstruction* gap = code()->GapAt(index);
1237 1249
1238 // TODO(titzer): no need to create the parallel move if it doesn't exist. 1250 // TODO(titzer): no need to create the parallel move if it doesn't exist.
1239 ParallelMove* move = 1251 ParallelMove* move =
1240 gap->GetOrCreateParallelMove(GapInstruction::START, code_zone()); 1252 gap->GetOrCreateParallelMove(GapInstruction::START, code_zone());
1241 const ZoneList<MoveOperands>* move_operands = move->move_operands(); 1253 const ZoneList<MoveOperands>* move_operands = move->move_operands();
1242 for (int i = 0; i < move_operands->length(); ++i) { 1254 for (int i = 0; i < move_operands->length(); ++i) {
1243 MoveOperands* cur = &move_operands->at(i); 1255 MoveOperands* cur = &move_operands->at(i);
1244 if (cur->IsIgnored()) continue;
1245 InstructionOperand* from = cur->source(); 1256 InstructionOperand* from = cur->source();
1246 InstructionOperand* to = cur->destination(); 1257 InstructionOperand* to = cur->destination();
1247 InstructionOperand* hint = to; 1258 InstructionOperand* hint = to;
1248 if (to->IsUnallocated()) { 1259 if (to->IsUnallocated()) {
1249 int to_vreg = UnallocatedOperand::cast(to)->virtual_register(); 1260 int to_vreg = UnallocatedOperand::cast(to)->virtual_register();
1250 LiveRange* to_range = LiveRangeFor(to_vreg); 1261 LiveRange* to_range = LiveRangeFor(to_vreg);
1251 if (to_range->is_phi()) { 1262 if (to_range->is_phi()) {
1252 DCHECK(!FLAG_turbo_delay_ssa_decon); 1263 DCHECK(!FLAG_turbo_delay_ssa_decon);
1253 if (to_range->is_non_loop_phi()) { 1264 if (to_range->is_non_loop_phi()) {
1254 hint = to_range->current_hint_operand(); 1265 hint = to_range->current_hint_operand();
(...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after
1356 code()->InstructionBlockAt(block->predecessors()[i]); 1367 code()->InstructionBlockAt(block->predecessors()[i]);
1357 // The gap move must be added without any special processing as in 1368 // The gap move must be added without any special processing as in
1358 // the AddConstraintsGapMove. 1369 // the AddConstraintsGapMove.
1359 code()->AddGapMove(cur_block->last_instruction_index() - 1, 1370 code()->AddGapMove(cur_block->last_instruction_index() - 1,
1360 phi->inputs()[i], output); 1371 phi->inputs()[i], output);
1361 DCHECK(!InstructionAt(cur_block->last_instruction_index()) 1372 DCHECK(!InstructionAt(cur_block->last_instruction_index())
1362 ->HasPointerMap()); 1373 ->HasPointerMap());
1363 } 1374 }
1364 } 1375 }
1365 LiveRange* live_range = LiveRangeFor(phi_vreg); 1376 LiveRange* live_range = LiveRangeFor(phi_vreg);
1366 BlockStartInstruction* block_start = 1377 int gap_index = block->first_instruction_index();
1367 code()->GetBlockStart(block->rpo_number()); 1378 live_range->SpillAtDefinition(local_zone(), gap_index, output);
1368 block_start->GetOrCreateParallelMove(GapInstruction::BEFORE, code_zone()) 1379 live_range->SetSpillStartIndex(gap_index);
1369 ->AddMove(output, live_range->GetSpillOperand(), code_zone());
1370 live_range->SetSpillStartIndex(block->first_instruction_index());
1371 // We use the phi-ness of some nodes in some later heuristics. 1380 // We use the phi-ness of some nodes in some later heuristics.
1372 live_range->set_is_phi(true); 1381 live_range->set_is_phi(true);
1373 if (!block->IsLoopHeader()) { 1382 if (!block->IsLoopHeader()) {
1374 live_range->set_is_non_loop_phi(true); 1383 live_range->set_is_non_loop_phi(true);
1375 } 1384 }
1376 } 1385 }
1377 } 1386 }
1378 1387
1379 1388
1380 void RegisterAllocator::MeetRegisterConstraints() { 1389 void RegisterAllocator::MeetRegisterConstraints() {
(...skipping 354 matching lines...) Expand 10 before | Expand all | Expand 10 after
1735 1744
1736 for (size_t i = 0; i < live_ranges_.size(); ++i) { 1745 for (size_t i = 0; i < live_ranges_.size(); ++i) {
1737 if (live_ranges_[i] != NULL) { 1746 if (live_ranges_[i] != NULL) {
1738 live_ranges_[i]->kind_ = RequiredRegisterKind(live_ranges_[i]->id()); 1747 live_ranges_[i]->kind_ = RequiredRegisterKind(live_ranges_[i]->id());
1739 1748
1740 // TODO(bmeurer): This is a horrible hack to make sure that for constant 1749 // TODO(bmeurer): This is a horrible hack to make sure that for constant
1741 // live ranges, every use requires the constant to be in a register. 1750 // live ranges, every use requires the constant to be in a register.
1742 // Without this hack, all uses with "any" policy would get the constant 1751 // Without this hack, all uses with "any" policy would get the constant
1743 // operand assigned. 1752 // operand assigned.
1744 LiveRange* range = live_ranges_[i]; 1753 LiveRange* range = live_ranges_[i];
1745 if (range->HasAllocatedSpillOperand() && 1754 if (range->HasSpillOperand() && range->GetSpillOperand()->IsConstant()) {
1746 range->GetSpillOperand()->IsConstant()) {
1747 for (UsePosition* pos = range->first_pos(); pos != NULL; 1755 for (UsePosition* pos = range->first_pos(); pos != NULL;
1748 pos = pos->next_) { 1756 pos = pos->next_) {
1749 pos->register_beneficial_ = true; 1757 pos->register_beneficial_ = true;
1750 // TODO(dcarney): should the else case assert requires_reg_ == false? 1758 // TODO(dcarney): should the else case assert requires_reg_ == false?
1751 // Can't mark phis as needing a register. 1759 // Can't mark phis as needing a register.
1752 if (!code() 1760 if (!code()
1753 ->InstructionAt(pos->pos().InstructionIndex()) 1761 ->InstructionAt(pos->pos().InstructionIndex())
1754 ->IsGapMoves()) { 1762 ->IsGapMoves()) {
1755 pos->requires_reg_ = true; 1763 pos->requires_reg_ = true;
1756 } 1764 }
(...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after
1848 LifetimePosition safe_point_pos = 1856 LifetimePosition safe_point_pos =
1849 LifetimePosition::FromInstructionIndex(safe_point); 1857 LifetimePosition::FromInstructionIndex(safe_point);
1850 LiveRange* cur = range; 1858 LiveRange* cur = range;
1851 while (cur != NULL && !cur->Covers(safe_point_pos)) { 1859 while (cur != NULL && !cur->Covers(safe_point_pos)) {
1852 cur = cur->next(); 1860 cur = cur->next();
1853 } 1861 }
1854 if (cur == NULL) continue; 1862 if (cur == NULL) continue;
1855 1863
1856 // Check if the live range is spilled and the safe point is after 1864 // Check if the live range is spilled and the safe point is after
1857 // the spill position. 1865 // the spill position.
1858 if (range->HasAllocatedSpillOperand() && 1866 if (range->HasSpillOperand() &&
1859 safe_point >= range->spill_start_index() && 1867 safe_point >= range->spill_start_index() &&
1860 !range->GetSpillOperand()->IsConstant()) { 1868 !range->GetSpillOperand()->IsConstant()) {
1861 TraceAlloc("Pointer for range %d (spilled at %d) at safe point %d\n", 1869 TraceAlloc("Pointer for range %d (spilled at %d) at safe point %d\n",
1862 range->id(), range->spill_start_index(), safe_point); 1870 range->id(), range->spill_start_index(), safe_point);
1863 map->RecordPointer(range->GetSpillOperand(), code_zone()); 1871 map->RecordPointer(range->GetSpillOperand(), code_zone());
1864 } 1872 }
1865 1873
1866 if (!cur->IsSpilled()) { 1874 if (!cur->IsSpilled()) {
1867 TraceAlloc( 1875 TraceAlloc(
1868 "Pointer in register for range %d (start at %d) " 1876 "Pointer in register for range %d (start at %d) "
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after
1928 DCHECK(UnhandledIsSorted()); 1936 DCHECK(UnhandledIsSorted());
1929 LiveRange* current = unhandled_live_ranges_.RemoveLast(); 1937 LiveRange* current = unhandled_live_ranges_.RemoveLast();
1930 DCHECK(UnhandledIsSorted()); 1938 DCHECK(UnhandledIsSorted());
1931 LifetimePosition position = current->Start(); 1939 LifetimePosition position = current->Start();
1932 #ifdef DEBUG 1940 #ifdef DEBUG
1933 allocation_finger_ = position; 1941 allocation_finger_ = position;
1934 #endif 1942 #endif
1935 TraceAlloc("Processing interval %d start=%d\n", current->id(), 1943 TraceAlloc("Processing interval %d start=%d\n", current->id(),
1936 position.Value()); 1944 position.Value());
1937 1945
1938 if (current->HasAllocatedSpillOperand()) { 1946 if (!current->HasNoSpillType()) {
1939 TraceAlloc("Live range %d already has a spill operand\n", current->id()); 1947 TraceAlloc("Live range %d already has a spill operand\n", current->id());
1940 LifetimePosition next_pos = position; 1948 LifetimePosition next_pos = position;
1941 if (code()->IsGapAt(next_pos.InstructionIndex())) { 1949 if (code()->IsGapAt(next_pos.InstructionIndex())) {
1942 next_pos = next_pos.NextInstruction(); 1950 next_pos = next_pos.NextInstruction();
1943 } 1951 }
1944 UsePosition* pos = current->NextUsePositionRegisterIsBeneficial(next_pos); 1952 UsePosition* pos = current->NextUsePositionRegisterIsBeneficial(next_pos);
1945 // If the range already has a spill operand and it doesn't need a 1953 // If the range already has a spill operand and it doesn't need a
1946 // register immediately, split it and spill the first part of the range. 1954 // register immediately, split it and spill the first part of the range.
1947 if (pos == NULL) { 1955 if (pos == NULL) {
1948 Spill(current); 1956 Spill(current);
(...skipping 144 matching lines...) Expand 10 before | Expand all | Expand 10 after
2093 } 2101 }
2094 return true; 2102 return true;
2095 } 2103 }
2096 2104
2097 2105
2098 void RegisterAllocator::FreeSpillSlot(LiveRange* range) { 2106 void RegisterAllocator::FreeSpillSlot(LiveRange* range) {
2099 DCHECK(!FLAG_turbo_reuse_spill_slots); 2107 DCHECK(!FLAG_turbo_reuse_spill_slots);
2100 // Check that we are the last range. 2108 // Check that we are the last range.
2101 if (range->next() != NULL) return; 2109 if (range->next() != NULL) return;
2102 2110
2103 if (!range->TopLevel()->HasAllocatedSpillOperand()) return; 2111 if (!range->TopLevel()->HasSpillOperand()) return;
2104 2112
2105 InstructionOperand* spill_operand = range->TopLevel()->GetSpillOperand(); 2113 InstructionOperand* spill_operand = range->TopLevel()->GetSpillOperand();
2106 if (spill_operand->IsConstant()) return; 2114 if (spill_operand->IsConstant()) return;
2107 if (spill_operand->index() >= 0) { 2115 if (spill_operand->index() >= 0) {
2108 reusable_slots_.Add(range, local_zone()); 2116 reusable_slots_.Add(range, local_zone());
2109 } 2117 }
2110 } 2118 }
2111 2119
2112 2120
2113 InstructionOperand* RegisterAllocator::TryReuseSpillSlot(LiveRange* range) { 2121 InstructionOperand* RegisterAllocator::TryReuseSpillSlot(LiveRange* range) {
(...skipping 119 matching lines...) Expand 10 before | Expand all | Expand 10 after
2233 2241
2234 void RegisterAllocator::AllocateBlockedReg(LiveRange* current) { 2242 void RegisterAllocator::AllocateBlockedReg(LiveRange* current) {
2235 UsePosition* register_use = current->NextRegisterPosition(current->Start()); 2243 UsePosition* register_use = current->NextRegisterPosition(current->Start());
2236 if (register_use == NULL) { 2244 if (register_use == NULL) {
2237 // There is no use in the current live range that requires a register. 2245 // There is no use in the current live range that requires a register.
2238 // We can just spill it. 2246 // We can just spill it.
2239 Spill(current); 2247 Spill(current);
2240 return; 2248 return;
2241 } 2249 }
2242 2250
2243 LifetimePosition use_pos[RegisterConfiguration::kMaxGeneralRegisters]; 2251 LifetimePosition use_pos[RegisterConfiguration::kMaxDoubleRegisters];
2244 LifetimePosition block_pos[RegisterConfiguration::kMaxDoubleRegisters]; 2252 LifetimePosition block_pos[RegisterConfiguration::kMaxDoubleRegisters];
2245 2253
2246 for (int i = 0; i < num_registers_; i++) { 2254 for (int i = 0; i < num_registers_; i++) {
2247 use_pos[i] = block_pos[i] = LifetimePosition::MaxPosition(); 2255 use_pos[i] = block_pos[i] = LifetimePosition::MaxPosition();
2248 } 2256 }
2249 2257
2250 for (int i = 0; i < active_live_ranges_.length(); ++i) { 2258 for (int i = 0; i < active_live_ranges_.length(); ++i) {
2251 LiveRange* range = active_live_ranges_[i]; 2259 LiveRange* range = active_live_ranges_[i];
2252 int cur_reg = range->assigned_register(); 2260 int cur_reg = range->assigned_register();
2253 if (range->IsFixed() || !range->CanBeSpilled(current->Start())) { 2261 if (range->IsFixed() || !range->CanBeSpilled(current->Start())) {
(...skipping 266 matching lines...) Expand 10 before | Expand all | Expand 10 after
2520 // Nothing to spill. Just put it to unhandled as whole. 2528 // Nothing to spill. Just put it to unhandled as whole.
2521 AddToUnhandledSorted(second_part); 2529 AddToUnhandledSorted(second_part);
2522 } 2530 }
2523 } 2531 }
2524 2532
2525 2533
2526 void RegisterAllocator::Spill(LiveRange* range) { 2534 void RegisterAllocator::Spill(LiveRange* range) {
2527 DCHECK(!range->IsSpilled()); 2535 DCHECK(!range->IsSpilled());
2528 TraceAlloc("Spilling live range %d\n", range->id()); 2536 TraceAlloc("Spilling live range %d\n", range->id());
2529 LiveRange* first = range->TopLevel(); 2537 LiveRange* first = range->TopLevel();
2530 2538 if (first->HasNoSpillType()) {
2531 if (!first->HasAllocatedSpillOperand()) {
2532 if (FLAG_turbo_reuse_spill_slots) { 2539 if (FLAG_turbo_reuse_spill_slots) {
2533 AssignSpillRangeToLiveRange(first); 2540 AssignSpillRangeToLiveRange(first);
2534 } else { 2541 } else {
2535 InstructionOperand* op = TryReuseSpillSlot(range); 2542 InstructionOperand* op = TryReuseSpillSlot(range);
2536 if (op == NULL) { 2543 if (op == NULL) {
2537 // Allocate a new operand referring to the spill slot. 2544 // Allocate a new operand referring to the spill slot.
2538 RegisterKind kind = range->Kind(); 2545 RegisterKind kind = range->Kind();
2539 int index = frame()->AllocateSpillSlot(kind == DOUBLE_REGISTERS); 2546 int index = frame()->AllocateSpillSlot(kind == DOUBLE_REGISTERS);
2540 if (kind == DOUBLE_REGISTERS) { 2547 auto op_kind = kind == DOUBLE_REGISTERS
2541 op = DoubleStackSlotOperand::Create(index, local_zone()); 2548 ? InstructionOperand::DOUBLE_STACK_SLOT
2542 } else { 2549 : InstructionOperand::STACK_SLOT;
2543 DCHECK(kind == GENERAL_REGISTERS); 2550 op = new (code_zone()) InstructionOperand(op_kind, index);
2544 op = StackSlotOperand::Create(index, local_zone());
2545 }
2546 } 2551 }
2547 first->SetSpillOperand(op); 2552 first->SetSpillOperand(op);
2548 } 2553 }
2549 } 2554 }
2550 range->MakeSpilled(code_zone()); 2555 range->MakeSpilled();
2551 } 2556 }
2552 2557
2553 2558
2554 int RegisterAllocator::RegisterCount() const { return num_registers_; } 2559 int RegisterAllocator::RegisterCount() const { return num_registers_; }
2555 2560
2556 2561
2557 #ifdef DEBUG 2562 #ifdef DEBUG
2558 2563
2559 2564
2560 void RegisterAllocator::Verify() const { 2565 void RegisterAllocator::Verify() const {
2561 for (auto current : live_ranges()) { 2566 for (auto current : live_ranges()) {
2562 if (current != NULL) current->Verify(); 2567 if (current != NULL) current->Verify();
2563 } 2568 }
2564 } 2569 }
2565 2570
2566 2571
2567 #endif 2572 #endif
2568 2573
2569 2574
2570 void RegisterAllocator::SetLiveRangeAssignedRegister(LiveRange* range, 2575 void RegisterAllocator::SetLiveRangeAssignedRegister(LiveRange* range,
2571 int reg) { 2576 int reg) {
2572 if (range->Kind() == DOUBLE_REGISTERS) { 2577 if (range->Kind() == DOUBLE_REGISTERS) {
2573 assigned_double_registers_->Add(reg); 2578 assigned_double_registers_->Add(reg);
2574 } else { 2579 } else {
2575 DCHECK(range->Kind() == GENERAL_REGISTERS); 2580 DCHECK(range->Kind() == GENERAL_REGISTERS);
2576 assigned_registers_->Add(reg); 2581 assigned_registers_->Add(reg);
2577 } 2582 }
2578 range->set_assigned_register(reg, code_zone()); 2583 range->set_assigned_register(reg);
2579 } 2584 }
2580 2585
2581 } // namespace compiler 2586 } // namespace compiler
2582 } // namespace internal 2587 } // namespace internal
2583 } // namespace v8 2588 } // 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