| Index: runtime/vm/flow_graph_allocator.cc
|
| diff --git a/runtime/vm/flow_graph_allocator.cc b/runtime/vm/flow_graph_allocator.cc
|
| index db6d1e0704716cefbc0f7f2a424fbf7d0aa6a7a3..168cfb7c37dea97a7949f145450e6cc738ee72c4 100644
|
| --- a/runtime/vm/flow_graph_allocator.cc
|
| +++ b/runtime/vm/flow_graph_allocator.cc
|
| @@ -635,7 +635,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) ||
|
| @@ -805,8 +804,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.
|
| @@ -830,13 +833,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]);
|
| }
|
| @@ -872,13 +885,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]);
|
| }
|
| @@ -892,7 +917,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);
|
| @@ -906,6 +932,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);
|
| @@ -1117,6 +1146,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);
|
|
|
| @@ -1131,6 +1166,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();
|
| @@ -1138,12 +1177,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);
|
| }
|
| }
|
| }
|
| @@ -1525,6 +1564,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)) {
|
| @@ -1698,7 +1747,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);
|
| }
|
| @@ -1825,8 +1875,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);
|
| @@ -2201,9 +2250,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
|
| @@ -2283,7 +2331,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);
|
| @@ -2318,6 +2366,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());
|
| @@ -2352,7 +2401,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());
|
| }
|
| }
|
| }
|
| @@ -2666,12 +2715,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());
|
| }
|
|
|
| @@ -2687,7 +2746,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.
|
| @@ -2697,7 +2758,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());
|
| }
|
| }
|
| }
|
| @@ -2708,9 +2771,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());
|
| }
|
| }
|
| }
|
|
|