[maglev] Support double registers in MergePointRegisterState

- Introduces an array of RegisterStates for double registers
- Adds two functions to iterate over the arrays

We will be able to call the ForEach functions using a templated lambda
for RegisterBase<T>.

Bug: v8:7700
Change-Id: I7ef86917d9377933a4bc3456e30de3e4ec547f65
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3596122
Reviewed-by: Leszek Swirski <leszeks@chromium.org>
Commit-Queue: Victor Gomes <victorgomes@chromium.org>
Cr-Commit-Position: refs/heads/main@{#80116}
This commit is contained in:
Victor Gomes 2022-04-22 10:16:04 +02:00 committed by V8 LUCI CQ
parent 3508f70cb7
commit 97e86869ba
4 changed files with 55 additions and 68 deletions

View File

@ -254,21 +254,19 @@ class MaglevCodeGeneratingNodeProcessor {
__ RecordComment("-- Gap moves:");
for (auto entry : target->state()->register_state()) {
RegisterMerge* merge;
if (LoadMergeState(entry.state, &merge)) {
compiler::AllocatedOperand source = merge->operand(predecessor_id);
Register target_reg = entry.reg;
if (FLAG_code_comments) {
std::stringstream ss;
ss << "-- * " << source << "" << target_reg;
__ RecordComment(ss.str());
}
RecordGapMove(source, target_reg, register_moves,
stack_to_register_moves);
}
}
target->state()->register_state().ForEachGeneralRegister(
[&](Register reg, RegisterState& state) {
RegisterMerge* merge;
if (LoadMergeState(state, &merge)) {
compiler::AllocatedOperand source = merge->operand(predecessor_id);
if (FLAG_code_comments) {
std::stringstream ss;
ss << "-- * " << source << "" << reg;
__ RecordComment(ss.str());
}
RecordGapMove(source, reg, register_moves, stack_to_register_moves);
}
});
if (target->has_phi()) {
Phi::List* phis = target->phis();

View File

@ -185,41 +185,29 @@ class CompactInterpreterFrameState {
class MergePointRegisterState {
public:
class Iterator {
public:
struct Entry {
RegisterState& state;
Register reg;
};
explicit Iterator(RegisterState* value_pointer,
RegList::Iterator reg_iterator)
: current_value_(value_pointer), reg_iterator_(reg_iterator) {}
Entry operator*() { return {*current_value_, *reg_iterator_}; }
void operator++() {
++current_value_;
++reg_iterator_;
}
bool operator!=(const Iterator& other) const {
return current_value_ != other.current_value_;
}
private:
RegisterState* current_value_;
RegList::Iterator reg_iterator_;
};
bool is_initialized() const { return values_[0].GetPayload().is_initialized; }
Iterator begin() {
return Iterator(values_, kAllocatableGeneralRegisters.begin());
template <typename Function>
void ForEachGeneralRegister(Function&& f) {
RegisterState* current_value = &values_[0];
for (Register reg : kAllocatableGeneralRegisters) {
f(reg, *current_value);
++current_value;
}
}
Iterator end() {
return Iterator(values_ + kAllocatableGeneralRegisterCount,
kAllocatableGeneralRegisters.end());
template <typename Function>
void ForEachDoubleRegister(Function&& f) {
RegisterState* current_value = &double_values_[0];
for (DoubleRegister reg : kAllocatableDoubleRegisters) {
f(reg, *current_value);
++current_value;
}
}
private:
RegisterState values_[kAllocatableGeneralRegisterCount] = {{}};
RegisterState double_values_[kAllocatableDoubleRegisterCount] = {{}};
};
class MergePointInterpreterFrameState {

View File

@ -20,6 +20,11 @@ static constexpr int kAllocatableGeneralRegisterCount =
ALLOCATABLE_GENERAL_REGISTERS(COUNT);
#undef COUNT
#define COUNT(V) +1
static constexpr int kAllocatableDoubleRegisterCount =
ALLOCATABLE_DOUBLE_REGISTERS(COUNT);
#undef COUNT
struct RegisterStateFlags {
// TODO(v8:7700): Use the good old Flags mechanism.
static constexpr int kIsMergeShift = 0;

View File

@ -806,31 +806,30 @@ void StraightForwardRegisterAllocator::InitializeRegisterValues(
DCHECK_EQ(free_registers_, kAllocatableGeneralRegisters);
// Then fill it in with target information.
for (auto entry : target_state) {
Register reg = entry.reg;
target_state.ForEachGeneralRegister([&](Register reg, RegisterState& state) {
ValueNode* node;
RegisterMerge* merge;
LoadMergeState(entry.state, &node, &merge);
LoadMergeState(state, &node, &merge);
if (node != nullptr) {
free_registers_.clear(reg);
SetRegister(reg, node);
} else {
DCHECK(!entry.state.GetPayload().is_merge);
DCHECK(!state.GetPayload().is_merge);
}
}
});
}
void StraightForwardRegisterAllocator::EnsureInRegister(
MergePointRegisterState& target_state, ValueNode* incoming) {
#ifdef DEBUG
bool found = false;
for (auto entry : target_state) {
ValueNode* node;
RegisterMerge* merge;
LoadMergeState(entry.state, &node, &merge);
if (node == incoming) found = true;
}
target_state.ForEachGeneralRegister(
[&found, &incoming](Register reg, RegisterState& state) {
ValueNode* node;
RegisterMerge* merge;
LoadMergeState(state, &node, &merge);
if (node == incoming) found = true;
});
DCHECK(found);
#endif
}
@ -839,15 +838,14 @@ void StraightForwardRegisterAllocator::InitializeBranchTargetRegisterValues(
ControlNode* source, BasicBlock* target) {
MergePointRegisterState& target_state = target->state()->register_state();
DCHECK(!target_state.is_initialized());
for (auto entry : target_state) {
Register reg = entry.reg;
target_state.ForEachGeneralRegister([&](Register reg, RegisterState& state) {
ValueNode* node = nullptr;
if (!free_registers_.has(reg)) {
node = GetRegisterValue(reg);
if (!IsLiveAtTarget(node, source, target)) node = nullptr;
}
entry.state = {node, initialized_node};
}
state = {node, initialized_node};
});
}
void StraightForwardRegisterAllocator::MergeRegisterValues(ControlNode* control,
@ -860,12 +858,10 @@ void StraightForwardRegisterAllocator::MergeRegisterValues(ControlNode* control,
}
int predecessor_count = target->state()->predecessor_count();
for (auto entry : target_state) {
Register reg = entry.reg;
target_state.ForEachGeneralRegister([&](Register reg, RegisterState& state) {
ValueNode* node;
RegisterMerge* merge;
LoadMergeState(entry.state, &node, &merge);
LoadMergeState(state, &node, &merge);
compiler::AllocatedOperand register_info = {
compiler::LocationOperand::REGISTER, MachineRepresentation::kTagged,
@ -883,7 +879,7 @@ void StraightForwardRegisterAllocator::MergeRegisterValues(ControlNode* control,
// We're using the same register as the target already has. If registers
// are merged, add input information.
if (merge) merge->operand(predecessor_id) = register_info;
continue;
return;
}
if (merge) {
@ -896,7 +892,7 @@ void StraightForwardRegisterAllocator::MergeRegisterValues(ControlNode* control,
if (incoming != nullptr && incoming->is_spilled()) {
EnsureInRegister(target_state, incoming);
}
continue;
return;
}
DCHECK_IMPLIES(node == nullptr, incoming != nullptr);
@ -905,7 +901,7 @@ void StraightForwardRegisterAllocator::MergeRegisterValues(ControlNode* control,
// value isn't spilled, that means we must have seen it already in a
// different register.
EnsureInRegister(target_state, incoming);
continue;
return;
}
const size_t size = sizeof(RegisterMerge) +
@ -936,8 +932,8 @@ void StraightForwardRegisterAllocator::MergeRegisterValues(ControlNode* control,
} else {
merge->operand(predecessor_id) = node->allocation();
}
entry.state = {merge, initialized_merge};
}
state = {merge, initialized_merge};
});
}
} // namespace maglev