Chromium Code Reviews| Index: src/compiler/register-allocator.cc |
| diff --git a/src/compiler/register-allocator.cc b/src/compiler/register-allocator.cc |
| index 5197b945fb8fc8e19cdb0597263712dec55e833d..d5d192aaeb6015732d8c712336356f2fde852bc0 100644 |
| --- a/src/compiler/register-allocator.cc |
| +++ b/src/compiler/register-allocator.cc |
| @@ -33,7 +33,7 @@ int GetRegisterCount(const RegisterConfiguration* cfg, RegisterKind kind) { |
| int GetAllocatableRegisterCount(const RegisterConfiguration* cfg, |
| RegisterKind kind) { |
| - return kind == FP_REGISTERS ? cfg->num_allocatable_aliased_double_registers() |
| + return kind == FP_REGISTERS ? cfg->num_allocatable_double_registers() |
| : cfg->num_allocatable_general_registers(); |
| } |
| @@ -74,19 +74,13 @@ int GetByteWidth(MachineRepresentation rep) { |
| case MachineRepresentation::kTaggedSigned: |
| case MachineRepresentation::kTaggedPointer: |
| case MachineRepresentation::kTagged: |
| - return kPointerSize; |
| case MachineRepresentation::kFloat32: |
| -// TODO(bbudge) Eliminate this when FP register aliasing works. |
| -#if V8_TARGET_ARCH_ARM |
| - return kDoubleSize; |
| -#else |
| return kPointerSize; |
| -#endif |
| case MachineRepresentation::kWord64: |
| case MachineRepresentation::kFloat64: |
| - return kDoubleSize; |
| + return 8; |
|
Mircea Trofin
2016/10/12 21:09:26
here and below, don't we have a constant somewhere
bbudge
2016/10/12 23:07:18
Indeed. Done.
|
| case MachineRepresentation::kSimd128: |
| - return kSimd128Size; |
| + return 16; |
| case MachineRepresentation::kNone: |
| break; |
| } |
| @@ -1360,8 +1354,12 @@ RegisterAllocationData::RegisterAllocationData( |
| allocation_zone()), |
| fixed_live_ranges_(this->config()->num_general_registers(), nullptr, |
| allocation_zone()), |
| + fixed_float_live_ranges_(this->config()->num_float_registers(), nullptr, |
| + allocation_zone()), |
| fixed_double_live_ranges_(this->config()->num_double_registers(), nullptr, |
| allocation_zone()), |
| + fixed_simd128_live_ranges_(this->config()->num_simd128_registers(), |
| + nullptr, allocation_zone()), |
| spill_ranges_(code->VirtualRegisterCount(), nullptr, allocation_zone()), |
| delayed_references_(allocation_zone()), |
| assigned_registers_(nullptr), |
| @@ -1539,8 +1537,21 @@ void RegisterAllocationData::MarkAllocated(MachineRepresentation rep, |
| int index) { |
| switch (rep) { |
| case MachineRepresentation::kFloat32: |
| - case MachineRepresentation::kFloat64: |
| case MachineRepresentation::kSimd128: |
| + if (kSimpleFPAliasing) { |
| + assigned_double_registers_->Add(index); |
| + } else { |
| + int alias_base_index = -1; |
| + int aliases = config()->GetAliases( |
| + rep, index, MachineRepresentation::kFloat64, &alias_base_index); |
| + DCHECK(aliases > 0 || (aliases == 0 && alias_base_index == -1)); |
| + while (aliases--) { |
| + int aliased_reg = alias_base_index + aliases; |
| + assigned_double_registers_->Add(aliased_reg); |
| + } |
| + } |
| + break; |
| + case MachineRepresentation::kFloat64: |
| assigned_double_registers_->Add(index); |
| break; |
| default: |
| @@ -1867,7 +1878,11 @@ int LiveRangeBuilder::FixedFPLiveRangeID(int index, MachineRepresentation rep) { |
| int result = -index - 1; |
| switch (rep) { |
| case MachineRepresentation::kSimd128: |
| + result -= config()->num_float_registers(); |
| + // Fall through. |
| case MachineRepresentation::kFloat32: |
| + result -= config()->num_double_registers(); |
| + // Fall through. |
| case MachineRepresentation::kFloat64: |
| result -= config()->num_general_registers(); |
| break; |
| @@ -1894,25 +1909,35 @@ TopLevelLiveRange* LiveRangeBuilder::FixedLiveRangeFor(int index) { |
| TopLevelLiveRange* LiveRangeBuilder::FixedFPLiveRangeFor( |
| int index, MachineRepresentation rep) { |
| - TopLevelLiveRange* result = nullptr; |
| + int num_regs = -1; |
| + ZoneVector<TopLevelLiveRange*>* live_ranges = nullptr; |
| switch (rep) { |
| case MachineRepresentation::kFloat32: |
| + num_regs = config()->num_float_registers(); |
| + live_ranges = &data()->fixed_float_live_ranges(); |
| + break; |
| case MachineRepresentation::kFloat64: |
| + num_regs = config()->num_double_registers(); |
| + live_ranges = &data()->fixed_double_live_ranges(); |
| + break; |
| case MachineRepresentation::kSimd128: |
| - DCHECK(index < config()->num_double_registers()); |
| - result = data()->fixed_double_live_ranges()[index]; |
| - if (result == nullptr) { |
| - result = data()->NewLiveRange(FixedFPLiveRangeID(index, rep), rep); |
| - DCHECK(result->IsFixed()); |
| - result->set_assigned_register(index); |
| - data()->MarkAllocated(rep, index); |
| - data()->fixed_double_live_ranges()[index] = result; |
| - } |
| + num_regs = config()->num_simd128_registers(); |
| + live_ranges = &data()->fixed_simd128_live_ranges(); |
| break; |
| default: |
| UNREACHABLE(); |
| break; |
| } |
| + |
| + DCHECK(index < num_regs); |
| + TopLevelLiveRange* result = (*live_ranges)[index]; |
| + if (result == nullptr) { |
| + result = data()->NewLiveRange(FixedFPLiveRangeID(index, rep), rep); |
| + DCHECK(result->IsFixed()); |
| + result->set_assigned_register(index); |
| + data()->MarkAllocated(rep, index); |
| + (*live_ranges)[index] = result; |
| + } |
| return result; |
| } |
| @@ -2035,8 +2060,7 @@ void LiveRangeBuilder::ProcessInstructions(const InstructionBlock* block, |
| } |
| if (instr->ClobbersDoubleRegisters()) { |
| - for (int i = 0; i < config()->num_allocatable_aliased_double_registers(); |
| - ++i) { |
| + for (int i = 0; i < config()->num_allocatable_double_registers(); ++i) { |
| // Add a UseInterval for all DoubleRegisters. See comment above for |
| // general registers. |
| int code = config()->GetAllocatableDoubleCode(i); |
| @@ -2045,6 +2069,26 @@ void LiveRangeBuilder::ProcessInstructions(const InstructionBlock* block, |
| range->AddUseInterval(curr_position, curr_position.End(), |
| allocation_zone()); |
| } |
| + // Preserve fixed float registers on archs with non-simple aliasing. |
| + if (!kSimpleFPAliasing) { |
| + for (int i = 0; i < config()->num_allocatable_float_registers(); ++i) { |
| + // Add a UseInterval for all FloatRegisters. See comment above for |
| + // general registers. |
| + int code = config()->GetAllocatableFloatCode(i); |
| + TopLevelLiveRange* range = |
| + FixedFPLiveRangeFor(code, MachineRepresentation::kFloat32); |
| + range->AddUseInterval(curr_position, curr_position.End(), |
| + allocation_zone()); |
| + } |
| + for (int i = 0; i < config()->num_allocatable_simd128_registers(); |
| + ++i) { |
| + int code = config()->GetAllocatableSimd128Code(i); |
| + TopLevelLiveRange* range = |
| + FixedFPLiveRangeFor(code, MachineRepresentation::kSimd128); |
| + range->AddUseInterval(curr_position, curr_position.End(), |
| + allocation_zone()); |
| + } |
| + } |
| } |
| for (size_t i = 0; i < instr->InputCount(); i++) { |
| @@ -2611,9 +2655,15 @@ void LinearScanAllocator::AllocateRegisters() { |
| if (current != nullptr) AddToInactive(current); |
| } |
| } else { |
| + for (TopLevelLiveRange* current : data()->fixed_float_live_ranges()) { |
| + if (current != nullptr) AddToInactive(current); |
| + } |
| for (TopLevelLiveRange* current : data()->fixed_double_live_ranges()) { |
| if (current != nullptr) AddToInactive(current); |
| } |
| + for (TopLevelLiveRange* current : data()->fixed_simd128_live_ranges()) { |
| + if (current != nullptr) AddToInactive(current); |
| + } |
| } |
| while (!unhandled_live_ranges().empty()) { |
| @@ -2794,7 +2844,21 @@ void LinearScanAllocator::InactiveToActive(LiveRange* range) { |
| void LinearScanAllocator::FindFreeRegistersForRange( |
| LiveRange* range, Vector<LifetimePosition> positions) { |
| + MachineRepresentation rep = range->representation(); |
| int num_regs = num_registers(); |
| + int num_codes = num_allocatable_registers(); |
| + const int* codes = allocatable_register_codes(); |
| + if (!kSimpleFPAliasing) { |
| + if (rep == MachineRepresentation::kFloat32) { |
| + num_regs = data()->config()->num_float_registers(); |
| + num_codes = data()->config()->num_allocatable_float_registers(); |
| + codes = data()->config()->allocatable_float_codes(); |
|
Mircea Trofin
2016/10/12 21:09:26
would it make sense to move this logic to num_regi
bbudge
2016/10/12 23:07:17
I'd like to avoid the procedure call for non-ARM a
|
| + } else if (rep == MachineRepresentation::kSimd128) { |
| + num_regs = data()->config()->num_simd128_registers(); |
| + num_codes = data()->config()->num_allocatable_simd128_registers(); |
| + codes = data()->config()->allocatable_simd128_codes(); |
| + } |
| + } |
| DCHECK_GE(positions.length(), num_regs); |
| for (int i = 0; i < num_regs; i++) { |
| @@ -2803,9 +2867,20 @@ void LinearScanAllocator::FindFreeRegistersForRange( |
| for (LiveRange* cur_active : active_live_ranges()) { |
| int cur_reg = cur_active->assigned_register(); |
| - positions[cur_reg] = LifetimePosition::GapFromInstructionIndex(0); |
| - TRACE("Register %s is free until pos %d (1)\n", RegisterName(cur_reg), |
| - LifetimePosition::GapFromInstructionIndex(0).value()); |
| + if (kSimpleFPAliasing || mode() == GENERAL_REGISTERS) { |
| + positions[cur_reg] = LifetimePosition::GapFromInstructionIndex(0); |
| + TRACE("Register %s is free until pos %d (1)\n", RegisterName(cur_reg), |
| + LifetimePosition::GapFromInstructionIndex(0).value()); |
| + } else { |
| + int alias_base_index = -1; |
| + int aliases = data()->config()->GetAliases( |
| + cur_active->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] = LifetimePosition::GapFromInstructionIndex(0); |
| + } |
| + } |
| } |
| for (LiveRange* cur_inactive : inactive_live_ranges()) { |
| @@ -2813,9 +2888,20 @@ void LinearScanAllocator::FindFreeRegistersForRange( |
| LifetimePosition next_intersection = cur_inactive->FirstIntersection(range); |
| if (!next_intersection.IsValid()) continue; |
| int cur_reg = cur_inactive->assigned_register(); |
| - 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()); |
| + if (kSimpleFPAliasing || mode() == GENERAL_REGISTERS) { |
| + 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); |
| + } |
| + } |
| } |
| } |
| @@ -2896,8 +2982,18 @@ bool LinearScanAllocator::TryAllocatePreferredReg( |
| bool LinearScanAllocator::TryAllocateFreeReg( |
| LiveRange* current, const Vector<LifetimePosition>& free_until_pos) { |
| + MachineRepresentation rep = current->representation(); |
| int num_codes = num_allocatable_registers(); |
| const int* codes = allocatable_register_codes(); |
| + if (!kSimpleFPAliasing) { |
| + if (rep == MachineRepresentation::kFloat32) { |
| + num_codes = data()->config()->num_allocatable_float_registers(); |
| + codes = data()->config()->allocatable_float_codes(); |
| + } else if (rep == MachineRepresentation::kSimd128) { |
| + num_codes = data()->config()->num_allocatable_simd128_registers(); |
| + codes = data()->config()->allocatable_simd128_codes(); |
|
Mircea Trofin
2016/10/12 21:09:26
see factoring comment above about the num_allocata
bbudge
2016/10/12 23:07:18
Done.
|
| + } |
| + } |
| DCHECK_GE(free_until_pos.length(), num_codes); |
| // Find the register which stays free for the longest time. |
| @@ -2942,9 +3038,21 @@ void LinearScanAllocator::AllocateBlockedReg(LiveRange* current) { |
| return; |
| } |
| + MachineRepresentation rep = current->representation(); |
| int num_regs = num_registers(); |
| int num_codes = num_allocatable_registers(); |
| const int* codes = allocatable_register_codes(); |
| + if (!kSimpleFPAliasing) { |
| + if (rep == MachineRepresentation::kFloat32) { |
| + num_regs = data()->config()->num_float_registers(); |
| + num_codes = data()->config()->num_allocatable_float_registers(); |
| + codes = data()->config()->allocatable_float_codes(); |
| + } else if (rep == MachineRepresentation::kSimd128) { |
| + num_regs = data()->config()->num_simd128_registers(); |
| + num_codes = data()->config()->num_allocatable_simd128_registers(); |
| + codes = data()->config()->allocatable_simd128_codes(); |
|
Mircea Trofin
2016/10/12 21:09:26
factoring comment above
bbudge
2016/10/12 23:07:17
Done.
|
| + } |
| + } |
| LifetimePosition use_pos[RegisterConfiguration::kMaxFPRegisters]; |
| LifetimePosition block_pos[RegisterConfiguration::kMaxFPRegisters]; |
| @@ -2956,16 +3064,38 @@ void LinearScanAllocator::AllocateBlockedReg(LiveRange* current) { |
| int cur_reg = range->assigned_register(); |
| bool is_fixed_or_cant_spill = |
| range->TopLevel()->IsFixed() || !range->CanBeSpilled(current->Start()); |
| - if (is_fixed_or_cant_spill) { |
| - block_pos[cur_reg] = use_pos[cur_reg] = |
| - LifetimePosition::GapFromInstructionIndex(0); |
| - } else { |
| - UsePosition* next_use = |
| - range->NextUsePositionRegisterIsBeneficial(current->Start()); |
| - if (next_use == nullptr) { |
| - use_pos[cur_reg] = range->End(); |
| + if (kSimpleFPAliasing || mode() == GENERAL_REGISTERS) { |
| + if (is_fixed_or_cant_spill) { |
| + block_pos[cur_reg] = use_pos[cur_reg] = |
| + LifetimePosition::GapFromInstructionIndex(0); |
| } else { |
| - use_pos[cur_reg] = next_use->pos(); |
| + UsePosition* next_use = |
| + range->NextUsePositionRegisterIsBeneficial(current->Start()); |
| + if (next_use == nullptr) { |
| + use_pos[cur_reg] = range->End(); |
|
Mircea Trofin
2016/10/12 21:09:26
this logic around next_use appears below, too. Cou
bbudge
2016/10/12 23:07:17
I added a LiveRange;:NextLifetimePositionRegisterI
|
| + } else { |
| + use_pos[cur_reg] = next_use->pos(); |
| + } |
| + } |
| + } 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_or_cant_spill) { |
| + block_pos[aliased_reg] = use_pos[aliased_reg] = |
| + LifetimePosition::GapFromInstructionIndex(0); |
| + } else { |
| + UsePosition* next_use = |
| + range->NextUsePositionRegisterIsBeneficial(current->Start()); |
| + if (next_use == nullptr) { |
| + use_pos[aliased_reg] = range->End(); |
| + } else { |
| + use_pos[aliased_reg] = next_use->pos(); |
| + } |
| + } |
| } |
| } |
| } |
| @@ -2976,11 +3106,29 @@ void LinearScanAllocator::AllocateBlockedReg(LiveRange* current) { |
| if (!next_intersection.IsValid()) continue; |
| int cur_reg = range->assigned_register(); |
| bool is_fixed = range->TopLevel()->IsFixed(); |
| - 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]); |
| + if (kSimpleFPAliasing || mode() == GENERAL_REGISTERS) { |
| + 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 { |
| - use_pos[cur_reg] = Min(use_pos[cur_reg], next_intersection); |
| + 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); |
| + } |
| + } |
| } |
| } |
| @@ -3032,7 +3180,15 @@ void LinearScanAllocator::SplitAndSpillIntersecting(LiveRange* current) { |
| LifetimePosition split_pos = current->Start(); |
| for (size_t i = 0; i < active_live_ranges().size(); ++i) { |
| LiveRange* range = active_live_ranges()[i]; |
| - if (range->assigned_register() != reg) continue; |
| + if (kSimpleFPAliasing || mode() == GENERAL_REGISTERS) { |
| + if (range->assigned_register() != reg) continue; |
| + } else { |
| + if (!data()->config()->AreAliases(current->representation(), reg, |
| + range->representation(), |
| + range->assigned_register())) { |
| + continue; |
| + } |
| + } |
| UsePosition* next_pos = range->NextRegisterPosition(current->Start()); |
| LifetimePosition spill_pos = FindOptimalSpillingPos(range, split_pos); |
| @@ -3059,7 +3215,14 @@ void LinearScanAllocator::SplitAndSpillIntersecting(LiveRange* current) { |
| LiveRange* range = inactive_live_ranges()[i]; |
| DCHECK(range->End() > current->Start()); |
| if (range->TopLevel()->IsFixed()) continue; |
| - if (range->assigned_register() != reg) continue; |
| + if (kSimpleFPAliasing || mode() == GENERAL_REGISTERS) { |
| + if (range->assigned_register() != reg) continue; |
| + } else { |
| + if (!data()->config()->AreAliases(current->representation(), reg, |
| + range->representation(), |
| + range->assigned_register())) |
| + continue; |
| + } |
| LifetimePosition next_intersection = range->FirstIntersection(current); |
| if (next_intersection.IsValid()) { |
| @@ -3550,7 +3713,6 @@ int LiveRangeConnector::ResolveControlFlow(const InstructionBlock* block, |
| return gap_index; |
| } |
| - |
| void LiveRangeConnector::ConnectRanges(Zone* local_zone) { |
| DelayedInsertionMap delayed_insertion_map(local_zone); |
| for (TopLevelLiveRange* top_range : data()->live_ranges()) { |
| @@ -3638,9 +3800,8 @@ void LiveRangeConnector::ConnectRanges(Zone* local_zone) { |
| // Gather all MoveOperands for a single ParallelMove. |
| MoveOperands* move = |
| new (code_zone()) MoveOperands(it->first.second, it->second); |
| - MoveOperands* eliminate = moves->PrepareInsertAfter(move); |
| + moves->PrepareInsertAfter(move, &to_eliminate); |
| to_insert.push_back(move); |
| - if (eliminate != nullptr) to_eliminate.push_back(eliminate); |
| } |
| } |