diff options
Diffstat (limited to 'deps/v8/src/compiler/backend/register-allocator.cc')
-rw-r--r-- | deps/v8/src/compiler/backend/register-allocator.cc | 344 |
1 files changed, 180 insertions, 164 deletions
diff --git a/deps/v8/src/compiler/backend/register-allocator.cc b/deps/v8/src/compiler/backend/register-allocator.cc index 21eef0485c..945554eb32 100644 --- a/deps/v8/src/compiler/backend/register-allocator.cc +++ b/deps/v8/src/compiler/backend/register-allocator.cc @@ -6,7 +6,7 @@ #include <iomanip> -#include "src/base/adapters.h" +#include "src/base/iterator.h" #include "src/base/small-vector.h" #include "src/codegen/assembler-inl.h" #include "src/codegen/tick-counter.h" @@ -317,7 +317,6 @@ UsePositionHintType UsePosition::HintTypeForOperand( switch (op.kind()) { case InstructionOperand::CONSTANT: case InstructionOperand::IMMEDIATE: - case InstructionOperand::EXPLICIT: return UsePositionHintType::kNone; case InstructionOperand::UNALLOCATED: return UsePositionHintType::kUnresolved; @@ -797,12 +796,13 @@ LifetimePosition LiveRange::NextEndAfter(LifetimePosition position) const { return start_search->end(); } -LifetimePosition LiveRange::NextStartAfter(LifetimePosition position) const { +LifetimePosition LiveRange::NextStartAfter(LifetimePosition position) { UseInterval* start_search = FirstSearchIntervalForPosition(position); while (start_search->start() < position) { start_search = start_search->next(); } - return start_search->start(); + next_start_ = start_search->start(); + return next_start_; } LifetimePosition LiveRange::FirstIntersection(LiveRange* other) const { @@ -1940,8 +1940,8 @@ void ConstraintBuilder::MeetConstraintsBefore(int instr_index) { // Handle fixed input operands of second instruction. for (size_t i = 0; i < second->InputCount(); i++) { InstructionOperand* input = second->InputAt(i); - if (input->IsImmediate() || input->IsExplicit()) { - continue; // Ignore immediates and explicitly reserved registers. + if (input->IsImmediate()) { + continue; // Ignore immediates. } UnallocatedOperand* cur_input = UnallocatedOperand::cast(input); if (cur_input->HasFixedPolicy()) { @@ -2323,8 +2323,8 @@ void LiveRangeBuilder::ProcessInstructions(const InstructionBlock* block, for (size_t i = 0; i < instr->InputCount(); i++) { InstructionOperand* input = instr->InputAt(i); - if (input->IsImmediate() || input->IsExplicit()) { - continue; // Ignore immediates and explicitly reserved registers. + if (input->IsImmediate()) { + continue; // Ignore immediates. } LifetimePosition use_pos; if (input->IsUnallocated() && @@ -2504,10 +2504,10 @@ void LiveRangeBuilder::ProcessPhis(const InstructionBlock* block, predecessor_hint_preference |= kNotDeferredBlockPreference; } - // - Prefer hints from allocated (or explicit) operands. + // - Prefer hints from allocated operands. // - // Already-allocated or explicit operands are typically assigned using - // the parallel moves on the last instruction. For example: + // Already-allocated operands are typically assigned using the parallel + // moves on the last instruction. For example: // // gap (v101 = [x0|R|w32]) (v100 = v101) // ArchJmp @@ -2515,7 +2515,7 @@ void LiveRangeBuilder::ProcessPhis(const InstructionBlock* block, // phi: v100 = v101 v102 // // We have already found the END move, so look for a matching START move - // from an allocated (or explicit) operand. + // from an allocated operand. // // Note that we cannot simply look up data()->live_ranges()[vreg] here // because the live ranges are still being built when this function is @@ -2527,7 +2527,7 @@ void LiveRangeBuilder::ProcessPhis(const InstructionBlock* block, for (MoveOperands* move : *moves) { InstructionOperand& to = move->destination(); if (predecessor_hint->Equals(to)) { - if (move->source().IsAllocated() || move->source().IsExplicit()) { + if (move->source().IsAllocated()) { predecessor_hint_preference |= kMoveIsAllocatedPreference; } break; @@ -3095,11 +3095,11 @@ LinearScanAllocator::LinearScanAllocator(RegisterAllocationData* data, : RegisterAllocator(data, kind), unhandled_live_ranges_(local_zone), active_live_ranges_(local_zone), - inactive_live_ranges_(local_zone), + inactive_live_ranges_(num_registers(), InactiveLiveRangeQueue(local_zone), + local_zone), next_active_ranges_change_(LifetimePosition::Invalid()), next_inactive_ranges_change_(LifetimePosition::Invalid()) { active_live_ranges().reserve(8); - inactive_live_ranges().reserve(8); } void LinearScanAllocator::MaybeSpillPreviousRanges(LiveRange* begin_range, @@ -3143,15 +3143,15 @@ void LinearScanAllocator::MaybeUndoPreviousSplit(LiveRange* range) { } } -void LinearScanAllocator::SpillNotLiveRanges(RangeWithRegisterSet& to_be_live, +void LinearScanAllocator::SpillNotLiveRanges(RangeWithRegisterSet* to_be_live, LifetimePosition position, SpillMode spill_mode) { for (auto it = active_live_ranges().begin(); it != active_live_ranges().end();) { LiveRange* active_range = *it; TopLevelLiveRange* toplevel = (*it)->TopLevel(); - auto found = to_be_live.find({toplevel, kUnassignedRegister}); - if (found == to_be_live.end()) { + auto found = to_be_live->find({toplevel, kUnassignedRegister}); + if (found == to_be_live->end()) { // Is not contained in {to_be_live}, spill it. // Fixed registers are exempt from this. They might have been // added from inactive at the block boundary but we know that @@ -3207,7 +3207,7 @@ void LinearScanAllocator::SpillNotLiveRanges(RangeWithRegisterSet& to_be_live, } else { // This range is contained in {to_be_live}, so we can keep it. int expected_register = (*found).expected_register; - to_be_live.erase(found); + to_be_live->erase(found); if (expected_register == active_range->assigned_register()) { // Was life and in correct register, simply pass through. TRACE("Keeping %d:%d in %s\n", toplevel->vreg(), @@ -3238,31 +3238,22 @@ LiveRange* LinearScanAllocator::AssignRegisterOnReload(LiveRange* range, // give reloading registers pecedence. That way we would compute the // intersection for the entire future. LifetimePosition new_end = range->End(); - for (const auto inactive : inactive_live_ranges()) { - if (kSimpleFPAliasing || !check_fp_aliasing()) { - if (inactive->assigned_register() != reg) continue; - } else { - bool conflict = inactive->assigned_register() == reg; - if (!conflict) { - int alias_base_index = -1; - int aliases = data()->config()->GetAliases(range->representation(), reg, - inactive->representation(), - &alias_base_index); - DCHECK(aliases > 0 || (aliases == 0 && alias_base_index == -1)); - while (aliases-- && !conflict) { - int aliased_reg = alias_base_index + aliases; - if (aliased_reg == reg) { - conflict = true; - } - } - } - if (!conflict) continue; + for (int cur_reg = 0; cur_reg < num_registers(); ++cur_reg) { + if ((kSimpleFPAliasing || !check_fp_aliasing()) && cur_reg != reg) { + continue; } - for (auto interval = inactive->first_interval(); interval != nullptr; - interval = interval->next()) { - if (interval->start() > new_end) break; - if (interval->end() <= range->Start()) continue; - if (new_end > interval->start()) new_end = interval->start(); + for (const auto cur_inactive : inactive_live_ranges(cur_reg)) { + if (!kSimpleFPAliasing && check_fp_aliasing() && + !data()->config()->AreAliases(cur_inactive->representation(), cur_reg, + range->representation(), reg)) { + continue; + } + for (auto interval = cur_inactive->first_interval(); interval != nullptr; + interval = interval->next()) { + if (interval->start() > new_end) break; + if (interval->end() <= range->Start()) continue; + if (new_end > interval->start()) new_end = interval->start(); + } } } if (new_end != range->End()) { @@ -3275,8 +3266,8 @@ LiveRange* LinearScanAllocator::AssignRegisterOnReload(LiveRange* range, return range; } -void LinearScanAllocator::ReloadLiveRanges(RangeWithRegisterSet& to_be_live, - LifetimePosition position) { +void LinearScanAllocator::ReloadLiveRanges( + RangeWithRegisterSet const& to_be_live, LifetimePosition position) { // Assumption: All ranges in {to_be_live} are currently spilled and there are // no conflicting registers in the active ranges. // The former is ensured by SpillNotLiveRanges, the latter is by construction @@ -3558,11 +3549,17 @@ void LinearScanAllocator::UpdateDeferredFixedRanges(SpillMode spill_mode, Min(updated->End(), next_active_ranges_change_); }); } - for (auto inactive : inactive_live_ranges()) { - split_conflicting(range, inactive, [this](LiveRange* updated) { - next_inactive_ranges_change_ = - Min(updated->End(), next_inactive_ranges_change_); - }); + for (int reg = 0; reg < num_registers(); ++reg) { + if ((kSimpleFPAliasing || !check_fp_aliasing()) && + reg != range->assigned_register()) { + continue; + } + for (auto inactive : inactive_live_ranges(reg)) { + split_conflicting(range, inactive, [this](LiveRange* updated) { + next_inactive_ranges_change_ = + Min(updated->End(), next_inactive_ranges_change_); + }); + } } }; if (mode() == GENERAL_REGISTERS) { @@ -3600,12 +3597,14 @@ void LinearScanAllocator::UpdateDeferredFixedRanges(SpillMode spill_mode, } } else { // Remove all ranges. - for (auto it = inactive_live_ranges().begin(); - it != inactive_live_ranges().end();) { - if ((*it)->TopLevel()->IsDeferredFixed()) { - it = inactive_live_ranges().erase(it); - } else { - ++it; + for (int reg = 0; reg < num_registers(); ++reg) { + for (auto it = inactive_live_ranges(reg).begin(); + it != inactive_live_ranges(reg).end();) { + if ((*it)->TopLevel()->IsDeferredFixed()) { + it = inactive_live_ranges(reg).erase(it); + } else { + ++it; + } } } } @@ -3636,7 +3635,9 @@ bool LinearScanAllocator::HasNonDeferredPredecessor(InstructionBlock* block) { void LinearScanAllocator::AllocateRegisters() { DCHECK(unhandled_live_ranges().empty()); DCHECK(active_live_ranges().empty()); - DCHECK(inactive_live_ranges().empty()); + for (int reg = 0; reg < num_registers(); ++reg) { + DCHECK(inactive_live_ranges(reg).empty()); + } SplitAndSpillRangesDefinedByMemoryOperand(); data()->ResetSpillState(); @@ -3853,7 +3854,7 @@ void LinearScanAllocator::AllocateRegisters() { } if (!no_change_required) { - SpillNotLiveRanges(to_be_live, next_block_boundary, spill_mode); + SpillNotLiveRanges(&to_be_live, next_block_boundary, spill_mode); ReloadLiveRanges(to_be_live, next_block_boundary); } @@ -3941,9 +3942,10 @@ void LinearScanAllocator::AddToActive(LiveRange* range) { void LinearScanAllocator::AddToInactive(LiveRange* range) { TRACE("Add live range %d:%d to inactive\n", range->TopLevel()->vreg(), range->relative_id()); - inactive_live_ranges().push_back(range); next_inactive_ranges_change_ = std::min( next_inactive_ranges_change_, range->NextStartAfter(range->Start())); + DCHECK(range->HasRegisterAssigned()); + inactive_live_ranges(range->assigned_register()).insert(range); } void LinearScanAllocator::AddToUnhandled(LiveRange* range) { @@ -3966,30 +3968,36 @@ ZoneVector<LiveRange*>::iterator LinearScanAllocator::ActiveToHandled( ZoneVector<LiveRange*>::iterator LinearScanAllocator::ActiveToInactive( const ZoneVector<LiveRange*>::iterator it, LifetimePosition position) { LiveRange* range = *it; - inactive_live_ranges().push_back(range); TRACE("Moving live range %d:%d from active to inactive\n", (range)->TopLevel()->vreg(), range->relative_id()); + LifetimePosition next_active = range->NextStartAfter(position); next_inactive_ranges_change_ = - std::min(next_inactive_ranges_change_, range->NextStartAfter(position)); + std::min(next_inactive_ranges_change_, next_active); + DCHECK(range->HasRegisterAssigned()); + inactive_live_ranges(range->assigned_register()).insert(range); return active_live_ranges().erase(it); } -ZoneVector<LiveRange*>::iterator LinearScanAllocator::InactiveToHandled( - ZoneVector<LiveRange*>::iterator it) { +LinearScanAllocator::InactiveLiveRangeQueue::iterator +LinearScanAllocator::InactiveToHandled(InactiveLiveRangeQueue::iterator it) { + LiveRange* range = *it; TRACE("Moving live range %d:%d from inactive to handled\n", - (*it)->TopLevel()->vreg(), (*it)->relative_id()); - return inactive_live_ranges().erase(it); + range->TopLevel()->vreg(), range->relative_id()); + int reg = range->assigned_register(); + return inactive_live_ranges(reg).erase(it); } -ZoneVector<LiveRange*>::iterator LinearScanAllocator::InactiveToActive( - ZoneVector<LiveRange*>::iterator it, LifetimePosition position) { +LinearScanAllocator::InactiveLiveRangeQueue::iterator +LinearScanAllocator::InactiveToActive(InactiveLiveRangeQueue::iterator it, + LifetimePosition position) { LiveRange* range = *it; active_live_ranges().push_back(range); TRACE("Moving live range %d:%d from inactive to active\n", range->TopLevel()->vreg(), range->relative_id()); next_active_ranges_change_ = std::min(next_active_ranges_change_, range->NextEndAfter(position)); - return inactive_live_ranges().erase(it); + int reg = range->assigned_register(); + return inactive_live_ranges(reg).erase(it); } void LinearScanAllocator::ForwardStateTo(LifetimePosition position) { @@ -4012,18 +4020,25 @@ void LinearScanAllocator::ForwardStateTo(LifetimePosition position) { if (position >= next_inactive_ranges_change_) { next_inactive_ranges_change_ = LifetimePosition::MaxPosition(); - for (auto it = inactive_live_ranges().begin(); - it != inactive_live_ranges().end();) { - LiveRange* cur_inactive = *it; - if (cur_inactive->End() <= position) { - it = InactiveToHandled(it); - } else if (cur_inactive->Covers(position)) { - it = InactiveToActive(it, position); - } else { - next_inactive_ranges_change_ = - std::min(next_inactive_ranges_change_, - cur_inactive->NextStartAfter(position)); - ++it; + for (int reg = 0; reg < num_registers(); ++reg) { + ZoneVector<LiveRange*> reorder(data()->allocation_zone()); + for (auto it = inactive_live_ranges(reg).begin(); + it != inactive_live_ranges(reg).end();) { + LiveRange* cur_inactive = *it; + if (cur_inactive->End() <= position) { + it = InactiveToHandled(it); + } else if (cur_inactive->Covers(position)) { + it = InactiveToActive(it, position); + } else { + next_inactive_ranges_change_ = + std::min(next_inactive_ranges_change_, + cur_inactive->NextStartAfter(position)); + it = inactive_live_ranges(reg).erase(it); + reorder.push_back(cur_inactive); + } + } + for (LiveRange* range : reorder) { + inactive_live_ranges(reg).insert(range); } } } @@ -4094,31 +4109,34 @@ void LinearScanAllocator::FindFreeRegistersForRange( } } - for (LiveRange* cur_inactive : inactive_live_ranges()) { - DCHECK(cur_inactive->End() > range->Start()); - int cur_reg = cur_inactive->assigned_register(); - // No need to carry out intersections, when this register won't be - // interesting to this range anyway. - // TODO(mtrofin): extend to aliased ranges, too. - if ((kSimpleFPAliasing || !check_fp_aliasing()) && - positions[cur_reg] < range->Start()) { - continue; - } - - LifetimePosition next_intersection = cur_inactive->FirstIntersection(range); - if (!next_intersection.IsValid()) continue; - if (kSimpleFPAliasing || !check_fp_aliasing()) { - positions[cur_reg] = Min(positions[cur_reg], next_intersection); - TRACE("Register %s is free until pos %d (2)\n", RegisterName(cur_reg), - Min(positions[cur_reg], next_intersection).value()); - } else { - int alias_base_index = -1; - int aliases = data()->config()->GetAliases( - cur_inactive->representation(), cur_reg, rep, &alias_base_index); - DCHECK(aliases > 0 || (aliases == 0 && alias_base_index == -1)); - while (aliases--) { - int aliased_reg = alias_base_index + aliases; - positions[aliased_reg] = Min(positions[aliased_reg], next_intersection); + for (int cur_reg = 0; cur_reg < num_regs; ++cur_reg) { + for (LiveRange* cur_inactive : inactive_live_ranges(cur_reg)) { + DCHECK_GT(cur_inactive->End(), range->Start()); + CHECK_EQ(cur_inactive->assigned_register(), cur_reg); + // No need to carry out intersections, when this register won't be + // interesting to this range anyway. + // TODO(mtrofin): extend to aliased ranges, too. + if ((kSimpleFPAliasing || !check_fp_aliasing()) && + positions[cur_reg] <= cur_inactive->NextStart()) { + break; + } + LifetimePosition next_intersection = + cur_inactive->FirstIntersection(range); + if (!next_intersection.IsValid()) continue; + if (kSimpleFPAliasing || !check_fp_aliasing()) { + positions[cur_reg] = std::min(positions[cur_reg], next_intersection); + TRACE("Register %s is free until pos %d (2)\n", RegisterName(cur_reg), + positions[cur_reg].value()); + } else { + int alias_base_index = -1; + int aliases = data()->config()->GetAliases( + cur_inactive->representation(), cur_reg, rep, &alias_base_index); + DCHECK(aliases > 0 || (aliases == 0 && alias_base_index == -1)); + while (aliases--) { + int aliased_reg = alias_base_index + aliases; + positions[aliased_reg] = + std::min(positions[aliased_reg], next_intersection); + } } } } @@ -4337,46 +4355,46 @@ void LinearScanAllocator::AllocateBlockedReg(LiveRange* current, } } - for (LiveRange* range : inactive_live_ranges()) { - DCHECK(range->End() > current->Start()); - int cur_reg = range->assigned_register(); - bool is_fixed = range->TopLevel()->IsFixed(); - - // Don't perform costly intersections if they are guaranteed to not update - // block_pos or use_pos. - // TODO(mtrofin): extend to aliased ranges, too. - if ((kSimpleFPAliasing || !check_fp_aliasing())) { - if (is_fixed) { - if (block_pos[cur_reg] < range->Start()) continue; - } else { - if (use_pos[cur_reg] < range->Start()) continue; + for (int cur_reg = 0; cur_reg < num_registers(); ++cur_reg) { + for (LiveRange* range : inactive_live_ranges(cur_reg)) { + DCHECK(range->End() > current->Start()); + DCHECK_EQ(range->assigned_register(), cur_reg); + bool is_fixed = range->TopLevel()->IsFixed(); + + // Don't perform costly intersections if they are guaranteed to not update + // block_pos or use_pos. + // TODO(mtrofin): extend to aliased ranges, too. + if ((kSimpleFPAliasing || !check_fp_aliasing())) { + DCHECK_LE(use_pos[cur_reg], block_pos[cur_reg]); + if (block_pos[cur_reg] <= range->NextStart()) break; + if (!is_fixed && use_pos[cur_reg] <= range->NextStart()) continue; } - } - LifetimePosition next_intersection = range->FirstIntersection(current); - if (!next_intersection.IsValid()) continue; + LifetimePosition next_intersection = range->FirstIntersection(current); + if (!next_intersection.IsValid()) continue; - if (kSimpleFPAliasing || !check_fp_aliasing()) { - if (is_fixed) { - block_pos[cur_reg] = Min(block_pos[cur_reg], next_intersection); - use_pos[cur_reg] = Min(block_pos[cur_reg], use_pos[cur_reg]); - } else { - use_pos[cur_reg] = Min(use_pos[cur_reg], next_intersection); - } - } else { - int alias_base_index = -1; - int aliases = data()->config()->GetAliases( - range->representation(), cur_reg, rep, &alias_base_index); - DCHECK(aliases > 0 || (aliases == 0 && alias_base_index == -1)); - while (aliases--) { - int aliased_reg = alias_base_index + aliases; + if (kSimpleFPAliasing || !check_fp_aliasing()) { if (is_fixed) { - block_pos[aliased_reg] = - Min(block_pos[aliased_reg], next_intersection); - use_pos[aliased_reg] = - Min(block_pos[aliased_reg], use_pos[aliased_reg]); + block_pos[cur_reg] = Min(block_pos[cur_reg], next_intersection); + use_pos[cur_reg] = Min(block_pos[cur_reg], use_pos[cur_reg]); } else { - use_pos[aliased_reg] = Min(use_pos[aliased_reg], next_intersection); + use_pos[cur_reg] = Min(use_pos[cur_reg], next_intersection); + } + } else { + int alias_base_index = -1; + int aliases = data()->config()->GetAliases( + range->representation(), cur_reg, rep, &alias_base_index); + DCHECK(aliases > 0 || (aliases == 0 && alias_base_index == -1)); + while (aliases--) { + int aliased_reg = alias_base_index + aliases; + if (is_fixed) { + block_pos[aliased_reg] = + Min(block_pos[aliased_reg], next_intersection); + use_pos[aliased_reg] = + Min(block_pos[aliased_reg], use_pos[aliased_reg]); + } else { + use_pos[aliased_reg] = Min(use_pos[aliased_reg], next_intersection); + } } } } @@ -4490,40 +4508,38 @@ void LinearScanAllocator::SplitAndSpillIntersecting(LiveRange* current, it = ActiveToHandled(it); } - for (auto it = inactive_live_ranges().begin(); - it != inactive_live_ranges().end();) { - LiveRange* range = *it; - DCHECK(range->End() > current->Start()); - if (range->TopLevel()->IsFixed()) { - ++it; - continue; - } + for (int cur_reg = 0; cur_reg < num_registers(); ++cur_reg) { if (kSimpleFPAliasing || !check_fp_aliasing()) { - if (range->assigned_register() != reg) { + if (cur_reg != reg) continue; + } + for (auto it = inactive_live_ranges(cur_reg).begin(); + it != inactive_live_ranges(cur_reg).end();) { + LiveRange* range = *it; + if (!kSimpleFPAliasing && check_fp_aliasing() && + !data()->config()->AreAliases(current->representation(), reg, + range->representation(), cur_reg)) { ++it; continue; } - } else { - if (!data()->config()->AreAliases(current->representation(), reg, - range->representation(), - range->assigned_register())) { + DCHECK(range->End() > current->Start()); + if (range->TopLevel()->IsFixed()) { ++it; continue; } - } - LifetimePosition next_intersection = range->FirstIntersection(current); - if (next_intersection.IsValid()) { - UsePosition* next_pos = range->NextRegisterPosition(current->Start()); - if (next_pos == nullptr) { - SpillAfter(range, split_pos, spill_mode); + LifetimePosition next_intersection = range->FirstIntersection(current); + if (next_intersection.IsValid()) { + UsePosition* next_pos = range->NextRegisterPosition(current->Start()); + if (next_pos == nullptr) { + SpillAfter(range, split_pos, spill_mode); + } else { + next_intersection = Min(next_intersection, next_pos->pos()); + SpillBetween(range, split_pos, next_intersection, spill_mode); + } + it = InactiveToHandled(it); } else { - next_intersection = Min(next_intersection, next_pos->pos()); - SpillBetween(range, split_pos, next_intersection, spill_mode); + ++it; } - it = InactiveToHandled(it); - } else { - ++it; } } } |