| Index: runtime/vm/flow_graph_allocator.cc
|
| diff --git a/runtime/vm/flow_graph_allocator.cc b/runtime/vm/flow_graph_allocator.cc
|
| index 4a3d66dc4f371fc85a04fe32470edf14a8bfde2e..bfc098f8a727cf7458891c635ecc29caee3e2064 100644
|
| --- a/runtime/vm/flow_graph_allocator.cc
|
| +++ b/runtime/vm/flow_graph_allocator.cc
|
| @@ -398,11 +398,24 @@ void LiveRange::Print() {
|
| return;
|
| }
|
|
|
| - OS::Print(" live range v%" Pd " [%" Pd ", %" Pd ") in ",
|
| - vreg(), Start(), End());
|
| + OS::Print(" live range v%" Pd " [%" Pd ", %" Pd ") in ", vreg(),
|
| + Start(),
|
| + End());
|
| assigned_location().Print();
|
| + if (spill_slot_.HasStackIndex()) {
|
| + intptr_t stack_slot = spill_slot_.stack_index();
|
| + OS::Print(" allocated spill slot: %" Pd "", stack_slot);
|
| + }
|
| OS::Print("\n");
|
|
|
| + SafepointPosition* safepoint = first_safepoint();
|
| + while (safepoint != NULL) {
|
| + OS::Print(" Safepoint [%" Pd "]: ", safepoint->pos());
|
| + safepoint->locs()->stack_bitmap()->Print();
|
| + OS::Print("\n");
|
| + safepoint = safepoint->next();
|
| + }
|
| +
|
| UsePosition* use_pos = uses_;
|
| for (UseInterval* interval = first_use_interval_;
|
| interval != NULL;
|
| @@ -564,6 +577,7 @@ void FlowGraphAllocator::BuildLiveRanges() {
|
| GraphEntryInstr* graph_entry = flow_graph_.graph_entry();
|
| for (intptr_t i = 0; i < graph_entry->initial_definitions()->length(); i++) {
|
| Definition* defn = (*graph_entry->initial_definitions())[i];
|
| + ASSERT(!defn->HasPairRepresentation());
|
| LiveRange* range = GetLiveRange(defn->ssa_temp_index());
|
| range->AddUseInterval(graph_entry->start_pos(), graph_entry->end_pos());
|
| range->DefineAt(graph_entry->start_pos());
|
| @@ -612,11 +626,14 @@ void FlowGraphAllocator::ProcessInitialDefinition(Definition* defn,
|
| // in stack maps.
|
| spill_slots_.Add(range_end);
|
| quad_spill_slots_.Add(false);
|
| + untagged_spill_slots_.Add(false);
|
| + // Note, all incoming parameters are assumed to be tagged.
|
| MarkAsObjectAtSafepoints(range);
|
| } else if (defn->IsConstant() && block->IsCatchBlockEntry()) {
|
| // Constants at catch block entries consume spill slots.
|
| spill_slots_.Add(range_end);
|
| quad_spill_slots_.Add(false);
|
| + untagged_spill_slots_.Add(false);
|
| }
|
| }
|
|
|
| @@ -632,7 +649,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) ||
|
| @@ -802,8 +818,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.
|
| @@ -827,13 +847,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]);
|
| }
|
| @@ -869,13 +899,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]);
|
| }
|
| @@ -889,7 +931,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);
|
| @@ -903,6 +946,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);
|
| @@ -1114,6 +1160,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);
|
|
|
| @@ -1128,6 +1180,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();
|
| @@ -1135,12 +1191,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);
|
| }
|
| }
|
| }
|
| @@ -1522,6 +1578,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)) {
|
| @@ -1695,7 +1761,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);
|
| }
|
| @@ -1769,6 +1836,8 @@ void FlowGraphAllocator::AllocateSpillSlotFor(LiveRange* range) {
|
| ((range->representation() == kUnboxedFloat32x4) ||
|
| (range->representation() == kUnboxedInt32x4) ||
|
| (range->representation() == kUnboxedFloat64x2));
|
| + const bool need_untagged = (register_kind_ == Location::kRegister) &&
|
| + ((range->representation() == kUntagged));
|
|
|
| // Search for a free spill slot among allocated: the value in it should be
|
| // dead and its type should match (e.g. it should not be a part of the quad if
|
| @@ -1780,6 +1849,7 @@ void FlowGraphAllocator::AllocateSpillSlotFor(LiveRange* range) {
|
| : 0;
|
| for (; idx < spill_slots_.length(); idx++) {
|
| if ((need_quad == quad_spill_slots_[idx]) &&
|
| + (need_untagged == untagged_spill_slots_[idx]) &&
|
| (spill_slots_[idx] <= start)) {
|
| break;
|
| }
|
| @@ -1789,9 +1859,11 @@ void FlowGraphAllocator::AllocateSpillSlotFor(LiveRange* range) {
|
| // No free spill slot found. Allocate a new one.
|
| spill_slots_.Add(0);
|
| quad_spill_slots_.Add(need_quad);
|
| + untagged_spill_slots_.Add(need_untagged);
|
| if (need_quad) { // Allocate two double stack slots if we need quad slot.
|
| spill_slots_.Add(0);
|
| quad_spill_slots_.Add(need_quad);
|
| + untagged_spill_slots_.Add(need_untagged);
|
| }
|
| }
|
|
|
| @@ -1822,8 +1894,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);
|
| @@ -1841,6 +1912,7 @@ void FlowGraphAllocator::MarkAsObjectAtSafepoints(LiveRange* range) {
|
| for (SafepointPosition* safepoint = range->first_safepoint();
|
| safepoint != NULL;
|
| safepoint = safepoint->next()) {
|
| + // Mark the stack slot as having an object.
|
| safepoint->locs()->stack_bitmap()->Set(stack_index, true);
|
| }
|
| range = range->next_sibling();
|
| @@ -2199,9 +2271,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
|
| @@ -2281,7 +2352,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);
|
| @@ -2316,6 +2387,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());
|
| @@ -2350,7 +2422,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());
|
| }
|
| }
|
| }
|
| @@ -2669,12 +2741,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());
|
| }
|
|
|
| @@ -2690,7 +2772,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.
|
| @@ -2700,7 +2784,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());
|
| }
|
| }
|
| }
|
| @@ -2711,9 +2797,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());
|
| }
|
| }
|
| }
|
| @@ -2761,6 +2849,7 @@ void FlowGraphAllocator::AllocateRegisters() {
|
| cpu_spill_slot_count_ = spill_slots_.length();
|
| spill_slots_.Clear();
|
| quad_spill_slots_.Clear();
|
| + untagged_spill_slots_.Clear();
|
|
|
| PrepareForAllocation(Location::kFpuRegister,
|
| kNumberOfFpuRegisters,
|
|
|