Index: src/compiler/register-allocator.cc |
diff --git a/src/compiler/register-allocator.cc b/src/compiler/register-allocator.cc |
index 283603a44e1728e6a9c8ae82b79fa053415a5c73..3e1ac629417d6f5c8a66ccd425fc5f323df8730c 100644 |
--- a/src/compiler/register-allocator.cc |
+++ b/src/compiler/register-allocator.cc |
@@ -100,6 +100,8 @@ bool LiveRange::HasOverlap(UseInterval* target) const { |
LiveRange::LiveRange(int id, Zone* zone) |
: id_(id), |
spilled_(false), |
+ is_phi_(false), |
+ is_non_loop_phi_(false), |
kind_(UNALLOCATED_REGISTERS), |
assigned_register_(kInvalidAssignment), |
last_interval_(NULL), |
@@ -1163,12 +1165,20 @@ void RegisterAllocator::ProcessInstructions(const InstructionBlock* block, |
InstructionOperand* hint = to; |
if (to->IsUnallocated()) { |
int to_vreg = UnallocatedOperand::cast(to)->virtual_register(); |
- if (live->Contains(to_vreg)) { |
- Define(curr_position, to, from); |
- live->Remove(to_vreg); |
+ LiveRange* to_range = LiveRangeFor(to_vreg); |
+ if (to_range->is_phi()) { |
+ DCHECK(!FLAG_turbo_delay_ssa_decon); |
+ if (to_range->is_non_loop_phi()) { |
+ hint = to_range->current_hint_operand(); |
+ } |
} else { |
- cur->Eliminate(); |
- continue; |
+ if (live->Contains(to_vreg)) { |
+ Define(curr_position, to, from); |
+ live->Remove(to_vreg); |
+ } else { |
+ cur->Eliminate(); |
+ continue; |
+ } |
} |
} else { |
Define(curr_position, to, from); |
@@ -1248,28 +1258,53 @@ void RegisterAllocator::ProcessInstructions(const InstructionBlock* block, |
} |
-void RegisterAllocator::ProcessPhis(const InstructionBlock* block) { |
+void RegisterAllocator::ResolvePhis(const InstructionBlock* block) { |
for (auto phi : block->phis()) { |
auto output = phi->output(); |
int phi_vreg = phi->virtual_register(); |
+ if (!FLAG_turbo_delay_ssa_decon) { |
+ for (size_t i = 0; i < phi->operands().size(); ++i) { |
+ InstructionBlock* cur_block = |
+ code()->InstructionBlockAt(block->predecessors()[i]); |
+ // The gap move must be added without any special processing as in |
+ // the AddConstraintsGapMove. |
+ code()->AddGapMove(cur_block->last_instruction_index() - 1, |
+ phi->inputs()[i], output); |
+ DCHECK(!InstructionAt(cur_block->last_instruction_index()) |
+ ->HasPointerMap()); |
+ } |
+ } |
LiveRange* live_range = LiveRangeFor(phi_vreg); |
BlockStartInstruction* block_start = |
code()->GetBlockStart(block->rpo_number()); |
block_start->GetOrCreateParallelMove(GapInstruction::BEFORE, code_zone()) |
->AddMove(output, live_range->GetSpillOperand(), code_zone()); |
live_range->SetSpillStartIndex(block->first_instruction_index()); |
+ // We use the phi-ness of some nodes in some later heuristics. |
+ live_range->set_is_phi(true); |
+ if (!block->IsLoopHeader()) { |
+ live_range->set_is_non_loop_phi(true); |
+ } |
} |
} |
void RegisterAllocator::MeetRegisterConstraints() { |
for (auto block : code()->instruction_blocks()) { |
- ProcessPhis(block); |
MeetRegisterConstraints(block); |
} |
} |
+void RegisterAllocator::ResolvePhis() { |
+ // Process the blocks in reverse order. |
+ for (auto i = code()->instruction_blocks().rbegin(); |
+ i != code()->instruction_blocks().rend(); ++i) { |
+ ResolvePhis(*i); |
+ } |
+} |
+ |
+ |
ParallelMove* RegisterAllocator::GetConnectingParallelMove( |
LifetimePosition pos) { |
int index = pos.InstructionIndex(); |
@@ -1474,21 +1509,24 @@ void RegisterAllocator::ResolveControlFlow() { |
LiveRangeFinder finder(*this); |
for (auto block : code()->instruction_blocks()) { |
if (CanEagerlyResolveControlFlow(block)) continue; |
- // resolve phis |
- for (auto phi : block->phis()) { |
- auto* block_bound = |
- finder.ArrayFor(phi->virtual_register())->FindSucc(block); |
- auto phi_output = block_bound->range_->CreateAssignedOperand(code_zone()); |
- 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()); |
- phi->inputs()[pred_index] = pred_op; |
- ResolveControlFlow(block, phi_output, pred_block, pred_op); |
- pred_index++; |
+ if (FLAG_turbo_delay_ssa_decon) { |
+ // resolve phis |
+ for (auto phi : block->phis()) { |
+ auto* block_bound = |
+ finder.ArrayFor(phi->virtual_register())->FindSucc(block); |
+ auto phi_output = |
+ block_bound->range_->CreateAssignedOperand(code_zone()); |
+ 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()); |
+ phi->inputs()[pred_index] = pred_op; |
+ ResolveControlFlow(block, phi_output, pred_block, pred_op); |
+ pred_index++; |
+ } |
} |
} |
BitVector* live = live_in_sets_[block->rpo_number().ToInt()]; |
@@ -1556,6 +1594,27 @@ void RegisterAllocator::BuildLiveRanges() { |
// block. |
int phi_vreg = phi->virtual_register(); |
live->Remove(phi_vreg); |
+ if (!FLAG_turbo_delay_ssa_decon) { |
+ InstructionOperand* hint = NULL; |
+ InstructionOperand* phi_operand = NULL; |
+ GapInstruction* gap = |
+ GetLastGap(code()->InstructionBlockAt(block->predecessors()[0])); |
+ ParallelMove* move = |
+ gap->GetOrCreateParallelMove(GapInstruction::START, code_zone()); |
+ for (int j = 0; j < move->move_operands()->length(); ++j) { |
+ InstructionOperand* to = move->move_operands()->at(j).destination(); |
+ if (to->IsUnallocated() && |
+ UnallocatedOperand::cast(to)->virtual_register() == phi_vreg) { |
+ hint = move->move_operands()->at(j).source(); |
+ phi_operand = to; |
+ break; |
+ } |
+ } |
+ DCHECK(hint != NULL); |
+ LifetimePosition block_start = LifetimePosition::FromInstructionIndex( |
+ block->first_instruction_index()); |
+ Define(block_start, phi_operand, hint); |
+ } |
} |
// Now live is live_in for this block except not including values live |
@@ -1600,7 +1659,13 @@ void RegisterAllocator::BuildLiveRanges() { |
for (UsePosition* pos = range->first_pos(); pos != NULL; |
pos = pos->next_) { |
pos->register_beneficial_ = true; |
- pos->requires_reg_ = true; |
+ // TODO(dcarney): should the else case assert requires_reg_ == false? |
+ // Can't mark phis as needing a register. |
+ if (!code() |
+ ->InstructionAt(pos->pos().InstructionIndex()) |
+ ->IsGapMoves()) { |
+ pos->requires_reg_ = true; |
+ } |
} |
} |
} |