Commit 785fc6bd authored by Toon Verwaest's avatar Toon Verwaest Committed by V8 LUCI CQ

[maglev] Keep an array of free registers and a vector of stack slots

Instead of scanning the array of registers, keep an explicit list of
free registers. Stack slots are equally changed to use an std::vector of
free slots instead of a linked list. Now we only need to scan
- the list of free registers when we want to allocate a specific
  register,
- and scan the list of allocated registers to see if the free value is
  already in a different register,
- scan the list of allocated registers to free some register if we don't
  have enough registers (for input, output, or temp).

Bug: v8:7700
Change-Id: Iff41b06aae656b59e4ed25e9066671a21660a73e
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3489487Reviewed-by: 's avatarLeszek Swirski <leszeks@chromium.org>
Commit-Queue: Toon Verwaest <verwaest@chromium.org>
Auto-Submit: Toon Verwaest <verwaest@chromium.org>
Cr-Commit-Position: refs/heads/main@{#79278}
parent 72f105fe
...@@ -525,12 +525,14 @@ void CheckMaps::GenerateCode(MaglevCodeGenState* code_gen_state, ...@@ -525,12 +525,14 @@ void CheckMaps::GenerateCode(MaglevCodeGenState* code_gen_state,
__ Push(object); __ Push(object);
__ Move(kContextRegister, __ Move(kContextRegister,
code_gen_state->broker()->target_native_context().object()); code_gen_state->broker()->target_native_context().object());
// TODO(verwaest): We're calling so we need to spill around it.
__ CallRuntime(Runtime::kTryMigrateInstance); __ CallRuntime(Runtime::kTryMigrateInstance);
__ cmpl(kReturnRegister0, Immediate(0)); __ cmpl(kReturnRegister0, Immediate(0));
__ j(equal, &deopt); __ j(equal, &deopt);
// The migrated object is returned on success, retry the map check. // The migrated object is returned on success, retry the map check.
__ LoadMap(map_tmp, kReturnRegister0); __ Move(object, kReturnRegister0);
__ LoadMap(map_tmp, object);
__ Cmp(map_tmp, node->map().object()); __ Cmp(map_tmp, node->map().object());
__ j(equal, return_label); __ j(equal, return_label);
......
...@@ -818,7 +818,11 @@ class CheckMaps : public FixedInputNodeT<1, CheckMaps> { ...@@ -818,7 +818,11 @@ class CheckMaps : public FixedInputNodeT<1, CheckMaps> {
explicit CheckMaps(size_t input_count, const compiler::MapRef& map) explicit CheckMaps(size_t input_count, const compiler::MapRef& map)
: Base(input_count), map_(map) {} : Base(input_count), map_(map) {}
static constexpr OpProperties kProperties = OpProperties::Deopt(); // TODO(verwaest): This just calls in deferred code, so probably we'll need to
// mark that to generate stack maps. Mark as call so we at least clear the
// registers since we currently don't properly spill either.
static constexpr OpProperties kProperties =
OpProperties::Deopt() | OpProperties::Call();
compiler::MapRef map() const { return map_; } compiler::MapRef map() const { return map_; }
......
...@@ -13,6 +13,7 @@ ...@@ -13,6 +13,7 @@
#include "src/maglev/maglev-graph.h" #include "src/maglev/maglev-graph.h"
#include "src/maglev/maglev-interpreter-frame-state.h" #include "src/maglev/maglev-interpreter-frame-state.h"
#include "src/maglev/maglev-ir.h" #include "src/maglev/maglev-ir.h"
#include "src/maglev/maglev-regalloc-data.h"
namespace v8 { namespace v8 {
namespace internal { namespace internal {
...@@ -77,6 +78,9 @@ StraightForwardRegisterAllocator::StraightForwardRegisterAllocator( ...@@ -77,6 +78,9 @@ StraightForwardRegisterAllocator::StraightForwardRegisterAllocator(
MaglevCompilationUnit* compilation_unit, Graph* graph) MaglevCompilationUnit* compilation_unit, Graph* graph)
: compilation_unit_(compilation_unit) { : compilation_unit_(compilation_unit) {
ComputePostDominatingHoles(graph); ComputePostDominatingHoles(graph);
for (int i = 0; i < kAllocatableGeneralRegisterCount; i++) {
free_registers_[i] = i;
}
AllocateRegisters(graph); AllocateRegisters(graph);
graph->set_stack_slots(top_of_stack_); graph->set_stack_slots(top_of_stack_);
} }
...@@ -281,7 +285,8 @@ void StraightForwardRegisterAllocator::AllocateRegisters(Graph* graph) { ...@@ -281,7 +285,8 @@ void StraightForwardRegisterAllocator::AllocateRegisters(Graph* graph) {
LiveNodeInfo& info = values_[phi]; LiveNodeInfo& info = values_[phi];
AllocateSpillSlot(&info); AllocateSpillSlot(&info);
// TODO(verwaest): Will this be used at all? // TODO(verwaest): Will this be used at all?
phi->result().SetAllocated(info.stack_slot->slot); phi->result().SetAllocated(
compiler::AllocatedOperand::cast(info.stack_slot));
if (FLAG_trace_maglev_regalloc) { if (FLAG_trace_maglev_regalloc) {
printing_visitor_->Process( printing_visitor_->Process(
phi, ProcessingState(compilation_unit_, block_it_, nullptr, phi, ProcessingState(compilation_unit_, block_it_, nullptr,
...@@ -315,8 +320,8 @@ class StraightForwardRegisterAllocator::InputsUpdater { ...@@ -315,8 +320,8 @@ class StraightForwardRegisterAllocator::InputsUpdater {
void UpdateInputUse(const Input& input) { void UpdateInputUse(const Input& input) {
ValueNode* node = input.node(); ValueNode* node = input.node();
auto it = allocator_->values_.find(node); auto it = allocator_->values_.find(node);
// If a value is dead, make sure it's cleared.
if (node->live_range().end == use_) { if (node->live_range().end == use_) {
// If a value is dead, make sure it's cleared.
// Mark the info for clearing by clearing the node. // Mark the info for clearing by clearing the node.
if (it->second.node == nullptr) return; if (it->second.node == nullptr) return;
if (it->second.reg.is_valid()) { if (it->second.reg.is_valid()) {
...@@ -347,7 +352,7 @@ class StraightForwardRegisterAllocator::InputsUpdater { ...@@ -347,7 +352,7 @@ class StraightForwardRegisterAllocator::InputsUpdater {
// DCHECK_GT(value->last_use, use_); // DCHECK_GT(value->last_use, use_);
continue; continue;
} }
allocator_->register_values_[i] = nullptr; allocator_->FreeRegister(i);
} }
// Then clear the infos. // Then clear the infos.
for (int i = 0; i < register_values_to_clear_; i++) Clear(to_clear_[i]); for (int i = 0; i < register_values_to_clear_; i++) Clear(to_clear_[i]);
...@@ -357,8 +362,10 @@ class StraightForwardRegisterAllocator::InputsUpdater { ...@@ -357,8 +362,10 @@ class StraightForwardRegisterAllocator::InputsUpdater {
void Clear(LiveNodeInfoMap::iterator& it) { void Clear(LiveNodeInfoMap::iterator& it) {
LiveNodeInfo& info = it->second; LiveNodeInfo& info = it->second;
// If the stack slot is a local slot, free it so it can be reused. // If the stack slot is a local slot, free it so it can be reused.
if (info.stack_slot != nullptr && info.stack_slot->slot.index() > 0) { if (info.stack_slot.IsAnyStackSlot()) {
allocator_->free_slots_.Add(info.stack_slot); compiler::AllocatedOperand slot =
compiler::AllocatedOperand::cast(info.stack_slot);
if (slot.index() > 0) allocator_->free_slots_.push_back(slot.index());
} }
allocator_->values_.erase(it); allocator_->values_.erase(it);
} }
...@@ -407,9 +414,10 @@ void StraightForwardRegisterAllocator::AllocateNodeResult(ValueNode* node) { ...@@ -407,9 +414,10 @@ void StraightForwardRegisterAllocator::AllocateNodeResult(ValueNode* node) {
DCHECK(node->Is<InitialValue>()); DCHECK(node->Is<InitialValue>());
DCHECK_LT(operand.fixed_slot_index(), 0); DCHECK_LT(operand.fixed_slot_index(), 0);
// Set the stack slot to exactly where the value is. // Set the stack slot to exactly where the value is.
info->stack_slot = compilation_unit_->zone()->New<StackSlot>( node->result().SetAllocated(compiler::AllocatedOperand::STACK_SLOT,
MachineRepresentation::kTagged, operand.fixed_slot_index()); MachineRepresentation::kTagged,
node->result().SetAllocated(info->stack_slot->slot); operand.fixed_slot_index());
info->stack_slot = node->result().operand();
return; return;
} }
...@@ -448,18 +456,18 @@ void StraightForwardRegisterAllocator::AllocateNodeResult(ValueNode* node) { ...@@ -448,18 +456,18 @@ void StraightForwardRegisterAllocator::AllocateNodeResult(ValueNode* node) {
Register reg = it->second.reg; Register reg = it->second.reg;
DCHECK(reg.is_valid()); DCHECK(reg.is_valid());
values_.erase(it); values_.erase(it);
register_values_[MapRegisterToIndex(reg)] = nullptr; FreeRegister(MapRegisterToIndex(reg));
} }
} }
void StraightForwardRegisterAllocator::Free(const Register& reg, void StraightForwardRegisterAllocator::Free(const Register& reg) {
bool try_move) {
int index = MapRegisterToIndex(reg); int index = MapRegisterToIndex(reg);
LiveNodeInfo* info = register_values_[index]; LiveNodeInfo* info = register_values_[index];
// If the register is already free, return. // If the register is already free, return.
if (info == nullptr) return; if (info == nullptr) return;
// Free the register without adding it to the list.
register_values_[index] = nullptr; register_values_[index] = nullptr;
// If the value we're freeing from the register is already known to be // If the value we're freeing from the register is already known to be
...@@ -472,52 +480,37 @@ void StraightForwardRegisterAllocator::Free(const Register& reg, ...@@ -472,52 +480,37 @@ void StraightForwardRegisterAllocator::Free(const Register& reg,
info->reg = Register::no_reg(); info->reg = Register::no_reg();
// If the value is already spilled, return. // If the value is already spilled, return.
if (info->stack_slot != nullptr) return; if (info->stack_slot.IsAnyStackSlot()) return;
if (try_move) { // If the value is already in another register, return.
// Try to move the value to another register. for (int i = 0; i < kAllocatableGeneralRegisterCount; i++) {
int index = -1; if (register_values_[i] == info) {
int skip = MapRegisterToIndex(reg); // Found an existing register.
for (int i = 0; i < kAllocatableGeneralRegisterCount; i++) { info->reg = MapIndexToRegister(i);
if (i == skip) continue; return;
if (register_values_[i] == nullptr) {
index = i;
} else if (register_values_[i]->node == info->node) {
// Found an existing register.
info->reg = MapIndexToRegister(i);
return;
}
} }
}
// Allocation succeeded. This might have found an existing allocation. // Try to move the value to another register.
// Simply update the state anyway. if (free_register_size_ > 0) {
if (index != -1) { Register target_reg =
Register target_reg = MapIndexToRegister(index); MapIndexToRegister(free_registers_[--free_register_size_]);
SetRegister(target_reg, info); SetRegister(target_reg, info);
// Emit a gapmove. // Emit a gapmove.
compiler::AllocatedOperand source(compiler::LocationOperand::REGISTER, compiler::AllocatedOperand source(compiler::LocationOperand::REGISTER,
MachineRepresentation::kTagged, MachineRepresentation::kTagged,
reg.code()); reg.code());
compiler::AllocatedOperand target(compiler::LocationOperand::REGISTER, compiler::AllocatedOperand target(compiler::LocationOperand::REGISTER,
MachineRepresentation::kTagged, MachineRepresentation::kTagged,
target_reg.code()); target_reg.code());
if (FLAG_trace_maglev_regalloc) { if (FLAG_trace_maglev_regalloc) {
printing_visitor_->os() << "gap move: "; printing_visitor_->os() << "gap move: ";
graph_labeller()->PrintNodeLabel(std::cout, info->node); graph_labeller()->PrintNodeLabel(std::cout, info->node);
printing_visitor_->os() printing_visitor_->os() << ": " << target << " ← " << source << std::endl;
<< ": " << target << " ← " << source << std::endl;
}
AddMoveBeforeCurrentNode(source, target);
return;
}
} else {
for (int i = 0; i < kAllocatableGeneralRegisterCount; i++) {
if (register_values_[i] == info) {
info->reg = MapIndexToRegister(i);
return;
}
} }
AddMoveBeforeCurrentNode(source, target);
return;
} }
// If all else fails, spill the value. // If all else fails, spill the value.
...@@ -542,7 +535,7 @@ void StraightForwardRegisterAllocator::InitializeConditionalBranchRegisters( ...@@ -542,7 +535,7 @@ void StraightForwardRegisterAllocator::InitializeConditionalBranchRegisters(
LiveNodeInfo* info = register_values_[i]; LiveNodeInfo* info = register_values_[i];
if (info != nullptr && !IsLiveAtTarget(info, node, target)) { if (info != nullptr && !IsLiveAtTarget(info, node, target)) {
info->reg = Register::no_reg(); info->reg = Register::no_reg();
register_values_[i] = nullptr; FreeRegister(i);
} }
} }
} }
...@@ -607,7 +600,7 @@ void StraightForwardRegisterAllocator::TryAllocateToInput(LiveNodeInfo* info, ...@@ -607,7 +600,7 @@ void StraightForwardRegisterAllocator::TryAllocateToInput(LiveNodeInfo* info,
Register reg = input.AssignedRegister(); Register reg = input.AssignedRegister();
int index = MapRegisterToIndex(reg); int index = MapRegisterToIndex(reg);
if (register_values_[index] == nullptr) { if (register_values_[index] == nullptr) {
phi->result().SetAllocated(DoAllocate(reg, info)); phi->result().SetAllocated(ForceAllocate(reg, info));
if (FLAG_trace_maglev_regalloc) { if (FLAG_trace_maglev_regalloc) {
Phi* phi = info->node->Cast<Phi>(); Phi* phi = info->node->Cast<Phi>();
printing_visitor_->Process( printing_visitor_->Process(
...@@ -640,14 +633,14 @@ void StraightForwardRegisterAllocator::AddMoveBeforeCurrentNode( ...@@ -640,14 +633,14 @@ void StraightForwardRegisterAllocator::AddMoveBeforeCurrentNode(
} }
void StraightForwardRegisterAllocator::Spill(LiveNodeInfo* info) { void StraightForwardRegisterAllocator::Spill(LiveNodeInfo* info) {
if (info->stack_slot != nullptr) return; if (info->stack_slot.IsAnyStackSlot()) return;
AllocateSpillSlot(info); AllocateSpillSlot(info);
if (FLAG_trace_maglev_regalloc) { if (FLAG_trace_maglev_regalloc) {
printing_visitor_->os() printing_visitor_->os()
<< "spill: " << info->stack_slot->slot << " ← v" << "spill: " << info->stack_slot << " ← v"
<< graph_labeller()->NodeId(info->node) << std::endl; << graph_labeller()->NodeId(info->node) << std::endl;
} }
info->node->Spill(info->stack_slot->slot); info->node->Spill(compiler::AllocatedOperand::cast(info->stack_slot));
} }
void StraightForwardRegisterAllocator::AssignInput(Input& input) { void StraightForwardRegisterAllocator::AssignInput(Input& input) {
...@@ -702,97 +695,92 @@ void StraightForwardRegisterAllocator::SpillRegisters() { ...@@ -702,97 +695,92 @@ void StraightForwardRegisterAllocator::SpillRegisters() {
} }
} }
void StraightForwardRegisterAllocator::FreeRegister(int i) {
register_values_[i] = nullptr;
free_registers_[free_register_size_++] = i;
}
void StraightForwardRegisterAllocator::SpillAndClearRegisters() { void StraightForwardRegisterAllocator::SpillAndClearRegisters() {
for (int i = 0; i < kAllocatableGeneralRegisterCount; i++) { for (int i = 0; i < kAllocatableGeneralRegisterCount; i++) {
LiveNodeInfo* info = register_values_[i]; LiveNodeInfo* info = register_values_[i];
if (info == nullptr) continue; if (info == nullptr) continue;
Spill(info); Spill(info);
info->reg = Register::no_reg(); info->reg = Register::no_reg();
register_values_[i] = nullptr; FreeRegister(i);
} }
} }
void StraightForwardRegisterAllocator::AllocateSpillSlot(LiveNodeInfo* info) { void StraightForwardRegisterAllocator::AllocateSpillSlot(LiveNodeInfo* info) {
DCHECK_NULL(info->stack_slot); DCHECK(info->stack_slot.IsInvalid());
StackSlot* stack_slot = free_slots_.first(); uint32_t free_slot;
if (stack_slot == nullptr) { if (free_slots_.empty()) {
// If there are no free stack slots, allocate a new one. free_slot = top_of_stack_++;
stack_slot = compilation_unit_->zone()->New<StackSlot>(
MachineRepresentation::kTagged, top_of_stack_++);
} else { } else {
free_slots_.DropHead(); free_slot = free_slots_.back();
free_slots_.pop_back();
} }
info->stack_slot = stack_slot; info->stack_slot =
compiler::AllocatedOperand(compiler::AllocatedOperand::STACK_SLOT,
MachineRepresentation::kTagged, free_slot);
} }
RegList StraightForwardRegisterAllocator::GetFreeRegisters(int count) { RegList StraightForwardRegisterAllocator::GetFreeRegisters(int count) {
RegList free_registers = {}; RegList free_registers = {};
if (count == 0) return free_registers; while (count > free_register_size_) FreeSomeRegister();
for (int i = 0; i < kAllocatableGeneralRegisterCount; i++) { for (int i = 0; i < count; i++) {
if (register_values_[i] == nullptr) { Register reg = MapIndexToRegister(free_registers_[--free_register_size_]);
free_registers = CombineRegLists(free_registers, free_registers = CombineRegLists(free_registers, Register::ListOf(reg));
Register::ListOf(MapIndexToRegister(i)));
if (--count == 0) return free_registers;
}
} }
return free_registers;
}
void StraightForwardRegisterAllocator::FreeSomeRegister() {
int furthest_use = 0; int furthest_use = 0;
int longest = -1; int longest = -1;
while (count != 0) { for (int i = 0; i < kAllocatableGeneralRegisterCount; i++) {
// Free some register. if (!register_values_[i]) continue;
DCHECK_NOT_NULL(register_values_[0]); int use = register_values_[i]->next_use;
for (int i = 0; i < kAllocatableGeneralRegisterCount; i++) { if (use > furthest_use) {
if (!register_values_[i]) continue; furthest_use = use;
int use = register_values_[i]->next_use; longest = i;
if (use > furthest_use) {
furthest_use = use;
longest = i;
}
} }
DCHECK_NE(-1, longest);
Register reg = MapIndexToRegister(longest);
Free(reg, false);
free_registers = CombineRegLists(free_registers, Register::ListOf(reg));
count--;
} }
return free_registers; FreeRegister(longest);
} }
compiler::AllocatedOperand StraightForwardRegisterAllocator::AllocateRegister( compiler::AllocatedOperand StraightForwardRegisterAllocator::AllocateRegister(
LiveNodeInfo* info) { LiveNodeInfo* info) {
if (free_register_size_ == 0) FreeSomeRegister();
compiler::InstructionOperand allocation = TryAllocateRegister(info); compiler::InstructionOperand allocation = TryAllocateRegister(info);
if (allocation.IsAllocated()) { DCHECK(allocation.IsAllocated());
return compiler::AllocatedOperand::cast(allocation); return compiler::AllocatedOperand::cast(allocation);
}
// Free some register.
int furthest = 0;
DCHECK_NOT_NULL(register_values_[0]);
for (int i = 1; i < kAllocatableGeneralRegisterCount; i++) {
DCHECK_NOT_NULL(register_values_[i]);
if (register_values_[furthest]->next_use < register_values_[i]->next_use) {
furthest = i;
}
}
return ForceAllocate(MapIndexToRegister(furthest), info, false);
} }
compiler::AllocatedOperand StraightForwardRegisterAllocator::ForceAllocate( compiler::AllocatedOperand StraightForwardRegisterAllocator::ForceAllocate(
const Register& reg, LiveNodeInfo* info, bool try_move) { const Register& reg, LiveNodeInfo* info) {
if (register_values_[MapRegisterToIndex(reg)] == info) { if (register_values_[MapRegisterToIndex(reg)] == nullptr) {
// If it's already free, remove it from the free list.
for (int i = 0; i < free_register_size_; i++) {
if (MapRegisterToIndex(reg) == free_registers_[i]) {
std::swap(free_registers_[i], free_registers_[--free_register_size_]);
break;
}
}
} else if (register_values_[MapRegisterToIndex(reg)] == info) {
return compiler::AllocatedOperand(compiler::LocationOperand::REGISTER, return compiler::AllocatedOperand(compiler::LocationOperand::REGISTER,
MachineRepresentation::kTagged, MachineRepresentation::kTagged,
reg.code()); reg.code());
} else {
Free(reg);
DCHECK_NULL(register_values_[MapRegisterToIndex(reg)]);
} }
Free(reg, try_move); #ifdef DEBUG
DCHECK_NULL(register_values_[MapRegisterToIndex(reg)]); for (int i = 0; i < free_register_size_; i++) {
return DoAllocate(reg, info); CHECK_NE(MapRegisterToIndex(reg), free_registers_[i]);
} }
#endif
compiler::AllocatedOperand StraightForwardRegisterAllocator::DoAllocate(
const Register& reg, LiveNodeInfo* info) {
SetRegister(reg, info); SetRegister(reg, info);
return compiler::AllocatedOperand(compiler::LocationOperand::REGISTER, return compiler::AllocatedOperand(compiler::LocationOperand::REGISTER,
MachineRepresentation::kTagged, reg.code()); MachineRepresentation::kTagged, reg.code());
...@@ -809,16 +797,8 @@ void StraightForwardRegisterAllocator::SetRegister(Register reg, ...@@ -809,16 +797,8 @@ void StraightForwardRegisterAllocator::SetRegister(Register reg,
compiler::InstructionOperand compiler::InstructionOperand
StraightForwardRegisterAllocator::TryAllocateRegister(LiveNodeInfo* info) { StraightForwardRegisterAllocator::TryAllocateRegister(LiveNodeInfo* info) {
int index = -1; if (free_register_size_ == 0) return compiler::InstructionOperand();
for (int i = 0; i < kAllocatableGeneralRegisterCount; i++) { int index = free_registers_[--free_register_size_];
if (register_values_[i] == nullptr) {
index = i;
break;
}
}
// Allocation failed.
if (index == -1) return compiler::InstructionOperand();
// Allocation succeeded. This might have found an existing allocation. // Allocation succeeded. This might have found an existing allocation.
// Simply update the state anyway. // Simply update the state anyway.
...@@ -839,9 +819,11 @@ void StraightForwardRegisterAllocator::InitializeRegisterValues( ...@@ -839,9 +819,11 @@ void StraightForwardRegisterAllocator::InitializeRegisterValues(
LiveNodeInfo* info = register_values_[i]; LiveNodeInfo* info = register_values_[i];
if (info == nullptr) continue; if (info == nullptr) continue;
info->reg = Register::no_reg(); info->reg = Register::no_reg();
register_values_[i] = nullptr;
} }
// Mark no register as free.
free_register_size_ = 0;
// Then fill it in with target information. // Then fill it in with target information.
for (int i = 0; i < kAllocatableGeneralRegisterCount; i++) { for (int i = 0; i < kAllocatableGeneralRegisterCount; i++) {
LiveNodeInfo* node; LiveNodeInfo* node;
...@@ -849,6 +831,7 @@ void StraightForwardRegisterAllocator::InitializeRegisterValues( ...@@ -849,6 +831,7 @@ void StraightForwardRegisterAllocator::InitializeRegisterValues(
LoadMergeState(target_state[i], &node, &merge); LoadMergeState(target_state[i], &node, &merge);
if (node == nullptr) { if (node == nullptr) {
DCHECK(!target_state[i].GetPayload().is_merge); DCHECK(!target_state[i].GetPayload().is_merge);
FreeRegister(i);
continue; continue;
} }
register_values_[i] = node; register_values_[i] = node;
...@@ -917,14 +900,14 @@ void StraightForwardRegisterAllocator::MergeRegisterValues(ControlNode* control, ...@@ -917,14 +900,14 @@ void StraightForwardRegisterAllocator::MergeRegisterValues(ControlNode* control,
// If there's a value in the incoming state, that value is either // If there's a value in the incoming state, that value is either
// already spilled or in another place in the merge state. // already spilled or in another place in the merge state.
if (incoming != nullptr && incoming->stack_slot != nullptr) { if (incoming != nullptr && incoming->stack_slot.IsAnyStackSlot()) {
EnsureInRegister(target_state, incoming); EnsureInRegister(target_state, incoming);
} }
continue; continue;
} }
DCHECK_IMPLIES(node == nullptr, incoming != nullptr); DCHECK_IMPLIES(node == nullptr, incoming != nullptr);
if (node == nullptr && incoming->stack_slot == nullptr) { if (node == nullptr && !incoming->stack_slot.IsAnyStackSlot()) {
// If the register is unallocated at the merge point, and the incoming // If the register is unallocated at the merge point, and the incoming
// value isn't spilled, that means we must have seen it already in a // value isn't spilled, that means we must have seen it already in a
// different register. // different register.
...@@ -942,7 +925,8 @@ void StraightForwardRegisterAllocator::MergeRegisterValues(ControlNode* control, ...@@ -942,7 +925,8 @@ void StraightForwardRegisterAllocator::MergeRegisterValues(ControlNode* control,
// is the spill slot for the incoming value. Otherwise all incoming // is the spill slot for the incoming value. Otherwise all incoming
// branches agree that the current node is in the register info. // branches agree that the current node is in the register info.
compiler::AllocatedOperand info_so_far = compiler::AllocatedOperand info_so_far =
node == nullptr ? incoming->stack_slot->slot : register_info; node == nullptr ? compiler::AllocatedOperand::cast(incoming->stack_slot)
: register_info;
// Initialize the entire array with info_so_far since we don't know in // Initialize the entire array with info_so_far since we don't know in
// which order we've seen the predecessors so far. Predecessors we // which order we've seen the predecessors so far. Predecessors we
......
...@@ -5,6 +5,7 @@ ...@@ -5,6 +5,7 @@
#ifndef V8_MAGLEV_MAGLEV_REGALLOC_H_ #ifndef V8_MAGLEV_MAGLEV_REGALLOC_H_
#define V8_MAGLEV_MAGLEV_REGALLOC_H_ #define V8_MAGLEV_MAGLEV_REGALLOC_H_
#include "src/compiler/backend/instruction.h"
#include "src/maglev/maglev-compilation-data.h" #include "src/maglev/maglev-compilation-data.h"
#include "src/maglev/maglev-graph.h" #include "src/maglev/maglev-graph.h"
#include "src/maglev/maglev-ir.h" #include "src/maglev/maglev-ir.h"
...@@ -16,19 +17,11 @@ namespace maglev { ...@@ -16,19 +17,11 @@ namespace maglev {
class MaglevPrintingVisitor; class MaglevPrintingVisitor;
struct StackSlot {
StackSlot(MachineRepresentation representation, int index)
: slot(compiler::LocationOperand::STACK_SLOT, representation, index) {}
compiler::AllocatedOperand slot;
StackSlot* next_ = nullptr;
StackSlot** next() { return &next_; }
};
struct LiveNodeInfo { struct LiveNodeInfo {
ValueNode* node; ValueNode* node;
uint32_t last_use = 0; uint32_t last_use = 0;
uint32_t next_use = 0; uint32_t next_use = 0;
StackSlot* stack_slot = nullptr; compiler::InstructionOperand stack_slot = compiler::InstructionOperand();
Register reg = Register::no_reg(); Register reg = Register::no_reg();
compiler::AllocatedOperand allocation() const { compiler::AllocatedOperand allocation() const {
...@@ -37,8 +30,7 @@ struct LiveNodeInfo { ...@@ -37,8 +30,7 @@ struct LiveNodeInfo {
MachineRepresentation::kTagged, MachineRepresentation::kTagged,
reg.code()); reg.code());
} }
DCHECK_NOT_NULL(stack_slot); return compiler::AllocatedOperand::cast(stack_slot);
return stack_slot->slot;
} }
}; };
...@@ -57,13 +49,17 @@ class StraightForwardRegisterAllocator { ...@@ -57,13 +49,17 @@ class StraightForwardRegisterAllocator {
using LiveNodeInfoMap = std::map<ValueNode*, LiveNodeInfo>; using LiveNodeInfoMap = std::map<ValueNode*, LiveNodeInfo>;
LiveNodeInfoMap values_; LiveNodeInfoMap values_;
base::ThreadedList<StackSlot> free_slots_;
int top_of_stack_ = 0;
#define N(V) nullptr, #define N(V) nullptr,
LiveNodeInfo* register_values_[kAllocatableGeneralRegisterCount] = { LiveNodeInfo* register_values_[kAllocatableGeneralRegisterCount] = {
ALWAYS_ALLOCATABLE_GENERAL_REGISTERS(N)}; ALWAYS_ALLOCATABLE_GENERAL_REGISTERS(N)};
#undef N #undef N
int top_of_stack_ = 0;
// TODO(verwaest): Make this a RegList.
uint8_t free_register_size_ = kAllocatableGeneralRegisterCount;
uint8_t free_registers_[kAllocatableGeneralRegisterCount];
std::vector<uint32_t> free_slots_;
LiveNodeInfo* MakeLive(ValueNode* node) { LiveNodeInfo* MakeLive(ValueNode* node) {
uint32_t last_use = node->live_range().end; uint32_t last_use = node->live_range().end;
// TODO(verwaest): We don't currently have next_use info... // TODO(verwaest): We don't currently have next_use info...
...@@ -85,6 +81,8 @@ class StraightForwardRegisterAllocator { ...@@ -85,6 +81,8 @@ class StraightForwardRegisterAllocator {
void AssignTemporaries(NodeBase* node); void AssignTemporaries(NodeBase* node);
void TryAllocateToInput(LiveNodeInfo* info, Phi* phi); void TryAllocateToInput(LiveNodeInfo* info, Phi* phi);
void FreeRegister(int i);
void FreeSomeRegister();
RegList GetFreeRegisters(int count); RegList GetFreeRegisters(int count);
void AddMoveBeforeCurrentNode(compiler::AllocatedOperand source, void AddMoveBeforeCurrentNode(compiler::AllocatedOperand source,
compiler::AllocatedOperand target); compiler::AllocatedOperand target);
...@@ -96,12 +94,9 @@ class StraightForwardRegisterAllocator { ...@@ -96,12 +94,9 @@ class StraightForwardRegisterAllocator {
compiler::AllocatedOperand AllocateRegister(LiveNodeInfo* info); compiler::AllocatedOperand AllocateRegister(LiveNodeInfo* info);
compiler::AllocatedOperand ForceAllocate(const Register& reg, compiler::AllocatedOperand ForceAllocate(const Register& reg,
LiveNodeInfo* info, LiveNodeInfo* info);
bool try_move = true);
compiler::AllocatedOperand DoAllocate(const Register& reg,
LiveNodeInfo* info);
void SetRegister(Register reg, LiveNodeInfo* info); void SetRegister(Register reg, LiveNodeInfo* info);
void Free(const Register& reg, bool try_move); void Free(const Register& reg);
compiler::InstructionOperand TryAllocateRegister(LiveNodeInfo* info); compiler::InstructionOperand TryAllocateRegister(LiveNodeInfo* info);
void InitializeRegisterValues(RegisterState* target_state); void InitializeRegisterValues(RegisterState* target_state);
......
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