[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:
parent
3508f70cb7
commit
97e86869ba
@ -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();
|
||||
|
@ -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 {
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user