Index: runtime/vm/flow_graph_allocator.cc |
diff --git a/runtime/vm/flow_graph_allocator.cc b/runtime/vm/flow_graph_allocator.cc |
index 93d964ab067b2c6f308936cd0e09b5e4cad57c55..17b7cc2f2a48c1506f2091d167562cc2bb81193d 100644 |
--- a/runtime/vm/flow_graph_allocator.cc |
+++ b/runtime/vm/flow_graph_allocator.cc |
@@ -222,11 +222,14 @@ void SSALivenessAnalysis::ComputeInitialSets() { |
if (block->IsJoinEntry()) { |
JoinEntryInstr* join = block->AsJoinEntry(); |
for (PhiIterator it(join); !it.Done(); it.Advance()) { |
- // TODO(johnmccutchan): Fix handling of PhiInstr with PairLocation. |
PhiInstr* phi = it.Current(); |
ASSERT(phi != NULL); |
kill->Add(phi->ssa_temp_index()); |
live_in->Remove(phi->ssa_temp_index()); |
+ if (phi->HasPairRepresentation()) { |
+ kill->Add(ToSecondPairVreg(phi->ssa_temp_index())); |
+ live_in->Remove(ToSecondPairVreg(phi->ssa_temp_index())); |
+ } |
// If a phi input is not defined by the corresponding predecessor it |
// must be marked live-in for that predecessor. |
@@ -774,20 +777,18 @@ Instruction* FlowGraphAllocator::ConnectOutgoingPhiMoves( |
// Search for the index of the current block in the predecessors of |
// the join. |
- const intptr_t pred_idx = join->IndexOfPredecessor(block); |
+ const intptr_t pred_index = join->IndexOfPredecessor(block); |
// Record the corresponding phi input use for each phi. |
- intptr_t move_idx = 0; |
+ intptr_t move_index = 0; |
for (PhiIterator it(join); !it.Done(); it.Advance()) { |
- // TODO(johnmccutchan): Fix handling of PhiInstr with PairLocation. |
PhiInstr* phi = it.Current(); |
- Value* val = phi->InputAt(pred_idx); |
- MoveOperands* move = parallel_move->MoveOperandsAt(move_idx); |
+ Value* val = phi->InputAt(pred_index); |
+ MoveOperands* move = parallel_move->MoveOperandsAt(move_index++); |
ConstantInstr* constant = val->definition()->AsConstant(); |
if (constant != NULL) { |
move->set_src(Location::Constant(constant)); |
- move_idx++; |
continue; |
} |
@@ -796,8 +797,7 @@ Instruction* FlowGraphAllocator::ConnectOutgoingPhiMoves( |
// g g' |
// value --* |
// |
- |
- const intptr_t vreg = val->definition()->ssa_temp_index(); |
+ intptr_t vreg = val->definition()->ssa_temp_index(); |
LiveRange* range = GetLiveRange(vreg); |
if (interfere_at_backedge != NULL) interfere_at_backedge->Add(vreg); |
@@ -806,9 +806,23 @@ Instruction* FlowGraphAllocator::ConnectOutgoingPhiMoves( |
pos, |
move->src_slot(), |
GetLiveRange(phi->ssa_temp_index())->assigned_location_slot()); |
- |
move->set_src(Location::PrefersRegister()); |
- move_idx++; |
+ |
+ if (val->definition()->HasPairRepresentation()) { |
+ move = parallel_move->MoveOperandsAt(move_index++); |
+ vreg = ToSecondPairVreg(vreg); |
+ range = GetLiveRange(vreg); |
Cutch
2015/10/01 17:27:41
This code is the same as the first vreg code. Coul
Florian Schneider
2015/10/01 18:27:38
It would need to take vreg, block, interfere_at_ba
|
+ if (interfere_at_backedge != NULL) { |
+ interfere_at_backedge->Add(vreg); |
+ } |
+ range->AddUseInterval(block->start_pos(), pos); |
+ range->AddHintedUse( |
+ pos, |
+ move->src_slot(), |
+ GetLiveRange(ToSecondPairVreg( |
+ phi->ssa_temp_index()))->assigned_location_slot()); |
+ move->set_src(Location::PrefersRegister()); |
+ } |
} |
// Begin backward iteration with the instruction before the parallel |
@@ -826,11 +840,11 @@ void FlowGraphAllocator::ConnectIncomingPhiMoves(JoinEntryInstr* join) { |
const bool is_loop_header = BlockInfoAt(join->start_pos())->is_loop_header(); |
intptr_t move_idx = 0; |
for (PhiIterator it(join); !it.Done(); it.Advance()) { |
- // TODO(johnmccutchan): Fix handling of PhiInstr with PairLocation. |
PhiInstr* phi = it.Current(); |
ASSERT(phi != NULL); |
const intptr_t vreg = phi->ssa_temp_index(); |
ASSERT(vreg >= 0); |
+ bool is_pair_phi = phi->HasPairRepresentation(); |
Cutch
2015/10/01 17:27:41
const bool....
Florian Schneider
2015/10/01 18:27:39
Done.
|
// Expected shape of live range: |
// |
@@ -839,9 +853,14 @@ void FlowGraphAllocator::ConnectIncomingPhiMoves(JoinEntryInstr* join) { |
// |
LiveRange* range = GetLiveRange(vreg); |
range->DefineAt(pos); // Shorten live range. |
- |
if (is_loop_header) range->mark_loop_phi(); |
+ if (is_pair_phi) { |
+ LiveRange* range = GetLiveRange(ToSecondPairVreg(vreg)); |
Cutch
2015/10/01 17:27:41
Could you rename range here, it is confusing that
Florian Schneider
2015/10/01 18:27:38
Otoh, it prevents from accidentally using the oute
|
+ range->DefineAt(pos); // Shorten live range. |
+ if (is_loop_header) range->mark_loop_phi(); |
+ } |
+ |
for (intptr_t pred_idx = 0; pred_idx < phi->InputCount(); pred_idx++) { |
BlockEntryInstr* pred = join->PredecessorAt(pred_idx); |
GotoInstr* goto_instr = pred->last_instruction()->AsGoto(); |
@@ -850,15 +869,26 @@ void FlowGraphAllocator::ConnectIncomingPhiMoves(JoinEntryInstr* join) { |
goto_instr->parallel_move()->MoveOperandsAt(move_idx); |
move->set_dest(Location::PrefersRegister()); |
range->AddUse(pos, move->dest_slot()); |
+ if (is_pair_phi) { |
+ LiveRange* range = GetLiveRange(ToSecondPairVreg(vreg)); |
+ MoveOperands* move = |
+ goto_instr->parallel_move()->MoveOperandsAt(move_idx + 1); |
Cutch
2015/10/01 17:27:41
More duplicate code- how difficult would be to fac
Florian Schneider
2015/10/01 18:27:38
Same as above... I think 2 common lines don't seem
|
+ move->set_dest(Location::PrefersRegister()); |
+ range->AddUse(pos, move->dest_slot()); |
+ } |
} |
// All phi resolution moves are connected. Phi's live range is |
// complete. |
AssignSafepoints(phi, range); |
- |
CompleteRange(range, RegisterKindForResult(phi)); |
+ if (is_pair_phi) { |
+ LiveRange* range = GetLiveRange(ToSecondPairVreg(vreg)); |
Cutch
2015/10/01 17:27:41
This shadow of range confused me.
Florian Schneider
2015/10/01 18:27:38
I can rename it.
|
+ AssignSafepoints(phi, range); |
+ CompleteRange(range, RegisterKindForResult(phi)); |
+ } |
- move_idx++; |
+ move_idx += is_pair_phi ? 2 : 1; |
} |
} |
@@ -1499,10 +1529,11 @@ void FlowGraphAllocator::NumberInstructions() { |
// For join entry predecessors create phi resolution moves if |
// necessary. They will be populated by the register allocator. |
JoinEntryInstr* join = block->AsJoinEntry(); |
- if ((join != NULL) && |
- (join->phis() != NULL) && |
- !join->phis()->is_empty()) { |
- const intptr_t phi_count = join->phis()->length(); |
+ if (join != NULL) { |
+ intptr_t move_count = 0; |
+ for (PhiIterator it(join); !it.Done(); it.Advance()) { |
+ move_count += it.Current()->HasPairRepresentation() ? 2 : 1; |
+ } |
for (intptr_t i = 0; i < block->PredecessorCount(); i++) { |
// Insert the move between the last two instructions of the |
// predecessor block (all such blocks have at least two instructions: |
@@ -1513,7 +1544,7 @@ void FlowGraphAllocator::NumberInstructions() { |
ParallelMoveInstr* move = last->AsGoto()->GetParallelMove(); |
// Populate the ParallelMove with empty moves. |
- for (intptr_t j = 0; j < phi_count; j++) { |
+ for (intptr_t j = 0; j < move_count; j++) { |
move->AddMove(Location::NoLocation(), Location::NoLocation()); |
} |
} |
@@ -2023,7 +2054,6 @@ intptr_t FlowGraphAllocator::FirstIntersectionWithAllocated( |
void ReachingDefs::AddPhi(PhiInstr* phi) { |
- // TODO(johnmccutchan): Fix handling of PhiInstr with PairLocation. |
if (phi->reaching_defs() == NULL) { |
Zone* zone = flow_graph_.zone(); |
phi->set_reaching_defs(new(zone) BitVector( |
@@ -2037,6 +2067,9 @@ void ReachingDefs::AddPhi(PhiInstr* phi) { |
depends_on_phi = true; |
} |
phi->reaching_defs()->Add(input->ssa_temp_index()); |
+ if (phi->HasPairRepresentation()) { |
+ phi->reaching_defs()->Add(ToSecondPairVreg(input->ssa_temp_index())); |
+ } |
} |
// If this phi depends on another phi then we need fix point iteration. |
@@ -2048,7 +2081,6 @@ void ReachingDefs::AddPhi(PhiInstr* phi) { |
void ReachingDefs::Compute() { |
// Transitively collect all phis that are used by the given phi. |
for (intptr_t i = 0; i < phis_.length(); i++) { |
- // TODO(johnmccutchan): Fix handling of PhiInstr with PairLocation. |
PhiInstr* phi = phis_[i]; |
// Add all phis that affect this phi to the list. |
@@ -2153,18 +2185,26 @@ bool FlowGraphAllocator::AllocateFreeRegister(LiveRange* unallocated) { |
for (PhiIterator it(loop_header->entry()->AsJoinEntry()); |
!it.Done(); |
it.Advance()) { |
- // TODO(johnmccutchan): Fix handling of PhiInstr with PairLocation. |
PhiInstr* phi = it.Current(); |
ASSERT(phi->is_alive()); |
- const intptr_t phi_vreg = phi->ssa_temp_index(); |
+ intptr_t phi_vreg = phi->ssa_temp_index(); |
LiveRange* range = GetLiveRange(phi_vreg); |
if (range->assigned_location().kind() == register_kind_) { |
const intptr_t reg = range->assigned_location().register_code(); |
- |
if (!reaching_defs_.Get(phi)->Contains(unallocated->vreg())) { |
used_on_backedge[reg] = true; |
} |
} |
+ if (phi->HasPairRepresentation()) { |
+ phi_vreg = ToSecondPairVreg(phi_vreg); |
+ range = GetLiveRange(phi_vreg); |
+ if (range->assigned_location().kind() == register_kind_) { |
+ const intptr_t reg = range->assigned_location().register_code(); |
+ if (!reaching_defs_.Get(phi)->Contains(unallocated->vreg())) { |
Cutch
2015/10/01 17:27:41
Factor into another helper routine?
Florian Schneider
2015/10/01 18:27:38
Renamed locals like above.
|
+ used_on_backedge[reg] = true; |
+ } |
+ } |
+ } |
} |
if (used_on_backedge[candidate]) { |
@@ -2877,11 +2917,12 @@ void FlowGraphAllocator::CollectRepresentations() { |
if (block->IsJoinEntry()) { |
JoinEntryInstr* join = block->AsJoinEntry(); |
for (PhiIterator it(join); !it.Done(); it.Advance()) { |
- // TODO(johnmccutchan): Fix handling of PhiInstr with PairLocation. |
PhiInstr* phi = it.Current(); |
- if ((phi != NULL) && (phi->ssa_temp_index() >= 0)) { |
- ASSERT(!phi->HasPairRepresentation()); |
- value_representations_[phi->ssa_temp_index()] = |
+ ASSERT(phi != NULL && phi->ssa_temp_index() >= 0); |
+ value_representations_[phi->ssa_temp_index()] = |
+ RepresentationForRange(phi->representation()); |
+ if (phi->HasPairRepresentation()) { |
+ value_representations_[ToSecondPairVreg(phi->ssa_temp_index())] = |
RepresentationForRange(phi->representation()); |
} |
} |