| Index: runtime/vm/flow_graph_allocator.cc
|
| diff --git a/runtime/vm/flow_graph_allocator.cc b/runtime/vm/flow_graph_allocator.cc
|
| index c1f8f32ae3de9e664b8cae436d610f400da0314b..3b89ebad25f2a9007eddb9decafaa0b6642315ea 100644
|
| --- a/runtime/vm/flow_graph_allocator.cc
|
| +++ b/runtime/vm/flow_graph_allocator.cc
|
| @@ -606,6 +606,7 @@ void FlowGraphAllocator::BuildLiveRanges() {
|
| if (flow_graph_.num_copied_params() > 0) {
|
| ASSERT(spill_slots_.length() == slot_index);
|
| spill_slots_.Add(range->End());
|
| + quad_spill_slots_.Add(false);
|
| }
|
| AssignSafepoints(range);
|
| } else {
|
| @@ -993,9 +994,8 @@ void FlowGraphAllocator::ProcessOneInstruction(BlockEntryInstr* block,
|
| }
|
|
|
| for (intptr_t reg = 0; reg < kNumberOfFpuRegisters; reg++) {
|
| - Representation ignored = kNoRepresentation;
|
| BlockLocation(
|
| - Location::FpuRegisterLocation(static_cast<FpuRegister>(reg), ignored),
|
| + Location::FpuRegisterLocation(static_cast<FpuRegister>(reg)),
|
| pos,
|
| pos + 1);
|
| }
|
| @@ -1581,40 +1581,76 @@ void FlowGraphAllocator::SpillAfter(LiveRange* range, intptr_t from) {
|
| void FlowGraphAllocator::AllocateSpillSlotFor(LiveRange* range) {
|
| ASSERT(range->spill_slot().IsInvalid());
|
|
|
| + // Compute range start and end.
|
| + LiveRange* last_sibling = range;
|
| + while (last_sibling->next_sibling() != NULL) {
|
| + last_sibling = last_sibling->next_sibling();
|
| + }
|
| +
|
| + const intptr_t start = range->Start();
|
| + const intptr_t end = last_sibling->End();
|
| +
|
| + // During fpu register allocation spill slot indices are computed in terms of
|
| + // double (64bit) stack slots. We treat quad stack slot (128bit) as a
|
| + // consecutive pair of two double spill slots.
|
| + // Special care is taken to never allocate the same index to both
|
| + // double and quad spill slots as it complicates disambiguation during
|
| + // parallel move resolution.
|
| + const bool need_quad = (register_kind_ == Location::kFpuRegister) &&
|
| + ((range->representation() == kUnboxedFloat32x4) ||
|
| + (range->representation() == kUnboxedUint32x4));
|
| +
|
| + // 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
|
| + // we are allocating normal double slot).
|
| intptr_t idx = 0;
|
| for (; idx < spill_slots_.length(); idx++) {
|
| - if (spill_slots_[idx] <= range->Start()) break;
|
| + if ((need_quad == quad_spill_slots_[idx]) &&
|
| + (spill_slots_[idx] <= start)) {
|
| + break;
|
| + }
|
| }
|
|
|
| - if (idx == spill_slots_.length()) spill_slots_.Add(0);
|
| -
|
| - LiveRange* last_sibling = range;
|
| - while (last_sibling->next_sibling() != NULL) {
|
| - last_sibling = last_sibling->next_sibling();
|
| + if (idx == spill_slots_.length()) {
|
| + // No free spill slot found. Allocate a new one.
|
| + spill_slots_.Add(0);
|
| + quad_spill_slots_.Add(need_quad);
|
| + if (need_quad) { // Allocate two double stack slots if we need quad slot.
|
| + spill_slots_.Add(0);
|
| + quad_spill_slots_.Add(need_quad);
|
| + }
|
| }
|
|
|
| - spill_slots_[idx] = last_sibling->End();
|
|
|
| + // Set spill slot expiration boundary to the live range's end.
|
| + spill_slots_[idx] = end;
|
| + if (need_quad) {
|
| + ASSERT(quad_spill_slots_[idx] && quad_spill_slots_[idx + 1]);
|
| + idx++; // Use the higher index it corresponds to the lower stack address.
|
| + spill_slots_[idx] = end;
|
| + } else {
|
| + ASSERT(!quad_spill_slots_[idx]);
|
| + }
|
| +
|
| + // Assign spill slot to the range.
|
| if (register_kind_ == Location::kRegister) {
|
| range->set_spill_slot(Location::StackSlot(idx));
|
| } else {
|
| - // FPU register spill slots are essentially two (x64) or four (ia32) normal
|
| - // word size spill slots. We use the index of the slot with the lowest
|
| - // address as an index for the FPU register spill slot. In terms of indexes
|
| - // this relation is inverted: so we have to take the highest index.
|
| + // We use the index of the slot with the lowest address as an index for the
|
| + // FPU register spill slot. In terms of indexes this relation is inverted:
|
| + // so we have to take the highest index.
|
| const intptr_t slot_idx = cpu_spill_slot_count_ +
|
| - idx * kFpuRegisterSpillFactor + (kFpuRegisterSpillFactor - 1);
|
| + idx * kDoubleSpillFactor + (kDoubleSpillFactor - 1);
|
|
|
| Location location;
|
| - if (range->representation() == kUnboxedFloat32x4) {
|
| - location = Location::Float32x4StackSlot(slot_idx);
|
| - } else if (range->representation() == kUnboxedUint32x4) {
|
| - location = Location::Uint32x4StackSlot(slot_idx);
|
| + if ((range->representation() == kUnboxedFloat32x4) ||
|
| + (range->representation() == kUnboxedUint32x4)) {
|
| + ASSERT(need_quad);
|
| + location = Location::QuadStackSlot(slot_idx);
|
| } else {
|
| ASSERT((range->representation() == kUnboxedDouble) ||
|
| (range->representation() == kUnboxedMint));
|
| - location = Location::DoubleStackSlot(slot_idx,
|
| - range->representation());
|
| + location = Location::DoubleStackSlot(slot_idx);
|
| }
|
| range->set_spill_slot(location);
|
| }
|
| @@ -1815,7 +1851,7 @@ bool FlowGraphAllocator::AllocateFreeRegister(LiveRange* unallocated) {
|
| TRACE_ALLOC(OS::Print(
|
| "considering %s for v%"Pd": has interference on the back edge"
|
| " {loop [%"Pd", %"Pd")}\n",
|
| - MakeRegisterLocation(candidate, kUnboxedDouble).Name(),
|
| + MakeRegisterLocation(candidate).Name(),
|
| unallocated->vreg(),
|
| loop_header->entry()->start_pos(),
|
| loop_header->last_block()->end_pos()));
|
| @@ -1833,7 +1869,7 @@ bool FlowGraphAllocator::AllocateFreeRegister(LiveRange* unallocated) {
|
| free_until = intersection;
|
| TRACE_ALLOC(OS::Print(
|
| "found %s for v%"Pd" with no interference on the back edge\n",
|
| - MakeRegisterLocation(candidate, kUnboxedDouble).Name(),
|
| + MakeRegisterLocation(candidate).Name(),
|
| candidate));
|
| break;
|
| }
|
| @@ -1842,7 +1878,7 @@ bool FlowGraphAllocator::AllocateFreeRegister(LiveRange* unallocated) {
|
| }
|
|
|
| TRACE_ALLOC(OS::Print("assigning free register "));
|
| - TRACE_ALLOC(MakeRegisterLocation(candidate, kUnboxedDouble).Print());
|
| + TRACE_ALLOC(MakeRegisterLocation(candidate).Print());
|
| TRACE_ALLOC(OS::Print(" to v%"Pd"\n", unallocated->vreg()));
|
|
|
| if (free_until != kMaxPosition) {
|
| @@ -1853,8 +1889,7 @@ bool FlowGraphAllocator::AllocateFreeRegister(LiveRange* unallocated) {
|
| }
|
|
|
| registers_[candidate].Add(unallocated);
|
| - unallocated->set_assigned_location(
|
| - MakeRegisterLocation(candidate, unallocated->representation()));
|
| + unallocated->set_assigned_location(MakeRegisterLocation(candidate));
|
|
|
| return true;
|
| }
|
| @@ -1945,7 +1980,7 @@ void FlowGraphAllocator::AllocateAnyRegister(LiveRange* unallocated) {
|
| }
|
|
|
| TRACE_ALLOC(OS::Print("assigning blocked register "));
|
| - TRACE_ALLOC(MakeRegisterLocation(candidate, kUnboxedDouble).Print());
|
| + TRACE_ALLOC(MakeRegisterLocation(candidate).Print());
|
| TRACE_ALLOC(OS::Print(" to live range v%"Pd" until %"Pd"\n",
|
| unallocated->vreg(), blocked_at));
|
|
|
| @@ -2051,8 +2086,7 @@ void FlowGraphAllocator::AssignNonFreeRegister(LiveRange* unallocated,
|
| if (first_evicted != -1) RemoveEvicted(reg, first_evicted);
|
|
|
| registers_[reg].Add(unallocated);
|
| - unallocated->set_assigned_location(
|
| - MakeRegisterLocation(reg, unallocated->representation()));
|
| + unallocated->set_assigned_location(MakeRegisterLocation(reg));
|
| }
|
|
|
|
|
| @@ -2522,6 +2556,7 @@ void FlowGraphAllocator::AllocateRegisters() {
|
|
|
| cpu_spill_slot_count_ = spill_slots_.length();
|
| spill_slots_.Clear();
|
| + quad_spill_slots_.Clear();
|
|
|
| PrepareForAllocation(Location::kFpuRegister,
|
| kNumberOfFpuRegisters,
|
| @@ -2534,8 +2569,7 @@ void FlowGraphAllocator::AllocateRegisters() {
|
|
|
| GraphEntryInstr* entry = block_order_[0]->AsGraphEntry();
|
| ASSERT(entry != NULL);
|
| - intptr_t double_spill_slot_count =
|
| - spill_slots_.length() * kFpuRegisterSpillFactor;
|
| + intptr_t double_spill_slot_count = spill_slots_.length() * kDoubleSpillFactor;
|
| entry->set_spill_slot_count(cpu_spill_slot_count_ + double_spill_slot_count);
|
|
|
| if (FLAG_print_ssa_liveranges) {
|
|
|