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

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

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