Commit 7e7661a1 authored by Toon Verwaest's avatar Toon Verwaest Committed by V8 LUCI CQ

[maglev] Free a duplicate reg in FreeSomeRegister

If a value is in multiple registers, pick one of them to be freed.

Bug: v8:7700
Change-Id: I1886b977187b4d8e939ff106edde4ccf716661d7
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3522063
Auto-Submit: Toon Verwaest <verwaest@chromium.org>
Reviewed-by: 's avatarLeszek Swirski <leszeks@chromium.org>
Commit-Queue: Leszek Swirski <leszeks@chromium.org>
Cr-Commit-Position: refs/heads/main@{#79463}
parent 9694d9b6
...@@ -592,6 +592,8 @@ class ValueNode : public Node { ...@@ -592,6 +592,8 @@ class ValueNode : public Node {
RegList ClearRegisters() { RegList ClearRegisters() {
return std::exchange(registers_with_result_, kEmptyRegList); return std::exchange(registers_with_result_, kEmptyRegList);
} }
int num_registers() const { return registers_with_result_.Count(); }
bool has_register() const { return registers_with_result_ != kEmptyRegList; } bool has_register() const { return registers_with_result_ != kEmptyRegList; }
compiler::AllocatedOperand allocation() const { compiler::AllocatedOperand allocation() const {
......
...@@ -199,7 +199,7 @@ void StraightForwardRegisterAllocator::ComputePostDominatingHoles( ...@@ -199,7 +199,7 @@ void StraightForwardRegisterAllocator::ComputePostDominatingHoles(
void StraightForwardRegisterAllocator::PrintLiveRegs() const { void StraightForwardRegisterAllocator::PrintLiveRegs() const {
bool first = true; bool first = true;
for (Register reg : used_registers()) { for (Register reg : used_registers()) {
ValueNode* node = GetUsedRegister(reg); ValueNode* node = GetRegisterValue(reg);
if (first) { if (first) {
first = false; first = false;
} else { } else {
...@@ -414,7 +414,7 @@ void StraightForwardRegisterAllocator::DropRegisterValue(Register reg) { ...@@ -414,7 +414,7 @@ void StraightForwardRegisterAllocator::DropRegisterValue(Register reg) {
// The register should not already be free. // The register should not already be free.
DCHECK(!free_registers_.has(reg)); DCHECK(!free_registers_.has(reg));
ValueNode* node = GetUsedRegister(reg); ValueNode* node = GetRegisterValue(reg);
// Remove the register from the node's list. // Remove the register from the node's list.
node->RemoveRegister(reg); node->RemoveRegister(reg);
...@@ -464,7 +464,7 @@ void StraightForwardRegisterAllocator::InitializeConditionalBranchRegisters( ...@@ -464,7 +464,7 @@ void StraightForwardRegisterAllocator::InitializeConditionalBranchRegisters(
RegList registers = used_registers(); RegList registers = used_registers();
while (registers != kEmptyRegList) { while (registers != kEmptyRegList) {
Register reg = registers.PopFirst(); Register reg = registers.PopFirst();
ValueNode* node = GetUsedRegister(reg); ValueNode* node = GetRegisterValue(reg);
if (!IsLiveAtTarget(node, control_node, target)) { if (!IsLiveAtTarget(node, control_node, target)) {
FreeRegisters(node); FreeRegisters(node);
// Update the registers we're visiting to avoid revisiting this node. // Update the registers we're visiting to avoid revisiting this node.
...@@ -612,7 +612,7 @@ void StraightForwardRegisterAllocator::AssignInput(Input& input) { ...@@ -612,7 +612,7 @@ void StraightForwardRegisterAllocator::AssignInput(Input& input) {
void StraightForwardRegisterAllocator::SpillRegisters() { void StraightForwardRegisterAllocator::SpillRegisters() {
for (Register reg : used_registers()) { for (Register reg : used_registers()) {
ValueNode* node = GetUsedRegister(reg); ValueNode* node = GetRegisterValue(reg);
Spill(node); Spill(node);
} }
} }
...@@ -620,7 +620,7 @@ void StraightForwardRegisterAllocator::SpillRegisters() { ...@@ -620,7 +620,7 @@ void StraightForwardRegisterAllocator::SpillRegisters() {
void StraightForwardRegisterAllocator::SpillAndClearRegisters() { void StraightForwardRegisterAllocator::SpillAndClearRegisters() {
while (used_registers() != kEmptyRegList) { while (used_registers() != kEmptyRegList) {
Register reg = used_registers().first(); Register reg = used_registers().first();
ValueNode* node = GetUsedRegister(reg); ValueNode* node = GetRegisterValue(reg);
Spill(node); Spill(node);
FreeRegisters(node); FreeRegisters(node);
DCHECK(!used_registers().has(reg)); DCHECK(!used_registers().has(reg));
...@@ -645,7 +645,14 @@ void StraightForwardRegisterAllocator::FreeSomeRegister() { ...@@ -645,7 +645,14 @@ void StraightForwardRegisterAllocator::FreeSomeRegister() {
int furthest_use = 0; int furthest_use = 0;
Register best = Register::no_reg(); Register best = Register::no_reg();
for (Register reg : used_registers()) { for (Register reg : used_registers()) {
int use = GetUsedRegister(reg)->next_use(); ValueNode* value = GetRegisterValue(reg);
// The cheapest register to clear is a register containing a value that's
// contained in another register as well.
if (value->num_registers() > 1) {
best = reg;
break;
}
int use = value->next_use();
if (use > furthest_use) { if (use > furthest_use) {
furthest_use = use; furthest_use = use;
best = reg; best = reg;
...@@ -668,7 +675,7 @@ compiler::AllocatedOperand StraightForwardRegisterAllocator::ForceAllocate( ...@@ -668,7 +675,7 @@ compiler::AllocatedOperand StraightForwardRegisterAllocator::ForceAllocate(
if (free_registers_.has(reg)) { if (free_registers_.has(reg)) {
// If it's already free, remove it from the free list. // If it's already free, remove it from the free list.
free_registers_.clear(reg); free_registers_.clear(reg);
} else if (GetUsedRegister(reg) == node) { } else if (GetRegisterValue(reg) == node) {
return compiler::AllocatedOperand(compiler::LocationOperand::REGISTER, return compiler::AllocatedOperand(compiler::LocationOperand::REGISTER,
MachineRepresentation::kTagged, MachineRepresentation::kTagged,
reg.code()); reg.code());
...@@ -720,7 +727,7 @@ void StraightForwardRegisterAllocator::InitializeRegisterValues( ...@@ -720,7 +727,7 @@ void StraightForwardRegisterAllocator::InitializeRegisterValues(
// First clear the register state. // First clear the register state.
while (used_registers() != kEmptyRegList) { while (used_registers() != kEmptyRegList) {
Register reg = used_registers().first(); Register reg = used_registers().first();
ValueNode* node = GetUsedRegister(reg); ValueNode* node = GetRegisterValue(reg);
FreeRegisters(node); FreeRegisters(node);
DCHECK(!used_registers().has(reg)); DCHECK(!used_registers().has(reg));
} }
...@@ -766,7 +773,7 @@ void StraightForwardRegisterAllocator::InitializeBranchTargetRegisterValues( ...@@ -766,7 +773,7 @@ void StraightForwardRegisterAllocator::InitializeBranchTargetRegisterValues(
Register reg = entry.reg; Register reg = entry.reg;
ValueNode* node = nullptr; ValueNode* node = nullptr;
if (!free_registers_.has(reg)) { if (!free_registers_.has(reg)) {
node = GetUsedRegister(reg); node = GetRegisterValue(reg);
if (!IsLiveAtTarget(node, source, target)) node = nullptr; if (!IsLiveAtTarget(node, source, target)) node = nullptr;
} }
entry.state = {node, initialized_node}; entry.state = {node, initialized_node};
...@@ -796,7 +803,7 @@ void StraightForwardRegisterAllocator::MergeRegisterValues(ControlNode* control, ...@@ -796,7 +803,7 @@ void StraightForwardRegisterAllocator::MergeRegisterValues(ControlNode* control,
ValueNode* incoming = nullptr; ValueNode* incoming = nullptr;
if (!free_registers_.has(reg)) { if (!free_registers_.has(reg)) {
incoming = GetUsedRegister(reg); incoming = GetRegisterValue(reg);
if (!IsLiveAtTarget(incoming, control, target)) { if (!IsLiveAtTarget(incoming, control, target)) {
incoming = nullptr; incoming = nullptr;
} }
......
...@@ -62,18 +62,13 @@ class StraightForwardRegisterAllocator { ...@@ -62,18 +62,13 @@ class StraightForwardRegisterAllocator {
} }
void FreeRegister(Register reg) { free_registers_.set(reg); } void FreeRegister(Register reg) { free_registers_.set(reg); }
ValueNode* GetUsedRegister(Register reg) const { ValueNode* GetRegisterValue(Register reg) const {
DCHECK(!free_registers_.has(reg)); DCHECK(!free_registers_.has(reg));
ValueNode* node = register_values_[reg.code()]; ValueNode* node = register_values_[reg.code()];
DCHECK_NOT_NULL(node); DCHECK_NOT_NULL(node);
return node; return node;
} }
ValueNode* GetMaybeUsedRegister(Register reg) const {
if (!free_registers_.has(reg)) return nullptr;
return GetUsedRegister(reg);
}
void FreeSomeRegister(); void FreeSomeRegister();
void AddMoveBeforeCurrentNode(compiler::AllocatedOperand source, void AddMoveBeforeCurrentNode(compiler::AllocatedOperand source,
compiler::AllocatedOperand target); compiler::AllocatedOperand target);
......
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