| 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..208a4afbd8e8de0a726326ce18bb6fd2f55696eb 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.
|
| @@ -239,6 +242,12 @@ void SSALivenessAnalysis::ComputeInitialSets() {
|
| if (!kill_[pred->postorder_number()]->Contains(use)) {
|
| live_in_[pred->postorder_number()]->Add(use);
|
| }
|
| + if (phi->HasPairRepresentation()) {
|
| + const intptr_t second_use = ToSecondPairVreg(use);
|
| + if (!kill_[pred->postorder_number()]->Contains(second_use)) {
|
| + live_in_[pred->postorder_number()]->Add(second_use);
|
| + }
|
| + }
|
| }
|
| }
|
| } else if (block->IsCatchBlockEntry()) {
|
| @@ -774,20 +783,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 +803,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 +812,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);
|
| + 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 +846,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);
|
| + const bool is_pair_phi = phi->HasPairRepresentation();
|
|
|
| // Expected shape of live range:
|
| //
|
| @@ -839,9 +859,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* second_range = GetLiveRange(ToSecondPairVreg(vreg));
|
| + second_range->DefineAt(pos); // Shorten live range.
|
| + if (is_loop_header) second_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 +875,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* second_range = GetLiveRange(ToSecondPairVreg(vreg));
|
| + MoveOperands* second_move =
|
| + goto_instr->parallel_move()->MoveOperandsAt(move_idx + 1);
|
| + second_move->set_dest(Location::PrefersRegister());
|
| + second_range->AddUse(pos, second_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* second_range = GetLiveRange(ToSecondPairVreg(vreg));
|
| + AssignSafepoints(phi, second_range);
|
| + CompleteRange(second_range, RegisterKindForResult(phi));
|
| + }
|
|
|
| - move_idx++;
|
| + move_idx += is_pair_phi ? 2 : 1;
|
| }
|
| }
|
|
|
| @@ -1499,10 +1535,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 +1550,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 +2060,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 +2073,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 +2087,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 +2191,27 @@ 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();
|
| 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()) {
|
| + const intptr_t second_phi_vreg = ToSecondPairVreg(phi_vreg);
|
| + LiveRange* second_range = GetLiveRange(second_phi_vreg);
|
| + if (second_range->assigned_location().kind() == register_kind_) {
|
| + const intptr_t reg =
|
| + second_range->assigned_location().register_code();
|
| + if (!reaching_defs_.Get(phi)->Contains(unallocated->vreg())) {
|
| + used_on_backedge[reg] = true;
|
| + }
|
| + }
|
| + }
|
| }
|
|
|
| if (used_on_backedge[candidate]) {
|
| @@ -2877,11 +2924,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());
|
| }
|
| }
|
|
|