Index: src/compiler/register-allocator.cc |
diff --git a/src/compiler/register-allocator.cc b/src/compiler/register-allocator.cc |
index 9badf7931cdb1696baefec2730968aab59245673..49229d5872cd22b2aac4aaaed8392163f26e5776 100644 |
--- a/src/compiler/register-allocator.cc |
+++ b/src/compiler/register-allocator.cc |
@@ -87,27 +87,6 @@ |
} |
} |
return false; |
-} |
- |
- |
-// TODO(dcarney): fix frame to allow frame accesses to half size location. |
-int GetByteWidth(MachineType machine_type) { |
- DCHECK_EQ(RepresentationOf(machine_type), machine_type); |
- switch (machine_type) { |
- case kRepBit: |
- case kRepWord8: |
- case kRepWord16: |
- case kRepWord32: |
- case kRepTagged: |
- return kPointerSize; |
- case kRepFloat32: |
- case kRepWord64: |
- case kRepFloat64: |
- return 8; |
- default: |
- UNREACHABLE(); |
- return 0; |
- } |
} |
} // namespace |
@@ -235,7 +214,7 @@ |
}; |
-LiveRange::LiveRange(int id, MachineType machine_type) |
+LiveRange::LiveRange(int id) |
: id_(id), |
spill_start_index_(kMaxInt), |
bits_(0), |
@@ -249,10 +228,8 @@ |
current_interval_(nullptr), |
last_processed_use_(nullptr), |
current_hint_position_(nullptr) { |
- DCHECK(AllocatedOperand::IsSupportedMachineType(machine_type)); |
bits_ = SpillTypeField::encode(SpillType::kNoSpillType) | |
- AssignedRegisterField::encode(kUnassignedRegister) | |
- MachineTypeField::encode(machine_type); |
+ AssignedRegisterField::encode(kUnassignedRegister); |
} |
@@ -291,18 +268,6 @@ |
} |
-RegisterKind LiveRange::kind() const { |
- switch (RepresentationOf(machine_type())) { |
- case kRepFloat32: |
- case kRepFloat64: |
- return DOUBLE_REGISTERS; |
- default: |
- break; |
- } |
- return GENERAL_REGISTERS; |
-} |
- |
- |
void LiveRange::SpillAtDefinition(Zone* zone, int gap_index, |
InstructionOperand* operand) { |
DCHECK(HasNoSpillType()); |
@@ -312,9 +277,9 @@ |
void LiveRange::CommitSpillsAtDefinition(InstructionSequence* sequence, |
- const InstructionOperand& op, |
+ InstructionOperand* op, |
bool might_be_duplicated) { |
- DCHECK_IMPLIES(op.IsConstant(), spills_at_definition_ == nullptr); |
+ DCHECK_IMPLIES(op->IsConstant(), spills_at_definition_ == nullptr); |
DCHECK(!IsChild()); |
auto zone = sequence->zone(); |
for (auto to_spill = spills_at_definition_; to_spill != nullptr; |
@@ -327,15 +292,15 @@ |
bool found = false; |
for (auto move_op : *move) { |
if (move_op->IsEliminated()) continue; |
- if (move_op->source().Equals(*to_spill->operand) && |
- move_op->destination().Equals(op)) { |
+ if (move_op->source() == *to_spill->operand && |
+ move_op->destination() == *op) { |
found = true; |
break; |
} |
} |
if (found) continue; |
} |
- move->AddMove(*to_spill->operand, op); |
+ move->AddMove(*to_spill->operand, *op); |
} |
} |
@@ -361,6 +326,14 @@ |
DCHECK(spill_range); |
set_spill_type(SpillType::kSpillRange); |
spill_range_ = spill_range; |
+} |
+ |
+ |
+void LiveRange::CommitSpillOperand(AllocatedOperand* operand) { |
+ DCHECK(HasSpillRange()); |
+ DCHECK(!IsChild()); |
+ set_spill_type(SpillType::kSpillOperand); |
+ spill_operand_ = operand; |
} |
@@ -422,33 +395,18 @@ |
DCHECK(!spilled()); |
switch (kind()) { |
case GENERAL_REGISTERS: |
- return RegisterOperand(machine_type(), assigned_register()); |
+ return RegisterOperand(assigned_register()); |
case DOUBLE_REGISTERS: |
- return DoubleRegisterOperand(machine_type(), assigned_register()); |
+ return DoubleRegisterOperand(assigned_register()); |
+ default: |
+ UNREACHABLE(); |
} |
} |
DCHECK(spilled()); |
DCHECK(!HasRegisterAssigned()); |
- if (TopLevel()->HasSpillOperand()) { |
- auto op = TopLevel()->GetSpillOperand(); |
- DCHECK(!op->IsUnallocated()); |
- return *op; |
- } |
- return TopLevel()->GetSpillRangeOperand(); |
-} |
- |
- |
-AllocatedOperand LiveRange::GetSpillRangeOperand() const { |
- auto spill_range = GetSpillRange(); |
- int index = spill_range->assigned_slot(); |
- switch (kind()) { |
- case GENERAL_REGISTERS: |
- return StackSlotOperand(machine_type(), index); |
- case DOUBLE_REGISTERS: |
- return DoubleStackSlotOperand(machine_type(), index); |
- } |
- UNREACHABLE(); |
- return StackSlotOperand(kMachNone, 0); |
+ auto op = TopLevel()->GetSpillOperand(); |
+ DCHECK(!op->IsUnallocated()); |
+ return *op; |
} |
@@ -554,6 +512,7 @@ |
// Link the new live range in the chain before any of the other |
// ranges linked from the range before the split. |
result->parent_ = (parent_ == nullptr) ? this : parent_; |
+ result->set_kind(result->parent_->kind()); |
result->next_ = next_; |
next_ = result; |
@@ -667,14 +626,15 @@ |
void LiveRange::ConvertUsesToOperand(const InstructionOperand& op, |
- const InstructionOperand& spill_op) { |
+ InstructionOperand* spill_op) { |
for (auto pos = first_pos(); pos != nullptr; pos = pos->next()) { |
DCHECK(Start() <= pos->pos() && pos->pos() <= End()); |
if (!pos->HasOperand()) continue; |
switch (pos->type()) { |
case UsePositionType::kRequiresSlot: |
- DCHECK(spill_op.IsStackSlot() || spill_op.IsDoubleStackSlot()); |
- InstructionOperand::ReplaceWith(pos->operand(), &spill_op); |
+ if (spill_op != nullptr) { |
+ InstructionOperand::ReplaceWith(pos->operand(), spill_op); |
+ } |
break; |
case UsePositionType::kRequiresRegister: |
DCHECK(op.IsRegister() || op.IsDoubleRegister()); |
@@ -766,8 +726,7 @@ |
} |
-SpillRange::SpillRange(LiveRange* parent, Zone* zone) |
- : live_ranges_(zone), assigned_slot_(kUnassignedSlot) { |
+SpillRange::SpillRange(LiveRange* parent, Zone* zone) : live_ranges_(zone) { |
DCHECK(!parent->IsChild()); |
UseInterval* result = nullptr; |
UseInterval* node = nullptr; |
@@ -793,11 +752,6 @@ |
} |
-int SpillRange::ByteWidth() const { |
- return GetByteWidth(live_ranges_[0]->machine_type()); |
-} |
- |
- |
bool SpillRange::IsIntersectingWith(SpillRange* other) const { |
if (this->use_interval_ == nullptr || other->use_interval_ == nullptr || |
this->End() <= other->use_interval_->start() || |
@@ -809,11 +763,7 @@ |
bool SpillRange::TryMerge(SpillRange* other) { |
- // TODO(dcarney): byte widths should be compared here not kinds. |
- if (live_ranges_[0]->kind() != other->live_ranges_[0]->kind() || |
- IsIntersectingWith(other)) { |
- return false; |
- } |
+ if (kind() != other->kind() || IsIntersectingWith(other)) return false; |
auto max = LifetimePosition::MaxPosition(); |
if (End() < other->End() && other->End() != max) { |
@@ -834,6 +784,14 @@ |
other->live_ranges().clear(); |
return true; |
+} |
+ |
+ |
+void SpillRange::SetOperand(AllocatedOperand* op) { |
+ for (auto range : live_ranges()) { |
+ DCHECK(range->GetSpillRange() == this); |
+ range->CommitSpillOperand(op); |
+ } |
} |
@@ -903,8 +861,7 @@ |
allocation_zone()), |
spill_ranges_(allocation_zone()), |
assigned_registers_(nullptr), |
- assigned_double_registers_(nullptr), |
- virtual_register_count_(code->VirtualRegisterCount()) { |
+ assigned_double_registers_(nullptr) { |
DCHECK(this->config()->num_general_registers() <= |
RegisterConfiguration::kMaxGeneralRegisters); |
DCHECK(this->config()->num_double_registers() <= |
@@ -919,6 +876,19 @@ |
} |
+LiveRange* RegisterAllocationData::LiveRangeFor(int index) { |
+ if (index >= static_cast<int>(live_ranges().size())) { |
+ live_ranges().resize(index + 1, nullptr); |
+ } |
+ auto result = live_ranges()[index]; |
+ if (result == nullptr) { |
+ result = NewLiveRange(index); |
+ live_ranges()[index] = result; |
+ } |
+ return result; |
+} |
+ |
+ |
MoveOperands* RegisterAllocationData::AddGapMove( |
int index, Instruction::GapPosition position, |
const InstructionOperand& from, const InstructionOperand& to) { |
@@ -928,40 +898,8 @@ |
} |
-MachineType RegisterAllocationData::MachineTypeFor(int virtual_register) { |
- DCHECK_LT(virtual_register, code()->VirtualRegisterCount()); |
- return code()->GetRepresentation(virtual_register); |
-} |
- |
- |
-LiveRange* RegisterAllocationData::LiveRangeFor(int index) { |
- if (index >= static_cast<int>(live_ranges().size())) { |
- live_ranges().resize(index + 1, nullptr); |
- } |
- auto result = live_ranges()[index]; |
- if (result == nullptr) { |
- result = NewLiveRange(index, MachineTypeFor(index)); |
- live_ranges()[index] = result; |
- } |
- return result; |
-} |
- |
- |
-LiveRange* RegisterAllocationData::NewLiveRange(int index, |
- MachineType machine_type) { |
- return new (allocation_zone()) LiveRange(index, machine_type); |
-} |
- |
- |
-LiveRange* RegisterAllocationData::NewChildRangeFor(LiveRange* range) { |
- int vreg = virtual_register_count_++; |
- if (vreg >= static_cast<int>(live_ranges().size())) { |
- live_ranges().resize(vreg + 1, nullptr); |
- } |
- auto child = new (allocation_zone()) LiveRange(vreg, range->machine_type()); |
- DCHECK_NULL(live_ranges()[vreg]); |
- live_ranges()[vreg] = child; |
- return child; |
+LiveRange* RegisterAllocationData::NewLiveRange(int index) { |
+ return new (allocation_zone()) LiveRange(index); |
} |
@@ -1034,21 +972,15 @@ |
TRACE("Allocating fixed reg for op %d\n", operand->virtual_register()); |
DCHECK(operand->HasFixedPolicy()); |
InstructionOperand allocated; |
- MachineType machine_type = InstructionSequence::DefaultRepresentation(); |
- int virtual_register = operand->virtual_register(); |
- if (virtual_register != InstructionOperand::kInvalidVirtualRegister) { |
- machine_type = data()->MachineTypeFor(virtual_register); |
- } |
if (operand->HasFixedSlotPolicy()) { |
- allocated = AllocatedOperand(AllocatedOperand::STACK_SLOT, machine_type, |
+ allocated = AllocatedOperand(AllocatedOperand::STACK_SLOT, |
operand->fixed_slot_index()); |
} else if (operand->HasFixedRegisterPolicy()) { |
- allocated = AllocatedOperand(AllocatedOperand::REGISTER, machine_type, |
+ allocated = AllocatedOperand(AllocatedOperand::REGISTER, |
operand->fixed_register_index()); |
} else if (operand->HasFixedDoubleRegisterPolicy()) { |
- DCHECK_NE(InstructionOperand::kInvalidVirtualRegister, virtual_register); |
allocated = AllocatedOperand(AllocatedOperand::DOUBLE_REGISTER, |
- machine_type, operand->fixed_register_index()); |
+ operand->fixed_register_index()); |
} else { |
UNREACHABLE(); |
} |
@@ -1316,9 +1248,9 @@ |
DCHECK(index < config()->num_general_registers()); |
auto result = data()->fixed_live_ranges()[index]; |
if (result == nullptr) { |
- result = data()->NewLiveRange(FixedLiveRangeID(index), |
- InstructionSequence::DefaultRepresentation()); |
+ result = data()->NewLiveRange(FixedLiveRangeID(index)); |
DCHECK(result->IsFixed()); |
+ result->set_kind(GENERAL_REGISTERS); |
result->set_assigned_register(index); |
data()->MarkAllocated(GENERAL_REGISTERS, index); |
data()->fixed_live_ranges()[index] = result; |
@@ -1331,8 +1263,9 @@ |
DCHECK(index < config()->num_aliased_double_registers()); |
auto result = data()->fixed_double_live_ranges()[index]; |
if (result == nullptr) { |
- result = data()->NewLiveRange(FixedDoubleLiveRangeID(index), kRepFloat64); |
+ result = data()->NewLiveRange(FixedDoubleLiveRangeID(index)); |
DCHECK(result->IsFixed()); |
+ result->set_kind(DOUBLE_REGISTERS); |
result->set_assigned_register(index); |
data()->MarkAllocated(DOUBLE_REGISTERS, index); |
data()->fixed_double_live_ranges()[index] = result; |
@@ -1632,6 +1565,7 @@ |
// Postprocess the ranges. |
for (auto range : data()->live_ranges()) { |
if (range == nullptr) continue; |
+ range->set_kind(RequiredRegisterKind(range->id())); |
// Give slots to all ranges with a non fixed slot use. |
if (range->has_slot_use() && range->HasNoSpillType()) { |
data()->AssignSpillRangeToLiveRange(range); |
@@ -1676,6 +1610,13 @@ |
} |
+RegisterKind LiveRangeBuilder::RequiredRegisterKind( |
+ int virtual_register) const { |
+ return (code()->IsDouble(virtual_register)) ? DOUBLE_REGISTERS |
+ : GENERAL_REGISTERS; |
+} |
+ |
+ |
void LiveRangeBuilder::Verify() const { |
for (auto& hint : phi_hints_) { |
CHECK(hint.second->IsResolved()); |
@@ -1706,7 +1647,8 @@ |
(GetInstructionBlock(code(), pos)->last_instruction_index() != |
pos.ToInstructionIndex())); |
- auto result = data()->NewChildRangeFor(range); |
+ int vreg = code()->NextVirtualRegister(); |
+ auto result = LiveRangeFor(vreg); |
range->SplitAt(pos, result, allocation_zone()); |
return result; |
} |
@@ -2710,9 +2652,13 @@ |
for (auto range : spill_ranges) { |
if (range->IsEmpty()) continue; |
// Allocate a new operand referring to the spill slot. |
- int byte_width = range->ByteWidth(); |
- int index = data()->frame()->AllocateSpillSlot(byte_width); |
- range->set_assigned_slot(index); |
+ auto kind = range->kind(); |
+ int index = data()->frame()->AllocateSpillSlot(kind == DOUBLE_REGISTERS); |
+ auto op_kind = kind == DOUBLE_REGISTERS |
+ ? AllocatedOperand::DOUBLE_STACK_SLOT |
+ : AllocatedOperand::STACK_SLOT; |
+ auto op = AllocatedOperand::New(data()->code_zone(), op_kind, index); |
+ range->SetOperand(op); |
} |
} |
@@ -2720,18 +2666,16 @@ |
void OperandAssigner::CommitAssignment() { |
for (auto range : data()->live_ranges()) { |
if (range == nullptr || range->IsEmpty()) continue; |
- InstructionOperand spill_operand; |
- if (range->TopLevel()->HasSpillOperand()) { |
- spill_operand = *range->TopLevel()->GetSpillOperand(); |
- } else if (range->TopLevel()->HasSpillRange()) { |
- spill_operand = range->TopLevel()->GetSpillRangeOperand(); |
+ InstructionOperand* spill_operand = nullptr; |
+ if (!range->TopLevel()->HasNoSpillType()) { |
+ spill_operand = range->TopLevel()->GetSpillOperand(); |
} |
auto assigned = range->GetAssignedOperand(); |
range->ConvertUsesToOperand(assigned, spill_operand); |
if (range->is_phi()) { |
data()->GetPhiMapValueFor(range->id())->CommitAssignment(assigned); |
} |
- if (!range->IsChild() && !spill_operand.IsInvalid()) { |
+ if (!range->IsChild() && spill_operand != nullptr) { |
range->CommitSpillsAtDefinition(data()->code(), spill_operand, |
range->has_slot_use()); |
} |
@@ -2812,21 +2756,12 @@ |
// Check if the live range is spilled and the safe point is after |
// the spill position. |
- if (((range->HasSpillOperand() && |
- !range->GetSpillOperand()->IsConstant()) || |
- range->HasSpillRange()) && |
- safe_point >= range->spill_start_index()) { |
+ if (range->HasSpillOperand() && |
+ safe_point >= range->spill_start_index() && |
+ !range->GetSpillOperand()->IsConstant()) { |
TRACE("Pointer for range %d (spilled at %d) at safe point %d\n", |
range->id(), range->spill_start_index(), safe_point); |
- InstructionOperand operand; |
- if (range->HasSpillOperand()) { |
- operand = *range->GetSpillOperand(); |
- } else { |
- operand = range->GetSpillRangeOperand(); |
- } |
- DCHECK(operand.IsStackSlot()); |
- DCHECK_EQ(kRepTagged, AllocatedOperand::cast(operand).machine_type()); |
- map->RecordReference(operand); |
+ map->RecordReference(*range->GetSpillOperand()); |
} |
if (!cur->spilled()) { |
@@ -2836,7 +2771,6 @@ |
cur->id(), cur->Start().value(), safe_point); |
auto operand = cur->GetAssignedOperand(); |
DCHECK(!operand.IsStackSlot()); |
- DCHECK_EQ(kRepTagged, AllocatedOperand::cast(operand).machine_type()); |
map->RecordReference(operand); |
} |
} |
@@ -2974,24 +2908,6 @@ |
DISALLOW_COPY_AND_ASSIGN(LiveRangeFinder); |
}; |
- |
- |
-typedef std::pair<ParallelMove*, InstructionOperand> DelayedInsertionMapKey; |
- |
- |
-struct DelayedInsertionMapCompare { |
- bool operator()(const DelayedInsertionMapKey& a, |
- const DelayedInsertionMapKey& b) { |
- if (a.first == b.first) { |
- return a.second.Compare(b.second); |
- } |
- return a.first < b.first; |
- } |
-}; |
- |
- |
-typedef ZoneMap<DelayedInsertionMapKey, InstructionOperand, |
- DelayedInsertionMapCompare> DelayedInsertionMap; |
} // namespace |
@@ -3026,7 +2942,7 @@ |
continue; |
auto pred_op = result.pred_cover_->GetAssignedOperand(); |
auto cur_op = result.cur_cover_->GetAssignedOperand(); |
- if (pred_op.Equals(cur_op)) continue; |
+ if (pred_op == cur_op) continue; |
ResolveControlFlow(block, cur_op, pred_block, pred_op); |
} |
iterator.Advance(); |
@@ -3039,7 +2955,7 @@ |
const InstructionOperand& cur_op, |
const InstructionBlock* pred, |
const InstructionOperand& pred_op) { |
- DCHECK(!pred_op.Equals(cur_op)); |
+ DCHECK(pred_op != cur_op); |
int gap_index; |
Instruction::GapPosition position; |
if (block->PredecessorCount() == 1) { |
@@ -3058,7 +2974,8 @@ |
void LiveRangeConnector::ConnectRanges(Zone* local_zone) { |
- DelayedInsertionMap delayed_insertion_map(local_zone); |
+ ZoneMap<std::pair<ParallelMove*, InstructionOperand>, InstructionOperand> |
+ delayed_insertion_map(local_zone); |
for (auto first_range : data()->live_ranges()) { |
if (first_range == nullptr || first_range->IsChild()) continue; |
for (auto second_range = first_range->next(); second_range != nullptr; |
@@ -3074,7 +2991,7 @@ |
} |
auto prev_operand = first_range->GetAssignedOperand(); |
auto cur_operand = second_range->GetAssignedOperand(); |
- if (prev_operand.Equals(cur_operand)) continue; |
+ if (prev_operand == cur_operand) continue; |
bool delay_insertion = false; |
Instruction::GapPosition gap_pos; |
int gap_index = pos.ToInstructionIndex(); |