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

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

Issue 803493002: revert r25736 (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 56 matching lines...) Expand 10 before | Expand all | Expand 10 after
67 67
68 void UseInterval::SplitAt(LifetimePosition pos, Zone* zone) { 68 void UseInterval::SplitAt(LifetimePosition pos, Zone* zone) {
69 DCHECK(Contains(pos) && pos.Value() != start().Value()); 69 DCHECK(Contains(pos) && pos.Value() != start().Value());
70 auto after = new (zone) UseInterval(pos, end_); 70 auto after = new (zone) UseInterval(pos, end_);
71 after->next_ = next_; 71 after->next_ = next_;
72 next_ = after; 72 next_ = after;
73 end_ = pos; 73 end_ = pos;
74 } 74 }
75 75
76 76
77 struct LiveRange::SpillAtDefinitionList : ZoneObject {
78 SpillAtDefinitionList(int gap_index, InstructionOperand* operand,
79 SpillAtDefinitionList* next)
80 : gap_index(gap_index), operand(operand), next(next) {}
81 const int gap_index;
82 InstructionOperand* const operand;
83 SpillAtDefinitionList* const next;
84 };
85
86
87 #ifdef DEBUG 77 #ifdef DEBUG
88 78
89 79
90 void LiveRange::Verify() const { 80 void LiveRange::Verify() const {
91 UsePosition* cur = first_pos_; 81 UsePosition* cur = first_pos_;
92 while (cur != nullptr) { 82 while (cur != nullptr) {
93 DCHECK(Start().Value() <= cur->pos().Value() && 83 DCHECK(Start().Value() <= cur->pos().Value() &&
94 cur->pos().Value() <= End().Value()); 84 cur->pos().Value() <= End().Value());
95 cur = cur->next(); 85 cur = cur->next();
96 } 86 }
(...skipping 25 matching lines...) Expand all
122 kind_(UNALLOCATED_REGISTERS), 112 kind_(UNALLOCATED_REGISTERS),
123 assigned_register_(kInvalidAssignment), 113 assigned_register_(kInvalidAssignment),
124 last_interval_(nullptr), 114 last_interval_(nullptr),
125 first_interval_(nullptr), 115 first_interval_(nullptr),
126 first_pos_(nullptr), 116 first_pos_(nullptr),
127 parent_(nullptr), 117 parent_(nullptr),
128 next_(nullptr), 118 next_(nullptr),
129 current_interval_(nullptr), 119 current_interval_(nullptr),
130 last_processed_use_(nullptr), 120 last_processed_use_(nullptr),
131 current_hint_operand_(nullptr), 121 current_hint_operand_(nullptr),
122 spill_operand_(new (zone) InstructionOperand()),
132 spill_start_index_(kMaxInt), 123 spill_start_index_(kMaxInt),
133 spill_type_(SpillType::kNoSpillType), 124 spill_range_(nullptr) {}
134 spill_operand_(nullptr),
135 spills_at_definition_(nullptr) {}
136 125
137 126
138 void LiveRange::set_assigned_register(int reg, Zone* zone) { 127 void LiveRange::set_assigned_register(int reg, Zone* zone) {
139 DCHECK(!HasRegisterAssigned() && !IsSpilled()); 128 DCHECK(!HasRegisterAssigned() && !IsSpilled());
140 assigned_register_ = reg; 129 assigned_register_ = reg;
141 // TODO(dcarney): stop aliasing hint operands. 130 if (spill_range_ == nullptr) {
142 ConvertUsesToOperand(CreateAssignedOperand(zone)); 131 ConvertOperands(zone);
132 }
143 } 133 }
144 134
145 135
146 void LiveRange::MakeSpilled() { 136 void LiveRange::MakeSpilled(Zone* zone) {
147 DCHECK(!IsSpilled()); 137 DCHECK(!IsSpilled());
148 DCHECK(!TopLevel()->HasNoSpillType()); 138 DCHECK(TopLevel()->HasAllocatedSpillOperand());
149 spilled_ = true; 139 spilled_ = true;
150 assigned_register_ = kInvalidAssignment; 140 assigned_register_ = kInvalidAssignment;
141 ConvertOperands(zone);
151 } 142 }
152 143
153 144
154 void LiveRange::SpillAtDefinition(Zone* zone, int gap_index, 145 bool LiveRange::HasAllocatedSpillOperand() const {
155 InstructionOperand* operand) { 146 DCHECK(spill_operand_ != nullptr);
156 DCHECK(HasNoSpillType()); 147 return !spill_operand_->IsIgnored() || spill_range_ != nullptr;
157 spills_at_definition_ = new (zone)
158 SpillAtDefinitionList(gap_index, operand, spills_at_definition_);
159 }
160
161
162 void LiveRange::CommitSpillsAtDefinition(InstructionSequence* sequence,
163 InstructionOperand* op) {
164 auto to_spill = TopLevel()->spills_at_definition_;
165 if (to_spill == nullptr) return;
166 auto zone = sequence->zone();
167 for (; to_spill != nullptr; to_spill = to_spill->next) {
168 auto gap = sequence->GapAt(to_spill->gap_index);
169 auto move = gap->GetOrCreateParallelMove(GapInstruction::START, zone);
170 move->AddMove(to_spill->operand, op, zone);
171 }
172 TopLevel()->spills_at_definition_ = nullptr;
173 } 148 }
174 149
175 150
176 void LiveRange::SetSpillOperand(InstructionOperand* operand) { 151 void LiveRange::SetSpillOperand(InstructionOperand* operand) {
177 DCHECK(HasNoSpillType());
178 DCHECK(!operand->IsUnallocated()); 152 DCHECK(!operand->IsUnallocated());
179 spill_type_ = SpillType::kSpillOperand; 153 DCHECK(spill_operand_ != nullptr);
180 spill_operand_ = operand; 154 DCHECK(spill_operand_->IsIgnored());
181 } 155 spill_operand_->ConvertTo(operand->kind(), operand->index());
182
183
184 void LiveRange::SetSpillRange(SpillRange* spill_range) {
185 DCHECK(HasNoSpillType() || HasSpillRange());
186 DCHECK_NE(spill_range, nullptr);
187 spill_type_ = SpillType::kSpillRange;
188 spill_range_ = spill_range;
189 } 156 }
190 157
191 158
192 void LiveRange::CommitSpillOperand(InstructionOperand* operand) { 159 void LiveRange::CommitSpillOperand(InstructionOperand* operand) {
193 DCHECK(HasSpillRange()); 160 DCHECK(spill_range_ != nullptr);
194 DCHECK(!operand->IsUnallocated());
195 DCHECK(!IsChild()); 161 DCHECK(!IsChild());
196 spill_type_ = SpillType::kSpillOperand; 162 spill_range_ = nullptr;
197 spill_operand_ = operand; 163 SetSpillOperand(operand);
164 for (auto range = this; range != nullptr; range = range->next()) {
165 if (range->IsSpilled()) {
166 range->ConvertUsesToOperand(operand);
167 }
168 }
198 } 169 }
199 170
200 171
201 UsePosition* LiveRange::NextUsePosition(LifetimePosition start) { 172 UsePosition* LiveRange::NextUsePosition(LifetimePosition start) {
202 UsePosition* use_pos = last_processed_use_; 173 UsePosition* use_pos = last_processed_use_;
203 if (use_pos == nullptr) use_pos = first_pos(); 174 if (use_pos == nullptr) use_pos = first_pos();
204 while (use_pos != nullptr && use_pos->pos().Value() < start.Value()) { 175 while (use_pos != nullptr && use_pos->pos().Value() < start.Value()) {
205 use_pos = use_pos->next(); 176 use_pos = use_pos->next();
206 } 177 }
207 last_processed_use_ = use_pos; 178 last_processed_use_ = use_pos;
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after
257 switch (Kind()) { 228 switch (Kind()) {
258 case GENERAL_REGISTERS: 229 case GENERAL_REGISTERS:
259 op = RegisterOperand::Create(assigned_register(), zone); 230 op = RegisterOperand::Create(assigned_register(), zone);
260 break; 231 break;
261 case DOUBLE_REGISTERS: 232 case DOUBLE_REGISTERS:
262 op = DoubleRegisterOperand::Create(assigned_register(), zone); 233 op = DoubleRegisterOperand::Create(assigned_register(), zone);
263 break; 234 break;
264 default: 235 default:
265 UNREACHABLE(); 236 UNREACHABLE();
266 } 237 }
267 } else { 238 } else if (IsSpilled()) {
268 DCHECK(IsSpilled());
269 DCHECK(!HasRegisterAssigned()); 239 DCHECK(!HasRegisterAssigned());
270 op = TopLevel()->GetSpillOperand(); 240 op = TopLevel()->GetSpillOperand();
271 DCHECK(!op->IsUnallocated()); 241 DCHECK(!op->IsUnallocated());
242 } else {
243 UnallocatedOperand* unalloc =
244 new (zone) UnallocatedOperand(UnallocatedOperand::NONE);
245 unalloc->set_virtual_register(id_);
246 op = unalloc;
272 } 247 }
273 return op; 248 return op;
274 } 249 }
275 250
276 251
277 UseInterval* LiveRange::FirstSearchIntervalForPosition( 252 UseInterval* LiveRange::FirstSearchIntervalForPosition(
278 LifetimePosition position) const { 253 LifetimePosition position) const {
279 if (current_interval_ == nullptr) return first_interval_; 254 if (current_interval_ == nullptr) return first_interval_;
280 if (current_interval_->start().Value() > position.Value()) { 255 if (current_interval_->start().Value() > position.Value()) {
281 current_interval_ = nullptr; 256 current_interval_ = nullptr;
(...skipping 218 matching lines...) Expand 10 before | Expand all | Expand 10 after
500 if (use_pos->HasOperand()) { 475 if (use_pos->HasOperand()) {
501 DCHECK(op->IsRegister() || op->IsDoubleRegister() || 476 DCHECK(op->IsRegister() || op->IsDoubleRegister() ||
502 !use_pos->RequiresRegister()); 477 !use_pos->RequiresRegister());
503 use_pos->operand()->ConvertTo(op->kind(), op->index()); 478 use_pos->operand()->ConvertTo(op->kind(), op->index());
504 } 479 }
505 use_pos = use_pos->next(); 480 use_pos = use_pos->next();
506 } 481 }
507 } 482 }
508 483
509 484
485 void LiveRange::ConvertOperands(Zone* zone) {
486 ConvertUsesToOperand(CreateAssignedOperand(zone));
487 }
488
489
510 bool LiveRange::CanCover(LifetimePosition position) const { 490 bool LiveRange::CanCover(LifetimePosition position) const {
511 if (IsEmpty()) return false; 491 if (IsEmpty()) return false;
512 return Start().Value() <= position.Value() && 492 return Start().Value() <= position.Value() &&
513 position.Value() < End().Value(); 493 position.Value() < End().Value();
514 } 494 }
515 495
516 496
517 bool LiveRange::Covers(LifetimePosition position) { 497 bool LiveRange::Covers(LifetimePosition position) {
518 if (!CanCover(position)) return false; 498 if (!CanCover(position)) return false;
519 auto start_search = FirstSearchIntervalForPosition(position); 499 auto start_search = FirstSearchIntervalForPosition(position);
(...skipping 310 matching lines...) Expand 10 before | Expand all | Expand 10 after
830 result = new_node; 810 result = new_node;
831 } else { 811 } else {
832 node->set_next(new_node); 812 node->set_next(new_node);
833 } 813 }
834 node = new_node; 814 node = new_node;
835 src = src->next(); 815 src = src->next();
836 } 816 }
837 use_interval_ = result; 817 use_interval_ = result;
838 live_ranges().push_back(range); 818 live_ranges().push_back(range);
839 end_position_ = node->end(); 819 end_position_ = node->end();
840 DCHECK(!range->HasSpillRange()); 820 DCHECK(range->GetSpillRange() == nullptr);
841 range->SetSpillRange(this); 821 range->SetSpillRange(this);
842 } 822 }
843 823
844 824
845 bool SpillRange::IsIntersectingWith(SpillRange* other) const { 825 bool SpillRange::IsIntersectingWith(SpillRange* other) const {
846 if (this->use_interval_ == nullptr || other->use_interval_ == nullptr || 826 if (this->use_interval_ == nullptr || other->use_interval_ == nullptr ||
847 this->End().Value() <= other->use_interval_->start().Value() || 827 this->End().Value() <= other->use_interval_->start().Value() ||
848 other->End().Value() <= this->use_interval_->start().Value()) { 828 other->End().Value() <= this->use_interval_->start().Value()) {
849 return false; 829 return false;
850 } 830 }
(...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after
934 int index = frame()->AllocateSpillSlot(kind == DOUBLE_REGISTERS); 914 int index = frame()->AllocateSpillSlot(kind == DOUBLE_REGISTERS);
935 auto op_kind = kind == DOUBLE_REGISTERS 915 auto op_kind = kind == DOUBLE_REGISTERS
936 ? InstructionOperand::DOUBLE_STACK_SLOT 916 ? InstructionOperand::DOUBLE_STACK_SLOT
937 : InstructionOperand::STACK_SLOT; 917 : InstructionOperand::STACK_SLOT;
938 auto op = new (code_zone()) InstructionOperand(op_kind, index); 918 auto op = new (code_zone()) InstructionOperand(op_kind, index);
939 range->SetOperand(op); 919 range->SetOperand(op);
940 } 920 }
941 } 921 }
942 922
943 923
944 void RegisterAllocator::CommitAssignment() {
945 for (auto range : live_ranges()) {
946 if (range == nullptr || range->IsEmpty()) continue;
947 // Register assignments were committed in set_assigned_register.
948 if (range->HasRegisterAssigned()) continue;
949 auto assigned = range->CreateAssignedOperand(code_zone());
950 range->ConvertUsesToOperand(assigned);
951 if (range->IsSpilled()) {
952 range->CommitSpillsAtDefinition(code(), assigned);
953 }
954 }
955 }
956
957
958 SpillRange* RegisterAllocator::AssignSpillRangeToLiveRange(LiveRange* range) { 924 SpillRange* RegisterAllocator::AssignSpillRangeToLiveRange(LiveRange* range) {
959 DCHECK(FLAG_turbo_reuse_spill_slots); 925 DCHECK(FLAG_turbo_reuse_spill_slots);
960 auto spill_range = new (local_zone()) SpillRange(range, local_zone()); 926 auto spill_range = new (local_zone()) SpillRange(range, local_zone());
961 spill_ranges().push_back(spill_range); 927 spill_ranges().push_back(spill_range);
962 return spill_range; 928 return spill_range;
963 } 929 }
964 930
965 931
966 bool RegisterAllocator::TryReuseSpillForPhi(LiveRange* range) { 932 bool RegisterAllocator::TryReuseSpillForPhi(LiveRange* range) {
967 DCHECK(FLAG_turbo_reuse_spill_slots); 933 DCHECK(FLAG_turbo_reuse_spill_slots);
968 DCHECK(range->HasNoSpillType()); 934 DCHECK(!range->HasAllocatedSpillOperand());
969 if (range->IsChild() || !range->is_phi()) return false; 935 if (range->IsChild() || !range->is_phi()) return false;
970 936
971 auto lookup = phi_map_.find(range->id()); 937 auto lookup = phi_map_.find(range->id());
972 DCHECK(lookup != phi_map_.end()); 938 DCHECK(lookup != phi_map_.end());
973 auto phi = lookup->second.phi; 939 auto phi = lookup->second.phi;
974 auto block = lookup->second.block; 940 auto block = lookup->second.block;
975 // Count the number of spilled operands. 941 // Count the number of spilled operands.
976 size_t spilled_count = 0; 942 size_t spilled_count = 0;
977 LiveRange* first_op = nullptr; 943 LiveRange* first_op = nullptr;
978 for (size_t i = 0; i < phi->operands().size(); i++) { 944 for (size_t i = 0; i < phi->operands().size(); i++) {
(...skipping 123 matching lines...) Expand 10 before | Expand all | Expand 10 after
1102 1068
1103 code()->AddGapMove(gap_index, output, output_copy); 1069 code()->AddGapMove(gap_index, output, output_copy);
1104 } 1070 }
1105 } 1071 }
1106 1072
1107 if (!assigned) { 1073 if (!assigned) {
1108 for (auto succ : block->successors()) { 1074 for (auto succ : block->successors()) {
1109 const InstructionBlock* successor = code()->InstructionBlockAt(succ); 1075 const InstructionBlock* successor = code()->InstructionBlockAt(succ);
1110 DCHECK(successor->PredecessorCount() == 1); 1076 DCHECK(successor->PredecessorCount() == 1);
1111 int gap_index = successor->first_instruction_index() + 1; 1077 int gap_index = successor->first_instruction_index() + 1;
1112 range->SpillAtDefinition(local_zone(), gap_index, output);
1113 range->SetSpillStartIndex(gap_index); 1078 range->SetSpillStartIndex(gap_index);
1079
1080 // This move to spill operand is not a real use. Liveness analysis
1081 // and splitting of live ranges do not account for it.
1082 // Thus it should be inserted to a lifetime position corresponding to
1083 // the instruction end.
1084 auto gap = code()->GapAt(gap_index);
1085 auto move =
1086 gap->GetOrCreateParallelMove(GapInstruction::BEFORE, code_zone());
1087 move->AddMove(output, range->GetSpillOperand(), code_zone());
1114 } 1088 }
1115 } 1089 }
1116 } 1090 }
1117 } 1091 }
1118 1092
1119 1093
1120 void RegisterAllocator::MeetConstraintsBetween(Instruction* first, 1094 void RegisterAllocator::MeetConstraintsBetween(Instruction* first,
1121 Instruction* second, 1095 Instruction* second,
1122 int gap_index) { 1096 int gap_index) {
1123 if (first != nullptr) { 1097 if (first != nullptr) {
(...skipping 28 matching lines...) Expand all
1152 range->SetSpillOperand(first_output); 1126 range->SetSpillOperand(first_output);
1153 range->SetSpillStartIndex(gap_index - 1); 1127 range->SetSpillStartIndex(gap_index - 1);
1154 assigned = true; 1128 assigned = true;
1155 } 1129 }
1156 code()->AddGapMove(gap_index, first_output, output_copy); 1130 code()->AddGapMove(gap_index, first_output, output_copy);
1157 } 1131 }
1158 1132
1159 // Make sure we add a gap move for spilling (if we have not done 1133 // Make sure we add a gap move for spilling (if we have not done
1160 // so already). 1134 // so already).
1161 if (!assigned) { 1135 if (!assigned) {
1162 range->SpillAtDefinition(local_zone(), gap_index, first_output);
1163 range->SetSpillStartIndex(gap_index); 1136 range->SetSpillStartIndex(gap_index);
1137
1138 // This move to spill operand is not a real use. Liveness analysis
1139 // and splitting of live ranges do not account for it.
1140 // Thus it should be inserted to a lifetime position corresponding to
1141 // the instruction end.
1142 auto gap = code()->GapAt(gap_index);
1143 auto move =
1144 gap->GetOrCreateParallelMove(GapInstruction::BEFORE, code_zone());
1145 move->AddMove(first_output, range->GetSpillOperand(), code_zone());
1164 } 1146 }
1165 } 1147 }
1166 } 1148 }
1167 } 1149 }
1168 1150
1169 if (second != nullptr) { 1151 if (second != nullptr) {
1170 // Handle fixed input operands of second instruction. 1152 // Handle fixed input operands of second instruction.
1171 for (size_t i = 0; i < second->InputCount(); i++) { 1153 for (size_t i = 0; i < second->InputCount(); i++) {
1172 auto input = second->InputAt(i); 1154 auto input = second->InputAt(i);
1173 if (input->IsImmediate()) continue; // Ignore immediates. 1155 if (input->IsImmediate()) continue; // Ignore immediates.
(...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after
1249 if (instr->IsGapMoves()) { 1231 if (instr->IsGapMoves()) {
1250 // Process the moves of the gap instruction, making their sources live. 1232 // Process the moves of the gap instruction, making their sources live.
1251 auto gap = code()->GapAt(index); 1233 auto gap = code()->GapAt(index);
1252 1234
1253 // TODO(titzer): no need to create the parallel move if it doesn't exist. 1235 // TODO(titzer): no need to create the parallel move if it doesn't exist.
1254 auto move = 1236 auto move =
1255 gap->GetOrCreateParallelMove(GapInstruction::START, code_zone()); 1237 gap->GetOrCreateParallelMove(GapInstruction::START, code_zone());
1256 const ZoneList<MoveOperands>* move_operands = move->move_operands(); 1238 const ZoneList<MoveOperands>* move_operands = move->move_operands();
1257 for (int i = 0; i < move_operands->length(); ++i) { 1239 for (int i = 0; i < move_operands->length(); ++i) {
1258 auto cur = &move_operands->at(i); 1240 auto cur = &move_operands->at(i);
1241 if (cur->IsIgnored()) continue;
1259 auto from = cur->source(); 1242 auto from = cur->source();
1260 auto to = cur->destination(); 1243 auto to = cur->destination();
1261 auto hint = to; 1244 auto hint = to;
1262 if (to->IsUnallocated()) { 1245 if (to->IsUnallocated()) {
1263 int to_vreg = UnallocatedOperand::cast(to)->virtual_register(); 1246 int to_vreg = UnallocatedOperand::cast(to)->virtual_register();
1264 auto to_range = LiveRangeFor(to_vreg); 1247 auto to_range = LiveRangeFor(to_vreg);
1265 if (to_range->is_phi()) { 1248 if (to_range->is_phi()) {
1266 DCHECK(!FLAG_turbo_delay_ssa_decon); 1249 DCHECK(!FLAG_turbo_delay_ssa_decon);
1267 if (to_range->is_non_loop_phi()) { 1250 if (to_range->is_non_loop_phi()) {
1268 hint = to_range->current_hint_operand(); 1251 hint = to_range->current_hint_operand();
(...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after
1371 code()->InstructionBlockAt(block->predecessors()[i]); 1354 code()->InstructionBlockAt(block->predecessors()[i]);
1372 // The gap move must be added without any special processing as in 1355 // The gap move must be added without any special processing as in
1373 // the AddConstraintsGapMove. 1356 // the AddConstraintsGapMove.
1374 code()->AddGapMove(cur_block->last_instruction_index() - 1, 1357 code()->AddGapMove(cur_block->last_instruction_index() - 1,
1375 phi->inputs()[i], output); 1358 phi->inputs()[i], output);
1376 DCHECK(!InstructionAt(cur_block->last_instruction_index()) 1359 DCHECK(!InstructionAt(cur_block->last_instruction_index())
1377 ->HasPointerMap()); 1360 ->HasPointerMap());
1378 } 1361 }
1379 } 1362 }
1380 auto live_range = LiveRangeFor(phi_vreg); 1363 auto live_range = LiveRangeFor(phi_vreg);
1381 int gap_index = block->first_instruction_index(); 1364 auto block_start = code()->GetBlockStart(block->rpo_number());
1382 live_range->SpillAtDefinition(local_zone(), gap_index, output); 1365 block_start->GetOrCreateParallelMove(GapInstruction::BEFORE, code_zone())
1383 live_range->SetSpillStartIndex(gap_index); 1366 ->AddMove(output, live_range->GetSpillOperand(), code_zone());
1367 live_range->SetSpillStartIndex(block->first_instruction_index());
1384 // We use the phi-ness of some nodes in some later heuristics. 1368 // We use the phi-ness of some nodes in some later heuristics.
1385 live_range->set_is_phi(true); 1369 live_range->set_is_phi(true);
1386 live_range->set_is_non_loop_phi(!block->IsLoopHeader()); 1370 live_range->set_is_non_loop_phi(!block->IsLoopHeader());
1387 } 1371 }
1388 } 1372 }
1389 1373
1390 1374
1391 void RegisterAllocator::MeetRegisterConstraints() { 1375 void RegisterAllocator::MeetRegisterConstraints() {
1392 for (auto block : code()->instruction_blocks()) { 1376 for (auto block : code()->instruction_blocks()) {
1393 MeetRegisterConstraints(block); 1377 MeetRegisterConstraints(block);
(...skipping 338 matching lines...) Expand 10 before | Expand all | Expand 10 after
1732 } 1716 }
1733 } 1717 }
1734 1718
1735 for (auto range : live_ranges()) { 1719 for (auto range : live_ranges()) {
1736 if (range == nullptr) continue; 1720 if (range == nullptr) continue;
1737 range->kind_ = RequiredRegisterKind(range->id()); 1721 range->kind_ = RequiredRegisterKind(range->id());
1738 // TODO(bmeurer): This is a horrible hack to make sure that for constant 1722 // TODO(bmeurer): This is a horrible hack to make sure that for constant
1739 // live ranges, every use requires the constant to be in a register. 1723 // live ranges, every use requires the constant to be in a register.
1740 // Without this hack, all uses with "any" policy would get the constant 1724 // Without this hack, all uses with "any" policy would get the constant
1741 // operand assigned. 1725 // operand assigned.
1742 if (range->HasSpillOperand() && range->GetSpillOperand()->IsConstant()) { 1726 if (range->HasAllocatedSpillOperand() &&
1727 range->GetSpillOperand()->IsConstant()) {
1743 for (auto pos = range->first_pos(); pos != nullptr; pos = pos->next_) { 1728 for (auto pos = range->first_pos(); pos != nullptr; pos = pos->next_) {
1744 pos->register_beneficial_ = true; 1729 pos->register_beneficial_ = true;
1745 // TODO(dcarney): should the else case assert requires_reg_ == false? 1730 // TODO(dcarney): should the else case assert requires_reg_ == false?
1746 // Can't mark phis as needing a register. 1731 // Can't mark phis as needing a register.
1747 if (!code() 1732 if (!code()
1748 ->InstructionAt(pos->pos().InstructionIndex()) 1733 ->InstructionAt(pos->pos().InstructionIndex())
1749 ->IsGapMoves()) { 1734 ->IsGapMoves()) {
1750 pos->requires_reg_ = true; 1735 pos->requires_reg_ = true;
1751 } 1736 }
1752 } 1737 }
(...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after
1836 // safe point position. 1821 // safe point position.
1837 auto safe_point_pos = LifetimePosition::FromInstructionIndex(safe_point); 1822 auto safe_point_pos = LifetimePosition::FromInstructionIndex(safe_point);
1838 auto cur = range; 1823 auto cur = range;
1839 while (cur != nullptr && !cur->Covers(safe_point_pos)) { 1824 while (cur != nullptr && !cur->Covers(safe_point_pos)) {
1840 cur = cur->next(); 1825 cur = cur->next();
1841 } 1826 }
1842 if (cur == nullptr) continue; 1827 if (cur == nullptr) continue;
1843 1828
1844 // Check if the live range is spilled and the safe point is after 1829 // Check if the live range is spilled and the safe point is after
1845 // the spill position. 1830 // the spill position.
1846 if (range->HasSpillOperand() && 1831 if (range->HasAllocatedSpillOperand() &&
1847 safe_point >= range->spill_start_index() && 1832 safe_point >= range->spill_start_index() &&
1848 !range->GetSpillOperand()->IsConstant()) { 1833 !range->GetSpillOperand()->IsConstant()) {
1849 TraceAlloc("Pointer for range %d (spilled at %d) at safe point %d\n", 1834 TraceAlloc("Pointer for range %d (spilled at %d) at safe point %d\n",
1850 range->id(), range->spill_start_index(), safe_point); 1835 range->id(), range->spill_start_index(), safe_point);
1851 map->RecordPointer(range->GetSpillOperand(), code_zone()); 1836 map->RecordPointer(range->GetSpillOperand(), code_zone());
1852 } 1837 }
1853 1838
1854 if (!cur->IsSpilled()) { 1839 if (!cur->IsSpilled()) {
1855 TraceAlloc( 1840 TraceAlloc(
1856 "Pointer in register for range %d (start at %d) " 1841 "Pointer in register for range %d (start at %d) "
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after
1916 auto current = unhandled_live_ranges().back(); 1901 auto current = unhandled_live_ranges().back();
1917 unhandled_live_ranges().pop_back(); 1902 unhandled_live_ranges().pop_back();
1918 DCHECK(UnhandledIsSorted()); 1903 DCHECK(UnhandledIsSorted());
1919 auto position = current->Start(); 1904 auto position = current->Start();
1920 #ifdef DEBUG 1905 #ifdef DEBUG
1921 allocation_finger_ = position; 1906 allocation_finger_ = position;
1922 #endif 1907 #endif
1923 TraceAlloc("Processing interval %d start=%d\n", current->id(), 1908 TraceAlloc("Processing interval %d start=%d\n", current->id(),
1924 position.Value()); 1909 position.Value());
1925 1910
1926 if (!current->HasNoSpillType()) { 1911 if (current->HasAllocatedSpillOperand()) {
1927 TraceAlloc("Live range %d already has a spill operand\n", current->id()); 1912 TraceAlloc("Live range %d already has a spill operand\n", current->id());
1928 auto next_pos = position; 1913 auto next_pos = position;
1929 if (code()->IsGapAt(next_pos.InstructionIndex())) { 1914 if (code()->IsGapAt(next_pos.InstructionIndex())) {
1930 next_pos = next_pos.NextInstruction(); 1915 next_pos = next_pos.NextInstruction();
1931 } 1916 }
1932 auto pos = current->NextUsePositionRegisterIsBeneficial(next_pos); 1917 auto pos = current->NextUsePositionRegisterIsBeneficial(next_pos);
1933 // If the range already has a spill operand and it doesn't need a 1918 // If the range already has a spill operand and it doesn't need a
1934 // register immediately, split it and spill the first part of the range. 1919 // register immediately, split it and spill the first part of the range.
1935 if (pos == nullptr) { 1920 if (pos == nullptr) {
1936 Spill(current); 1921 Spill(current);
(...skipping 144 matching lines...) Expand 10 before | Expand all | Expand 10 after
2081 if (a->Start().Value() < b->Start().Value()) return false; 2066 if (a->Start().Value() < b->Start().Value()) return false;
2082 } 2067 }
2083 return true; 2068 return true;
2084 } 2069 }
2085 2070
2086 2071
2087 void RegisterAllocator::FreeSpillSlot(LiveRange* range) { 2072 void RegisterAllocator::FreeSpillSlot(LiveRange* range) {
2088 DCHECK(!FLAG_turbo_reuse_spill_slots); 2073 DCHECK(!FLAG_turbo_reuse_spill_slots);
2089 // Check that we are the last range. 2074 // Check that we are the last range.
2090 if (range->next() != nullptr) return; 2075 if (range->next() != nullptr) return;
2091 if (!range->TopLevel()->HasSpillOperand()) return; 2076 if (!range->TopLevel()->HasAllocatedSpillOperand()) return;
2092 auto spill_operand = range->TopLevel()->GetSpillOperand(); 2077 auto spill_operand = range->TopLevel()->GetSpillOperand();
2093 if (spill_operand->IsConstant()) return; 2078 if (spill_operand->IsConstant()) return;
2094 if (spill_operand->index() >= 0) { 2079 if (spill_operand->index() >= 0) {
2095 reusable_slots().push_back(range); 2080 reusable_slots().push_back(range);
2096 } 2081 }
2097 } 2082 }
2098 2083
2099 2084
2100 InstructionOperand* RegisterAllocator::TryReuseSpillSlot(LiveRange* range) { 2085 InstructionOperand* RegisterAllocator::TryReuseSpillSlot(LiveRange* range) {
2101 DCHECK(!FLAG_turbo_reuse_spill_slots); 2086 DCHECK(!FLAG_turbo_reuse_spill_slots);
(...skipping 394 matching lines...) Expand 10 before | Expand all | Expand 10 after
2496 // Nothing to spill. Just put it to unhandled as whole. 2481 // Nothing to spill. Just put it to unhandled as whole.
2497 AddToUnhandledSorted(second_part); 2482 AddToUnhandledSorted(second_part);
2498 } 2483 }
2499 } 2484 }
2500 2485
2501 2486
2502 void RegisterAllocator::Spill(LiveRange* range) { 2487 void RegisterAllocator::Spill(LiveRange* range) {
2503 DCHECK(!range->IsSpilled()); 2488 DCHECK(!range->IsSpilled());
2504 TraceAlloc("Spilling live range %d\n", range->id()); 2489 TraceAlloc("Spilling live range %d\n", range->id());
2505 auto first = range->TopLevel(); 2490 auto first = range->TopLevel();
2506 if (first->HasNoSpillType()) { 2491 if (!first->HasAllocatedSpillOperand()) {
2507 if (FLAG_turbo_reuse_spill_slots) { 2492 if (FLAG_turbo_reuse_spill_slots) {
2508 AssignSpillRangeToLiveRange(first); 2493 AssignSpillRangeToLiveRange(first);
2509 } else { 2494 } else {
2510 auto op = TryReuseSpillSlot(range); 2495 auto op = TryReuseSpillSlot(range);
2511 if (op == nullptr) { 2496 if (op == nullptr) {
2512 // Allocate a new operand referring to the spill slot. 2497 // Allocate a new operand referring to the spill slot.
2513 RegisterKind kind = range->Kind(); 2498 RegisterKind kind = range->Kind();
2514 int index = frame()->AllocateSpillSlot(kind == DOUBLE_REGISTERS); 2499 int index = frame()->AllocateSpillSlot(kind == DOUBLE_REGISTERS);
2515 auto op_kind = kind == DOUBLE_REGISTERS 2500 if (kind == DOUBLE_REGISTERS) {
2516 ? InstructionOperand::DOUBLE_STACK_SLOT 2501 op = DoubleStackSlotOperand::Create(index, local_zone());
2517 : InstructionOperand::STACK_SLOT; 2502 } else {
2518 op = new (code_zone()) InstructionOperand(op_kind, index); 2503 DCHECK(kind == GENERAL_REGISTERS);
2504 op = StackSlotOperand::Create(index, local_zone());
2505 }
2519 } 2506 }
2520 first->SetSpillOperand(op); 2507 first->SetSpillOperand(op);
2521 } 2508 }
2522 } 2509 }
2523 range->MakeSpilled(); 2510 range->MakeSpilled(code_zone());
2524 } 2511 }
2525 2512
2526 2513
2527 int RegisterAllocator::RegisterCount() const { return num_registers_; } 2514 int RegisterAllocator::RegisterCount() const { return num_registers_; }
2528 2515
2529 2516
2530 #ifdef DEBUG 2517 #ifdef DEBUG
2531 2518
2532 2519
2533 void RegisterAllocator::Verify() const { 2520 void RegisterAllocator::Verify() const {
(...skipping 13 matching lines...) Expand all
2547 } else { 2534 } else {
2548 DCHECK(range->Kind() == GENERAL_REGISTERS); 2535 DCHECK(range->Kind() == GENERAL_REGISTERS);
2549 assigned_registers_->Add(reg); 2536 assigned_registers_->Add(reg);
2550 } 2537 }
2551 range->set_assigned_register(reg, code_zone()); 2538 range->set_assigned_register(reg, code_zone());
2552 } 2539 }
2553 2540
2554 } // namespace compiler 2541 } // namespace compiler
2555 } // namespace internal 2542 } // namespace internal
2556 } // namespace v8 2543 } // 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