Commit 2dfba659 authored by Stephan Herhut's avatar Stephan Herhut Committed by Commit Bot

[regalloc] Prefer registers that are not used for arguments.

Simple experiment that prefers free registers that are not used for
arguments to prevent cases where we allocate a free register without
hint and thereby block later uses of that register for no good
reason.

Bug: v8:8311
Change-Id: I95e96b150410e97937cb72d575ae6bece9ee08f9
Reviewed-on: https://chromium-review.googlesource.com/c/1397668Reviewed-by: 's avatarSigurd Schneider <sigurds@chromium.org>
Commit-Queue: Stephan Herhut <herhut@chromium.org>
Cr-Commit-Position: refs/heads/master@{#58633}
parent 0adcb82a
...@@ -1413,6 +1413,11 @@ RegisterAllocationData::RegisterAllocationData( ...@@ -1413,6 +1413,11 @@ RegisterAllocationData::RegisterAllocationData(
BitVector(this->config()->num_general_registers(), code_zone()); BitVector(this->config()->num_general_registers(), code_zone());
assigned_double_registers_ = new (code_zone()) assigned_double_registers_ = new (code_zone())
BitVector(this->config()->num_double_registers(), code_zone()); BitVector(this->config()->num_double_registers(), code_zone());
fixed_register_use_ = new (code_zone())
BitVector(this->config()->num_general_registers(), code_zone());
fixed_fp_register_use_ = new (code_zone())
BitVector(this->config()->num_double_registers(), code_zone());
this->frame()->SetAllocatedRegisters(assigned_registers_); this->frame()->SetAllocatedRegisters(assigned_registers_);
this->frame()->SetAllocatedDoubleRegisters(assigned_double_registers_); this->frame()->SetAllocatedDoubleRegisters(assigned_double_registers_);
} }
...@@ -1567,6 +1572,63 @@ SpillRange* RegisterAllocationData::CreateSpillRangeForLiveRange( ...@@ -1567,6 +1572,63 @@ SpillRange* RegisterAllocationData::CreateSpillRangeForLiveRange(
return spill_range; return spill_range;
} }
void RegisterAllocationData::MarkFixedUse(MachineRepresentation rep,
int index) {
switch (rep) {
case MachineRepresentation::kFloat32:
case MachineRepresentation::kSimd128:
if (kSimpleFPAliasing) {
fixed_fp_register_use_->Add(index);
} else {
int alias_base_index = -1;
int aliases = config()->GetAliases(
rep, index, MachineRepresentation::kFloat64, &alias_base_index);
DCHECK(aliases > 0 || (aliases == 0 && alias_base_index == -1));
while (aliases--) {
int aliased_reg = alias_base_index + aliases;
fixed_fp_register_use_->Add(aliased_reg);
}
}
break;
case MachineRepresentation::kFloat64:
fixed_fp_register_use_->Add(index);
break;
default:
DCHECK(!IsFloatingPoint(rep));
fixed_register_use_->Add(index);
break;
}
}
bool RegisterAllocationData::HasFixedUse(MachineRepresentation rep, int index) {
switch (rep) {
case MachineRepresentation::kFloat32:
case MachineRepresentation::kSimd128:
if (kSimpleFPAliasing) {
return fixed_fp_register_use_->Contains(index);
} else {
int alias_base_index = -1;
int aliases = config()->GetAliases(
rep, index, MachineRepresentation::kFloat64, &alias_base_index);
DCHECK(aliases > 0 || (aliases == 0 && alias_base_index == -1));
bool result = false;
while (aliases-- && !result) {
int aliased_reg = alias_base_index + aliases;
result |= fixed_fp_register_use_->Contains(aliased_reg);
}
return result;
}
break;
case MachineRepresentation::kFloat64:
return fixed_fp_register_use_->Contains(index);
break;
default:
DCHECK(!IsFloatingPoint(rep));
return fixed_register_use_->Contains(index);
break;
}
}
void RegisterAllocationData::MarkAllocated(MachineRepresentation rep, void RegisterAllocationData::MarkAllocated(MachineRepresentation rep,
int index) { int index) {
switch (rep) { switch (rep) {
...@@ -1605,7 +1667,7 @@ ConstraintBuilder::ConstraintBuilder(RegisterAllocationData* data) ...@@ -1605,7 +1667,7 @@ ConstraintBuilder::ConstraintBuilder(RegisterAllocationData* data)
: data_(data) {} : data_(data) {}
InstructionOperand* ConstraintBuilder::AllocateFixed( InstructionOperand* ConstraintBuilder::AllocateFixed(
UnallocatedOperand* operand, int pos, bool is_tagged) { UnallocatedOperand* operand, int pos, bool is_tagged, bool is_input) {
TRACE("Allocating fixed reg for op %d\n", operand->virtual_register()); TRACE("Allocating fixed reg for op %d\n", operand->virtual_register());
DCHECK(operand->HasFixedPolicy()); DCHECK(operand->HasFixedPolicy());
InstructionOperand allocated; InstructionOperand allocated;
...@@ -1631,6 +1693,9 @@ InstructionOperand* ConstraintBuilder::AllocateFixed( ...@@ -1631,6 +1693,9 @@ InstructionOperand* ConstraintBuilder::AllocateFixed(
} else { } else {
UNREACHABLE(); UNREACHABLE();
} }
if (is_input && allocated.IsAnyRegister()) {
data()->MarkFixedUse(rep, operand->fixed_register_index());
}
InstructionOperand::ReplaceWith(operand, &allocated); InstructionOperand::ReplaceWith(operand, &allocated);
if (is_tagged) { if (is_tagged) {
TRACE("Fixed reg is tagged at %d\n", pos); TRACE("Fixed reg is tagged at %d\n", pos);
...@@ -1672,7 +1737,7 @@ void ConstraintBuilder::MeetRegisterConstraintsForLastInstructionInBlock( ...@@ -1672,7 +1737,7 @@ void ConstraintBuilder::MeetRegisterConstraintsForLastInstructionInBlock(
TopLevelLiveRange* range = data()->GetOrCreateLiveRangeFor(output_vreg); TopLevelLiveRange* range = data()->GetOrCreateLiveRangeFor(output_vreg);
bool assigned = false; bool assigned = false;
if (output->HasFixedPolicy()) { if (output->HasFixedPolicy()) {
AllocateFixed(output, -1, false); AllocateFixed(output, -1, false, false);
// This value is produced on the stack, we never need to spill it. // This value is produced on the stack, we never need to spill it.
if (output->IsStackSlot()) { if (output->IsStackSlot()) {
DCHECK(LocationOperand::cast(output)->index() < DCHECK(LocationOperand::cast(output)->index() <
...@@ -1711,7 +1776,7 @@ void ConstraintBuilder::MeetConstraintsAfter(int instr_index) { ...@@ -1711,7 +1776,7 @@ void ConstraintBuilder::MeetConstraintsAfter(int instr_index) {
// Handle fixed temporaries. // Handle fixed temporaries.
for (size_t i = 0; i < first->TempCount(); i++) { for (size_t i = 0; i < first->TempCount(); i++) {
UnallocatedOperand* temp = UnallocatedOperand::cast(first->TempAt(i)); UnallocatedOperand* temp = UnallocatedOperand::cast(first->TempAt(i));
if (temp->HasFixedPolicy()) AllocateFixed(temp, instr_index, false); if (temp->HasFixedPolicy()) AllocateFixed(temp, instr_index, false, false);
} }
// Handle constant/fixed output operands. // Handle constant/fixed output operands.
for (size_t i = 0; i < first->OutputCount(); i++) { for (size_t i = 0; i < first->OutputCount(); i++) {
...@@ -1737,7 +1802,7 @@ void ConstraintBuilder::MeetConstraintsAfter(int instr_index) { ...@@ -1737,7 +1802,7 @@ void ConstraintBuilder::MeetConstraintsAfter(int instr_index) {
data()->preassigned_slot_ranges().push_back( data()->preassigned_slot_ranges().push_back(
std::make_pair(range, first_output->GetSecondaryStorage())); std::make_pair(range, first_output->GetSecondaryStorage()));
} }
AllocateFixed(first_output, instr_index, is_tagged); AllocateFixed(first_output, instr_index, is_tagged, false);
// This value is produced on the stack, we never need to spill it. // This value is produced on the stack, we never need to spill it.
if (first_output->IsStackSlot()) { if (first_output->IsStackSlot()) {
...@@ -1774,7 +1839,7 @@ void ConstraintBuilder::MeetConstraintsBefore(int instr_index) { ...@@ -1774,7 +1839,7 @@ void ConstraintBuilder::MeetConstraintsBefore(int instr_index) {
UnallocatedOperand input_copy(UnallocatedOperand::REGISTER_OR_SLOT, UnallocatedOperand input_copy(UnallocatedOperand::REGISTER_OR_SLOT,
input_vreg); input_vreg);
bool is_tagged = code()->IsReference(input_vreg); bool is_tagged = code()->IsReference(input_vreg);
AllocateFixed(cur_input, instr_index, is_tagged); AllocateFixed(cur_input, instr_index, is_tagged, true);
data()->AddGapMove(instr_index, Instruction::END, input_copy, *cur_input); data()->AddGapMove(instr_index, Instruction::END, input_copy, *cur_input);
} }
} }
...@@ -3122,8 +3187,12 @@ bool LinearScanAllocator::TryAllocateFreeReg( ...@@ -3122,8 +3187,12 @@ bool LinearScanAllocator::TryAllocateFreeReg(
} }
for (int i = 0; i < num_codes; ++i) { for (int i = 0; i < num_codes; ++i) {
int code = codes[i]; int code = codes[i];
if (free_until_pos[code].ToInstructionIndex() > // Prefer registers that have no fixed uses to avoid blocking later hints.
free_until_pos[reg].ToInstructionIndex()) { int candidate_free = free_until_pos[code].ToInstructionIndex();
int current_free = free_until_pos[reg].ToInstructionIndex();
if (candidate_free > current_free ||
(candidate_free == current_free &&
!data()->HasFixedUse(current->representation(), code))) {
reg = code; reg = code;
} }
} }
......
...@@ -813,6 +813,9 @@ class RegisterAllocationData final : public ZoneObject { ...@@ -813,6 +813,9 @@ class RegisterAllocationData final : public ZoneObject {
bool ExistsUseWithoutDefinition(); bool ExistsUseWithoutDefinition();
bool RangesDefinedInDeferredStayInDeferred(); bool RangesDefinedInDeferredStayInDeferred();
void MarkFixedUse(MachineRepresentation rep, int index);
bool HasFixedUse(MachineRepresentation rep, int index);
void MarkAllocated(MachineRepresentation rep, int index); void MarkAllocated(MachineRepresentation rep, int index);
PhiMapValue* InitializePhiMap(const InstructionBlock* block, PhiMapValue* InitializePhiMap(const InstructionBlock* block,
...@@ -845,6 +848,8 @@ class RegisterAllocationData final : public ZoneObject { ...@@ -845,6 +848,8 @@ class RegisterAllocationData final : public ZoneObject {
DelayedReferences delayed_references_; DelayedReferences delayed_references_;
BitVector* assigned_registers_; BitVector* assigned_registers_;
BitVector* assigned_double_registers_; BitVector* assigned_double_registers_;
BitVector* fixed_register_use_;
BitVector* fixed_fp_register_use_;
int virtual_register_count_; int virtual_register_count_;
RangesWithPreassignedSlots preassigned_slot_ranges_; RangesWithPreassignedSlots preassigned_slot_ranges_;
...@@ -868,7 +873,7 @@ class ConstraintBuilder final : public ZoneObject { ...@@ -868,7 +873,7 @@ class ConstraintBuilder final : public ZoneObject {
Zone* allocation_zone() const { return data()->allocation_zone(); } Zone* allocation_zone() const { return data()->allocation_zone(); }
InstructionOperand* AllocateFixed(UnallocatedOperand* operand, int pos, InstructionOperand* AllocateFixed(UnallocatedOperand* operand, int pos,
bool is_tagged); bool is_tagged, bool is_input);
void MeetRegisterConstraints(const InstructionBlock* block); void MeetRegisterConstraints(const InstructionBlock* block);
void MeetConstraintsBefore(int index); void MeetConstraintsBefore(int index);
void MeetConstraintsAfter(int index); void MeetConstraintsAfter(int index);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment