| Index: src/compiler/register-allocator.cc
|
| diff --git a/src/compiler/register-allocator.cc b/src/compiler/register-allocator.cc
|
| index 7a72b9fd17b486835519930fa283fe9aa28e9952..38efdd4492da70dbb14e2f867e0e95d93481e03c 100644
|
| --- a/src/compiler/register-allocator.cc
|
| +++ b/src/compiler/register-allocator.cc
|
| @@ -135,11 +135,12 @@ LiveRange::LiveRange(int id, Zone* zone)
|
| spills_at_definition_(nullptr) {}
|
|
|
|
|
| -void LiveRange::set_assigned_register(int reg, Zone* zone) {
|
| +void LiveRange::set_assigned_register(int reg,
|
| + InstructionOperandCache* operand_cache) {
|
| DCHECK(!HasRegisterAssigned() && !IsSpilled());
|
| assigned_register_ = reg;
|
| // TODO(dcarney): stop aliasing hint operands.
|
| - ConvertUsesToOperand(CreateAssignedOperand(zone));
|
| + ConvertUsesToOperand(GetAssignedOperand(operand_cache));
|
| }
|
|
|
|
|
| @@ -250,30 +251,47 @@ bool LiveRange::CanBeSpilled(LifetimePosition pos) {
|
| }
|
|
|
|
|
| -InstructionOperand* LiveRange::CreateAssignedOperand(Zone* zone) const {
|
| - InstructionOperand* op = nullptr;
|
| +InstructionOperand* LiveRange::GetAssignedOperand(
|
| + InstructionOperandCache* cache) const {
|
| if (HasRegisterAssigned()) {
|
| DCHECK(!IsSpilled());
|
| switch (Kind()) {
|
| case GENERAL_REGISTERS:
|
| - op = RegisterOperand::Create(assigned_register(), zone);
|
| - break;
|
| + return cache->RegisterOperand(assigned_register());
|
| case DOUBLE_REGISTERS:
|
| - op = DoubleRegisterOperand::Create(assigned_register(), zone);
|
| - break;
|
| + return cache->DoubleRegisterOperand(assigned_register());
|
| default:
|
| UNREACHABLE();
|
| }
|
| - } else {
|
| - DCHECK(IsSpilled());
|
| - DCHECK(!HasRegisterAssigned());
|
| - op = TopLevel()->GetSpillOperand();
|
| - DCHECK(!op->IsUnallocated());
|
| }
|
| + DCHECK(IsSpilled());
|
| + DCHECK(!HasRegisterAssigned());
|
| + auto op = TopLevel()->GetSpillOperand();
|
| + DCHECK(!op->IsUnallocated());
|
| return op;
|
| }
|
|
|
|
|
| +InstructionOperand LiveRange::GetAssignedOperand() const {
|
| + if (HasRegisterAssigned()) {
|
| + DCHECK(!IsSpilled());
|
| + switch (Kind()) {
|
| + case GENERAL_REGISTERS:
|
| + return RegisterOperand(assigned_register());
|
| + case DOUBLE_REGISTERS:
|
| + return DoubleRegisterOperand(assigned_register());
|
| + default:
|
| + UNREACHABLE();
|
| + }
|
| + }
|
| + DCHECK(IsSpilled());
|
| + DCHECK(!HasRegisterAssigned());
|
| + auto op = TopLevel()->GetSpillOperand();
|
| + DCHECK(!op->IsUnallocated());
|
| + return *op;
|
| +}
|
| +
|
| +
|
| UseInterval* LiveRange::FirstSearchIntervalForPosition(
|
| LifetimePosition position) const {
|
| if (current_interval_ == nullptr) return first_interval_;
|
| @@ -553,6 +571,18 @@ LifetimePosition LiveRange::FirstIntersection(LiveRange* other) {
|
| }
|
|
|
|
|
| +InstructionOperandCache::InstructionOperandCache() {
|
| + for (size_t i = 0; i < arraysize(general_register_operands_); ++i) {
|
| + general_register_operands_[i] =
|
| + i::compiler::RegisterOperand(static_cast<int>(i));
|
| + }
|
| + for (size_t i = 0; i < arraysize(double_register_operands_); ++i) {
|
| + double_register_operands_[i] =
|
| + i::compiler::DoubleRegisterOperand(static_cast<int>(i));
|
| + }
|
| +}
|
| +
|
| +
|
| RegisterAllocator::RegisterAllocator(const RegisterConfiguration* config,
|
| Zone* zone, Frame* frame,
|
| InstructionSequence* code,
|
| @@ -562,6 +592,7 @@ RegisterAllocator::RegisterAllocator(const RegisterConfiguration* config,
|
| code_(code),
|
| debug_name_(debug_name),
|
| config_(config),
|
| + operand_cache_(new (code_zone()) InstructionOperandCache()),
|
| phi_map_(PhiMap::key_compare(), PhiMap::allocator_type(local_zone())),
|
| live_in_sets_(code->InstructionBlockCount(), nullptr, local_zone()),
|
| live_ranges_(code->VirtualRegisterCount() * 2, nullptr, local_zone()),
|
| @@ -572,7 +603,6 @@ RegisterAllocator::RegisterAllocator(const RegisterConfiguration* config,
|
| unhandled_live_ranges_(local_zone()),
|
| active_live_ranges_(local_zone()),
|
| inactive_live_ranges_(local_zone()),
|
| - reusable_slots_(local_zone()),
|
| spill_ranges_(local_zone()),
|
| mode_(UNALLOCATED_REGISTERS),
|
| num_registers_(-1) {
|
| @@ -588,7 +618,6 @@ RegisterAllocator::RegisterAllocator(const RegisterConfiguration* config,
|
| static_cast<size_t>(code->VirtualRegisterCount() * 2));
|
| active_live_ranges().reserve(8);
|
| inactive_live_ranges().reserve(8);
|
| - reusable_slots().reserve(8);
|
| spill_ranges().reserve(8);
|
| assigned_registers_ =
|
| new (code_zone()) BitVector(config->num_general_registers(), code_zone());
|
| @@ -930,7 +959,7 @@ void RegisterAllocator::CommitAssignment() {
|
| if (range == nullptr || range->IsEmpty()) continue;
|
| // Register assignments were committed in set_assigned_register.
|
| if (range->HasRegisterAssigned()) continue;
|
| - auto assigned = range->CreateAssignedOperand(code_zone());
|
| + auto assigned = range->GetAssignedOperand(operand_cache());
|
| range->ConvertUsesToOperand(assigned);
|
| if (range->IsSpilled()) {
|
| range->CommitSpillsAtDefinition(code(), assigned);
|
| @@ -1425,8 +1454,10 @@ void RegisterAllocator::ConnectRanges() {
|
| }
|
| if (should_insert) {
|
| auto move = GetConnectingParallelMove(pos);
|
| - auto prev_operand = first_range->CreateAssignedOperand(code_zone());
|
| - auto cur_operand = second_range->CreateAssignedOperand(code_zone());
|
| + auto prev_operand =
|
| + first_range->GetAssignedOperand(operand_cache());
|
| + auto cur_operand =
|
| + second_range->GetAssignedOperand(operand_cache());
|
| move->AddMove(prev_operand, cur_operand, code_zone());
|
| }
|
| }
|
| @@ -1590,14 +1621,15 @@ void RegisterAllocator::ResolveControlFlow() {
|
| auto* block_bound =
|
| finder.ArrayFor(phi->virtual_register())->FindSucc(block);
|
| auto phi_output =
|
| - block_bound->range_->CreateAssignedOperand(code_zone());
|
| + block_bound->range_->GetAssignedOperand(operand_cache());
|
| phi->output()->ConvertTo(phi_output->kind(), phi_output->index());
|
| size_t pred_index = 0;
|
| for (auto pred : block->predecessors()) {
|
| const InstructionBlock* pred_block = code()->InstructionBlockAt(pred);
|
| auto* pred_bound = finder.ArrayFor(phi->operands()[pred_index])
|
| ->FindPred(pred_block);
|
| - auto pred_op = pred_bound->range_->CreateAssignedOperand(code_zone());
|
| + auto pred_op =
|
| + pred_bound->range_->GetAssignedOperand(operand_cache());
|
| phi->inputs()[pred_index] = pred_op;
|
| ResolveControlFlow(block, phi_output, pred_block, pred_op);
|
| pred_index++;
|
| @@ -1615,8 +1647,8 @@ void RegisterAllocator::ResolveControlFlow() {
|
| if (result.cur_cover_ == result.pred_cover_ ||
|
| result.cur_cover_->IsSpilled())
|
| continue;
|
| - auto pred_op = result.pred_cover_->CreateAssignedOperand(code_zone());
|
| - auto cur_op = result.cur_cover_->CreateAssignedOperand(code_zone());
|
| + auto pred_op = result.pred_cover_->GetAssignedOperand(operand_cache());
|
| + auto cur_op = result.cur_cover_->GetAssignedOperand(operand_cache());
|
| ResolveControlFlow(block, cur_op, pred_block, pred_op);
|
| }
|
| iterator.Advance();
|
| @@ -1838,7 +1870,7 @@ void RegisterAllocator::PopulatePointerMaps() {
|
| "Pointer in register for range %d (start at %d) "
|
| "at safe point %d\n",
|
| cur->id(), cur->Start().Value(), safe_point);
|
| - InstructionOperand* operand = cur->CreateAssignedOperand(code_zone());
|
| + InstructionOperand* operand = cur->GetAssignedOperand(operand_cache());
|
| DCHECK(!operand->IsStackSlot());
|
| map->RecordPointer(operand, code_zone());
|
| }
|
| @@ -1873,7 +1905,6 @@ void RegisterAllocator::AllocateRegisters() {
|
| SortUnhandled();
|
| DCHECK(UnhandledIsSorted());
|
|
|
| - DCHECK(reusable_slots().empty());
|
| DCHECK(active_live_ranges().empty());
|
| DCHECK(inactive_live_ranges().empty());
|
|
|
| @@ -1960,7 +1991,6 @@ void RegisterAllocator::AllocateRegisters() {
|
| }
|
| }
|
|
|
| - reusable_slots().clear();
|
| active_live_ranges().clear();
|
| inactive_live_ranges().clear();
|
| }
|
| @@ -2475,7 +2505,7 @@ void RegisterAllocator::SetLiveRangeAssignedRegister(LiveRange* range,
|
| DCHECK(range->Kind() == GENERAL_REGISTERS);
|
| assigned_registers_->Add(reg);
|
| }
|
| - range->set_assigned_register(reg, code_zone());
|
| + range->set_assigned_register(reg, operand_cache());
|
| }
|
|
|
| } // namespace compiler
|
|
|