diff --git a/src/codegen/arm64/register-arm64.h b/src/codegen/arm64/register-arm64.h index 185e330df8..57322f0241 100644 --- a/src/codegen/arm64/register-arm64.h +++ b/src/codegen/arm64/register-arm64.h @@ -243,6 +243,19 @@ class Register : public CPURegister { return Register::Create(code, kXRegSizeInBits); } + // Copied from RegisterBase since there's no CPURegister::from_code. + static constexpr Register FirstOf(RegList list) { + DCHECK_NE(kEmptyRegList, list); + return from_code(base::bits::CountTrailingZerosNonZero(list)); + } + + static constexpr Register TakeFirst(RegList* list) { + RegList value = *list; + Register result = FirstOf(value); + result.RemoveFrom(list); + return result; + } + static const char* GetSpecialRegisterName(int code) { return (code == kSPRegInternalCode) ? "sp" : "UNKNOWN"; } diff --git a/src/codegen/register-base.h b/src/codegen/register-base.h index 4f859452b1..92812b14c6 100644 --- a/src/codegen/register-base.h +++ b/src/codegen/register-base.h @@ -55,25 +55,27 @@ class RegisterBase { return is_valid() ? RegList{1} << code() : RegList{}; } - static constexpr SubType AnyOf(RegList list) { + static constexpr SubType FirstOf(RegList list) { DCHECK_NE(kEmptyRegList, list); - return from_code(base::bits::CountTrailingZeros(list)); + return SubType::from_code(base::bits::CountTrailingZerosNonZero(list)); } - static constexpr SubType TakeAny(RegList* list) { + static constexpr SubType TakeFirst(RegList* list) { RegList value = *list; - SubType result = AnyOf(value); + SubType result = FirstOf(value); result.RemoveFrom(list); return result; } + constexpr bool IsIn(RegList list) const { return list & bit(); } + constexpr void InsertInto(RegList* list) const { - DCHECK_NE(bit(), (*list) & bit()); + DCHECK(!IsIn(*list)); *list |= bit(); } constexpr void RemoveFrom(RegList* list) const { - DCHECK_EQ(bit(), (*list) & bit()); + DCHECK(IsIn(*list)); *list ^= bit(); } diff --git a/src/codegen/register.h b/src/codegen/register.h index 552350c0eb..ff25d1f206 100644 --- a/src/codegen/register.h +++ b/src/codegen/register.h @@ -69,6 +69,29 @@ inline constexpr bool AreAliased(RegType first_reg, RegTypes... regs) { } #endif +class RegListIterator { + public: + class Iterator { + public: + explicit Iterator(RegList list) : list_(list) {} + Register operator*() { return Register::FirstOf(list_); } + void operator++() { Register::FirstOf(list_).RemoveFrom(&list_); } + bool operator!=(const Iterator& other) const { + return list_ != other.list_; + } + + private: + RegList list_; + }; + + explicit RegListIterator(RegList list) : list_(list) {} + Iterator begin() const { return Iterator(list_); } + Iterator end() const { return Iterator(kEmptyRegList); } + + private: + RegList list_; +}; + } // namespace internal } // namespace v8 diff --git a/src/maglev/maglev-code-generator.cc b/src/maglev/maglev-code-generator.cc index 3f0114b074..beea077f93 100644 --- a/src/maglev/maglev-code-generator.cc +++ b/src/maglev/maglev-code-generator.cc @@ -249,11 +249,11 @@ class MaglevCodeGeneratingNodeProcessor { __ RecordComment("-- Gap moves:"); - for (int index = 0; index < kAllocatableGeneralRegisterCount; ++index) { + for (auto entry : target->state()->register_state()) { RegisterMerge* merge; - if (LoadMergeState(target->state()->register_state()[index], &merge)) { + if (LoadMergeState(entry.state, &merge)) { compiler::AllocatedOperand source = merge->operand(predecessor_id); - Register target_reg = MapIndexToRegister(index); + Register target_reg = entry.reg; if (FLAG_code_comments) { std::stringstream ss; diff --git a/src/maglev/maglev-interpreter-frame-state.h b/src/maglev/maglev-interpreter-frame-state.h index 4786cd7099..14656ad667 100644 --- a/src/maglev/maglev-interpreter-frame-state.h +++ b/src/maglev/maglev-interpreter-frame-state.h @@ -67,6 +67,46 @@ class InterpreterFrameState { RegisterFrameArray frame_; }; +class MergePointRegisterState { + public: + class Iterator { + public: + struct Entry { + RegisterState& state; + Register reg; + }; + explicit Iterator(RegisterState* value_pointer, + RegListIterator::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_; + RegListIterator::Iterator reg_iterator_; + }; + + bool is_initialized() const { return values_[0].GetPayload().is_initialized; } + + Iterator begin() { + return Iterator(values_, + RegListIterator::Iterator(kAllocatableGeneralRegisters)); + } + Iterator end() { + return Iterator(values_ + kAllocatableGeneralRegisterCount, + RegListIterator::Iterator(kEmptyRegList)); + } + + private: + RegisterState values_[kAllocatableGeneralRegisterCount] = {{}}; +}; + class MergePointInterpreterFrameState { public: void CheckIsLoopPhiIfNeeded(const MaglevCompilationUnit& compilation_unit, @@ -161,7 +201,7 @@ class MergePointInterpreterFrameState { DCHECK_LE(predecessors_so_far_, predecessor_count_); } - RegisterState* register_state() { return register_values_; } + MergePointRegisterState& register_state() { return register_state_; } // Merges an unmerged framestate with a possibly merged framestate into |this| // framestate. @@ -340,10 +380,7 @@ class MergePointInterpreterFrameState { const compiler::BytecodeLivenessState* liveness_ = nullptr; BasicBlock** predecessors_; -#define N(V) RegisterState{nullptr}, - RegisterState register_values_[kAllocatableGeneralRegisterCount] = { - ALLOCATABLE_GENERAL_REGISTERS(N)}; -#undef N + MergePointRegisterState register_state_; }; void InterpreterFrameState::CopyFrom( diff --git a/src/maglev/maglev-ir.cc b/src/maglev/maglev-ir.cc index 8b83214b62..94849841d5 100644 --- a/src/maglev/maglev-ir.cc +++ b/src/maglev/maglev-ir.cc @@ -507,7 +507,7 @@ void CheckMaps::GenerateCode(MaglevCodeGenState* code_gen_state, const ProcessingState& state) { Register object = ToRegister(actual_map_input()); RegList temps = temporaries(); - Register map_tmp = Register::TakeAny(&temps); + Register map_tmp = Register::TakeFirst(&temps); __ LoadMap(map_tmp, object); __ Cmp(map_tmp, map().object()); diff --git a/src/maglev/maglev-ir.h b/src/maglev/maglev-ir.h index 13e2ca80e1..75dd014444 100644 --- a/src/maglev/maglev-ir.h +++ b/src/maglev/maglev-ir.h @@ -567,10 +567,7 @@ class ValueNode : public Node { // A node is dead once it has no more upcoming uses. bool is_dead() const { return next_use_ == kInvalidNodeId; } - void AddRegister(Register reg) { - registers_with_result_ = - CombineRegLists(registers_with_result_, Register::ListOf(reg)); - } + void AddRegister(Register reg) { reg.InsertInto(®isters_with_result_); } void RemoveRegister(Register reg) { reg.RemoveFrom(®isters_with_result_); } RegList ClearRegisters() { return std::exchange(registers_with_result_, kEmptyRegList); @@ -581,7 +578,7 @@ class ValueNode : public Node { if (has_register()) { return compiler::AllocatedOperand( compiler::LocationOperand::REGISTER, MachineRepresentation::kTagged, - Register::AnyOf(registers_with_result_).code()); + Register::FirstOf(registers_with_result_).code()); } DCHECK(is_spilled()); return compiler::AllocatedOperand::cast(spill_or_hint_); diff --git a/src/maglev/maglev-regalloc-data.h b/src/maglev/maglev-regalloc-data.h index 455febb271..f46b701147 100644 --- a/src/maglev/maglev-regalloc-data.h +++ b/src/maglev/maglev-regalloc-data.h @@ -20,32 +20,6 @@ static constexpr int kAllocatableGeneralRegisterCount = ALLOCATABLE_GENERAL_REGISTERS(COUNT); #undef COUNT -constexpr uint8_t MapRegisterToIndex(Register r) { - uint8_t count = 0; -#define EMIT_BRANCH(V) \ - if (r == V) return count; \ - count++; - ALLOCATABLE_GENERAL_REGISTERS(EMIT_BRANCH) -#undef EMIT_BRANCH - // TODO(v8:7700): Re-enable UNREACHABLE once we figure out how to to avoid - // the gcc error 'call to non-constexpr function'. - // UNREACHABLE(); - return 255; -} - -constexpr Register MapIndexToRegister(int i) { - uint8_t count = 0; -#define EMIT_BRANCH(V) \ - if (i == count) return V; \ - count++; - ALLOCATABLE_GENERAL_REGISTERS(EMIT_BRANCH) -#undef EMIT_BRANCH - // TODO(v8:7700): Re-enable UNREACHABLE once we figure out how to to avoid - // the gcc error 'call to non-constexpr function'. - // UNREACHABLE(); - return no_reg; -} - struct RegisterStateFlags { // TODO(v8:7700): Use the good old Flags mechanism. static constexpr int kIsMergeShift = 0; diff --git a/src/maglev/maglev-regalloc.cc b/src/maglev/maglev-regalloc.cc index 83fc40c446..5c56ac2558 100644 --- a/src/maglev/maglev-regalloc.cc +++ b/src/maglev/maglev-regalloc.cc @@ -6,6 +6,7 @@ #include "src/base/bits.h" #include "src/base/logging.h" +#include "src/codegen/register.h" #include "src/codegen/reglist.h" #include "src/compiler/backend/instruction.h" #include "src/maglev/maglev-compilation-data.h" @@ -58,7 +59,7 @@ ControlNode* NearestPostDominatingHole(ControlNode* node) { } bool IsLiveAtTarget(ValueNode* node, ControlNode* source, BasicBlock* target) { - if (!node) return false; + DCHECK_NOT_NULL(node); // TODO(leszeks): We shouldn't have any dead nodes passed into here. if (node->is_dead()) return false; @@ -197,15 +198,14 @@ void StraightForwardRegisterAllocator::ComputePostDominatingHoles( void StraightForwardRegisterAllocator::PrintLiveRegs() const { bool first = true; - for (int i = 0; i < kAllocatableGeneralRegisterCount; i++) { - ValueNode* node = register_values_[i]; - if (!node) continue; + for (Register reg : RegListIterator(used_registers())) { + ValueNode* node = GetUsedRegister(reg); if (first) { first = false; } else { printing_visitor_->os() << ", "; } - printing_visitor_->os() << MapIndexToRegister(i) << "=v" << node->id(); + printing_visitor_->os() << reg << "=v" << node->id(); } } @@ -410,27 +410,21 @@ void StraightForwardRegisterAllocator::AllocateNodeResult(ValueNode* node) { } } -void StraightForwardRegisterAllocator::Free(const Register& reg) { - int index = MapRegisterToIndex(reg); - ValueNode* node = register_values_[index]; +void StraightForwardRegisterAllocator::DropRegisterValue(Register reg) { + // The register should not already be free. + DCHECK(!reg.IsIn(free_registers_)); - // If the register is already free, return. - if (!node) return; + ValueNode* node = GetUsedRegister(reg); - // Free the register without adding it to the list. - register_values_[index] = nullptr; - - // Remove the register from the list. + // Remove the register from the node's list. node->RemoveRegister(reg); - // Return if the removed value already has another register. - if (node->has_register()) return; - // If the value is already spilled, return. - if (node->is_spilled()) return; + // Return if the removed value already has another register or is spilled. + if (node->has_register() || node->is_spilled()) return; // Try to move the value to another register. if (free_registers_ != kEmptyRegList) { - Register target_reg = Register::TakeAny(&free_registers_); + Register target_reg = Register::TakeFirst(&free_registers_); SetRegister(target_reg, node); // Emit a gapmove. compiler::AllocatedOperand source(compiler::LocationOperand::REGISTER, @@ -467,10 +461,14 @@ void StraightForwardRegisterAllocator::InitializeConditionalBranchRegisters( } // Clear dead fall-through registers. DCHECK_EQ(control_node->id() + 1, target->first_id()); - for (int i = 0; i < kAllocatableGeneralRegisterCount; i++) { - ValueNode* node = register_values_[i]; - if (node != nullptr && !IsLiveAtTarget(node, control_node, target)) { + RegList registers = used_registers(); + while (registers != kEmptyRegList) { + Register reg = Register::TakeFirst(®isters); + ValueNode* node = GetUsedRegister(reg); + if (!IsLiveAtTarget(node, control_node, target)) { FreeRegisters(node); + // Update the registers we're visiting to avoid revisiting this node. + registers &= !free_registers_; } } } @@ -526,8 +524,7 @@ void StraightForwardRegisterAllocator::TryAllocateToInput(Phi* phi) { for (Input& input : *phi) { if (input.operand().IsRegister()) { Register reg = input.AssignedRegister(); - int index = MapRegisterToIndex(reg); - if (register_values_[index] == nullptr) { + if (reg.IsIn(free_registers_)) { phi->result().SetAllocated(ForceAllocate(reg, phi)); if (FLAG_trace_maglev_regalloc) { printing_visitor_->Process( @@ -614,24 +611,19 @@ void StraightForwardRegisterAllocator::AssignInput(Input& input) { } void StraightForwardRegisterAllocator::SpillRegisters() { - for (int i = 0; i < kAllocatableGeneralRegisterCount; i++) { - ValueNode* node = register_values_[i]; - if (!node) continue; + for (Register reg : RegListIterator(used_registers())) { + ValueNode* node = GetUsedRegister(reg); Spill(node); } } -void StraightForwardRegisterAllocator::FreeRegister(int i) { - register_values_[i] = nullptr; - MapIndexToRegister(i).InsertInto(&free_registers_); -} - void StraightForwardRegisterAllocator::SpillAndClearRegisters() { - for (int i = 0; i < kAllocatableGeneralRegisterCount; i++) { - ValueNode* node = register_values_[i]; - if (!node) continue; + while (used_registers() != kEmptyRegList) { + Register reg = Register::FirstOf(used_registers()); + ValueNode* node = GetUsedRegister(reg); Spill(node); FreeRegisters(node); + DCHECK(!reg.IsIn(used_registers())); } } @@ -651,16 +643,16 @@ void StraightForwardRegisterAllocator::AllocateSpillSlot(ValueNode* node) { void StraightForwardRegisterAllocator::FreeSomeRegister() { int furthest_use = 0; - int longest = -1; - for (int i = 0; i < kAllocatableGeneralRegisterCount; i++) { - if (!register_values_[i]) continue; - int use = register_values_[i]->next_use(); + Register best = Register::no_reg(); + for (Register reg : RegListIterator(used_registers())) { + int use = GetUsedRegister(reg)->next_use(); if (use > furthest_use) { furthest_use = use; - longest = i; + best = reg; } } - FreeRegister(longest); + DCHECK(best.is_valid()); + FreeRegister(best); } compiler::AllocatedOperand StraightForwardRegisterAllocator::AllocateRegister( @@ -672,21 +664,19 @@ compiler::AllocatedOperand StraightForwardRegisterAllocator::AllocateRegister( } compiler::AllocatedOperand StraightForwardRegisterAllocator::ForceAllocate( - const Register& reg, ValueNode* node) { - if (register_values_[MapRegisterToIndex(reg)] == nullptr) { + Register reg, ValueNode* node) { + if (reg.IsIn(free_registers_)) { // If it's already free, remove it from the free list. reg.RemoveFrom(&free_registers_); - } else if (register_values_[MapRegisterToIndex(reg)] == node) { + } else if (GetUsedRegister(reg) == node) { return compiler::AllocatedOperand(compiler::LocationOperand::REGISTER, MachineRepresentation::kTagged, reg.code()); } else { - Free(reg); - DCHECK_NULL(register_values_[MapRegisterToIndex(reg)]); + DropRegisterValue(reg); } #ifdef DEBUG - DCHECK_NE(free_registers_, - CombineRegLists(free_registers_, Register::ListOf(reg))); + DCHECK(!reg.IsIn(free_registers_)); #endif SetRegister(reg, node); return compiler::AllocatedOperand(compiler::LocationOperand::REGISTER, @@ -695,17 +685,15 @@ compiler::AllocatedOperand StraightForwardRegisterAllocator::ForceAllocate( void StraightForwardRegisterAllocator::SetRegister(Register reg, ValueNode* node) { - int index = MapRegisterToIndex(reg); - DCHECK_IMPLIES(register_values_[index] != node, - register_values_[index] == nullptr); - register_values_[index] = node; + DCHECK(!reg.IsIn(free_registers_)); + register_values_[reg.code()] = node; node->AddRegister(reg); } compiler::InstructionOperand StraightForwardRegisterAllocator::TryAllocateRegister(ValueNode* node) { if (free_registers_ == kEmptyRegList) return compiler::InstructionOperand(); - Register reg = Register::TakeAny(&free_registers_); + Register reg = Register::TakeFirst(&free_registers_); // Allocation succeeded. This might have found an existing allocation. // Simply update the state anyway. @@ -729,79 +717,91 @@ void StraightForwardRegisterAllocator::AssignTemporaries(NodeBase* node) { } void StraightForwardRegisterAllocator::InitializeRegisterValues( - RegisterState* target_state) { + MergePointRegisterState& target_state) { // First clear the register state. - // TODO(verwaest): We could loop over the list of allocated registers by - // deducing it from the free registers. - for (int i = 0; i < kAllocatableGeneralRegisterCount; i++) { - ValueNode* node = register_values_[i]; - if (!node) continue; - node->ClearRegisters(); + while (used_registers() != kEmptyRegList) { + Register reg = Register::FirstOf(used_registers()); + ValueNode* node = GetUsedRegister(reg); + FreeRegisters(node); + DCHECK(!reg.IsIn(used_registers())); } - // Mark no register as free. - free_registers_ = kEmptyRegList; + // All registers should be free by now. + DCHECK_EQ(free_registers_, kAllocatableGeneralRegisters); // Then fill it in with target information. - for (int i = 0; i < kAllocatableGeneralRegisterCount; i++) { + for (auto entry : target_state) { + Register reg = entry.reg; + ValueNode* node; RegisterMerge* merge; - LoadMergeState(target_state[i], &node, &merge); - if (node == nullptr) { - DCHECK(!target_state[i].GetPayload().is_merge); - FreeRegister(i); + LoadMergeState(entry.state, &node, &merge); + if (node != nullptr) { + reg.RemoveFrom(&free_registers_); + SetRegister(reg, node); } else { - SetRegister(MapIndexToRegister(i), node); + DCHECK(!entry.state.GetPayload().is_merge); } } } void StraightForwardRegisterAllocator::EnsureInRegister( - RegisterState* target_state, ValueNode* incoming) { + MergePointRegisterState& target_state, ValueNode* incoming) { #ifdef DEBUG - int i; - for (i = 0; i < kAllocatableGeneralRegisterCount; i++) { + bool found = false; + for (auto entry : target_state) { ValueNode* node; RegisterMerge* merge; - LoadMergeState(target_state[i], &node, &merge); - if (node == incoming) break; + LoadMergeState(entry.state, &node, &merge); + if (node == incoming) found = true; } - CHECK_NE(kAllocatableGeneralRegisterCount, i); + DCHECK(found); #endif } void StraightForwardRegisterAllocator::InitializeBranchTargetRegisterValues( ControlNode* source, BasicBlock* target) { - RegisterState* target_state = target->state()->register_state(); - DCHECK(!target_state[0].GetPayload().is_initialized); - for (int i = 0; i < kAllocatableGeneralRegisterCount; i++) { - ValueNode* node = register_values_[i]; - if (!IsLiveAtTarget(node, source, target)) node = nullptr; - target_state[i] = {node, initialized_node}; + MergePointRegisterState& target_state = target->state()->register_state(); + DCHECK(!target_state.is_initialized()); + for (auto entry : target_state) { + Register reg = entry.reg; + ValueNode* node = nullptr; + if (!reg.IsIn(free_registers_)) { + node = GetUsedRegister(reg); + if (!IsLiveAtTarget(node, source, target)) node = nullptr; + } + entry.state = {node, initialized_node}; } } void StraightForwardRegisterAllocator::MergeRegisterValues(ControlNode* control, BasicBlock* target, int predecessor_id) { - RegisterState* target_state = target->state()->register_state(); - if (!target_state[0].GetPayload().is_initialized) { + MergePointRegisterState& target_state = target->state()->register_state(); + if (!target_state.is_initialized()) { // This is the first block we're merging, initialize the values. return InitializeBranchTargetRegisterValues(control, target); } int predecessor_count = target->state()->predecessor_count(); - for (int i = 0; i < kAllocatableGeneralRegisterCount; i++) { + for (auto entry : target_state) { + Register reg = entry.reg; + ValueNode* node; RegisterMerge* merge; - LoadMergeState(target_state[i], &node, &merge); + LoadMergeState(entry.state, &node, &merge); compiler::AllocatedOperand register_info = { compiler::LocationOperand::REGISTER, MachineRepresentation::kTagged, - MapIndexToRegister(i).code()}; + reg.code()}; - ValueNode* incoming = register_values_[i]; - if (!IsLiveAtTarget(incoming, control, target)) incoming = nullptr; + ValueNode* incoming = nullptr; + if (!reg.IsIn(free_registers_)) { + incoming = GetUsedRegister(reg); + if (!IsLiveAtTarget(incoming, control, target)) { + incoming = nullptr; + } + } if (incoming == node) { // We're using the same register as the target already has. If registers @@ -849,8 +849,8 @@ void StraightForwardRegisterAllocator::MergeRegisterValues(ControlNode* control, // 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 // haven't seen yet will simply overwrite their entry later. - for (int j = 0; j < predecessor_count; j++) { - merge->operand(j) = info_so_far; + for (int i = 0; i < predecessor_count; i++) { + merge->operand(i) = info_so_far; } // If the register is unallocated at the merge point, fill in the // incoming value. Otherwise find the merge-point node in the incoming @@ -860,7 +860,7 @@ void StraightForwardRegisterAllocator::MergeRegisterValues(ControlNode* control, } else { merge->operand(predecessor_id) = node->allocation(); } - target_state[i] = {merge, initialized_merge}; + entry.state = {merge, initialized_merge}; } } diff --git a/src/maglev/maglev-regalloc.h b/src/maglev/maglev-regalloc.h index fd1531b93d..2b71b63941 100644 --- a/src/maglev/maglev-regalloc.h +++ b/src/maglev/maglev-regalloc.h @@ -17,6 +17,7 @@ namespace internal { namespace maglev { class MaglevPrintingVisitor; +class MergePointRegisterState; class StraightForwardRegisterAllocator { public: @@ -27,17 +28,19 @@ class StraightForwardRegisterAllocator { int stack_slots() const { return top_of_stack_; } private: - std::vector future_register_uses_[kAllocatableGeneralRegisterCount]; - -#define N(V) nullptr, - ValueNode* register_values_[kAllocatableGeneralRegisterCount] = { - ALLOCATABLE_GENERAL_REGISTERS(N)}; -#undef N + std::vector future_register_uses_[Register::kNumRegisters]; + ValueNode* register_values_[Register::kNumRegisters]; int top_of_stack_ = 0; RegList free_registers_ = kAllocatableGeneralRegisters; std::vector free_slots_; + RegList used_registers() const { + // Only allocatable registers should be free. + DCHECK_EQ(free_registers_, free_registers_ & kAllocatableGeneralRegisters); + return kAllocatableGeneralRegisters ^ free_registers_; + } + void ComputePostDominatingHoles(Graph* graph); void AllocateRegisters(Graph* graph); @@ -54,12 +57,23 @@ class StraightForwardRegisterAllocator { void FreeRegisters(ValueNode* node) { RegList list = node->ClearRegisters(); - while (list != kEmptyRegList) { - Register reg = Register::TakeAny(&list); - FreeRegister(MapRegisterToIndex(reg)); - } + DCHECK_EQ(free_registers_ & list, kEmptyRegList); + free_registers_ |= list; } - void FreeRegister(int i); + void FreeRegister(Register reg) { reg.InsertInto(&free_registers_); } + + ValueNode* GetUsedRegister(Register reg) const { + DCHECK(!reg.IsIn(free_registers_)); + ValueNode* node = register_values_[reg.code()]; + DCHECK_NOT_NULL(node); + return node; + } + + ValueNode* GetMaybeUsedRegister(Register reg) const { + if (!reg.IsIn(free_registers_)) return nullptr; + return GetUsedRegister(reg); + } + void FreeSomeRegister(); void AddMoveBeforeCurrentNode(compiler::AllocatedOperand source, compiler::AllocatedOperand target); @@ -70,14 +84,14 @@ class StraightForwardRegisterAllocator { void SpillRegisters(); compiler::AllocatedOperand AllocateRegister(ValueNode* node); - compiler::AllocatedOperand ForceAllocate(const Register& reg, - ValueNode* node); + compiler::AllocatedOperand ForceAllocate(Register reg, ValueNode* node); void SetRegister(Register reg, ValueNode* node); - void Free(const Register& reg); + void DropRegisterValue(Register reg); compiler::InstructionOperand TryAllocateRegister(ValueNode* node); - void InitializeRegisterValues(RegisterState* target_state); - void EnsureInRegister(RegisterState* target_state, ValueNode* incoming); + void InitializeRegisterValues(MergePointRegisterState& target_state); + void EnsureInRegister(MergePointRegisterState& target_state, + ValueNode* incoming); void InitializeBranchTargetRegisterValues(ControlNode* source, BasicBlock* target);