[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/1397668
Reviewed-by: Sigurd Schneider <sigurds@chromium.org>
Commit-Queue: Stephan Herhut <herhut@chromium.org>
Cr-Commit-Position: refs/heads/master@{#58633}
diff --git a/src/compiler/backend/register-allocator.cc b/src/compiler/backend/register-allocator.cc
index cf8ddf1..449bc1a 100644
--- a/src/compiler/backend/register-allocator.cc
+++ b/src/compiler/backend/register-allocator.cc
@@ -1413,6 +1413,11 @@
BitVector(this->config()->num_general_registers(), code_zone());
assigned_double_registers_ = new (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()->SetAllocatedDoubleRegisters(assigned_double_registers_);
}
@@ -1567,6 +1572,63 @@
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,
int index) {
switch (rep) {
@@ -1605,7 +1667,7 @@
: data_(data) {}
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());
DCHECK(operand->HasFixedPolicy());
InstructionOperand allocated;
@@ -1631,6 +1693,9 @@
} else {
UNREACHABLE();
}
+ if (is_input && allocated.IsAnyRegister()) {
+ data()->MarkFixedUse(rep, operand->fixed_register_index());
+ }
InstructionOperand::ReplaceWith(operand, &allocated);
if (is_tagged) {
TRACE("Fixed reg is tagged at %d\n", pos);
@@ -1672,7 +1737,7 @@
TopLevelLiveRange* range = data()->GetOrCreateLiveRangeFor(output_vreg);
bool assigned = false;
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.
if (output->IsStackSlot()) {
DCHECK(LocationOperand::cast(output)->index() <
@@ -1711,7 +1776,7 @@
// Handle fixed temporaries.
for (size_t i = 0; i < first->TempCount(); 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.
for (size_t i = 0; i < first->OutputCount(); i++) {
@@ -1737,7 +1802,7 @@
data()->preassigned_slot_ranges().push_back(
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.
if (first_output->IsStackSlot()) {
@@ -1774,7 +1839,7 @@
UnallocatedOperand input_copy(UnallocatedOperand::REGISTER_OR_SLOT,
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);
}
}
@@ -3122,8 +3187,12 @@
}
for (int i = 0; i < num_codes; ++i) {
int code = codes[i];
- if (free_until_pos[code].ToInstructionIndex() >
- free_until_pos[reg].ToInstructionIndex()) {
+ // Prefer registers that have no fixed uses to avoid blocking later hints.
+ 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;
}
}
diff --git a/src/compiler/backend/register-allocator.h b/src/compiler/backend/register-allocator.h
index e48091e..579e4d3 100644
--- a/src/compiler/backend/register-allocator.h
+++ b/src/compiler/backend/register-allocator.h
@@ -813,6 +813,9 @@
bool ExistsUseWithoutDefinition();
bool RangesDefinedInDeferredStayInDeferred();
+ void MarkFixedUse(MachineRepresentation rep, int index);
+ bool HasFixedUse(MachineRepresentation rep, int index);
+
void MarkAllocated(MachineRepresentation rep, int index);
PhiMapValue* InitializePhiMap(const InstructionBlock* block,
@@ -845,6 +848,8 @@
DelayedReferences delayed_references_;
BitVector* assigned_registers_;
BitVector* assigned_double_registers_;
+ BitVector* fixed_register_use_;
+ BitVector* fixed_fp_register_use_;
int virtual_register_count_;
RangesWithPreassignedSlots preassigned_slot_ranges_;
@@ -868,7 +873,7 @@
Zone* allocation_zone() const { return data()->allocation_zone(); }
InstructionOperand* AllocateFixed(UnallocatedOperand* operand, int pos,
- bool is_tagged);
+ bool is_tagged, bool is_input);
void MeetRegisterConstraints(const InstructionBlock* block);
void MeetConstraintsBefore(int index);
void MeetConstraintsAfter(int index);