| Index: src/compiler/register-allocator.cc
|
| diff --git a/src/compiler/register-allocator.cc b/src/compiler/register-allocator.cc
|
| index 0dc76000f784771856dd10e29daedddb3b2ad27e..49ae35b63da63e85a1be1a478182782f5b719286 100644
|
| --- a/src/compiler/register-allocator.cc
|
| +++ b/src/compiler/register-allocator.cc
|
| @@ -671,13 +671,13 @@ unsigned LiveRange::GetSize() {
|
| }
|
|
|
|
|
| -struct TopLevelLiveRange::SpillAtDefinitionList : ZoneObject {
|
| - SpillAtDefinitionList(int gap_index, InstructionOperand* operand,
|
| - SpillAtDefinitionList* next)
|
| +struct TopLevelLiveRange::SpillMoveInsertionList : ZoneObject {
|
| + SpillMoveInsertionList(int gap_index, InstructionOperand* operand,
|
| + SpillMoveInsertionList* next)
|
| : gap_index(gap_index), operand(operand), next(next) {}
|
| const int gap_index;
|
| InstructionOperand* const operand;
|
| - SpillAtDefinitionList* const next;
|
| + SpillMoveInsertionList* const next;
|
| };
|
|
|
|
|
| @@ -687,12 +687,13 @@ TopLevelLiveRange::TopLevelLiveRange(int vreg, MachineType machine_type)
|
| last_child_id_(0),
|
| splintered_from_(nullptr),
|
| spill_operand_(nullptr),
|
| - spills_at_definition_(nullptr),
|
| + spill_move_insertion_locations_(nullptr),
|
| spilled_in_deferred_blocks_(false),
|
| spill_start_index_(kMaxInt),
|
| last_child_(this),
|
| last_pos_(nullptr),
|
| - splinter_(nullptr) {
|
| + splinter_(nullptr),
|
| + has_preassigned_slot_(false) {
|
| bits_ |= SpillTypeField::encode(SpillType::kNoSpillType);
|
| }
|
|
|
| @@ -704,11 +705,11 @@ int TopLevelLiveRange::debug_virt_reg() const {
|
| #endif
|
|
|
|
|
| -void TopLevelLiveRange::SpillAtDefinition(Zone* zone, int gap_index,
|
| - InstructionOperand* operand) {
|
| +void TopLevelLiveRange::RecordSpillLocation(Zone* zone, int gap_index,
|
| + InstructionOperand* operand) {
|
| DCHECK(HasNoSpillType());
|
| - spills_at_definition_ = new (zone)
|
| - SpillAtDefinitionList(gap_index, operand, spills_at_definition_);
|
| + spill_move_insertion_locations_ = new (zone) SpillMoveInsertionList(
|
| + gap_index, operand, spill_move_insertion_locations_);
|
| }
|
|
|
|
|
| @@ -754,7 +755,7 @@ void TopLevelLiveRange::MarkSpilledInDeferredBlock(
|
|
|
| spill_start_index_ = -1;
|
| spilled_in_deferred_blocks_ = true;
|
| - spills_at_definition_ = nullptr;
|
| + spill_move_insertion_locations_ = nullptr;
|
| }
|
|
|
|
|
| @@ -794,25 +795,26 @@ bool TopLevelLiveRange::TryCommitSpillInDeferredBlock(
|
| }
|
|
|
|
|
| -void TopLevelLiveRange::CommitSpillsAtDefinition(InstructionSequence* sequence,
|
| - const InstructionOperand& op,
|
| - bool might_be_duplicated) {
|
| - DCHECK_IMPLIES(op.IsConstant(), spills_at_definition_ == nullptr);
|
| +void TopLevelLiveRange::CommitSpillMoves(InstructionSequence* sequence,
|
| + const InstructionOperand& op,
|
| + bool might_be_duplicated) {
|
| + DCHECK_IMPLIES(op.IsConstant(), spill_move_insertion_locations() == nullptr);
|
| auto zone = sequence->zone();
|
|
|
| - for (auto to_spill = spills_at_definition_; to_spill != nullptr;
|
| + for (auto to_spill = spill_move_insertion_locations(); to_spill != nullptr;
|
| to_spill = to_spill->next) {
|
| auto instr = sequence->InstructionAt(to_spill->gap_index);
|
| auto move = instr->GetOrCreateParallelMove(Instruction::START, zone);
|
| // Skip insertion if it's possible that the move exists already as a
|
| // constraint move from a fixed output register to a slot.
|
| - if (might_be_duplicated) {
|
| + if (might_be_duplicated || has_preassigned_slot()) {
|
| bool found = false;
|
| for (auto move_op : *move) {
|
| if (move_op->IsEliminated()) continue;
|
| if (move_op->source().Equals(*to_spill->operand) &&
|
| move_op->destination().Equals(op)) {
|
| found = true;
|
| + if (has_preassigned_slot()) move_op->Eliminate();
|
| break;
|
| }
|
| }
|
| @@ -1609,7 +1611,7 @@ void ConstraintBuilder::MeetRegisterConstraintsForLastInstructionInBlock(
|
| const InstructionBlock* successor = code()->InstructionBlockAt(succ);
|
| DCHECK(successor->PredecessorCount() == 1);
|
| int gap_index = successor->first_instruction_index();
|
| - range->SpillAtDefinition(allocation_zone(), gap_index, output);
|
| + range->RecordSpillLocation(allocation_zone(), gap_index, output);
|
| range->SetSpillStartIndex(gap_index);
|
| }
|
| }
|
| @@ -1642,6 +1644,17 @@ void ConstraintBuilder::MeetConstraintsAfter(int instr_index) {
|
| int output_vreg = first_output->virtual_register();
|
| UnallocatedOperand output_copy(UnallocatedOperand::ANY, output_vreg);
|
| bool is_tagged = code()->IsReference(output_vreg);
|
| + if (first_output->HasSecondaryStorage()) {
|
| + range->MarkHasPreassignedSlot();
|
| + InstructionOperand* spill_op = AllocatedOperand::New(
|
| + data()->code_zone(), LocationOperand::LocationKind::STACK_SLOT,
|
| + range->machine_type(), first_output->GetSecondaryStorage());
|
| + range->RecordSpillLocation(allocation_zone(), instr_index + 1,
|
| + first_output);
|
| + range->SetSpillOperand(spill_op);
|
| + range->SetSpillStartIndex(instr_index + 1);
|
| + assigned = true;
|
| + }
|
| AllocateFixed(first_output, instr_index, is_tagged);
|
|
|
| // This value is produced on the stack, we never need to spill it.
|
| @@ -1658,8 +1671,8 @@ void ConstraintBuilder::MeetConstraintsAfter(int instr_index) {
|
| // Make sure we add a gap move for spilling (if we have not done
|
| // so already).
|
| if (!assigned) {
|
| - range->SpillAtDefinition(allocation_zone(), instr_index + 1,
|
| - first_output);
|
| + range->RecordSpillLocation(allocation_zone(), instr_index + 1,
|
| + first_output);
|
| range->SetSpillStartIndex(instr_index + 1);
|
| }
|
| }
|
| @@ -1744,7 +1757,7 @@ void ConstraintBuilder::ResolvePhis(const InstructionBlock* block) {
|
| }
|
| auto live_range = data()->GetOrCreateLiveRangeFor(phi_vreg);
|
| int gap_index = block->first_instruction_index();
|
| - live_range->SpillAtDefinition(allocation_zone(), gap_index, &output);
|
| + live_range->RecordSpillLocation(allocation_zone(), gap_index, &output);
|
| live_range->SetSpillStartIndex(gap_index);
|
| // We use the phi-ness of some nodes in some later heuristics.
|
| live_range->set_is_phi(true);
|
| @@ -2959,7 +2972,7 @@ void SpillSlotLocator::LocateSpillSlots() {
|
| }
|
| }
|
| } else {
|
| - auto spills = range->spills_at_definition();
|
| + auto spills = range->spill_move_insertion_locations();
|
| DCHECK_NOT_NULL(spills);
|
| for (; spills != nullptr; spills = spills->next) {
|
| code->GetInstructionBlock(spills->gap_index)->mark_needs_frame();
|
| @@ -3032,7 +3045,7 @@ void OperandAssigner::CommitAssignment() {
|
| spill_operand)) {
|
| // Spill at definition if the range isn't spilled only in deferred
|
| // blocks.
|
| - top_range->CommitSpillsAtDefinition(
|
| + top_range->CommitSpillMoves(
|
| data()->code(), spill_operand,
|
| top_range->has_slot_use() || top_range->spilled());
|
| }
|
| @@ -3073,6 +3086,7 @@ void ReferenceMapPopulator::PopulateReferenceMaps() {
|
| if (!data()->IsReference(range)) continue;
|
| // Skip empty live ranges.
|
| if (range->IsEmpty()) continue;
|
| + if (range->has_preassigned_slot()) continue;
|
|
|
| // Find the extent of the range and its children.
|
| int start = range->Start().ToInstructionIndex();
|
|
|