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 2210 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2221 LifetimePosition ret = LifetimePosition::Invalid(); | 2221 LifetimePosition ret = LifetimePosition::Invalid(); |
2222 | 2222 |
2223 ret = LifetimePosition::GapFromInstructionIndex(instruction_index); | 2223 ret = LifetimePosition::GapFromInstructionIndex(instruction_index); |
2224 if (range->Start() >= ret || ret >= range->End()) { | 2224 if (range->Start() >= ret || ret >= range->End()) { |
2225 return LifetimePosition::Invalid(); | 2225 return LifetimePosition::Invalid(); |
2226 } | 2226 } |
2227 return ret; | 2227 return ret; |
2228 } | 2228 } |
2229 | 2229 |
2230 | 2230 |
2231 void RegisterAllocator::SplitAndSpillRangesDefinedByMemoryOperand() { | 2231 void RegisterAllocator::SplitAndSpillRangesDefinedByMemoryOperand( |
| 2232 bool operands_only) { |
2232 size_t initial_range_count = data()->live_ranges().size(); | 2233 size_t initial_range_count = data()->live_ranges().size(); |
2233 for (size_t i = 0; i < initial_range_count; ++i) { | 2234 for (size_t i = 0; i < initial_range_count; ++i) { |
2234 TopLevelLiveRange* range = data()->live_ranges()[i]; | 2235 TopLevelLiveRange* range = data()->live_ranges()[i]; |
2235 if (!CanProcessRange(range)) continue; | 2236 if (!CanProcessRange(range)) continue; |
2236 if (!range->HasSpillOperand()) continue; | 2237 if (range->HasNoSpillType() || (operands_only && range->HasSpillRange())) { |
| 2238 continue; |
| 2239 } |
2237 | 2240 |
2238 LifetimePosition start = range->Start(); | 2241 LifetimePosition start = range->Start(); |
2239 TRACE("Live range %d:%d is defined by a spill operand.\n", | 2242 TRACE("Live range %d:%d is defined by a spill operand.\n", |
2240 range->TopLevel()->vreg(), range->relative_id()); | 2243 range->TopLevel()->vreg(), range->relative_id()); |
2241 LifetimePosition next_pos = start; | 2244 LifetimePosition next_pos = start; |
2242 if (next_pos.IsGapPosition()) { | 2245 if (next_pos.IsGapPosition()) { |
2243 next_pos = next_pos.NextStart(); | 2246 next_pos = next_pos.NextStart(); |
2244 } | 2247 } |
2245 UsePosition* pos = range->NextUsePositionRegisterIsBeneficial(next_pos); | 2248 UsePosition* pos = range->NextUsePositionRegisterIsBeneficial(next_pos); |
2246 // If the range already has a spill operand and it doesn't need a | 2249 // If the range already has a spill operand and it doesn't need a |
(...skipping 162 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2409 DCHECK(RegisterConfiguration::kMaxDoubleRegisters >= | 2412 DCHECK(RegisterConfiguration::kMaxDoubleRegisters >= |
2410 this->data()->config()->num_general_registers()); | 2413 this->data()->config()->num_general_registers()); |
2411 } | 2414 } |
2412 | 2415 |
2413 | 2416 |
2414 void LinearScanAllocator::AllocateRegisters() { | 2417 void LinearScanAllocator::AllocateRegisters() { |
2415 DCHECK(unhandled_live_ranges().empty()); | 2418 DCHECK(unhandled_live_ranges().empty()); |
2416 DCHECK(active_live_ranges().empty()); | 2419 DCHECK(active_live_ranges().empty()); |
2417 DCHECK(inactive_live_ranges().empty()); | 2420 DCHECK(inactive_live_ranges().empty()); |
2418 | 2421 |
2419 SplitAndSpillRangesDefinedByMemoryOperand(); | 2422 SplitAndSpillRangesDefinedByMemoryOperand(false); |
2420 | 2423 |
2421 for (TopLevelLiveRange* range : data()->live_ranges()) { | 2424 for (TopLevelLiveRange* range : data()->live_ranges()) { |
2422 if (!CanProcessRange(range)) continue; | 2425 if (!CanProcessRange(range)) continue; |
2423 for (LiveRange* to_add = range; to_add != nullptr; | 2426 for (LiveRange* to_add = range; to_add != nullptr; |
2424 to_add = to_add->next()) { | 2427 to_add = to_add->next()) { |
2425 if (!to_add->spilled()) { | 2428 if (!to_add->spilled()) { |
2426 AddToUnhandledUnsorted(to_add); | 2429 AddToUnhandledUnsorted(to_add); |
2427 } | 2430 } |
2428 } | 2431 } |
2429 } | 2432 } |
(...skipping 13 matching lines...) Expand all Loading... |
2443 auto current = unhandled_live_ranges().back(); | 2446 auto current = unhandled_live_ranges().back(); |
2444 unhandled_live_ranges().pop_back(); | 2447 unhandled_live_ranges().pop_back(); |
2445 DCHECK(UnhandledIsSorted()); | 2448 DCHECK(UnhandledIsSorted()); |
2446 auto position = current->Start(); | 2449 auto position = current->Start(); |
2447 #ifdef DEBUG | 2450 #ifdef DEBUG |
2448 allocation_finger_ = position; | 2451 allocation_finger_ = position; |
2449 #endif | 2452 #endif |
2450 TRACE("Processing interval %d:%d start=%d\n", current->TopLevel()->vreg(), | 2453 TRACE("Processing interval %d:%d start=%d\n", current->TopLevel()->vreg(), |
2451 current->relative_id(), position.value()); | 2454 current->relative_id(), position.value()); |
2452 | 2455 |
2453 if (current->IsTopLevel() && !current->TopLevel()->HasNoSpillType()) { | |
2454 TRACE("Live range %d:%d already has a spill operand\n", | |
2455 current->TopLevel()->vreg(), current->relative_id()); | |
2456 auto next_pos = position; | |
2457 if (next_pos.IsGapPosition()) { | |
2458 next_pos = next_pos.NextStart(); | |
2459 } | |
2460 auto pos = current->NextUsePositionRegisterIsBeneficial(next_pos); | |
2461 // If the range already has a spill operand and it doesn't need a | |
2462 // register immediately, split it and spill the first part of the range. | |
2463 if (pos == nullptr) { | |
2464 Spill(current); | |
2465 continue; | |
2466 } else if (pos->pos() > current->Start().NextStart()) { | |
2467 // Do not spill live range eagerly if use position that can benefit from | |
2468 // the register is too close to the start of live range. | |
2469 SpillBetween(current, current->Start(), pos->pos()); | |
2470 DCHECK(UnhandledIsSorted()); | |
2471 continue; | |
2472 } | |
2473 } | |
2474 | |
2475 if (current->IsTopLevel() && TryReuseSpillForPhi(current->TopLevel())) | 2456 if (current->IsTopLevel() && TryReuseSpillForPhi(current->TopLevel())) |
2476 continue; | 2457 continue; |
2477 | 2458 |
2478 for (size_t i = 0; i < active_live_ranges().size(); ++i) { | 2459 for (size_t i = 0; i < active_live_ranges().size(); ++i) { |
2479 auto cur_active = active_live_ranges()[i]; | 2460 auto cur_active = active_live_ranges()[i]; |
2480 if (cur_active->End() <= position) { | 2461 if (cur_active->End() <= position) { |
2481 ActiveToHandled(cur_active); | 2462 ActiveToHandled(cur_active); |
2482 --i; // The live range was removed from the list of active live ranges. | 2463 --i; // The live range was removed from the list of active live ranges. |
2483 } else if (!cur_active->Covers(position)) { | 2464 } else if (!cur_active->Covers(position)) { |
2484 ActiveToInactive(cur_active); | 2465 ActiveToInactive(cur_active); |
(...skipping 975 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3460 auto eliminate = moves->PrepareInsertAfter(move); | 3441 auto eliminate = moves->PrepareInsertAfter(move); |
3461 to_insert.push_back(move); | 3442 to_insert.push_back(move); |
3462 if (eliminate != nullptr) to_eliminate.push_back(eliminate); | 3443 if (eliminate != nullptr) to_eliminate.push_back(eliminate); |
3463 } | 3444 } |
3464 } | 3445 } |
3465 | 3446 |
3466 | 3447 |
3467 } // namespace compiler | 3448 } // namespace compiler |
3468 } // namespace internal | 3449 } // namespace internal |
3469 } // namespace v8 | 3450 } // namespace v8 |
OLD | NEW |