OLD | NEW |
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 21 matching lines...) Expand all Loading... |
32 | 32 |
33 static void RemoveElement(ZoneVector<LiveRange*>* v, LiveRange* range) { | 33 static void RemoveElement(ZoneVector<LiveRange*>* v, LiveRange* range) { |
34 auto it = std::find(v->begin(), v->end(), range); | 34 auto it = std::find(v->begin(), v->end(), range); |
35 DCHECK(it != v->end()); | 35 DCHECK(it != v->end()); |
36 v->erase(it); | 36 v->erase(it); |
37 } | 37 } |
38 | 38 |
39 | 39 |
40 UsePosition::UsePosition(LifetimePosition pos, InstructionOperand* operand, | 40 UsePosition::UsePosition(LifetimePosition pos, InstructionOperand* operand, |
41 InstructionOperand* hint) | 41 InstructionOperand* hint) |
42 : operand_(operand), | 42 : operand_(operand), hint_(hint), pos_(pos), next_(nullptr), flags_(0) { |
43 hint_(hint), | 43 bool register_beneficial = true; |
44 pos_(pos), | 44 UsePositionType type = UsePositionType::kAny; |
45 next_(nullptr), | |
46 requires_reg_(false), | |
47 register_beneficial_(true) { | |
48 if (operand_ != nullptr && operand_->IsUnallocated()) { | 45 if (operand_ != nullptr && operand_->IsUnallocated()) { |
49 const UnallocatedOperand* unalloc = UnallocatedOperand::cast(operand_); | 46 const UnallocatedOperand* unalloc = UnallocatedOperand::cast(operand_); |
50 requires_reg_ = unalloc->HasRegisterPolicy(); | 47 if (unalloc->HasRegisterPolicy()) { |
51 register_beneficial_ = !unalloc->HasAnyPolicy(); | 48 type = UsePositionType::kRequiresRegister; |
| 49 } else if (unalloc->HasSlotPolicy()) { |
| 50 type = UsePositionType::kRequiresSlot; |
| 51 register_beneficial = false; |
| 52 } else { |
| 53 register_beneficial = !unalloc->HasAnyPolicy(); |
| 54 } |
52 } | 55 } |
| 56 flags_ = TypeField::encode(type) | |
| 57 RegisterBeneficialField::encode(register_beneficial); |
53 DCHECK(pos_.IsValid()); | 58 DCHECK(pos_.IsValid()); |
54 } | 59 } |
55 | 60 |
56 | 61 |
57 bool UsePosition::HasHint() const { | 62 bool UsePosition::HasHint() const { |
58 return hint_ != nullptr && !hint_->IsUnallocated(); | 63 return hint_ != nullptr && !hint_->IsUnallocated(); |
59 } | 64 } |
60 | 65 |
61 | 66 |
62 bool UsePosition::RequiresRegister() const { return requires_reg_; } | 67 void UsePosition::set_type(UsePositionType type, bool register_beneficial) { |
63 | 68 DCHECK_IMPLIES(type == UsePositionType::kRequiresSlot, !register_beneficial); |
64 | 69 flags_ = TypeField::encode(type) | |
65 bool UsePosition::RegisterIsBeneficial() const { return register_beneficial_; } | 70 RegisterBeneficialField::encode(register_beneficial); |
| 71 } |
66 | 72 |
67 | 73 |
68 void UseInterval::SplitAt(LifetimePosition pos, Zone* zone) { | 74 void UseInterval::SplitAt(LifetimePosition pos, Zone* zone) { |
69 DCHECK(Contains(pos) && pos.Value() != start().Value()); | 75 DCHECK(Contains(pos) && pos.Value() != start().Value()); |
70 auto after = new (zone) UseInterval(pos, end_); | 76 auto after = new (zone) UseInterval(pos, end_); |
71 after->next_ = next_; | 77 after->next_ = next_; |
72 next_ = after; | 78 next_ = after; |
73 end_ = pos; | 79 end_ = pos; |
74 } | 80 } |
75 | 81 |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
110 return false; | 116 return false; |
111 } | 117 } |
112 | 118 |
113 | 119 |
114 #endif | 120 #endif |
115 | 121 |
116 | 122 |
117 LiveRange::LiveRange(int id, Zone* zone) | 123 LiveRange::LiveRange(int id, Zone* zone) |
118 : id_(id), | 124 : id_(id), |
119 spilled_(false), | 125 spilled_(false), |
| 126 has_slot_use_(false), |
120 is_phi_(false), | 127 is_phi_(false), |
121 is_non_loop_phi_(false), | 128 is_non_loop_phi_(false), |
122 kind_(UNALLOCATED_REGISTERS), | 129 kind_(UNALLOCATED_REGISTERS), |
123 assigned_register_(kInvalidAssignment), | 130 assigned_register_(kInvalidAssignment), |
124 last_interval_(nullptr), | 131 last_interval_(nullptr), |
125 first_interval_(nullptr), | 132 first_interval_(nullptr), |
126 first_pos_(nullptr), | 133 first_pos_(nullptr), |
127 parent_(nullptr), | 134 parent_(nullptr), |
128 next_(nullptr), | 135 next_(nullptr), |
129 current_interval_(nullptr), | 136 current_interval_(nullptr), |
130 last_processed_use_(nullptr), | 137 last_processed_use_(nullptr), |
131 current_hint_operand_(nullptr), | 138 current_hint_operand_(nullptr), |
132 spill_start_index_(kMaxInt), | 139 spill_start_index_(kMaxInt), |
133 spill_type_(SpillType::kNoSpillType), | 140 spill_type_(SpillType::kNoSpillType), |
134 spill_operand_(nullptr), | 141 spill_operand_(nullptr), |
135 spills_at_definition_(nullptr) {} | 142 spills_at_definition_(nullptr) {} |
136 | 143 |
137 | 144 |
138 void LiveRange::set_assigned_register(int reg, | 145 void LiveRange::set_assigned_register(int reg, |
139 InstructionOperandCache* operand_cache) { | 146 InstructionOperandCache* operand_cache) { |
140 DCHECK(!HasRegisterAssigned() && !IsSpilled()); | 147 DCHECK(!HasRegisterAssigned() && !IsSpilled()); |
141 assigned_register_ = reg; | 148 assigned_register_ = reg; |
142 // TODO(dcarney): stop aliasing hint operands. | 149 // TODO(dcarney): stop aliasing hint operands. |
143 ConvertUsesToOperand(GetAssignedOperand(operand_cache)); | 150 ConvertUsesToOperand(GetAssignedOperand(operand_cache), nullptr); |
144 } | 151 } |
145 | 152 |
146 | 153 |
147 void LiveRange::MakeSpilled() { | 154 void LiveRange::MakeSpilled() { |
148 DCHECK(!IsSpilled()); | 155 DCHECK(!IsSpilled()); |
149 DCHECK(!TopLevel()->HasNoSpillType()); | 156 DCHECK(!TopLevel()->HasNoSpillType()); |
150 spilled_ = true; | 157 spilled_ = true; |
151 assigned_register_ = kInvalidAssignment; | 158 assigned_register_ = kInvalidAssignment; |
152 } | 159 } |
153 | 160 |
154 | 161 |
155 void LiveRange::SpillAtDefinition(Zone* zone, int gap_index, | 162 void LiveRange::SpillAtDefinition(Zone* zone, int gap_index, |
156 InstructionOperand* operand) { | 163 InstructionOperand* operand) { |
157 DCHECK(HasNoSpillType()); | 164 DCHECK(HasNoSpillType()); |
158 spills_at_definition_ = new (zone) | 165 spills_at_definition_ = new (zone) |
159 SpillAtDefinitionList(gap_index, operand, spills_at_definition_); | 166 SpillAtDefinitionList(gap_index, operand, spills_at_definition_); |
160 } | 167 } |
161 | 168 |
162 | 169 |
163 void LiveRange::CommitSpillsAtDefinition(InstructionSequence* sequence, | 170 void LiveRange::CommitSpillsAtDefinition(InstructionSequence* sequence, |
164 InstructionOperand* op) { | 171 InstructionOperand* op, |
165 auto to_spill = TopLevel()->spills_at_definition_; | 172 bool might_be_duplicated) { |
166 if (to_spill == nullptr) return; | 173 DCHECK(!IsChild()); |
167 auto zone = sequence->zone(); | 174 auto zone = sequence->zone(); |
168 for (; to_spill != nullptr; to_spill = to_spill->next) { | 175 for (auto to_spill = spills_at_definition_; to_spill != nullptr; |
| 176 to_spill = to_spill->next) { |
169 auto gap = sequence->GapAt(to_spill->gap_index); | 177 auto gap = sequence->GapAt(to_spill->gap_index); |
170 auto move = gap->GetOrCreateParallelMove(GapInstruction::START, zone); | 178 auto move = gap->GetOrCreateParallelMove(GapInstruction::START, zone); |
| 179 // Skip insertion if it's possible that the move exists already as a |
| 180 // constraint move from a fixed output register to a slot. |
| 181 if (might_be_duplicated) { |
| 182 bool found = false; |
| 183 auto move_ops = move->move_operands(); |
| 184 for (auto move_op = move_ops->begin(); move_op != move_ops->end(); |
| 185 ++move_op) { |
| 186 if (move_op->IsEliminated()) continue; |
| 187 if (move_op->source()->Equals(to_spill->operand) && |
| 188 move_op->destination()->Equals(op)) { |
| 189 found = true; |
| 190 break; |
| 191 } |
| 192 } |
| 193 if (found) continue; |
| 194 } |
171 move->AddMove(to_spill->operand, op, zone); | 195 move->AddMove(to_spill->operand, op, zone); |
172 } | 196 } |
173 TopLevel()->spills_at_definition_ = nullptr; | |
174 } | 197 } |
175 | 198 |
176 | 199 |
177 void LiveRange::SetSpillOperand(InstructionOperand* operand) { | 200 void LiveRange::SetSpillOperand(InstructionOperand* operand) { |
178 DCHECK(HasNoSpillType()); | 201 DCHECK(HasNoSpillType()); |
179 DCHECK(!operand->IsUnallocated()); | 202 DCHECK(!operand->IsUnallocated()); |
180 spill_type_ = SpillType::kSpillOperand; | 203 spill_type_ = SpillType::kSpillOperand; |
181 spill_operand_ = operand; | 204 spill_operand_ = operand; |
182 } | 205 } |
183 | 206 |
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
227 while (pos != nullptr && pos->pos().Value() < start.Value()) { | 250 while (pos != nullptr && pos->pos().Value() < start.Value()) { |
228 if (pos->RegisterIsBeneficial()) prev = pos; | 251 if (pos->RegisterIsBeneficial()) prev = pos; |
229 pos = pos->next(); | 252 pos = pos->next(); |
230 } | 253 } |
231 return prev; | 254 return prev; |
232 } | 255 } |
233 | 256 |
234 | 257 |
235 UsePosition* LiveRange::NextRegisterPosition(LifetimePosition start) { | 258 UsePosition* LiveRange::NextRegisterPosition(LifetimePosition start) { |
236 UsePosition* pos = NextUsePosition(start); | 259 UsePosition* pos = NextUsePosition(start); |
237 while (pos != nullptr && !pos->RequiresRegister()) { | 260 while (pos != nullptr && pos->type() != UsePositionType::kRequiresRegister) { |
238 pos = pos->next(); | 261 pos = pos->next(); |
239 } | 262 } |
240 return pos; | 263 return pos; |
241 } | 264 } |
242 | 265 |
243 | 266 |
244 bool LiveRange::CanBeSpilled(LifetimePosition pos) { | 267 bool LiveRange::CanBeSpilled(LifetimePosition pos) { |
245 // We cannot spill a live range that has a use requiring a register | 268 // We cannot spill a live range that has a use requiring a register |
246 // at the current or the immediate next position. | 269 // at the current or the immediate next position. |
247 auto use_pos = NextRegisterPosition(pos); | 270 auto use_pos = NextRegisterPosition(pos); |
(...skipping 254 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
502 use_pos->next_ = prev->next_; | 525 use_pos->next_ = prev->next_; |
503 prev->next_ = use_pos; | 526 prev->next_ = use_pos; |
504 } | 527 } |
505 | 528 |
506 if (prev_hint == nullptr && use_pos->HasHint()) { | 529 if (prev_hint == nullptr && use_pos->HasHint()) { |
507 current_hint_operand_ = hint; | 530 current_hint_operand_ = hint; |
508 } | 531 } |
509 } | 532 } |
510 | 533 |
511 | 534 |
512 void LiveRange::ConvertUsesToOperand(InstructionOperand* op) { | 535 void LiveRange::ConvertUsesToOperand(InstructionOperand* op, |
513 auto use_pos = first_pos(); | 536 InstructionOperand* spill_op) { |
514 while (use_pos != nullptr) { | 537 for (auto pos = first_pos(); pos != nullptr; pos = pos->next()) { |
515 DCHECK(Start().Value() <= use_pos->pos().Value() && | 538 DCHECK(Start().Value() <= pos->pos().Value() && |
516 use_pos->pos().Value() <= End().Value()); | 539 pos->pos().Value() <= End().Value()); |
517 | 540 if (!pos->HasOperand()) { |
518 if (use_pos->HasOperand()) { | 541 continue; |
519 DCHECK(op->IsRegister() || op->IsDoubleRegister() || | |
520 !use_pos->RequiresRegister()); | |
521 use_pos->operand()->ConvertTo(op->kind(), op->index()); | |
522 } | 542 } |
523 use_pos = use_pos->next(); | 543 switch (pos->type()) { |
| 544 case UsePositionType::kRequiresSlot: |
| 545 if (spill_op != nullptr) { |
| 546 pos->operand()->ConvertTo(spill_op->kind(), spill_op->index()); |
| 547 } |
| 548 break; |
| 549 case UsePositionType::kRequiresRegister: |
| 550 DCHECK(op->IsRegister() || op->IsDoubleRegister()); |
| 551 // Fall through. |
| 552 case UsePositionType::kAny: |
| 553 pos->operand()->ConvertTo(op->kind(), op->index()); |
| 554 break; |
| 555 } |
524 } | 556 } |
525 } | 557 } |
526 | 558 |
527 | 559 |
528 bool LiveRange::CanCover(LifetimePosition position) const { | 560 bool LiveRange::CanCover(LifetimePosition position) const { |
529 if (IsEmpty()) return false; | 561 if (IsEmpty()) return false; |
530 return Start().Value() <= position.Value() && | 562 return Start().Value() <= position.Value() && |
531 position.Value() < End().Value(); | 563 position.Value() < End().Value(); |
532 } | 564 } |
533 | 565 |
(...skipping 416 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
950 : InstructionOperand::STACK_SLOT; | 982 : InstructionOperand::STACK_SLOT; |
951 auto op = InstructionOperand::New(code_zone(), op_kind, index); | 983 auto op = InstructionOperand::New(code_zone(), op_kind, index); |
952 range->SetOperand(op); | 984 range->SetOperand(op); |
953 } | 985 } |
954 } | 986 } |
955 | 987 |
956 | 988 |
957 void RegisterAllocator::CommitAssignment() { | 989 void RegisterAllocator::CommitAssignment() { |
958 for (auto range : live_ranges()) { | 990 for (auto range : live_ranges()) { |
959 if (range == nullptr || range->IsEmpty()) continue; | 991 if (range == nullptr || range->IsEmpty()) continue; |
960 // Register assignments were committed in set_assigned_register. | |
961 if (range->HasRegisterAssigned()) continue; | |
962 auto assigned = range->GetAssignedOperand(operand_cache()); | 992 auto assigned = range->GetAssignedOperand(operand_cache()); |
963 range->ConvertUsesToOperand(assigned); | 993 InstructionOperand* spill_operand = nullptr; |
964 if (range->IsSpilled()) { | 994 if (!range->TopLevel()->HasNoSpillType()) { |
965 range->CommitSpillsAtDefinition(code(), assigned); | 995 spill_operand = range->TopLevel()->GetSpillOperand(); |
| 996 } |
| 997 range->ConvertUsesToOperand(assigned, spill_operand); |
| 998 if (!range->IsChild() && spill_operand != nullptr) { |
| 999 range->CommitSpillsAtDefinition(code(), spill_operand, |
| 1000 range->has_slot_use()); |
966 } | 1001 } |
967 } | 1002 } |
968 } | 1003 } |
969 | 1004 |
970 | 1005 |
971 SpillRange* RegisterAllocator::AssignSpillRangeToLiveRange(LiveRange* range) { | 1006 SpillRange* RegisterAllocator::AssignSpillRangeToLiveRange(LiveRange* range) { |
972 auto spill_range = new (local_zone()) SpillRange(range, local_zone()); | 1007 auto spill_range = new (local_zone()) SpillRange(range, local_zone()); |
973 spill_ranges().push_back(spill_range); | 1008 spill_ranges().push_back(spill_range); |
974 return spill_range; | 1009 return spill_range; |
975 } | 1010 } |
976 | 1011 |
977 | 1012 |
978 bool RegisterAllocator::TryReuseSpillForPhi(LiveRange* range) { | 1013 bool RegisterAllocator::TryReuseSpillForPhi(LiveRange* range) { |
979 if (range->IsChild() || !range->is_phi()) return false; | 1014 if (range->IsChild() || !range->is_phi()) return false; |
980 DCHECK(range->HasNoSpillType()); | 1015 DCHECK(!range->HasSpillOperand()); |
981 | 1016 |
982 auto lookup = phi_map_.find(range->id()); | 1017 auto lookup = phi_map_.find(range->id()); |
983 DCHECK(lookup != phi_map_.end()); | 1018 DCHECK(lookup != phi_map_.end()); |
984 auto phi = lookup->second.phi; | 1019 auto phi = lookup->second.phi; |
985 auto block = lookup->second.block; | 1020 auto block = lookup->second.block; |
986 // Count the number of spilled operands. | 1021 // Count the number of spilled operands. |
987 size_t spilled_count = 0; | 1022 size_t spilled_count = 0; |
988 LiveRange* first_op = nullptr; | 1023 LiveRange* first_op = nullptr; |
989 for (size_t i = 0; i < phi->operands().size(); i++) { | 1024 for (size_t i = 0; i < phi->operands().size(); i++) { |
990 int op = phi->operands()[i]; | 1025 int op = phi->operands()[i]; |
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1033 } | 1068 } |
1034 | 1069 |
1035 // If the range does not need register soon, spill it to the merged | 1070 // If the range does not need register soon, spill it to the merged |
1036 // spill range. | 1071 // spill range. |
1037 auto next_pos = range->Start(); | 1072 auto next_pos = range->Start(); |
1038 if (code()->IsGapAt(next_pos.InstructionIndex())) { | 1073 if (code()->IsGapAt(next_pos.InstructionIndex())) { |
1039 next_pos = next_pos.NextInstruction(); | 1074 next_pos = next_pos.NextInstruction(); |
1040 } | 1075 } |
1041 auto pos = range->NextUsePositionRegisterIsBeneficial(next_pos); | 1076 auto pos = range->NextUsePositionRegisterIsBeneficial(next_pos); |
1042 if (pos == nullptr) { | 1077 if (pos == nullptr) { |
1043 auto spill_range = AssignSpillRangeToLiveRange(range->TopLevel()); | 1078 auto spill_range = range->TopLevel()->HasSpillRange() |
| 1079 ? range->TopLevel()->GetSpillRange() |
| 1080 : AssignSpillRangeToLiveRange(range->TopLevel()); |
1044 CHECK(first_op_spill->TryMerge(spill_range)); | 1081 CHECK(first_op_spill->TryMerge(spill_range)); |
1045 Spill(range); | 1082 Spill(range); |
1046 return true; | 1083 return true; |
1047 } else if (pos->pos().Value() > range->Start().NextInstruction().Value()) { | 1084 } else if (pos->pos().Value() > range->Start().NextInstruction().Value()) { |
1048 auto spill_range = AssignSpillRangeToLiveRange(range->TopLevel()); | 1085 auto spill_range = range->TopLevel()->HasSpillRange() |
| 1086 ? range->TopLevel()->GetSpillRange() |
| 1087 : AssignSpillRangeToLiveRange(range->TopLevel()); |
1049 CHECK(first_op_spill->TryMerge(spill_range)); | 1088 CHECK(first_op_spill->TryMerge(spill_range)); |
1050 SpillBetween(range, range->Start(), pos->pos()); | 1089 SpillBetween(range, range->Start(), pos->pos()); |
1051 DCHECK(UnhandledIsSorted()); | 1090 DCHECK(UnhandledIsSorted()); |
1052 return true; | 1091 return true; |
1053 } | 1092 } |
1054 return false; | 1093 return false; |
1055 } | 1094 } |
1056 | 1095 |
1057 | 1096 |
1058 void RegisterAllocator::MeetRegisterConstraints(const InstructionBlock* block) { | 1097 void RegisterAllocator::MeetRegisterConstraints(const InstructionBlock* block) { |
(...skipping 238 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1297 if (from->IsUnallocated()) { | 1336 if (from->IsUnallocated()) { |
1298 live->Add(UnallocatedOperand::cast(from)->virtual_register()); | 1337 live->Add(UnallocatedOperand::cast(from)->virtual_register()); |
1299 } | 1338 } |
1300 } | 1339 } |
1301 } | 1340 } |
1302 } else { | 1341 } else { |
1303 // Process output, inputs, and temps of this non-gap instruction. | 1342 // Process output, inputs, and temps of this non-gap instruction. |
1304 for (size_t i = 0; i < instr->OutputCount(); i++) { | 1343 for (size_t i = 0; i < instr->OutputCount(); i++) { |
1305 auto output = instr->OutputAt(i); | 1344 auto output = instr->OutputAt(i); |
1306 if (output->IsUnallocated()) { | 1345 if (output->IsUnallocated()) { |
| 1346 // Unsupported. |
| 1347 DCHECK(!UnallocatedOperand::cast(output)->HasSlotPolicy()); |
1307 int out_vreg = UnallocatedOperand::cast(output)->virtual_register(); | 1348 int out_vreg = UnallocatedOperand::cast(output)->virtual_register(); |
1308 live->Remove(out_vreg); | 1349 live->Remove(out_vreg); |
1309 } else if (output->IsConstant()) { | 1350 } else if (output->IsConstant()) { |
1310 int out_vreg = output->index(); | 1351 int out_vreg = output->index(); |
1311 live->Remove(out_vreg); | 1352 live->Remove(out_vreg); |
1312 } | 1353 } |
1313 Define(curr_position, output, nullptr); | 1354 Define(curr_position, output, nullptr); |
1314 } | 1355 } |
1315 | 1356 |
1316 if (instr->ClobbersRegisters()) { | 1357 if (instr->ClobbersRegisters()) { |
(...skipping 20 matching lines...) Expand all Loading... |
1337 auto input = instr->InputAt(i); | 1378 auto input = instr->InputAt(i); |
1338 if (input->IsImmediate()) continue; // Ignore immediates. | 1379 if (input->IsImmediate()) continue; // Ignore immediates. |
1339 LifetimePosition use_pos; | 1380 LifetimePosition use_pos; |
1340 if (input->IsUnallocated() && | 1381 if (input->IsUnallocated() && |
1341 UnallocatedOperand::cast(input)->IsUsedAtStart()) { | 1382 UnallocatedOperand::cast(input)->IsUsedAtStart()) { |
1342 use_pos = curr_position; | 1383 use_pos = curr_position; |
1343 } else { | 1384 } else { |
1344 use_pos = curr_position.InstructionEnd(); | 1385 use_pos = curr_position.InstructionEnd(); |
1345 } | 1386 } |
1346 | 1387 |
| 1388 if (input->IsUnallocated()) { |
| 1389 UnallocatedOperand* unalloc = UnallocatedOperand::cast(input); |
| 1390 int vreg = unalloc->virtual_register(); |
| 1391 live->Add(vreg); |
| 1392 if (unalloc->HasSlotPolicy()) { |
| 1393 LiveRangeFor(vreg)->set_has_slot_use(true); |
| 1394 } |
| 1395 } |
1347 Use(block_start_position, use_pos, input, nullptr); | 1396 Use(block_start_position, use_pos, input, nullptr); |
1348 if (input->IsUnallocated()) { | |
1349 live->Add(UnallocatedOperand::cast(input)->virtual_register()); | |
1350 } | |
1351 } | 1397 } |
1352 | 1398 |
1353 for (size_t i = 0; i < instr->TempCount(); i++) { | 1399 for (size_t i = 0; i < instr->TempCount(); i++) { |
1354 auto temp = instr->TempAt(i); | 1400 auto temp = instr->TempAt(i); |
| 1401 // Unsupported. |
| 1402 DCHECK_IMPLIES(temp->IsUnallocated(), |
| 1403 !UnallocatedOperand::cast(temp)->HasSlotPolicy()); |
1355 if (instr->ClobbersTemps()) { | 1404 if (instr->ClobbersTemps()) { |
1356 if (temp->IsRegister()) continue; | 1405 if (temp->IsRegister()) continue; |
1357 if (temp->IsUnallocated()) { | 1406 if (temp->IsUnallocated()) { |
1358 UnallocatedOperand* temp_unalloc = UnallocatedOperand::cast(temp); | 1407 UnallocatedOperand* temp_unalloc = UnallocatedOperand::cast(temp); |
1359 if (temp_unalloc->HasFixedPolicy()) { | 1408 if (temp_unalloc->HasFixedPolicy()) { |
1360 continue; | 1409 continue; |
1361 } | 1410 } |
1362 } | 1411 } |
1363 } | 1412 } |
1364 Use(block_start_position, curr_position.InstructionEnd(), temp, | 1413 Use(block_start_position, curr_position.InstructionEnd(), temp, |
(...skipping 401 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1766 for (int i = block->rpo_number().ToInt() + 1; | 1815 for (int i = block->rpo_number().ToInt() + 1; |
1767 i < block->loop_end().ToInt(); ++i) { | 1816 i < block->loop_end().ToInt(); ++i) { |
1768 live_in_sets_[i]->Union(*live); | 1817 live_in_sets_[i]->Union(*live); |
1769 } | 1818 } |
1770 } | 1819 } |
1771 } | 1820 } |
1772 | 1821 |
1773 for (auto range : live_ranges()) { | 1822 for (auto range : live_ranges()) { |
1774 if (range == nullptr) continue; | 1823 if (range == nullptr) continue; |
1775 range->kind_ = RequiredRegisterKind(range->id()); | 1824 range->kind_ = RequiredRegisterKind(range->id()); |
| 1825 // Give slots to all ranges with a non fixed slot use. |
| 1826 if (range->has_slot_use() && range->HasNoSpillType()) { |
| 1827 AssignSpillRangeToLiveRange(range); |
| 1828 } |
1776 // TODO(bmeurer): This is a horrible hack to make sure that for constant | 1829 // TODO(bmeurer): This is a horrible hack to make sure that for constant |
1777 // live ranges, every use requires the constant to be in a register. | 1830 // live ranges, every use requires the constant to be in a register. |
1778 // Without this hack, all uses with "any" policy would get the constant | 1831 // Without this hack, all uses with "any" policy would get the constant |
1779 // operand assigned. | 1832 // operand assigned. |
1780 if (range->HasSpillOperand() && range->GetSpillOperand()->IsConstant()) { | 1833 if (range->HasSpillOperand() && range->GetSpillOperand()->IsConstant()) { |
1781 for (auto pos = range->first_pos(); pos != nullptr; pos = pos->next_) { | 1834 for (auto pos = range->first_pos(); pos != nullptr; pos = pos->next_) { |
1782 pos->register_beneficial_ = true; | 1835 if (pos->type() == UsePositionType::kRequiresSlot) continue; |
1783 // TODO(dcarney): should the else case assert requires_reg_ == false? | 1836 UsePositionType new_type = UsePositionType::kAny; |
1784 // Can't mark phis as needing a register. | 1837 // Can't mark phis as needing a register. |
1785 if (!code() | 1838 if (!code() |
1786 ->InstructionAt(pos->pos().InstructionIndex()) | 1839 ->InstructionAt(pos->pos().InstructionIndex()) |
1787 ->IsGapMoves()) { | 1840 ->IsGapMoves()) { |
1788 pos->requires_reg_ = true; | 1841 new_type = UsePositionType::kRequiresRegister; |
1789 } | 1842 } |
| 1843 pos->set_type(new_type, true); |
1790 } | 1844 } |
1791 } | 1845 } |
1792 } | 1846 } |
1793 } | 1847 } |
1794 | 1848 |
1795 | 1849 |
1796 bool RegisterAllocator::ExistsUseWithoutDefinition() { | 1850 bool RegisterAllocator::ExistsUseWithoutDefinition() { |
1797 bool found = false; | 1851 bool found = false; |
1798 BitVector::Iterator iterator(live_in_sets_[0]); | 1852 BitVector::Iterator iterator(live_in_sets_[0]); |
1799 while (!iterator.Done()) { | 1853 while (!iterator.Done()) { |
(...skipping 728 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2528 } else { | 2582 } else { |
2529 DCHECK(range->Kind() == GENERAL_REGISTERS); | 2583 DCHECK(range->Kind() == GENERAL_REGISTERS); |
2530 assigned_registers_->Add(reg); | 2584 assigned_registers_->Add(reg); |
2531 } | 2585 } |
2532 range->set_assigned_register(reg, operand_cache()); | 2586 range->set_assigned_register(reg, operand_cache()); |
2533 } | 2587 } |
2534 | 2588 |
2535 } // namespace compiler | 2589 } // namespace compiler |
2536 } // namespace internal | 2590 } // namespace internal |
2537 } // namespace v8 | 2591 } // namespace v8 |
OLD | NEW |