| 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/base/adapters.h" | 5 #include "src/base/adapters.h" |
| 6 #include "src/compiler/linkage.h" | 6 #include "src/compiler/linkage.h" |
| 7 #include "src/compiler/register-allocator.h" | 7 #include "src/compiler/register-allocator.h" |
| 8 #include "src/string-stream.h" | 8 #include "src/string-stream.h" |
| 9 | 9 |
| 10 namespace v8 { | 10 namespace v8 { |
| (...skipping 686 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 697 spills_at_definition_(nullptr), | 697 spills_at_definition_(nullptr), |
| 698 spilled_in_deferred_blocks_(false), | 698 spilled_in_deferred_blocks_(false), |
| 699 spill_start_index_(kMaxInt), | 699 spill_start_index_(kMaxInt), |
| 700 last_child_(this), | 700 last_child_(this), |
| 701 last_pos_(nullptr), | 701 last_pos_(nullptr), |
| 702 splinter_(nullptr) { | 702 splinter_(nullptr) { |
| 703 bits_ |= SpillTypeField::encode(SpillType::kNoSpillType); | 703 bits_ |= SpillTypeField::encode(SpillType::kNoSpillType); |
| 704 } | 704 } |
| 705 | 705 |
| 706 | 706 |
| 707 #if DEBUG |
| 708 int TopLevelLiveRange::debug_virt_reg() const { |
| 709 return IsSplinter() ? splintered_from()->vreg() : vreg(); |
| 710 } |
| 711 #endif |
| 712 |
| 713 |
| 707 void TopLevelLiveRange::SpillAtDefinition(Zone* zone, int gap_index, | 714 void TopLevelLiveRange::SpillAtDefinition(Zone* zone, int gap_index, |
| 708 InstructionOperand* operand) { | 715 InstructionOperand* operand) { |
| 709 DCHECK(HasNoSpillType()); | 716 DCHECK(HasNoSpillType()); |
| 710 spills_at_definition_ = new (zone) | 717 spills_at_definition_ = new (zone) |
| 711 SpillAtDefinitionList(gap_index, operand, spills_at_definition_); | 718 SpillAtDefinitionList(gap_index, operand, spills_at_definition_); |
| 712 } | 719 } |
| 713 | 720 |
| 714 | 721 |
| 715 bool TopLevelLiveRange::TryCommitSpillInDeferredBlock( | 722 bool TopLevelLiveRange::TryCommitSpillInDeferredBlock( |
| 716 InstructionSequence* code, const InstructionOperand& spill_operand) { | 723 InstructionSequence* code, const InstructionOperand& spill_operand) { |
| (...skipping 1489 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2206 RegisterKind kind) | 2213 RegisterKind kind) |
| 2207 : data_(data), | 2214 : data_(data), |
| 2208 mode_(kind), | 2215 mode_(kind), |
| 2209 num_registers_(GetRegisterCount(data->config(), kind)), | 2216 num_registers_(GetRegisterCount(data->config(), kind)), |
| 2210 num_allocatable_registers_( | 2217 num_allocatable_registers_( |
| 2211 GetAllocatableRegisterCount(data->config(), kind)), | 2218 GetAllocatableRegisterCount(data->config(), kind)), |
| 2212 allocatable_register_codes_( | 2219 allocatable_register_codes_( |
| 2213 GetAllocatableRegisterCodes(data->config(), kind)) {} | 2220 GetAllocatableRegisterCodes(data->config(), kind)) {} |
| 2214 | 2221 |
| 2215 | 2222 |
| 2223 LifetimePosition RegisterAllocator::GetSplitPositionForInstruction( |
| 2224 const LiveRange* range, int instruction_index) { |
| 2225 LifetimePosition ret = LifetimePosition::Invalid(); |
| 2226 |
| 2227 ret = LifetimePosition::GapFromInstructionIndex(instruction_index); |
| 2228 if (range->Start() >= ret || ret >= range->End()) { |
| 2229 return LifetimePosition::Invalid(); |
| 2230 } |
| 2231 return ret; |
| 2232 } |
| 2233 |
| 2234 |
| 2235 void RegisterAllocator::SplitAndSpillRangesDefinedByMemoryOperand() { |
| 2236 size_t initial_range_count = data()->live_ranges().size(); |
| 2237 for (size_t i = 0; i < initial_range_count; ++i) { |
| 2238 TopLevelLiveRange* range = data()->live_ranges()[i]; |
| 2239 if (!CanProcessRange(range)) continue; |
| 2240 if (!range->HasSpillOperand()) continue; |
| 2241 |
| 2242 LifetimePosition start = range->Start(); |
| 2243 TRACE("Live range %d:%d is defined by a spill operand.\n", |
| 2244 range->TopLevel()->vreg(), range->relative_id()); |
| 2245 LifetimePosition next_pos = start; |
| 2246 if (next_pos.IsGapPosition()) { |
| 2247 next_pos = next_pos.NextStart(); |
| 2248 } |
| 2249 UsePosition* pos = range->NextUsePositionRegisterIsBeneficial(next_pos); |
| 2250 // If the range already has a spill operand and it doesn't need a |
| 2251 // register immediately, split it and spill the first part of the range. |
| 2252 if (pos == nullptr) { |
| 2253 Spill(range); |
| 2254 } else if (pos->pos() > range->Start().NextStart()) { |
| 2255 // Do not spill live range eagerly if use position that can benefit from |
| 2256 // the register is too close to the start of live range. |
| 2257 LifetimePosition split_pos = GetSplitPositionForInstruction( |
| 2258 range, pos->pos().ToInstructionIndex()); |
| 2259 // There is no place to split, so we can't split and spill. |
| 2260 if (!split_pos.IsValid()) continue; |
| 2261 |
| 2262 split_pos = |
| 2263 FindOptimalSplitPos(range->Start().NextFullStart(), split_pos); |
| 2264 |
| 2265 SplitRangeAt(range, split_pos); |
| 2266 Spill(range); |
| 2267 } |
| 2268 } |
| 2269 } |
| 2270 |
| 2271 |
| 2216 LiveRange* RegisterAllocator::SplitRangeAt(LiveRange* range, | 2272 LiveRange* RegisterAllocator::SplitRangeAt(LiveRange* range, |
| 2217 LifetimePosition pos) { | 2273 LifetimePosition pos) { |
| 2218 DCHECK(!range->TopLevel()->IsFixed()); | 2274 DCHECK(!range->TopLevel()->IsFixed()); |
| 2219 TRACE("Splitting live range %d:%d at %d\n", range->TopLevel()->vreg(), | 2275 TRACE("Splitting live range %d:%d at %d\n", range->TopLevel()->vreg(), |
| 2220 range->relative_id(), pos.value()); | 2276 range->relative_id(), pos.value()); |
| 2221 | 2277 |
| 2222 if (pos <= range->Start()) return range; | 2278 if (pos <= range->Start()) return range; |
| 2223 | 2279 |
| 2224 // We can't properly connect liveranges if splitting occurred at the end | 2280 // We can't properly connect liveranges if splitting occurred at the end |
| 2225 // a block. | 2281 // a block. |
| (...skipping 131 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2357 DCHECK(RegisterConfiguration::kMaxDoubleRegisters >= | 2413 DCHECK(RegisterConfiguration::kMaxDoubleRegisters >= |
| 2358 this->data()->config()->num_general_registers()); | 2414 this->data()->config()->num_general_registers()); |
| 2359 } | 2415 } |
| 2360 | 2416 |
| 2361 | 2417 |
| 2362 void LinearScanAllocator::AllocateRegisters() { | 2418 void LinearScanAllocator::AllocateRegisters() { |
| 2363 DCHECK(unhandled_live_ranges().empty()); | 2419 DCHECK(unhandled_live_ranges().empty()); |
| 2364 DCHECK(active_live_ranges().empty()); | 2420 DCHECK(active_live_ranges().empty()); |
| 2365 DCHECK(inactive_live_ranges().empty()); | 2421 DCHECK(inactive_live_ranges().empty()); |
| 2366 | 2422 |
| 2367 for (LiveRange* range : data()->live_ranges()) { | 2423 SplitAndSpillRangesDefinedByMemoryOperand(); |
| 2368 if (range == nullptr) continue; | 2424 |
| 2369 if (range->kind() == mode()) { | 2425 for (TopLevelLiveRange* range : data()->live_ranges()) { |
| 2370 AddToUnhandledUnsorted(range); | 2426 if (!CanProcessRange(range)) continue; |
| 2427 for (LiveRange* to_add = range; to_add != nullptr; |
| 2428 to_add = to_add->next()) { |
| 2429 if (!to_add->spilled()) { |
| 2430 AddToUnhandledUnsorted(to_add); |
| 2431 } |
| 2371 } | 2432 } |
| 2372 } | 2433 } |
| 2373 SortUnhandled(); | 2434 SortUnhandled(); |
| 2374 DCHECK(UnhandledIsSorted()); | 2435 DCHECK(UnhandledIsSorted()); |
| 2375 | 2436 |
| 2376 auto& fixed_ranges = GetFixedRegisters(); | 2437 auto& fixed_ranges = GetFixedRegisters(); |
| 2377 for (auto current : fixed_ranges) { | 2438 for (auto current : fixed_ranges) { |
| 2378 if (current != nullptr) { | 2439 if (current != nullptr) { |
| 2379 DCHECK_EQ(mode(), current->kind()); | 2440 DCHECK_EQ(mode(), current->kind()); |
| 2380 AddToInactive(current); | 2441 AddToInactive(current); |
| (...skipping 1012 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3393 auto eliminate = moves->PrepareInsertAfter(move); | 3454 auto eliminate = moves->PrepareInsertAfter(move); |
| 3394 to_insert.push_back(move); | 3455 to_insert.push_back(move); |
| 3395 if (eliminate != nullptr) to_eliminate.push_back(eliminate); | 3456 if (eliminate != nullptr) to_eliminate.push_back(eliminate); |
| 3396 } | 3457 } |
| 3397 } | 3458 } |
| 3398 | 3459 |
| 3399 | 3460 |
| 3400 } // namespace compiler | 3461 } // namespace compiler |
| 3401 } // namespace internal | 3462 } // namespace internal |
| 3402 } // namespace v8 | 3463 } // namespace v8 |
| OLD | NEW |