| Index: runtime/vm/flow_graph_allocator.cc
|
| diff --git a/runtime/vm/flow_graph_allocator.cc b/runtime/vm/flow_graph_allocator.cc
|
| index 1359ea73872a61d4d373e0dbd0fff7e751951b33..7dc8bd5cd86f38f1c1f66d3a12bed191f1400380 100644
|
| --- a/runtime/vm/flow_graph_allocator.cc
|
| +++ b/runtime/vm/flow_graph_allocator.cc
|
| @@ -629,7 +629,6 @@ static Location::Kind RegisterKindFromPolicy(Location loc) {
|
|
|
| static Location::Kind RegisterKindForResult(Instruction* instr) {
|
| if ((instr->representation() == kUnboxedDouble) ||
|
| - (instr->representation() == kUnboxedMint) ||
|
| (instr->representation() == kUnboxedFloat32x4) ||
|
| (instr->representation() == kUnboxedInt32x4) ||
|
| (instr->representation() == kUnboxedFloat64x2) ||
|
| @@ -799,8 +798,12 @@ void FlowGraphAllocator::ProcessEnvironmentUses(BlockEntryInstr* block,
|
|
|
| for (intptr_t i = 0; i < env->Length(); ++i) {
|
| Value* value = env->ValueAt(i);
|
| - locations[i] = Location::Any();
|
| Definition* def = value->definition();
|
| + if (def->HasPairRepresentation()) {
|
| + locations[i] = Location::Pair(Location::Any(), Location::Any());
|
| + } else {
|
| + locations[i] = Location::Any();
|
| + }
|
|
|
| if (def->IsPushArgument()) {
|
| // Frame size is unknown until after allocation.
|
| @@ -824,13 +827,23 @@ void FlowGraphAllocator::ProcessEnvironmentUses(BlockEntryInstr* block,
|
| continue;
|
| }
|
|
|
| - LiveRange* range = GetLiveRange(def->ssa_temp_index());
|
| - range->AddUseInterval(block_start_pos, use_pos);
|
| - range->AddUse(use_pos, &locations[i]);
|
| -
|
| if (def->HasPairRepresentation()) {
|
| - LiveRange* range =
|
| + PairLocation* location_pair = locations[i].AsPairLocation();
|
| + {
|
| + // First live range.
|
| + LiveRange* range = GetLiveRange(def->ssa_temp_index());
|
| + range->AddUseInterval(block_start_pos, use_pos);
|
| + range->AddUse(use_pos, location_pair->SlotAt(0));
|
| + }
|
| + {
|
| + // Second live range.
|
| + LiveRange* range =
|
| GetLiveRange(ToSecondPairVreg(def->ssa_temp_index()));
|
| + range->AddUseInterval(block_start_pos, use_pos);
|
| + range->AddUse(use_pos, location_pair->SlotAt(1));
|
| + }
|
| + } else {
|
| + LiveRange* range = GetLiveRange(def->ssa_temp_index());
|
| range->AddUseInterval(block_start_pos, use_pos);
|
| range->AddUse(use_pos, &locations[i]);
|
| }
|
| @@ -866,13 +879,25 @@ void FlowGraphAllocator::ProcessMaterializationUses(
|
| continue;
|
| }
|
|
|
| - locations[i] = Location::Any();
|
| -
|
| - LiveRange* range = GetLiveRange(def->ssa_temp_index());
|
| - range->AddUseInterval(block_start_pos, use_pos);
|
| - range->AddUse(use_pos, &locations[i]);
|
| if (def->HasPairRepresentation()) {
|
| - LiveRange* range = GetLiveRange(ToSecondPairVreg(def->ssa_temp_index()));
|
| + locations[i] = Location::Pair(Location::Any(), Location::Any());
|
| + PairLocation* location_pair = locations[i].AsPairLocation();
|
| + {
|
| + // First live range.
|
| + LiveRange* range = GetLiveRange(def->ssa_temp_index());
|
| + range->AddUseInterval(block_start_pos, use_pos);
|
| + range->AddUse(use_pos, location_pair->SlotAt(0));
|
| + }
|
| + {
|
| + // Second live range.
|
| + LiveRange* range =
|
| + GetLiveRange(ToSecondPairVreg(def->ssa_temp_index()));
|
| + range->AddUseInterval(block_start_pos, use_pos);
|
| + range->AddUse(use_pos, location_pair->SlotAt(1));
|
| + }
|
| + } else {
|
| + locations[i] = Location::Any();
|
| + LiveRange* range = GetLiveRange(def->ssa_temp_index());
|
| range->AddUseInterval(block_start_pos, use_pos);
|
| range->AddUse(use_pos, &locations[i]);
|
| }
|
| @@ -886,7 +911,8 @@ void FlowGraphAllocator::ProcessOneInput(BlockEntryInstr* block,
|
| intptr_t pos,
|
| Location* in_ref,
|
| Value* input,
|
| - intptr_t vreg) {
|
| + intptr_t vreg,
|
| + RegisterSet* live_registers) {
|
| ASSERT(in_ref != NULL);
|
| ASSERT(!in_ref->IsPairLocation());
|
| ASSERT(input != NULL);
|
| @@ -900,6 +926,9 @@ void FlowGraphAllocator::ProcessOneInput(BlockEntryInstr* block,
|
| // value --*
|
| // register [-----)
|
| //
|
| + if (live_registers != NULL) {
|
| + live_registers->Add(*in_ref, range->representation());
|
| + }
|
| MoveOperands* move =
|
| AddMoveAt(pos - 1, *in_ref, Location::Any());
|
| BlockLocation(*in_ref, pos - 1, pos + 1);
|
| @@ -1111,6 +1140,12 @@ void FlowGraphAllocator::ProcessOneInstruction(BlockEntryInstr* block,
|
| locs->out(0).IsUnallocated() &&
|
| (locs->out(0).policy() == Location::kSameAsFirstInput);
|
|
|
| + // Output is same as first input which is a pair.
|
| + if (output_same_as_first_input && locs->in(0).IsPairLocation()) {
|
| + // Make out into a PairLocation.
|
| + locs->set_out(0, Location::Pair(Location::RequiresRegister(),
|
| + Location::RequiresRegister()));
|
| + }
|
| // Add uses from the deoptimization environment.
|
| if (current->env() != NULL) ProcessEnvironmentUses(block, current);
|
|
|
| @@ -1125,6 +1160,10 @@ void FlowGraphAllocator::ProcessOneInstruction(BlockEntryInstr* block,
|
| // the location is the first register or second register.
|
| Value* input = current->InputAt(j);
|
| Location* in_ref = locs->in_slot(j);
|
| + RegisterSet* live_registers = NULL;
|
| + if (locs->HasCallOnSlowPath()) {
|
| + live_registers = locs->live_registers();
|
| + }
|
| if (in_ref->IsPairLocation()) {
|
| ASSERT(input->definition()->HasPairRepresentation());
|
| PairLocation* pair = in_ref->AsPairLocation();
|
| @@ -1132,12 +1171,12 @@ void FlowGraphAllocator::ProcessOneInstruction(BlockEntryInstr* block,
|
| // Each element of the pair is assigned it's own virtual register number
|
| // and is allocated its own LiveRange.
|
| ProcessOneInput(block, pos, pair->SlotAt(0),
|
| - input, vreg);
|
| + input, vreg, live_registers);
|
| ProcessOneInput(block, pos, pair->SlotAt(1), input,
|
| - ToSecondPairVreg(vreg));
|
| + ToSecondPairVreg(vreg), live_registers);
|
| } else {
|
| ProcessOneInput(block, pos, in_ref, input,
|
| - input->definition()->ssa_temp_index());
|
| + input->definition()->ssa_temp_index(), live_registers);
|
| }
|
| }
|
| }
|
| @@ -1519,6 +1558,16 @@ UsePosition* AllocationFinger::FirstRegisterBeneficialUse(intptr_t after) {
|
| }
|
|
|
|
|
| +UsePosition* AllocationFinger::FirstInterferingUse(intptr_t after) {
|
| + if (IsInstructionEndPosition(after)) {
|
| + // If after is a position at the end of the instruction disregard
|
| + // any use occuring at it.
|
| + after += 1;
|
| + }
|
| + return FirstRegisterUse(after);
|
| +}
|
| +
|
| +
|
| void AllocationFinger::UpdateAfterSplit(intptr_t first_use_after_split_pos) {
|
| if ((first_register_use_ != NULL) &&
|
| (first_register_use_->pos() >= first_use_after_split_pos)) {
|
| @@ -1692,7 +1741,8 @@ LiveRange* FlowGraphAllocator::SplitBetween(LiveRange* range,
|
| split_pos = ToInstructionStart(to) - 1;
|
| }
|
|
|
| - ASSERT((split_pos != kIllegalPosition) && (from < split_pos));
|
| + ASSERT(split_pos != kIllegalPosition);
|
| + ASSERT(from < split_pos);
|
|
|
| return range->SplitAt(split_pos);
|
| }
|
| @@ -1819,8 +1869,7 @@ void FlowGraphAllocator::AllocateSpillSlotFor(LiveRange* range) {
|
| ASSERT(need_quad);
|
| location = Location::QuadStackSlot(slot_idx);
|
| } else {
|
| - ASSERT((range->representation() == kUnboxedDouble) ||
|
| - (range->representation() == kUnboxedMint));
|
| + ASSERT((range->representation() == kUnboxedDouble));
|
| location = Location::DoubleStackSlot(slot_idx);
|
| }
|
| range->set_spill_slot(location);
|
| @@ -2195,9 +2244,8 @@ bool FlowGraphAllocator::UpdateFreeUntil(intptr_t reg,
|
| return false;
|
| }
|
|
|
| - const UsePosition* use =
|
| - allocated->finger()->FirstRegisterBeneficialUse(unallocated->Start());
|
| -
|
| + UsePosition* use =
|
| + allocated->finger()->FirstInterferingUse(start);
|
| if ((use != NULL) && ((ToInstructionStart(use->pos()) - start) <= 1)) {
|
| // This register is blocked by interval that is used
|
| // as register in the current instruction and can't
|
| @@ -2277,7 +2325,7 @@ bool FlowGraphAllocator::EvictIntersection(LiveRange* allocated,
|
| if (intersection == kMaxPosition) return false;
|
|
|
| const intptr_t spill_position = first_unallocated->start();
|
| - UsePosition* use = allocated->finger()->FirstRegisterUse(spill_position);
|
| + UsePosition* use = allocated->finger()->FirstInterferingUse(spill_position);
|
| if (use == NULL) {
|
| // No register uses after this point.
|
| SpillAfter(allocated, spill_position);
|
| @@ -2312,6 +2360,7 @@ MoveOperands* FlowGraphAllocator::AddMoveAt(intptr_t pos,
|
|
|
|
|
| void FlowGraphAllocator::ConvertUseTo(UsePosition* use, Location loc) {
|
| + ASSERT(!loc.IsPairLocation());
|
| ASSERT(use->location_slot() != NULL);
|
| Location* slot = use->location_slot();
|
| ASSERT(slot->IsUnallocated());
|
| @@ -2346,7 +2395,7 @@ void FlowGraphAllocator::ConvertAllUses(LiveRange* range) {
|
| safepoint = safepoint->next()) {
|
| if (!safepoint->locs()->always_calls()) {
|
| ASSERT(safepoint->locs()->can_call());
|
| - safepoint->locs()->live_registers()->Add(loc);
|
| + safepoint->locs()->live_registers()->Add(loc, range->representation());
|
| }
|
| }
|
| }
|
| @@ -2660,12 +2709,22 @@ void FlowGraphAllocator::ResolveControlFlow() {
|
| }
|
|
|
|
|
| +static Representation RepresentationForRange(Representation definition_rep) {
|
| + if (definition_rep == kUnboxedMint) {
|
| + // kUnboxedMint is split into two ranges, each of which are kUntagged.
|
| + return kUntagged;
|
| + }
|
| + return definition_rep;
|
| +}
|
| +
|
| +
|
| void FlowGraphAllocator::CollectRepresentations() {
|
| // Parameters.
|
| GraphEntryInstr* graph_entry = flow_graph_.graph_entry();
|
| for (intptr_t i = 0; i < graph_entry->initial_definitions()->length(); ++i) {
|
| Definition* def = (*graph_entry->initial_definitions())[i];
|
| - value_representations_[def->ssa_temp_index()] = def->representation();
|
| + value_representations_[def->ssa_temp_index()] =
|
| + RepresentationForRange(def->representation());
|
| ASSERT(!def->HasPairRepresentation());
|
| }
|
|
|
| @@ -2681,7 +2740,9 @@ void FlowGraphAllocator::CollectRepresentations() {
|
| i < catch_entry->initial_definitions()->length();
|
| ++i) {
|
| Definition* def = (*catch_entry->initial_definitions())[i];
|
| - value_representations_[def->ssa_temp_index()] = def->representation();
|
| + ASSERT(!def->HasPairRepresentation());
|
| + value_representations_[def->ssa_temp_index()] =
|
| + RepresentationForRange(def->representation());
|
| }
|
| }
|
| // Phis.
|
| @@ -2691,7 +2752,9 @@ void FlowGraphAllocator::CollectRepresentations() {
|
| // TODO(johnmccutchan): Fix handling of PhiInstr with PairLocation.
|
| PhiInstr* phi = it.Current();
|
| if ((phi != NULL) && (phi->ssa_temp_index() >= 0)) {
|
| - value_representations_[phi->ssa_temp_index()] = phi->representation();
|
| + ASSERT(!phi->HasPairRepresentation());
|
| + value_representations_[phi->ssa_temp_index()] =
|
| + RepresentationForRange(phi->representation());
|
| }
|
| }
|
| }
|
| @@ -2702,9 +2765,11 @@ void FlowGraphAllocator::CollectRepresentations() {
|
| Definition* def = instr_it.Current()->AsDefinition();
|
| if ((def != NULL) && (def->ssa_temp_index() >= 0)) {
|
| const intptr_t vreg = def->ssa_temp_index();
|
| - value_representations_[vreg] = def->representation();
|
| + value_representations_[vreg] =
|
| + RepresentationForRange(def->representation());
|
| if (def->HasPairRepresentation()) {
|
| - value_representations_[ToSecondPairVreg(vreg)] = def->representation();
|
| + value_representations_[ToSecondPairVreg(vreg)] =
|
| + RepresentationForRange(def->representation());
|
| }
|
| }
|
| }
|
|
|