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(); |