Commit 21a471f2 authored by Sigurd Schneider's avatar Sigurd Schneider Committed by Commit Bot

Revert "Reland "[regalloc] Introduce deferred fixed ranges""

This reverts commit 1ca08865.

Reason for revert: Regressions across the board

Original change's description:
> Reland "[regalloc] Introduce deferred fixed ranges"
> 
> This is a reland of b1769313
> 
> Original change's description:
> > [regalloc] Introduce deferred fixed ranges
> > 
> > Fixed ranges are used to express register constraints in the
> > allocator. This change splits these fixed ranges into one for
> > normal code and deferred code. The former are handeled as before
> > whereas the latter are only made visible while allocating
> > registers for deferred code.
> > 
> > This prevents forward looking decisions in normal code to be
> > impacted by register constraints from deferred code.
> > 
> > Change-Id: I67d562bb41166194e62765d5ab051bc961054fc7
> > Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/1477742
> > Commit-Queue: Sigurd Schneider <sigurds@chromium.org>
> > Reviewed-by: Jaroslav Sevcik <jarin@chromium.org>
> > Reviewed-by: Sigurd Schneider <sigurds@chromium.org>
> > Cr-Commit-Position: refs/heads/master@{#60322}
> 
> Change-Id: I1a31150256eb5608db985b144aab7ea457169d0d
> Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/1530810
> Commit-Queue: Sigurd Schneider <sigurds@chromium.org>
> Reviewed-by: Jaroslav Sevcik <jarin@chromium.org>
> Cr-Commit-Position: refs/heads/master@{#60364}

TBR=jarin@chromium.org,sigurds@chromium.org,herhut@chromium.org

Change-Id: Id8ad6c39774e38dd67decea997e08a4c58c452ec
No-Presubmit: true
No-Tree-Checks: true
No-Try: true
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/1532327Reviewed-by: 's avatarSigurd Schneider <sigurds@chromium.org>
Commit-Queue: Sigurd Schneider <sigurds@chromium.org>
Cr-Commit-Position: refs/heads/master@{#60381}
parent 1a88414c
...@@ -651,11 +651,7 @@ std::ostream& operator<<(std::ostream& os, ...@@ -651,11 +651,7 @@ std::ostream& operator<<(std::ostream& os,
const InstructionSequence* code = printable_block.code_; const InstructionSequence* code = printable_block.code_;
os << "B" << block->rpo_number(); os << "B" << block->rpo_number();
if (block->ao_number().IsValid()) {
os << ": AO#" << block->ao_number(); os << ": AO#" << block->ao_number();
} else {
os << ": AO#?";
}
if (block->IsDeferred()) os << " (deferred)"; if (block->IsDeferred()) os << " (deferred)";
if (!block->needs_frame()) os << " (no frame)"; if (!block->needs_frame()) os << " (no frame)";
if (block->must_construct_frame()) os << " (construct frame)"; if (block->must_construct_frame()) os << " (construct frame)";
......
...@@ -162,7 +162,6 @@ void LiveRangeMerger::MarkRangesSpilledInDeferredBlocks() { ...@@ -162,7 +162,6 @@ void LiveRangeMerger::MarkRangesSpilledInDeferredBlocks() {
} }
} }
if (child == nullptr) { if (child == nullptr) {
DCHECK(!data()->is_turbo_control_flow_aware_allocation());
top->TreatAsSpilledInDeferredBlock(data()->allocation_zone(), top->TreatAsSpilledInDeferredBlock(data()->allocation_zone(),
code->InstructionBlockCount()); code->InstructionBlockCount());
} }
......
...@@ -735,10 +735,10 @@ bool LiveRange::ShouldBeAllocatedBefore(const LiveRange* other) const { ...@@ -735,10 +735,10 @@ bool LiveRange::ShouldBeAllocatedBefore(const LiveRange* other) const {
return true; return true;
} }
// The other has a smaller hint. // The other has a smaller hint.
if (controlflow_hint() > other->controlflow_hint()) { if (other->controlflow_hint() != kUnassignedRegister) {
return false; return false;
} }
// Both have the same hint or no hint at all. Use first use position. // No hint, use first use position.
UsePosition* pos = first_pos(); UsePosition* pos = first_pos();
UsePosition* other_pos = other->first_pos(); UsePosition* other_pos = other->first_pos();
// To make the order total, handle the case where both positions are null. // To make the order total, handle the case where both positions are null.
...@@ -891,15 +891,13 @@ void TopLevelLiveRange::RecordSpillLocation(Zone* zone, int gap_index, ...@@ -891,15 +891,13 @@ void TopLevelLiveRange::RecordSpillLocation(Zone* zone, int gap_index,
gap_index, operand, spill_move_insertion_locations_); gap_index, operand, spill_move_insertion_locations_);
} }
void TopLevelLiveRange::CommitSpillMoves(RegisterAllocationData* data, void TopLevelLiveRange::CommitSpillMoves(InstructionSequence* sequence,
const InstructionOperand& op, const InstructionOperand& op,
bool might_be_duplicated) { bool might_be_duplicated) {
DCHECK_IMPLIES(op.IsConstant(), DCHECK_IMPLIES(op.IsConstant(), GetSpillMoveInsertionLocations() == nullptr);
GetSpillMoveInsertionLocations(data) == nullptr);
InstructionSequence* sequence = data->code();
Zone* zone = sequence->zone(); Zone* zone = sequence->zone();
for (SpillMoveInsertionList* to_spill = GetSpillMoveInsertionLocations(data); for (SpillMoveInsertionList* to_spill = GetSpillMoveInsertionLocations();
to_spill != nullptr; to_spill = to_spill->next) { to_spill != nullptr; to_spill = to_spill->next) {
Instruction* instr = sequence->InstructionAt(to_spill->gap_index); Instruction* instr = sequence->InstructionAt(to_spill->gap_index);
ParallelMove* move = ParallelMove* move =
...@@ -1469,8 +1467,7 @@ void RegisterAllocationData::PhiMapValue::CommitAssignment( ...@@ -1469,8 +1467,7 @@ void RegisterAllocationData::PhiMapValue::CommitAssignment(
RegisterAllocationData::RegisterAllocationData( RegisterAllocationData::RegisterAllocationData(
const RegisterConfiguration* config, Zone* zone, Frame* frame, const RegisterConfiguration* config, Zone* zone, Frame* frame,
InstructionSequence* code, RegisterAllocationFlags flags, InstructionSequence* code, const char* debug_name)
const char* debug_name)
: allocation_zone_(zone), : allocation_zone_(zone),
frame_(frame), frame_(frame),
code_(code), code_(code),
...@@ -1481,13 +1478,11 @@ RegisterAllocationData::RegisterAllocationData( ...@@ -1481,13 +1478,11 @@ RegisterAllocationData::RegisterAllocationData(
live_out_sets_(code->InstructionBlockCount(), nullptr, allocation_zone()), live_out_sets_(code->InstructionBlockCount(), nullptr, allocation_zone()),
live_ranges_(code->VirtualRegisterCount() * 2, nullptr, live_ranges_(code->VirtualRegisterCount() * 2, nullptr,
allocation_zone()), allocation_zone()),
fixed_live_ranges_(kNumberOfFixedRangesPerRegister * fixed_live_ranges_(this->config()->num_general_registers(), nullptr,
this->config()->num_general_registers(), allocation_zone()),
nullptr, allocation_zone()),
fixed_float_live_ranges_(allocation_zone()), fixed_float_live_ranges_(allocation_zone()),
fixed_double_live_ranges_(kNumberOfFixedRangesPerRegister * fixed_double_live_ranges_(this->config()->num_double_registers(), nullptr,
this->config()->num_double_registers(), allocation_zone()),
nullptr, allocation_zone()),
fixed_simd128_live_ranges_(allocation_zone()), fixed_simd128_live_ranges_(allocation_zone()),
spill_ranges_(code->VirtualRegisterCount(), nullptr, allocation_zone()), spill_ranges_(code->VirtualRegisterCount(), nullptr, allocation_zone()),
delayed_references_(allocation_zone()), delayed_references_(allocation_zone()),
...@@ -1496,15 +1491,11 @@ RegisterAllocationData::RegisterAllocationData( ...@@ -1496,15 +1491,11 @@ RegisterAllocationData::RegisterAllocationData(
virtual_register_count_(code->VirtualRegisterCount()), virtual_register_count_(code->VirtualRegisterCount()),
preassigned_slot_ranges_(zone), preassigned_slot_ranges_(zone),
spill_state_(code->InstructionBlockCount(), ZoneVector<LiveRange*>(zone), spill_state_(code->InstructionBlockCount(), ZoneVector<LiveRange*>(zone),
zone), zone) {
flags_(flags) {
if (!kSimpleFPAliasing) { if (!kSimpleFPAliasing) {
fixed_float_live_ranges_.resize( fixed_float_live_ranges_.resize(this->config()->num_float_registers(),
kNumberOfFixedRangesPerRegister * this->config()->num_float_registers(),
nullptr); nullptr);
fixed_simd128_live_ranges_.resize( fixed_simd128_live_ranges_.resize(this->config()->num_simd128_registers(),
kNumberOfFixedRangesPerRegister *
this->config()->num_simd128_registers(),
nullptr); nullptr);
} }
...@@ -1655,7 +1646,7 @@ SpillRange* RegisterAllocationData::AssignSpillRangeToLiveRange( ...@@ -1655,7 +1646,7 @@ SpillRange* RegisterAllocationData::AssignSpillRangeToLiveRange(
} }
if (spill_mode == SpillMode::kSpillDeferred && if (spill_mode == SpillMode::kSpillDeferred &&
(range->spill_type() != SpillType::kSpillRange)) { (range->spill_type() != SpillType::kSpillRange)) {
DCHECK(is_turbo_control_flow_aware_allocation()); DCHECK(FLAG_turbo_control_flow_aware_allocation);
range->set_spill_type(SpillType::kDeferredSpillRange); range->set_spill_type(SpillType::kDeferredSpillRange);
} else { } else {
range->set_spill_type(SpillType::kSpillRange); range->set_spill_type(SpillType::kSpillRange);
...@@ -1671,7 +1662,7 @@ SpillRange* RegisterAllocationData::AssignSpillRangeToLiveRange( ...@@ -1671,7 +1662,7 @@ SpillRange* RegisterAllocationData::AssignSpillRangeToLiveRange(
SpillRange* RegisterAllocationData::CreateSpillRangeForLiveRange( SpillRange* RegisterAllocationData::CreateSpillRangeForLiveRange(
TopLevelLiveRange* range) { TopLevelLiveRange* range) {
DCHECK(is_turbo_preprocess_ranges()); DCHECK(FLAG_turbo_preprocess_ranges);
DCHECK(!range->HasSpillOperand()); DCHECK(!range->HasSpillOperand());
DCHECK(!range->IsSplinter()); DCHECK(!range->IsSplinter());
SpillRange* spill_range = SpillRange* spill_range =
...@@ -2081,16 +2072,13 @@ int LiveRangeBuilder::FixedFPLiveRangeID(int index, MachineRepresentation rep) { ...@@ -2081,16 +2072,13 @@ int LiveRangeBuilder::FixedFPLiveRangeID(int index, MachineRepresentation rep) {
int result = -index - 1; int result = -index - 1;
switch (rep) { switch (rep) {
case MachineRepresentation::kSimd128: case MachineRepresentation::kSimd128:
result -= result -= config()->num_float_registers();
kNumberOfFixedRangesPerRegister * config()->num_float_registers();
V8_FALLTHROUGH; V8_FALLTHROUGH;
case MachineRepresentation::kFloat32: case MachineRepresentation::kFloat32:
result -= result -= config()->num_double_registers();
kNumberOfFixedRangesPerRegister * config()->num_double_registers();
V8_FALLTHROUGH; V8_FALLTHROUGH;
case MachineRepresentation::kFloat64: case MachineRepresentation::kFloat64:
result -= result -= config()->num_general_registers();
kNumberOfFixedRangesPerRegister * config()->num_general_registers();
break; break;
default: default:
UNREACHABLE(); UNREACHABLE();
...@@ -2099,29 +2087,22 @@ int LiveRangeBuilder::FixedFPLiveRangeID(int index, MachineRepresentation rep) { ...@@ -2099,29 +2087,22 @@ int LiveRangeBuilder::FixedFPLiveRangeID(int index, MachineRepresentation rep) {
return result; return result;
} }
TopLevelLiveRange* LiveRangeBuilder::FixedLiveRangeFor(int index, TopLevelLiveRange* LiveRangeBuilder::FixedLiveRangeFor(int index) {
SpillMode spill_mode) {
int offset = spill_mode == SpillMode::kSpillAtDefinition
? 0
: config()->num_general_registers();
DCHECK(index < config()->num_general_registers()); DCHECK(index < config()->num_general_registers());
TopLevelLiveRange* result = data()->fixed_live_ranges()[offset + index]; TopLevelLiveRange* result = data()->fixed_live_ranges()[index];
if (result == nullptr) { if (result == nullptr) {
MachineRepresentation rep = InstructionSequence::DefaultRepresentation(); MachineRepresentation rep = InstructionSequence::DefaultRepresentation();
result = data()->NewLiveRange(FixedLiveRangeID(offset + index), rep); result = data()->NewLiveRange(FixedLiveRangeID(index), rep);
DCHECK(result->IsFixed()); DCHECK(result->IsFixed());
result->set_assigned_register(index); result->set_assigned_register(index);
data()->MarkAllocated(rep, index); data()->MarkAllocated(rep, index);
if (spill_mode == SpillMode::kSpillDeferred) { data()->fixed_live_ranges()[index] = result;
result->set_deferred_fixed();
}
data()->fixed_live_ranges()[offset + index] = result;
} }
return result; return result;
} }
TopLevelLiveRange* LiveRangeBuilder::FixedFPLiveRangeFor( TopLevelLiveRange* LiveRangeBuilder::FixedFPLiveRangeFor(
int index, MachineRepresentation rep, SpillMode spill_mode) { int index, MachineRepresentation rep) {
int num_regs = config()->num_double_registers(); int num_regs = config()->num_double_registers();
ZoneVector<TopLevelLiveRange*>* live_ranges = ZoneVector<TopLevelLiveRange*>* live_ranges =
&data()->fixed_double_live_ranges(); &data()->fixed_double_live_ranges();
...@@ -2140,26 +2121,20 @@ TopLevelLiveRange* LiveRangeBuilder::FixedFPLiveRangeFor( ...@@ -2140,26 +2121,20 @@ TopLevelLiveRange* LiveRangeBuilder::FixedFPLiveRangeFor(
} }
} }
int offset = spill_mode == SpillMode::kSpillAtDefinition ? 0 : num_regs;
DCHECK(index < num_regs); DCHECK(index < num_regs);
USE(num_regs); USE(num_regs);
TopLevelLiveRange* result = (*live_ranges)[offset + index]; TopLevelLiveRange* result = (*live_ranges)[index];
if (result == nullptr) { if (result == nullptr) {
result = data()->NewLiveRange(FixedFPLiveRangeID(offset + index, rep), rep); result = data()->NewLiveRange(FixedFPLiveRangeID(index, rep), rep);
DCHECK(result->IsFixed()); DCHECK(result->IsFixed());
result->set_assigned_register(index); result->set_assigned_register(index);
data()->MarkAllocated(rep, index); data()->MarkAllocated(rep, index);
if (spill_mode == SpillMode::kSpillDeferred) { (*live_ranges)[index] = result;
result->set_deferred_fixed();
}
(*live_ranges)[offset + index] = result;
} }
return result; return result;
} }
TopLevelLiveRange* LiveRangeBuilder::LiveRangeFor(InstructionOperand* operand, TopLevelLiveRange* LiveRangeBuilder::LiveRangeFor(InstructionOperand* operand) {
SpillMode spill_mode) {
if (operand->IsUnallocated()) { if (operand->IsUnallocated()) {
return data()->GetOrCreateLiveRangeFor( return data()->GetOrCreateLiveRangeFor(
UnallocatedOperand::cast(operand)->virtual_register()); UnallocatedOperand::cast(operand)->virtual_register());
...@@ -2168,11 +2143,10 @@ TopLevelLiveRange* LiveRangeBuilder::LiveRangeFor(InstructionOperand* operand, ...@@ -2168,11 +2143,10 @@ TopLevelLiveRange* LiveRangeBuilder::LiveRangeFor(InstructionOperand* operand,
ConstantOperand::cast(operand)->virtual_register()); ConstantOperand::cast(operand)->virtual_register());
} else if (operand->IsRegister()) { } else if (operand->IsRegister()) {
return FixedLiveRangeFor( return FixedLiveRangeFor(
LocationOperand::cast(operand)->GetRegister().code(), spill_mode); LocationOperand::cast(operand)->GetRegister().code());
} else if (operand->IsFPRegister()) { } else if (operand->IsFPRegister()) {
LocationOperand* op = LocationOperand::cast(operand); LocationOperand* op = LocationOperand::cast(operand);
return FixedFPLiveRangeFor(op->register_code(), op->representation(), return FixedFPLiveRangeFor(op->register_code(), op->representation());
spill_mode);
} else { } else {
return nullptr; return nullptr;
} }
...@@ -2187,9 +2161,8 @@ UsePosition* LiveRangeBuilder::NewUsePosition(LifetimePosition pos, ...@@ -2187,9 +2161,8 @@ UsePosition* LiveRangeBuilder::NewUsePosition(LifetimePosition pos,
UsePosition* LiveRangeBuilder::Define(LifetimePosition position, UsePosition* LiveRangeBuilder::Define(LifetimePosition position,
InstructionOperand* operand, void* hint, InstructionOperand* operand, void* hint,
UsePositionHintType hint_type, UsePositionHintType hint_type) {
SpillMode spill_mode) { TopLevelLiveRange* range = LiveRangeFor(operand);
TopLevelLiveRange* range = LiveRangeFor(operand, spill_mode);
if (range == nullptr) return nullptr; if (range == nullptr) return nullptr;
if (range->IsEmpty() || range->Start() > position) { if (range->IsEmpty() || range->Start() > position) {
...@@ -2210,9 +2183,8 @@ UsePosition* LiveRangeBuilder::Define(LifetimePosition position, ...@@ -2210,9 +2183,8 @@ UsePosition* LiveRangeBuilder::Define(LifetimePosition position,
UsePosition* LiveRangeBuilder::Use(LifetimePosition block_start, UsePosition* LiveRangeBuilder::Use(LifetimePosition block_start,
LifetimePosition position, LifetimePosition position,
InstructionOperand* operand, void* hint, InstructionOperand* operand, void* hint,
UsePositionHintType hint_type, UsePositionHintType hint_type) {
SpillMode spill_mode) { TopLevelLiveRange* range = LiveRangeFor(operand);
TopLevelLiveRange* range = LiveRangeFor(operand, spill_mode);
if (range == nullptr) return nullptr; if (range == nullptr) return nullptr;
UsePosition* use_pos = nullptr; UsePosition* use_pos = nullptr;
if (operand->IsUnallocated()) { if (operand->IsUnallocated()) {
...@@ -2236,7 +2208,6 @@ void LiveRangeBuilder::ProcessInstructions(const InstructionBlock* block, ...@@ -2236,7 +2208,6 @@ void LiveRangeBuilder::ProcessInstructions(const InstructionBlock* block,
fixed_float_live_ranges = (mask & kFloat32Bit) != 0; fixed_float_live_ranges = (mask & kFloat32Bit) != 0;
fixed_simd128_live_ranges = (mask & kSimd128Bit) != 0; fixed_simd128_live_ranges = (mask & kSimd128Bit) != 0;
} }
SpillMode spill_mode = SpillModeForBlock(block);
for (int index = block->last_instruction_index(); index >= block_start; for (int index = block->last_instruction_index(); index >= block_start;
index--) { index--) {
...@@ -2265,10 +2236,9 @@ void LiveRangeBuilder::ProcessInstructions(const InstructionBlock* block, ...@@ -2265,10 +2236,9 @@ void LiveRangeBuilder::ProcessInstructions(const InstructionBlock* block,
// exception value. // exception value.
// TODO(mtrofin): should we explore an explicit opcode for // TODO(mtrofin): should we explore an explicit opcode for
// the first instruction in the handler? // the first instruction in the handler?
Define(LifetimePosition::GapFromInstructionIndex(index), output, Define(LifetimePosition::GapFromInstructionIndex(index), output);
spill_mode);
} else { } else {
Define(curr_position, output, spill_mode); Define(curr_position, output);
} }
} }
...@@ -2279,7 +2249,7 @@ void LiveRangeBuilder::ProcessInstructions(const InstructionBlock* block, ...@@ -2279,7 +2249,7 @@ void LiveRangeBuilder::ProcessInstructions(const InstructionBlock* block,
// is OK because AddUseInterval will just merge it with the existing // is OK because AddUseInterval will just merge it with the existing
// one at the end of the range. // one at the end of the range.
int code = config()->GetAllocatableGeneralCode(i); int code = config()->GetAllocatableGeneralCode(i);
TopLevelLiveRange* range = FixedLiveRangeFor(code, spill_mode); TopLevelLiveRange* range = FixedLiveRangeFor(code);
range->AddUseInterval(curr_position, curr_position.End(), range->AddUseInterval(curr_position, curr_position.End(),
allocation_zone()); allocation_zone());
} }
...@@ -2290,8 +2260,8 @@ void LiveRangeBuilder::ProcessInstructions(const InstructionBlock* block, ...@@ -2290,8 +2260,8 @@ void LiveRangeBuilder::ProcessInstructions(const InstructionBlock* block,
// Add a UseInterval for all DoubleRegisters. See comment above for // Add a UseInterval for all DoubleRegisters. See comment above for
// general registers. // general registers.
int code = config()->GetAllocatableDoubleCode(i); int code = config()->GetAllocatableDoubleCode(i);
TopLevelLiveRange* range = FixedFPLiveRangeFor( TopLevelLiveRange* range =
code, MachineRepresentation::kFloat64, spill_mode); FixedFPLiveRangeFor(code, MachineRepresentation::kFloat64);
range->AddUseInterval(curr_position, curr_position.End(), range->AddUseInterval(curr_position, curr_position.End(),
allocation_zone()); allocation_zone());
} }
...@@ -2303,8 +2273,8 @@ void LiveRangeBuilder::ProcessInstructions(const InstructionBlock* block, ...@@ -2303,8 +2273,8 @@ void LiveRangeBuilder::ProcessInstructions(const InstructionBlock* block,
// Add a UseInterval for all FloatRegisters. See comment above for // Add a UseInterval for all FloatRegisters. See comment above for
// general registers. // general registers.
int code = config()->GetAllocatableFloatCode(i); int code = config()->GetAllocatableFloatCode(i);
TopLevelLiveRange* range = FixedFPLiveRangeFor( TopLevelLiveRange* range =
code, MachineRepresentation::kFloat32, spill_mode); FixedFPLiveRangeFor(code, MachineRepresentation::kFloat32);
range->AddUseInterval(curr_position, curr_position.End(), range->AddUseInterval(curr_position, curr_position.End(),
allocation_zone()); allocation_zone());
} }
...@@ -2313,8 +2283,8 @@ void LiveRangeBuilder::ProcessInstructions(const InstructionBlock* block, ...@@ -2313,8 +2283,8 @@ void LiveRangeBuilder::ProcessInstructions(const InstructionBlock* block,
for (int i = 0; i < config()->num_allocatable_simd128_registers(); for (int i = 0; i < config()->num_allocatable_simd128_registers();
++i) { ++i) {
int code = config()->GetAllocatableSimd128Code(i); int code = config()->GetAllocatableSimd128Code(i);
TopLevelLiveRange* range = FixedFPLiveRangeFor( TopLevelLiveRange* range =
code, MachineRepresentation::kSimd128, spill_mode); FixedFPLiveRangeFor(code, MachineRepresentation::kSimd128);
range->AddUseInterval(curr_position, curr_position.End(), range->AddUseInterval(curr_position, curr_position.End(),
allocation_zone()); allocation_zone());
} }
...@@ -2340,7 +2310,7 @@ void LiveRangeBuilder::ProcessInstructions(const InstructionBlock* block, ...@@ -2340,7 +2310,7 @@ void LiveRangeBuilder::ProcessInstructions(const InstructionBlock* block,
int vreg = unalloc->virtual_register(); int vreg = unalloc->virtual_register();
live->Add(vreg); live->Add(vreg);
if (unalloc->HasSlotPolicy()) { if (unalloc->HasSlotPolicy()) {
if (data()->is_turbo_control_flow_aware_allocation()) { if (FLAG_turbo_control_flow_aware_allocation) {
data()->GetOrCreateLiveRangeFor(vreg)->register_slot_use( data()->GetOrCreateLiveRangeFor(vreg)->register_slot_use(
block->IsDeferred() block->IsDeferred()
? TopLevelLiveRange::SlotUseKind::kDeferredSlotUse ? TopLevelLiveRange::SlotUseKind::kDeferredSlotUse
...@@ -2351,7 +2321,7 @@ void LiveRangeBuilder::ProcessInstructions(const InstructionBlock* block, ...@@ -2351,7 +2321,7 @@ void LiveRangeBuilder::ProcessInstructions(const InstructionBlock* block,
} }
} }
} }
Use(block_start_position, use_pos, input, spill_mode); Use(block_start_position, use_pos, input);
} }
for (size_t i = 0; i < instr->TempCount(); i++) { for (size_t i = 0; i < instr->TempCount(); i++) {
...@@ -2368,8 +2338,8 @@ void LiveRangeBuilder::ProcessInstructions(const InstructionBlock* block, ...@@ -2368,8 +2338,8 @@ void LiveRangeBuilder::ProcessInstructions(const InstructionBlock* block,
} }
} }
} }
Use(block_start_position, curr_position.End(), temp, spill_mode); Use(block_start_position, curr_position.End(), temp);
Define(curr_position, temp, spill_mode); Define(curr_position, temp);
} }
// Process the moves of the instruction's gaps, making their sources live. // Process the moves of the instruction's gaps, making their sources live.
...@@ -2408,9 +2378,8 @@ void LiveRangeBuilder::ProcessInstructions(const InstructionBlock* block, ...@@ -2408,9 +2378,8 @@ void LiveRangeBuilder::ProcessInstructions(const InstructionBlock* block,
} }
} else { } else {
if (live->Contains(to_vreg)) { if (live->Contains(to_vreg)) {
to_use = to_use = Define(curr_position, &to, &from,
Define(curr_position, &to, &from, UsePosition::HintTypeForOperand(from));
UsePosition::HintTypeForOperand(from), spill_mode);
live->Remove(to_vreg); live->Remove(to_vreg);
} else { } else {
cur->Eliminate(); cur->Eliminate();
...@@ -2418,10 +2387,10 @@ void LiveRangeBuilder::ProcessInstructions(const InstructionBlock* block, ...@@ -2418,10 +2387,10 @@ void LiveRangeBuilder::ProcessInstructions(const InstructionBlock* block,
} }
} }
} else { } else {
Define(curr_position, &to, spill_mode); Define(curr_position, &to);
} }
UsePosition* from_use = Use(block_start_position, curr_position, &from, UsePosition* from_use =
hint, hint_type, spill_mode); Use(block_start_position, curr_position, &from, hint, hint_type);
// Mark range live. // Mark range live.
if (from.IsUnallocated()) { if (from.IsUnallocated()) {
live->Add(UnallocatedOperand::cast(from).virtual_register()); live->Add(UnallocatedOperand::cast(from).virtual_register());
...@@ -2556,8 +2525,7 @@ void LiveRangeBuilder::ProcessPhis(const InstructionBlock* block, ...@@ -2556,8 +2525,7 @@ void LiveRangeBuilder::ProcessPhis(const InstructionBlock* block,
LifetimePosition block_start = LifetimePosition::GapFromInstructionIndex( LifetimePosition block_start = LifetimePosition::GapFromInstructionIndex(
block->first_instruction_index()); block->first_instruction_index());
UsePosition* use_pos = Define(block_start, &phi->output(), hint, UsePosition* use_pos = Define(block_start, &phi->output(), hint,
UsePosition::HintTypeForOperand(*hint), UsePosition::HintTypeForOperand(*hint));
SpillModeForBlock(block));
MapPhiHint(hint, use_pos); MapPhiHint(hint, use_pos);
} }
} }
...@@ -3435,117 +3403,6 @@ bool LinearScanAllocator::ConsiderBlockForControlFlow( ...@@ -3435,117 +3403,6 @@ bool LinearScanAllocator::ConsiderBlockForControlFlow(
!code()->InstructionBlockAt(predecessor)->IsDeferred()); !code()->InstructionBlockAt(predecessor)->IsDeferred());
} }
void LinearScanAllocator::UpdateDeferredFixedRanges(SpillMode spill_mode,
InstructionBlock* block) {
if (spill_mode == SpillMode::kSpillDeferred) {
LifetimePosition max = LifetimePosition::InstructionFromInstructionIndex(
LastDeferredInstructionIndex(block));
// Adds range back to inactive, resolving resulting conflicts.
auto add_to_inactive = [this, max](LiveRange* range) {
AddToInactive(range);
// Splits other if it conflicts with range. Other is placed in unhandled
// for later reallocation.
auto split_conflicting = [this, max](LiveRange* range, LiveRange* other,
std::function<void(LiveRange*)>
update_caches) {
if (other->TopLevel()->IsFixed()) return;
int reg = range->assigned_register();
if (kSimpleFPAliasing || !check_fp_aliasing()) {
if (other->assigned_register() != reg) {
return;
}
} else {
if (!data()->config()->AreAliases(range->representation(), reg,
other->representation(),
other->assigned_register())) {
return;
}
}
// The inactive range might conflict, so check whether we need to
// split and spill. We can look for the first intersection, as there
// cannot be any intersections in the past, as those would have been a
// conflict then.
LifetimePosition next_start = range->FirstIntersection(other);
if (!next_start.IsValid() || (next_start > max)) {
// There is no conflict or the conflict is outside of the current
// stretch of deferred code. In either case we can ignore the
// inactive range.
return;
}
// They overlap. So we need to split active and reschedule it
// for allocation.
TRACE("Resolving conflict of %d with deferred fixed for register %s\n",
other->TopLevel()->vreg(),
RegisterName(other->assigned_register()));
LiveRange* split_off =
other->SplitAt(next_start, data()->allocation_zone());
DCHECK_NE(split_off, other);
AddToUnhandled(split_off);
update_caches(other);
};
// Now check for conflicts in active and inactive ranges. We might have
// conflicts in inactive, as we do not do this check on every block
// boundary but only on deferred/non-deferred changes but inactive
// live ranges might become live on any block boundary.
for (auto active : active_live_ranges()) {
split_conflicting(range, active, [this](LiveRange* updated) {
next_active_ranges_change_ =
Min(updated->End(), next_active_ranges_change_);
});
}
for (auto inactive : inactive_live_ranges()) {
split_conflicting(range, inactive, [this](LiveRange* updated) {
next_inactive_ranges_change_ =
Min(updated->End(), next_inactive_ranges_change_);
});
}
};
if (mode() == GENERAL_REGISTERS) {
for (TopLevelLiveRange* current : data()->fixed_live_ranges()) {
if (current != nullptr) {
if (current->IsDeferredFixed()) {
add_to_inactive(current);
}
}
}
} else {
for (TopLevelLiveRange* current : data()->fixed_double_live_ranges()) {
if (current != nullptr) {
if (current->IsDeferredFixed()) {
add_to_inactive(current);
}
}
}
if (!kSimpleFPAliasing && check_fp_aliasing()) {
for (TopLevelLiveRange* current : data()->fixed_float_live_ranges()) {
if (current != nullptr) {
if (current->IsDeferredFixed()) {
add_to_inactive(current);
}
}
}
for (TopLevelLiveRange* current : data()->fixed_simd128_live_ranges()) {
if (current != nullptr) {
if (current->IsDeferredFixed()) {
add_to_inactive(current);
}
}
}
}
}
} else {
// Remove all ranges.
for (auto it = inactive_live_ranges().begin();
it != inactive_live_ranges().end();) {
if ((*it)->TopLevel()->IsDeferredFixed()) {
it = inactive_live_ranges().erase(it);
} else {
++it;
}
}
}
}
bool LinearScanAllocator::BlockIsDeferredOrImmediatePredecessorIsNotDeferred( bool LinearScanAllocator::BlockIsDeferredOrImmediatePredecessorIsNotDeferred(
const InstructionBlock* block) { const InstructionBlock* block) {
if (block->IsDeferred()) return true; if (block->IsDeferred()) return true;
...@@ -3560,14 +3417,6 @@ bool LinearScanAllocator::BlockIsDeferredOrImmediatePredecessorIsNotDeferred( ...@@ -3560,14 +3417,6 @@ bool LinearScanAllocator::BlockIsDeferredOrImmediatePredecessorIsNotDeferred(
return !pred_is_deferred; return !pred_is_deferred;
} }
bool LinearScanAllocator::HasNonDeferredPredecessor(InstructionBlock* block) {
for (auto pred : block->predecessors()) {
InstructionBlock* pred_block = code()->InstructionBlockAt(pred);
if (!pred_block->IsDeferred()) return true;
}
return false;
}
void LinearScanAllocator::AllocateRegisters() { void LinearScanAllocator::AllocateRegisters() {
DCHECK(unhandled_live_ranges().empty()); DCHECK(unhandled_live_ranges().empty());
DCHECK(active_live_ranges().empty()); DCHECK(active_live_ranges().empty());
...@@ -3595,30 +3444,18 @@ void LinearScanAllocator::AllocateRegisters() { ...@@ -3595,30 +3444,18 @@ void LinearScanAllocator::AllocateRegisters() {
if (mode() == GENERAL_REGISTERS) { if (mode() == GENERAL_REGISTERS) {
for (TopLevelLiveRange* current : data()->fixed_live_ranges()) { for (TopLevelLiveRange* current : data()->fixed_live_ranges()) {
if (current != nullptr) { if (current != nullptr) AddToInactive(current);
if (current->IsDeferredFixed()) continue;
AddToInactive(current);
}
} }
} else { } else {
for (TopLevelLiveRange* current : data()->fixed_double_live_ranges()) { for (TopLevelLiveRange* current : data()->fixed_double_live_ranges()) {
if (current != nullptr) { if (current != nullptr) AddToInactive(current);
if (current->IsDeferredFixed()) continue;
AddToInactive(current);
}
} }
if (!kSimpleFPAliasing && check_fp_aliasing()) { if (!kSimpleFPAliasing && check_fp_aliasing()) {
for (TopLevelLiveRange* current : data()->fixed_float_live_ranges()) { for (TopLevelLiveRange* current : data()->fixed_float_live_ranges()) {
if (current != nullptr) { if (current != nullptr) AddToInactive(current);
if (current->IsDeferredFixed()) continue;
AddToInactive(current);
}
} }
for (TopLevelLiveRange* current : data()->fixed_simd128_live_ranges()) { for (TopLevelLiveRange* current : data()->fixed_simd128_live_ranges()) {
if (current != nullptr) { if (current != nullptr) AddToInactive(current);
if (current->IsDeferredFixed()) continue;
AddToInactive(current);
}
} }
} }
} }
...@@ -3641,9 +3478,9 @@ void LinearScanAllocator::AllocateRegisters() { ...@@ -3641,9 +3478,9 @@ void LinearScanAllocator::AllocateRegisters() {
// those. Not only does this produce a potentially bad assignment, it also // those. Not only does this produce a potentially bad assignment, it also
// breaks with the invariant that we undo spills that happen in deferred code // breaks with the invariant that we undo spills that happen in deferred code
// when crossing a deferred/non-deferred boundary. // when crossing a deferred/non-deferred boundary.
while (!unhandled_live_ranges().empty() || while (
(data()->is_turbo_control_flow_aware_allocation() && !unhandled_live_ranges().empty() ||
last_block < max_blocks)) { (FLAG_turbo_control_flow_aware_allocation && last_block < max_blocks)) {
LiveRange* current = unhandled_live_ranges().empty() LiveRange* current = unhandled_live_ranges().empty()
? nullptr ? nullptr
: *unhandled_live_ranges().begin(); : *unhandled_live_ranges().begin();
...@@ -3652,9 +3489,9 @@ void LinearScanAllocator::AllocateRegisters() { ...@@ -3652,9 +3489,9 @@ void LinearScanAllocator::AllocateRegisters() {
#ifdef DEBUG #ifdef DEBUG
allocation_finger_ = position; allocation_finger_ = position;
#endif #endif
if (data()->is_turbo_control_flow_aware_allocation()) { if (FLAG_turbo_control_flow_aware_allocation) {
// Splintering is not supported. // Splintering is not supported.
CHECK(!data()->is_turbo_preprocess_ranges()); CHECK(!FLAG_turbo_preprocess_ranges);
// Check whether we just moved across a block boundary. This will trigger // Check whether we just moved across a block boundary. This will trigger
// for the first range that is past the current boundary. // for the first range that is past the current boundary.
if (position >= next_block_boundary) { if (position >= next_block_boundary) {
...@@ -3681,29 +3518,10 @@ void LinearScanAllocator::AllocateRegisters() { ...@@ -3681,29 +3518,10 @@ void LinearScanAllocator::AllocateRegisters() {
current_block->predecessors()[0].IsNext( current_block->predecessors()[0].IsNext(
current_block->rpo_number()); current_block->rpo_number());
// When crossing a deferred/non-deferred boundary, we have to load or
// remove the deferred fixed ranges from inactive.
if ((spill_mode == SpillMode::kSpillDeferred) !=
current_block->IsDeferred()) {
// Update spill mode.
spill_mode = current_block->IsDeferred() spill_mode = current_block->IsDeferred()
? SpillMode::kSpillDeferred ? SpillMode::kSpillDeferred
: SpillMode::kSpillAtDefinition; : SpillMode::kSpillAtDefinition;
ForwardStateTo(next_block_boundary);
#ifdef DEBUG
// Allow allocation at current position.
allocation_finger_ = next_block_boundary;
#endif
UpdateDeferredFixedRanges(spill_mode, current_block);
}
// Allocation relies on the fact that each non-deferred block has at
// least one non-deferred predecessor. Check this invariant here.
DCHECK_IMPLIES(!current_block->IsDeferred(),
HasNonDeferredPredecessor(current_block));
if (!fallthrough) { if (!fallthrough) {
#ifdef DEBUG #ifdef DEBUG
// Allow allocation at current position. // Allow allocation at current position.
...@@ -3832,7 +3650,7 @@ void LinearScanAllocator::AllocateRegisters() { ...@@ -3832,7 +3650,7 @@ void LinearScanAllocator::AllocateRegisters() {
} }
bool LinearScanAllocator::TrySplitAndSpillSplinter(LiveRange* range) { bool LinearScanAllocator::TrySplitAndSpillSplinter(LiveRange* range) {
DCHECK(!data()->is_turbo_control_flow_aware_allocation()); DCHECK(!FLAG_turbo_control_flow_aware_allocation);
DCHECK(range->TopLevel()->IsSplinter()); DCHECK(range->TopLevel()->IsSplinter());
// If we can spill the whole range, great. Otherwise, split above the // If we can spill the whole range, great. Otherwise, split above the
// first use needing a register and spill the top part. // first use needing a register and spill the top part.
...@@ -4100,7 +3918,7 @@ void LinearScanAllocator::ProcessCurrentRange(LiveRange* current, ...@@ -4100,7 +3918,7 @@ void LinearScanAllocator::ProcessCurrentRange(LiveRange* current,
FindFreeRegistersForRange(current, free_until_pos); FindFreeRegistersForRange(current, free_until_pos);
if (!TryAllocatePreferredReg(current, free_until_pos)) { if (!TryAllocatePreferredReg(current, free_until_pos)) {
if (current->TopLevel()->IsSplinter()) { if (current->TopLevel()->IsSplinter()) {
DCHECK(!data()->is_turbo_control_flow_aware_allocation()); DCHECK(!FLAG_turbo_control_flow_aware_allocation);
if (TrySplitAndSpillSplinter(current)) return; if (TrySplitAndSpillSplinter(current)) return;
} }
if (!TryAllocateFreeReg(current, free_until_pos)) { if (!TryAllocateFreeReg(current, free_until_pos)) {
...@@ -4352,14 +4170,6 @@ void LinearScanAllocator::AllocateBlockedReg(LiveRange* current, ...@@ -4352,14 +4170,6 @@ void LinearScanAllocator::AllocateBlockedReg(LiveRange* current,
new_end = block_pos[reg].Start(); new_end = block_pos[reg].Start();
} }
// If there is no register available at all, we can only spill this range.
// Happens for instance on entry to deferred code where registers might
// become blocked yet we aim to reload ranges.
if (new_end == current->Start()) {
SpillBetween(current, new_end, register_use->pos(), spill_mode);
return;
}
// Split at the new end if we found one. // Split at the new end if we found one.
if (new_end != current->End()) { if (new_end != current->End()) {
LiveRange* tail = SplitBetween(current, current->Start(), new_end); LiveRange* tail = SplitBetween(current, current->Start(), new_end);
...@@ -4585,12 +4395,11 @@ void SpillSlotLocator::LocateSpillSlots() { ...@@ -4585,12 +4395,11 @@ void SpillSlotLocator::LocateSpillSlots() {
data()->live_ranges().size()); // TODO(neis): crbug.com/831822 data()->live_ranges().size()); // TODO(neis): crbug.com/831822
if (range == nullptr || range->IsEmpty()) continue; if (range == nullptr || range->IsEmpty()) continue;
// We care only about ranges which spill in the frame. // We care only about ranges which spill in the frame.
if (!range->HasSpillRange() || if (!range->HasSpillRange() || range->IsSpilledOnlyInDeferredBlocks()) {
range->IsSpilledOnlyInDeferredBlocks(data())) {
continue; continue;
} }
TopLevelLiveRange::SpillMoveInsertionList* spills = TopLevelLiveRange::SpillMoveInsertionList* spills =
range->GetSpillMoveInsertionLocations(data()); range->GetSpillMoveInsertionLocations();
DCHECK_NOT_NULL(spills); DCHECK_NOT_NULL(spills);
for (; spills != nullptr; spills = spills->next) { for (; spills != nullptr; spills = spills->next) {
code->GetInstructionBlock(spills->gap_index)->mark_needs_frame(); code->GetInstructionBlock(spills->gap_index)->mark_needs_frame();
...@@ -4601,10 +4410,10 @@ void SpillSlotLocator::LocateSpillSlots() { ...@@ -4601,10 +4410,10 @@ void SpillSlotLocator::LocateSpillSlots() {
OperandAssigner::OperandAssigner(RegisterAllocationData* data) : data_(data) {} OperandAssigner::OperandAssigner(RegisterAllocationData* data) : data_(data) {}
void OperandAssigner::DecideSpillingMode() { void OperandAssigner::DecideSpillingMode() {
if (data()->is_turbo_control_flow_aware_allocation()) { if (FLAG_turbo_control_flow_aware_allocation) {
for (auto range : data()->live_ranges()) { for (auto range : data()->live_ranges()) {
int max_blocks = data()->code()->InstructionBlockCount(); int max_blocks = data()->code()->InstructionBlockCount();
if (range != nullptr && range->IsSpilledOnlyInDeferredBlocks(data())) { if (range != nullptr && range->IsSpilledOnlyInDeferredBlocks()) {
// If the range is spilled only in deferred blocks and starts in // If the range is spilled only in deferred blocks and starts in
// a non-deferred block, we transition its representation here so // a non-deferred block, we transition its representation here so
// that the LiveRangeConnector processes them correctly. If, // that the LiveRangeConnector processes them correctly. If,
...@@ -4620,7 +4429,6 @@ void OperandAssigner::DecideSpillingMode() { ...@@ -4620,7 +4429,6 @@ void OperandAssigner::DecideSpillingMode() {
TRACE( TRACE(
"Live range %d is spilled deferred code only but alive outside\n", "Live range %d is spilled deferred code only but alive outside\n",
range->vreg()); range->vreg());
DCHECK(data()->is_turbo_control_flow_aware_allocation());
range->TransitionRangeToDeferredSpill(data()->allocation_zone(), range->TransitionRangeToDeferredSpill(data()->allocation_zone(),
max_blocks); max_blocks);
} }
...@@ -4693,11 +4501,11 @@ void OperandAssigner::CommitAssignment() { ...@@ -4693,11 +4501,11 @@ void OperandAssigner::CommitAssignment() {
// blocks, we let ConnectLiveRanges and ResolveControlFlow find the blocks // blocks, we let ConnectLiveRanges and ResolveControlFlow find the blocks
// where a spill operand is expected, and then finalize by inserting the // where a spill operand is expected, and then finalize by inserting the
// spills in the deferred blocks dominators. // spills in the deferred blocks dominators.
if (!top_range->IsSpilledOnlyInDeferredBlocks(data())) { if (!top_range->IsSpilledOnlyInDeferredBlocks()) {
// Spill at definition if the range isn't spilled only in deferred // Spill at definition if the range isn't spilled only in deferred
// blocks. // blocks.
top_range->CommitSpillMoves( top_range->CommitSpillMoves(
data(), spill_operand, data()->code(), spill_operand,
top_range->has_slot_use() || top_range->spilled()); top_range->has_slot_use() || top_range->spilled());
} }
} }
...@@ -4735,7 +4543,7 @@ void ReferenceMapPopulator::PopulateReferenceMaps() { ...@@ -4735,7 +4543,7 @@ void ReferenceMapPopulator::PopulateReferenceMaps() {
data()->live_ranges().size()); // TODO(neis): crbug.com/831822 data()->live_ranges().size()); // TODO(neis): crbug.com/831822
if (range == nullptr) continue; if (range == nullptr) continue;
// Skip non-reference values. // Skip non-reference values.
if (!data()->code()->IsReference(range->vreg())) continue; if (!data()->IsReference(range)) continue;
// Skip empty live ranges. // Skip empty live ranges.
if (range->IsEmpty()) continue; if (range->IsEmpty()) continue;
if (range->has_preassigned_slot()) continue; if (range->has_preassigned_slot()) continue;
...@@ -4817,7 +4625,7 @@ void ReferenceMapPopulator::PopulateReferenceMaps() { ...@@ -4817,7 +4625,7 @@ void ReferenceMapPopulator::PopulateReferenceMaps() {
// Check if the live range is spilled and the safe point is after // Check if the live range is spilled and the safe point is after
// the spill position. // the spill position.
int spill_index = range->IsSpilledOnlyInDeferredBlocks(data()) int spill_index = range->IsSpilledOnlyInDeferredBlocks()
? cur->Start().ToInstructionIndex() ? cur->Start().ToInstructionIndex()
: range->spill_start_index(); : range->spill_start_index();
...@@ -4900,23 +4708,21 @@ void LiveRangeConnector::ResolveControlFlow(Zone* local_zone) { ...@@ -4900,23 +4708,21 @@ void LiveRangeConnector::ResolveControlFlow(Zone* local_zone) {
} }
if (!uses_reg) continue; if (!uses_reg) continue;
} }
if (current->TopLevel()->IsSpilledOnlyInDeferredBlocks(data()) && if (current->TopLevel()->IsSpilledOnlyInDeferredBlocks() &&
pred_block->IsDeferred()) { pred_block->IsDeferred()) {
// The spill location should be defined in pred_block, so add // The spill location should be defined in pred_block, so add
// pred_block to the list of blocks requiring a spill operand. // pred_block to the list of blocks requiring a spill operand.
TRACE("Adding B%d to list of spill blocks for %d\n", TRACE("Adding B%d to list of spill blocks for %d\n",
pred_block->rpo_number().ToInt(), pred_block->rpo_number().ToInt(),
current->TopLevel()->vreg()); current->TopLevel()->vreg());
current->TopLevel() current->TopLevel()->GetListOfBlocksRequiringSpillOperands()->Add(
->GetListOfBlocksRequiringSpillOperands(data()) pred_block->rpo_number().ToInt());
->Add(pred_block->rpo_number().ToInt());
} }
} }
int move_loc = ResolveControlFlow(block, cur_op, pred_block, pred_op); int move_loc = ResolveControlFlow(block, cur_op, pred_block, pred_op);
USE(move_loc); USE(move_loc);
DCHECK_IMPLIES( DCHECK_IMPLIES(
result.cur_cover_->TopLevel()->IsSpilledOnlyInDeferredBlocks( result.cur_cover_->TopLevel()->IsSpilledOnlyInDeferredBlocks() &&
data()) &&
!(pred_op.IsAnyRegister() && cur_op.IsAnyRegister()), !(pred_op.IsAnyRegister() && cur_op.IsAnyRegister()),
code()->GetInstructionBlock(move_loc)->IsDeferred()); code()->GetInstructionBlock(move_loc)->IsDeferred());
} }
...@@ -4932,7 +4738,7 @@ void LiveRangeConnector::ResolveControlFlow(Zone* local_zone) { ...@@ -4932,7 +4738,7 @@ void LiveRangeConnector::ResolveControlFlow(Zone* local_zone) {
CHECK_EQ(live_ranges_size, CHECK_EQ(live_ranges_size,
data()->live_ranges().size()); // TODO(neis): crbug.com/831822 data()->live_ranges().size()); // TODO(neis): crbug.com/831822
if (top == nullptr || top->IsEmpty() || if (top == nullptr || top->IsEmpty() ||
!top->IsSpilledOnlyInDeferredBlocks(data())) !top->IsSpilledOnlyInDeferredBlocks())
continue; continue;
CommitSpillsInDeferredBlocks(top, finder.ArrayFor(top->vreg()), local_zone); CommitSpillsInDeferredBlocks(top, finder.ArrayFor(top->vreg()), local_zone);
} }
...@@ -4967,7 +4773,7 @@ void LiveRangeConnector::ConnectRanges(Zone* local_zone) { ...@@ -4967,7 +4773,7 @@ void LiveRangeConnector::ConnectRanges(Zone* local_zone) {
CHECK_EQ(live_ranges_size, CHECK_EQ(live_ranges_size,
data()->live_ranges().size()); // TODO(neis): crbug.com/831822 data()->live_ranges().size()); // TODO(neis): crbug.com/831822
if (top_range == nullptr) continue; if (top_range == nullptr) continue;
bool connect_spilled = top_range->IsSpilledOnlyInDeferredBlocks(data()); bool connect_spilled = top_range->IsSpilledOnlyInDeferredBlocks();
LiveRange* first_range = top_range; LiveRange* first_range = top_range;
for (LiveRange *second_range = first_range->next(); second_range != nullptr; for (LiveRange *second_range = first_range->next(); second_range != nullptr;
first_range = second_range, second_range = second_range->next()) { first_range = second_range, second_range = second_range->next()) {
...@@ -4992,7 +4798,7 @@ void LiveRangeConnector::ConnectRanges(Zone* local_zone) { ...@@ -4992,7 +4798,7 @@ void LiveRangeConnector::ConnectRanges(Zone* local_zone) {
DCHECK(block->IsDeferred()); DCHECK(block->IsDeferred());
// Performing a reload in this block, meaning the spill operand must // Performing a reload in this block, meaning the spill operand must
// be defined here. // be defined here.
top_range->GetListOfBlocksRequiringSpillOperands(data())->Add( top_range->GetListOfBlocksRequiringSpillOperands()->Add(
block->rpo_number().ToInt()); block->rpo_number().ToInt());
} }
...@@ -5056,7 +4862,7 @@ void LiveRangeConnector::ConnectRanges(Zone* local_zone) { ...@@ -5056,7 +4862,7 @@ void LiveRangeConnector::ConnectRanges(Zone* local_zone) {
void LiveRangeConnector::CommitSpillsInDeferredBlocks( void LiveRangeConnector::CommitSpillsInDeferredBlocks(
TopLevelLiveRange* range, LiveRangeBoundArray* array, Zone* temp_zone) { TopLevelLiveRange* range, LiveRangeBoundArray* array, Zone* temp_zone) {
DCHECK(range->IsSpilledOnlyInDeferredBlocks(data())); DCHECK(range->IsSpilledOnlyInDeferredBlocks());
DCHECK(!range->spilled()); DCHECK(!range->spilled());
InstructionSequence* code = data()->code(); InstructionSequence* code = data()->code();
...@@ -5074,15 +4880,14 @@ void LiveRangeConnector::CommitSpillsInDeferredBlocks( ...@@ -5074,15 +4880,14 @@ void LiveRangeConnector::CommitSpillsInDeferredBlocks(
continue; continue;
range->AddBlockRequiringSpillOperand( range->AddBlockRequiringSpillOperand(
code->GetInstructionBlock(pos->pos().ToInstructionIndex()) code->GetInstructionBlock(pos->pos().ToInstructionIndex())
->rpo_number(), ->rpo_number());
data());
} }
} }
ZoneQueue<int> worklist(temp_zone); ZoneQueue<int> worklist(temp_zone);
for (BitVector::Iterator iterator( for (BitVector::Iterator iterator(
range->GetListOfBlocksRequiringSpillOperands(data())); range->GetListOfBlocksRequiringSpillOperands());
!iterator.Done(); iterator.Advance()) { !iterator.Done(); iterator.Advance()) {
worklist.push(iterator.Current()); worklist.push(iterator.Current());
} }
...@@ -5091,8 +4896,7 @@ void LiveRangeConnector::CommitSpillsInDeferredBlocks( ...@@ -5091,8 +4896,7 @@ void LiveRangeConnector::CommitSpillsInDeferredBlocks(
// Seek the deferred blocks that dominate locations requiring spill operands, // Seek the deferred blocks that dominate locations requiring spill operands,
// and spill there. We only need to spill at the start of such blocks. // and spill there. We only need to spill at the start of such blocks.
BitVector done_blocks( BitVector done_blocks(
range->GetListOfBlocksRequiringSpillOperands(data())->length(), range->GetListOfBlocksRequiringSpillOperands()->length(), temp_zone);
temp_zone);
while (!worklist.empty()) { while (!worklist.empty()) {
int block_id = worklist.front(); int block_id = worklist.front();
worklist.pop(); worklist.pop();
......
...@@ -8,7 +8,6 @@ ...@@ -8,7 +8,6 @@
#include "src/base/bits.h" #include "src/base/bits.h"
#include "src/base/compiler-specific.h" #include "src/base/compiler-specific.h"
#include "src/compiler/backend/instruction.h" #include "src/compiler/backend/instruction.h"
#include "src/flags.h"
#include "src/globals.h" #include "src/globals.h"
#include "src/ostreams.h" #include "src/ostreams.h"
#include "src/register-configuration.h" #include "src/register-configuration.h"
...@@ -18,8 +17,6 @@ namespace v8 { ...@@ -18,8 +17,6 @@ namespace v8 {
namespace internal { namespace internal {
namespace compiler { namespace compiler {
static const int32_t kUnassignedRegister = RegisterConfiguration::kMaxRegisters;
enum RegisterKind { GENERAL_REGISTERS, FP_REGISTERS }; enum RegisterKind { GENERAL_REGISTERS, FP_REGISTERS };
// This class represents a single point of a InstructionOperand's lifetime. For // This class represents a single point of a InstructionOperand's lifetime. For
...@@ -173,191 +170,6 @@ class LifetimePosition final { ...@@ -173,191 +170,6 @@ class LifetimePosition final {
std::ostream& operator<<(std::ostream& os, const LifetimePosition pos); std::ostream& operator<<(std::ostream& os, const LifetimePosition pos);
enum class RegisterAllocationFlag : unsigned {
kTurboControlFlowAwareAllocation = 1 << 0,
kTurboPreprocessRanges = 1 << 1
};
typedef base::Flags<RegisterAllocationFlag> RegisterAllocationFlags;
class SpillRange;
class LiveRange;
class TopLevelLiveRange;
class RegisterAllocationData final : public ZoneObject {
public:
// Encodes whether a spill happens in deferred code (kSpillDeferred) or
// regular code (kSpillAtDefinition).
enum SpillMode { kSpillAtDefinition, kSpillDeferred };
bool is_turbo_control_flow_aware_allocation() const {
return flags_ & RegisterAllocationFlag::kTurboControlFlowAwareAllocation;
}
bool is_turbo_preprocess_ranges() const {
return flags_ & RegisterAllocationFlag::kTurboPreprocessRanges;
}
static constexpr int kNumberOfFixedRangesPerRegister = 2;
class PhiMapValue : public ZoneObject {
public:
PhiMapValue(PhiInstruction* phi, const InstructionBlock* block, Zone* zone);
const PhiInstruction* phi() const { return phi_; }
const InstructionBlock* block() const { return block_; }
// For hinting.
int assigned_register() const { return assigned_register_; }
void set_assigned_register(int register_code) {
DCHECK_EQ(assigned_register_, kUnassignedRegister);
assigned_register_ = register_code;
}
void UnsetAssignedRegister() { assigned_register_ = kUnassignedRegister; }
void AddOperand(InstructionOperand* operand);
void CommitAssignment(const InstructionOperand& operand);
private:
PhiInstruction* const phi_;
const InstructionBlock* const block_;
ZoneVector<InstructionOperand*> incoming_operands_;
int assigned_register_;
};
typedef ZoneMap<int, PhiMapValue*> PhiMap;
struct DelayedReference {
ReferenceMap* map;
InstructionOperand* operand;
};
typedef ZoneVector<DelayedReference> DelayedReferences;
typedef ZoneVector<std::pair<TopLevelLiveRange*, int>>
RangesWithPreassignedSlots;
RegisterAllocationData(const RegisterConfiguration* config,
Zone* allocation_zone, Frame* frame,
InstructionSequence* code,
RegisterAllocationFlags flags,
const char* debug_name = nullptr);
const ZoneVector<TopLevelLiveRange*>& live_ranges() const {
return live_ranges_;
}
ZoneVector<TopLevelLiveRange*>& live_ranges() { return live_ranges_; }
const ZoneVector<TopLevelLiveRange*>& fixed_live_ranges() const {
return fixed_live_ranges_;
}
ZoneVector<TopLevelLiveRange*>& fixed_live_ranges() {
return fixed_live_ranges_;
}
ZoneVector<TopLevelLiveRange*>& fixed_float_live_ranges() {
return fixed_float_live_ranges_;
}
const ZoneVector<TopLevelLiveRange*>& fixed_float_live_ranges() const {
return fixed_float_live_ranges_;
}
ZoneVector<TopLevelLiveRange*>& fixed_double_live_ranges() {
return fixed_double_live_ranges_;
}
const ZoneVector<TopLevelLiveRange*>& fixed_double_live_ranges() const {
return fixed_double_live_ranges_;
}
ZoneVector<TopLevelLiveRange*>& fixed_simd128_live_ranges() {
return fixed_simd128_live_ranges_;
}
const ZoneVector<TopLevelLiveRange*>& fixed_simd128_live_ranges() const {
return fixed_simd128_live_ranges_;
}
ZoneVector<BitVector*>& live_in_sets() { return live_in_sets_; }
ZoneVector<BitVector*>& live_out_sets() { return live_out_sets_; }
ZoneVector<SpillRange*>& spill_ranges() { return spill_ranges_; }
DelayedReferences& delayed_references() { return delayed_references_; }
InstructionSequence* code() const { return code_; }
// This zone is for data structures only needed during register allocation
// phases.
Zone* allocation_zone() const { return allocation_zone_; }
// This zone is for InstructionOperands and moves that live beyond register
// allocation.
Zone* code_zone() const { return code()->zone(); }
Frame* frame() const { return frame_; }
const char* debug_name() const { return debug_name_; }
const RegisterConfiguration* config() const { return config_; }
MachineRepresentation RepresentationFor(int virtual_register);
TopLevelLiveRange* GetOrCreateLiveRangeFor(int index);
// Creates a new live range.
TopLevelLiveRange* NewLiveRange(int index, MachineRepresentation rep);
TopLevelLiveRange* NextLiveRange(MachineRepresentation rep);
SpillRange* AssignSpillRangeToLiveRange(TopLevelLiveRange* range,
SpillMode spill_mode);
SpillRange* CreateSpillRangeForLiveRange(TopLevelLiveRange* range);
MoveOperands* AddGapMove(int index, Instruction::GapPosition position,
const InstructionOperand& from,
const InstructionOperand& to);
bool ExistsUseWithoutDefinition();
bool RangesDefinedInDeferredStayInDeferred();
void MarkFixedUse(MachineRepresentation rep, int index);
bool HasFixedUse(MachineRepresentation rep, int index);
void MarkAllocated(MachineRepresentation rep, int index);
PhiMapValue* InitializePhiMap(const InstructionBlock* block,
PhiInstruction* phi);
PhiMapValue* GetPhiMapValueFor(TopLevelLiveRange* top_range);
PhiMapValue* GetPhiMapValueFor(int virtual_register);
bool IsBlockBoundary(LifetimePosition pos) const;
RangesWithPreassignedSlots& preassigned_slot_ranges() {
return preassigned_slot_ranges_;
}
void RememberSpillState(RpoNumber block,
const ZoneVector<LiveRange*>& state) {
spill_state_[block.ToSize()] = state;
}
ZoneVector<LiveRange*>& GetSpillState(RpoNumber block) {
auto& result = spill_state_[block.ToSize()];
return result;
}
void ResetSpillState() { spill_state_.clear(); }
private:
int GetNextLiveRangeId();
Zone* const allocation_zone_;
Frame* const frame_;
InstructionSequence* const code_;
const char* const debug_name_;
const RegisterConfiguration* const config_;
PhiMap phi_map_;
ZoneVector<BitVector*> live_in_sets_;
ZoneVector<BitVector*> live_out_sets_;
ZoneVector<TopLevelLiveRange*> live_ranges_;
ZoneVector<TopLevelLiveRange*> fixed_live_ranges_;
ZoneVector<TopLevelLiveRange*> fixed_float_live_ranges_;
ZoneVector<TopLevelLiveRange*> fixed_double_live_ranges_;
ZoneVector<TopLevelLiveRange*> fixed_simd128_live_ranges_;
ZoneVector<SpillRange*> spill_ranges_;
DelayedReferences delayed_references_;
BitVector* assigned_registers_;
BitVector* assigned_double_registers_;
BitVector* fixed_register_use_;
BitVector* fixed_fp_register_use_;
int virtual_register_count_;
RangesWithPreassignedSlots preassigned_slot_ranges_;
ZoneVector<ZoneVector<LiveRange*>> spill_state_;
RegisterAllocationFlags flags_;
DISALLOW_COPY_AND_ASSIGN(RegisterAllocationData);
};
// Representation of the non-empty interval [start,end[. // Representation of the non-empty interval [start,end[.
class UseInterval final : public ZoneObject { class UseInterval final : public ZoneObject {
public: public:
...@@ -430,6 +242,8 @@ enum class UsePositionHintType : uint8_t { ...@@ -430,6 +242,8 @@ enum class UsePositionHintType : uint8_t {
kUnresolved kUnresolved
}; };
static const int32_t kUnassignedRegister = RegisterConfiguration::kMaxRegisters;
// Representation of a use position. // Representation of a use position.
class V8_EXPORT_PRIVATE UsePosition final class V8_EXPORT_PRIVATE UsePosition final
: public NON_EXPORTED_BASE(ZoneObject) { : public NON_EXPORTED_BASE(ZoneObject) {
...@@ -653,12 +467,11 @@ class V8_EXPORT_PRIVATE LiveRange : public NON_EXPORTED_BASE(ZoneObject) { ...@@ -653,12 +467,11 @@ class V8_EXPORT_PRIVATE LiveRange : public NON_EXPORTED_BASE(ZoneObject) {
void VerifyIntervals() const; void VerifyIntervals() const;
typedef BitField<bool, 0, 1> SpilledField; typedef BitField<bool, 0, 1> SpilledField;
// Bits (1,7[ are used by TopLevelLiveRange. // Bits (1,7] are used by TopLevelLiveRange.
typedef BitField<int32_t, 7, 6> AssignedRegisterField; typedef BitField<int32_t, 7, 6> AssignedRegisterField;
typedef BitField<MachineRepresentation, 13, 8> RepresentationField; typedef BitField<MachineRepresentation, 13, 8> RepresentationField;
typedef BitField<bool, 21, 1> RecombineField; typedef BitField<bool, 21, 1> RecombineField;
typedef BitField<uint8_t, 22, 6> ControlFlowRegisterHint; typedef BitField<uint8_t, 22, 6> ControlFlowRegisterHint;
// Bit 28 is used by TopLevelLiveRange.
// Unique among children and splinters of the same virtual register. // Unique among children and splinters of the same virtual register.
int relative_id_; int relative_id_;
...@@ -756,8 +569,6 @@ class V8_EXPORT_PRIVATE TopLevelLiveRange final : public LiveRange { ...@@ -756,8 +569,6 @@ class V8_EXPORT_PRIVATE TopLevelLiveRange final : public LiveRange {
bool IsFixed() const { return vreg_ < 0; } bool IsFixed() const { return vreg_ < 0; }
bool IsDeferredFixed() const { return DeferredFixedField::decode(bits_); }
void set_deferred_fixed() { bits_ = DeferredFixedField::update(bits_, true); }
bool is_phi() const { return IsPhiField::decode(bits_); } bool is_phi() const { return IsPhiField::decode(bits_); }
void set_is_phi(bool value) { bits_ = IsPhiField::update(bits_, value); } void set_is_phi(bool value) { bits_ = IsPhiField::update(bits_, value); }
...@@ -859,7 +670,7 @@ class V8_EXPORT_PRIVATE TopLevelLiveRange final : public LiveRange { ...@@ -859,7 +670,7 @@ class V8_EXPORT_PRIVATE TopLevelLiveRange final : public LiveRange {
spill_start_index_ = Min(start, spill_start_index_); spill_start_index_ = Min(start, spill_start_index_);
} }
void CommitSpillMoves(RegisterAllocationData* data, void CommitSpillMoves(InstructionSequence* sequence,
const InstructionOperand& operand, const InstructionOperand& operand,
bool might_be_duplicated); bool might_be_duplicated);
...@@ -871,6 +682,7 @@ class V8_EXPORT_PRIVATE TopLevelLiveRange final : public LiveRange { ...@@ -871,6 +682,7 @@ class V8_EXPORT_PRIVATE TopLevelLiveRange final : public LiveRange {
// deferred blocks. If so, we insert here spills for non-spilled ranges // deferred blocks. If so, we insert here spills for non-spilled ranges
// with slot use positions. // with slot use positions.
void TreatAsSpilledInDeferredBlock(Zone* zone, int total_block_count) { void TreatAsSpilledInDeferredBlock(Zone* zone, int total_block_count) {
DCHECK(!FLAG_turbo_control_flow_aware_allocation);
spill_start_index_ = -1; spill_start_index_ = -1;
spilled_in_deferred_blocks_ = true; spilled_in_deferred_blocks_ = true;
spill_move_insertion_locations_ = nullptr; spill_move_insertion_locations_ = nullptr;
...@@ -881,6 +693,7 @@ class V8_EXPORT_PRIVATE TopLevelLiveRange final : public LiveRange { ...@@ -881,6 +693,7 @@ class V8_EXPORT_PRIVATE TopLevelLiveRange final : public LiveRange {
// Updates internal data structures to reflect that this range is not // Updates internal data structures to reflect that this range is not
// spilled at definition but instead spilled in some blocks only. // spilled at definition but instead spilled in some blocks only.
void TransitionRangeToDeferredSpill(Zone* zone, int total_block_count) { void TransitionRangeToDeferredSpill(Zone* zone, int total_block_count) {
DCHECK(FLAG_turbo_control_flow_aware_allocation);
spill_start_index_ = -1; spill_start_index_ = -1;
spill_move_insertion_locations_ = nullptr; spill_move_insertion_locations_ = nullptr;
list_of_blocks_requiring_spill_operands_ = list_of_blocks_requiring_spill_operands_ =
...@@ -919,8 +732,8 @@ class V8_EXPORT_PRIVATE TopLevelLiveRange final : public LiveRange { ...@@ -919,8 +732,8 @@ class V8_EXPORT_PRIVATE TopLevelLiveRange final : public LiveRange {
int GetMaxChildCount() const { return last_child_id_ + 1; } int GetMaxChildCount() const { return last_child_id_ + 1; }
bool IsSpilledOnlyInDeferredBlocks(const RegisterAllocationData* data) const { bool IsSpilledOnlyInDeferredBlocks() const {
if (data->is_turbo_control_flow_aware_allocation()) { if (FLAG_turbo_control_flow_aware_allocation) {
return spill_type() == SpillType::kDeferredSpillRange; return spill_type() == SpillType::kDeferredSpillRange;
} }
return spilled_in_deferred_blocks_; return spilled_in_deferred_blocks_;
...@@ -928,9 +741,8 @@ class V8_EXPORT_PRIVATE TopLevelLiveRange final : public LiveRange { ...@@ -928,9 +741,8 @@ class V8_EXPORT_PRIVATE TopLevelLiveRange final : public LiveRange {
struct SpillMoveInsertionList; struct SpillMoveInsertionList;
SpillMoveInsertionList* GetSpillMoveInsertionLocations( SpillMoveInsertionList* GetSpillMoveInsertionLocations() const {
const RegisterAllocationData* data) const { DCHECK(!IsSpilledOnlyInDeferredBlocks());
DCHECK(!IsSpilledOnlyInDeferredBlocks(data));
return spill_move_insertion_locations_; return spill_move_insertion_locations_;
} }
TopLevelLiveRange* splinter() const { return splinter_; } TopLevelLiveRange* splinter() const { return splinter_; }
...@@ -948,15 +760,13 @@ class V8_EXPORT_PRIVATE TopLevelLiveRange final : public LiveRange { ...@@ -948,15 +760,13 @@ class V8_EXPORT_PRIVATE TopLevelLiveRange final : public LiveRange {
void MarkHasPreassignedSlot() { has_preassigned_slot_ = true; } void MarkHasPreassignedSlot() { has_preassigned_slot_ = true; }
bool has_preassigned_slot() const { return has_preassigned_slot_; } bool has_preassigned_slot() const { return has_preassigned_slot_; }
void AddBlockRequiringSpillOperand(RpoNumber block_id, void AddBlockRequiringSpillOperand(RpoNumber block_id) {
const RegisterAllocationData* data) { DCHECK(IsSpilledOnlyInDeferredBlocks());
DCHECK(IsSpilledOnlyInDeferredBlocks(data)); GetListOfBlocksRequiringSpillOperands()->Add(block_id.ToInt());
GetListOfBlocksRequiringSpillOperands(data)->Add(block_id.ToInt());
} }
BitVector* GetListOfBlocksRequiringSpillOperands( BitVector* GetListOfBlocksRequiringSpillOperands() const {
const RegisterAllocationData* data) const { DCHECK(IsSpilledOnlyInDeferredBlocks());
DCHECK(IsSpilledOnlyInDeferredBlocks(data));
return list_of_blocks_requiring_spill_operands_; return list_of_blocks_requiring_spill_operands_;
} }
...@@ -968,7 +778,6 @@ class V8_EXPORT_PRIVATE TopLevelLiveRange final : public LiveRange { ...@@ -968,7 +778,6 @@ class V8_EXPORT_PRIVATE TopLevelLiveRange final : public LiveRange {
typedef BitField<bool, 3, 1> IsPhiField; typedef BitField<bool, 3, 1> IsPhiField;
typedef BitField<bool, 4, 1> IsNonLoopPhiField; typedef BitField<bool, 4, 1> IsNonLoopPhiField;
typedef BitField<SpillType, 5, 2> SpillTypeField; typedef BitField<SpillType, 5, 2> SpillTypeField;
typedef BitField<bool, 28, 1> DeferredFixedField;
int vreg_; int vreg_;
int last_child_id_; int last_child_id_;
...@@ -1046,6 +855,171 @@ class SpillRange final : public ZoneObject { ...@@ -1046,6 +855,171 @@ class SpillRange final : public ZoneObject {
DISALLOW_COPY_AND_ASSIGN(SpillRange); DISALLOW_COPY_AND_ASSIGN(SpillRange);
}; };
class RegisterAllocationData final : public ZoneObject {
public:
// Encodes whether a spill happens in deferred code (kSpillDeferred) or
// regular code (kSpillAtDefinition).
enum SpillMode { kSpillAtDefinition, kSpillDeferred };
class PhiMapValue : public ZoneObject {
public:
PhiMapValue(PhiInstruction* phi, const InstructionBlock* block, Zone* zone);
const PhiInstruction* phi() const { return phi_; }
const InstructionBlock* block() const { return block_; }
// For hinting.
int assigned_register() const { return assigned_register_; }
void set_assigned_register(int register_code) {
DCHECK_EQ(assigned_register_, kUnassignedRegister);
assigned_register_ = register_code;
}
void UnsetAssignedRegister() { assigned_register_ = kUnassignedRegister; }
void AddOperand(InstructionOperand* operand);
void CommitAssignment(const InstructionOperand& operand);
private:
PhiInstruction* const phi_;
const InstructionBlock* const block_;
ZoneVector<InstructionOperand*> incoming_operands_;
int assigned_register_;
};
typedef ZoneMap<int, PhiMapValue*> PhiMap;
struct DelayedReference {
ReferenceMap* map;
InstructionOperand* operand;
};
typedef ZoneVector<DelayedReference> DelayedReferences;
typedef ZoneVector<std::pair<TopLevelLiveRange*, int>>
RangesWithPreassignedSlots;
RegisterAllocationData(const RegisterConfiguration* config,
Zone* allocation_zone, Frame* frame,
InstructionSequence* code,
const char* debug_name = nullptr);
const ZoneVector<TopLevelLiveRange*>& live_ranges() const {
return live_ranges_;
}
ZoneVector<TopLevelLiveRange*>& live_ranges() { return live_ranges_; }
const ZoneVector<TopLevelLiveRange*>& fixed_live_ranges() const {
return fixed_live_ranges_;
}
ZoneVector<TopLevelLiveRange*>& fixed_live_ranges() {
return fixed_live_ranges_;
}
ZoneVector<TopLevelLiveRange*>& fixed_float_live_ranges() {
return fixed_float_live_ranges_;
}
const ZoneVector<TopLevelLiveRange*>& fixed_float_live_ranges() const {
return fixed_float_live_ranges_;
}
ZoneVector<TopLevelLiveRange*>& fixed_double_live_ranges() {
return fixed_double_live_ranges_;
}
const ZoneVector<TopLevelLiveRange*>& fixed_double_live_ranges() const {
return fixed_double_live_ranges_;
}
ZoneVector<TopLevelLiveRange*>& fixed_simd128_live_ranges() {
return fixed_simd128_live_ranges_;
}
const ZoneVector<TopLevelLiveRange*>& fixed_simd128_live_ranges() const {
return fixed_simd128_live_ranges_;
}
ZoneVector<BitVector*>& live_in_sets() { return live_in_sets_; }
ZoneVector<BitVector*>& live_out_sets() { return live_out_sets_; }
ZoneVector<SpillRange*>& spill_ranges() { return spill_ranges_; }
DelayedReferences& delayed_references() { return delayed_references_; }
InstructionSequence* code() const { return code_; }
// This zone is for data structures only needed during register allocation
// phases.
Zone* allocation_zone() const { return allocation_zone_; }
// This zone is for InstructionOperands and moves that live beyond register
// allocation.
Zone* code_zone() const { return code()->zone(); }
Frame* frame() const { return frame_; }
const char* debug_name() const { return debug_name_; }
const RegisterConfiguration* config() const { return config_; }
MachineRepresentation RepresentationFor(int virtual_register);
TopLevelLiveRange* GetOrCreateLiveRangeFor(int index);
// Creates a new live range.
TopLevelLiveRange* NewLiveRange(int index, MachineRepresentation rep);
TopLevelLiveRange* NextLiveRange(MachineRepresentation rep);
SpillRange* AssignSpillRangeToLiveRange(TopLevelLiveRange* range,
SpillMode spill_mode);
SpillRange* CreateSpillRangeForLiveRange(TopLevelLiveRange* range);
MoveOperands* AddGapMove(int index, Instruction::GapPosition position,
const InstructionOperand& from,
const InstructionOperand& to);
bool IsReference(TopLevelLiveRange* top_range) const {
return code()->IsReference(top_range->vreg());
}
bool ExistsUseWithoutDefinition();
bool RangesDefinedInDeferredStayInDeferred();
void MarkFixedUse(MachineRepresentation rep, int index);
bool HasFixedUse(MachineRepresentation rep, int index);
void MarkAllocated(MachineRepresentation rep, int index);
PhiMapValue* InitializePhiMap(const InstructionBlock* block,
PhiInstruction* phi);
PhiMapValue* GetPhiMapValueFor(TopLevelLiveRange* top_range);
PhiMapValue* GetPhiMapValueFor(int virtual_register);
bool IsBlockBoundary(LifetimePosition pos) const;
RangesWithPreassignedSlots& preassigned_slot_ranges() {
return preassigned_slot_ranges_;
}
void RememberSpillState(RpoNumber block,
const ZoneVector<LiveRange*>& state) {
spill_state_[block.ToSize()] = state;
}
ZoneVector<LiveRange*>& GetSpillState(RpoNumber block) {
auto& result = spill_state_[block.ToSize()];
return result;
}
void ResetSpillState() { spill_state_.clear(); }
private:
int GetNextLiveRangeId();
Zone* const allocation_zone_;
Frame* const frame_;
InstructionSequence* const code_;
const char* const debug_name_;
const RegisterConfiguration* const config_;
PhiMap phi_map_;
ZoneVector<BitVector*> live_in_sets_;
ZoneVector<BitVector*> live_out_sets_;
ZoneVector<TopLevelLiveRange*> live_ranges_;
ZoneVector<TopLevelLiveRange*> fixed_live_ranges_;
ZoneVector<TopLevelLiveRange*> fixed_float_live_ranges_;
ZoneVector<TopLevelLiveRange*> fixed_double_live_ranges_;
ZoneVector<TopLevelLiveRange*> fixed_simd128_live_ranges_;
ZoneVector<SpillRange*> spill_ranges_;
DelayedReferences delayed_references_;
BitVector* assigned_registers_;
BitVector* assigned_double_registers_;
BitVector* fixed_register_use_;
BitVector* fixed_fp_register_use_;
int virtual_register_count_;
RangesWithPreassignedSlots preassigned_slot_ranges_;
ZoneVector<ZoneVector<LiveRange*>> spill_state_;
DISALLOW_COPY_AND_ASSIGN(RegisterAllocationData);
};
class ConstraintBuilder final : public ZoneObject { class ConstraintBuilder final : public ZoneObject {
public: public:
explicit ConstraintBuilder(RegisterAllocationData* data); explicit ConstraintBuilder(RegisterAllocationData* data);
...@@ -1087,8 +1061,6 @@ class LiveRangeBuilder final : public ZoneObject { ...@@ -1087,8 +1061,6 @@ class LiveRangeBuilder final : public ZoneObject {
private: private:
using SpillMode = RegisterAllocationData::SpillMode; using SpillMode = RegisterAllocationData::SpillMode;
static constexpr int kNumberOfFixedRangesPerRegister =
RegisterAllocationData::kNumberOfFixedRangesPerRegister;
RegisterAllocationData* data() const { return data_; } RegisterAllocationData* data() const { return data_; }
InstructionSequence* code() const { return data()->code(); } InstructionSequence* code() const { return data()->code(); }
...@@ -1114,9 +1086,8 @@ class LiveRangeBuilder final : public ZoneObject { ...@@ -1114,9 +1086,8 @@ class LiveRangeBuilder final : public ZoneObject {
static int FixedLiveRangeID(int index) { return -index - 1; } static int FixedLiveRangeID(int index) { return -index - 1; }
int FixedFPLiveRangeID(int index, MachineRepresentation rep); int FixedFPLiveRangeID(int index, MachineRepresentation rep);
TopLevelLiveRange* FixedLiveRangeFor(int index, SpillMode spill_mode); TopLevelLiveRange* FixedLiveRangeFor(int index);
TopLevelLiveRange* FixedFPLiveRangeFor(int index, MachineRepresentation rep, TopLevelLiveRange* FixedFPLiveRangeFor(int index, MachineRepresentation rep);
SpillMode spill_mode);
void MapPhiHint(InstructionOperand* operand, UsePosition* use_pos); void MapPhiHint(InstructionOperand* operand, UsePosition* use_pos);
void ResolvePhiHint(InstructionOperand* operand, UsePosition* use_pos); void ResolvePhiHint(InstructionOperand* operand, UsePosition* use_pos);
...@@ -1126,30 +1097,19 @@ class LiveRangeBuilder final : public ZoneObject { ...@@ -1126,30 +1097,19 @@ class LiveRangeBuilder final : public ZoneObject {
UsePosition* NewUsePosition(LifetimePosition pos) { UsePosition* NewUsePosition(LifetimePosition pos) {
return NewUsePosition(pos, nullptr, nullptr, UsePositionHintType::kNone); return NewUsePosition(pos, nullptr, nullptr, UsePositionHintType::kNone);
} }
TopLevelLiveRange* LiveRangeFor(InstructionOperand* operand, TopLevelLiveRange* LiveRangeFor(InstructionOperand* operand);
SpillMode spill_mode);
// Helper methods for building intervals. // Helper methods for building intervals.
UsePosition* Define(LifetimePosition position, InstructionOperand* operand, UsePosition* Define(LifetimePosition position, InstructionOperand* operand,
void* hint, UsePositionHintType hint_type, void* hint, UsePositionHintType hint_type);
SpillMode spill_mode); void Define(LifetimePosition position, InstructionOperand* operand) {
void Define(LifetimePosition position, InstructionOperand* operand, Define(position, operand, nullptr, UsePositionHintType::kNone);
SpillMode spill_mode) {
Define(position, operand, nullptr, UsePositionHintType::kNone, spill_mode);
} }
UsePosition* Use(LifetimePosition block_start, LifetimePosition position, UsePosition* Use(LifetimePosition block_start, LifetimePosition position,
InstructionOperand* operand, void* hint, InstructionOperand* operand, void* hint,
UsePositionHintType hint_type, SpillMode spill_mode); UsePositionHintType hint_type);
void Use(LifetimePosition block_start, LifetimePosition position, void Use(LifetimePosition block_start, LifetimePosition position,
InstructionOperand* operand, SpillMode spill_mode) { InstructionOperand* operand) {
Use(block_start, position, operand, nullptr, UsePositionHintType::kNone, Use(block_start, position, operand, nullptr, UsePositionHintType::kNone);
spill_mode);
}
SpillMode SpillModeForBlock(const InstructionBlock* block) const {
if (data()->is_turbo_control_flow_aware_allocation()) {
return block->IsDeferred() ? SpillMode::kSpillDeferred
: SpillMode::kSpillAtDefinition;
}
return SpillMode::kSpillAtDefinition;
} }
RegisterAllocationData* const data_; RegisterAllocationData* const data_;
ZoneMap<InstructionOperand*, UsePosition*> phi_hints_; ZoneMap<InstructionOperand*, UsePosition*> phi_hints_;
...@@ -1285,10 +1245,8 @@ class LinearScanAllocator final : public RegisterAllocator { ...@@ -1285,10 +1245,8 @@ class LinearScanAllocator final : public RegisterAllocator {
void ReloadLiveRanges(RangeWithRegisterSet& to_be_live, void ReloadLiveRanges(RangeWithRegisterSet& to_be_live,
LifetimePosition position); LifetimePosition position);
void UpdateDeferredFixedRanges(SpillMode spill_mode, InstructionBlock* block);
bool BlockIsDeferredOrImmediatePredecessorIsNotDeferred( bool BlockIsDeferredOrImmediatePredecessorIsNotDeferred(
const InstructionBlock* block); const InstructionBlock* block);
bool HasNonDeferredPredecessor(InstructionBlock* block);
struct LiveRangeOrdering { struct LiveRangeOrdering {
bool operator()(const LiveRange* a, const LiveRange* b) const { bool operator()(const LiveRange* a, const LiveRange* b) const {
......
...@@ -401,12 +401,11 @@ class PipelineData { ...@@ -401,12 +401,11 @@ class PipelineData {
} }
void InitializeRegisterAllocationData(const RegisterConfiguration* config, void InitializeRegisterAllocationData(const RegisterConfiguration* config,
CallDescriptor* call_descriptor, CallDescriptor* call_descriptor) {
RegisterAllocationFlags flags) {
DCHECK_NULL(register_allocation_data_); DCHECK_NULL(register_allocation_data_);
register_allocation_data_ = new (register_allocation_zone()) register_allocation_data_ = new (register_allocation_zone())
RegisterAllocationData(config, register_allocation_zone(), frame(), RegisterAllocationData(config, register_allocation_zone(), frame(),
sequence(), flags, debug_name()); sequence(), debug_name());
} }
void InitializeOsrHelper() { void InitializeOsrHelper() {
...@@ -915,12 +914,6 @@ PipelineCompilationJob::Status PipelineCompilationJob::PrepareJobImpl( ...@@ -915,12 +914,6 @@ PipelineCompilationJob::Status PipelineCompilationJob::PrepareJobImpl(
if (FLAG_inline_accessors) { if (FLAG_inline_accessors) {
compilation_info()->MarkAsAccessorInliningEnabled(); compilation_info()->MarkAsAccessorInliningEnabled();
} }
if (FLAG_turbo_control_flow_aware_allocation) {
compilation_info()->MarkAsTurboControlFlowAwareAllocation();
}
if (FLAG_turbo_preprocess_ranges) {
compilation_info()->MarkAsTurboPreprocessRanges();
}
// This is the bottleneck for computing and setting poisoning level in the // This is the bottleneck for computing and setting poisoning level in the
// optimizing compiler. // optimizing compiler.
...@@ -2529,12 +2522,6 @@ bool Pipeline::AllocateRegistersForTesting(const RegisterConfiguration* config, ...@@ -2529,12 +2522,6 @@ bool Pipeline::AllocateRegistersForTesting(const RegisterConfiguration* config,
bool run_verifier) { bool run_verifier) {
OptimizedCompilationInfo info(ArrayVector("testing"), sequence->zone(), OptimizedCompilationInfo info(ArrayVector("testing"), sequence->zone(),
Code::STUB); Code::STUB);
if (FLAG_turbo_control_flow_aware_allocation) {
info.MarkAsTurboControlFlowAwareAllocation();
}
if (FLAG_turbo_preprocess_ranges) {
info.MarkAsTurboPreprocessRanges();
}
ZoneStats zone_stats(sequence->isolate()->allocator()); ZoneStats zone_stats(sequence->isolate()->allocator());
PipelineData data(&zone_stats, &info, sequence->isolate(), sequence); PipelineData data(&zone_stats, &info, sequence->isolate(), sequence);
data.InitializeFrameData(nullptr); data.InitializeFrameData(nullptr);
...@@ -2875,14 +2862,7 @@ void PipelineImpl::AllocateRegisters(const RegisterConfiguration* config, ...@@ -2875,14 +2862,7 @@ void PipelineImpl::AllocateRegisters(const RegisterConfiguration* config,
data_->sequence()->ValidateDeferredBlockExitPaths(); data_->sequence()->ValidateDeferredBlockExitPaths();
#endif #endif
RegisterAllocationFlags flags; data->InitializeRegisterAllocationData(config, call_descriptor);
if (data->info()->is_turbo_control_flow_aware_allocation()) {
flags |= RegisterAllocationFlag::kTurboControlFlowAwareAllocation;
}
if (data->info()->is_turbo_preprocess_ranges()) {
flags |= RegisterAllocationFlag::kTurboPreprocessRanges;
}
data->InitializeRegisterAllocationData(config, call_descriptor, flags);
if (info()->is_osr()) data->osr_helper()->SetupFrame(data->frame()); if (info()->is_osr()) data->osr_helper()->SetupFrame(data->frame());
Run<MeetRegisterConstraintsPhase>(); Run<MeetRegisterConstraintsPhase>();
...@@ -2903,7 +2883,7 @@ void PipelineImpl::AllocateRegisters(const RegisterConfiguration* config, ...@@ -2903,7 +2883,7 @@ void PipelineImpl::AllocateRegisters(const RegisterConfiguration* config,
data->register_allocation_data()); data->register_allocation_data());
} }
if (info()->is_turbo_preprocess_ranges()) { if (FLAG_turbo_preprocess_ranges) {
Run<SplinterLiveRangesPhase>(); Run<SplinterLiveRangesPhase>();
if (info()->trace_turbo_json_enabled() && if (info()->trace_turbo_json_enabled() &&
!data->MayHaveUnverifiableGraph()) { !data->MayHaveUnverifiableGraph()) {
...@@ -2919,7 +2899,7 @@ void PipelineImpl::AllocateRegisters(const RegisterConfiguration* config, ...@@ -2919,7 +2899,7 @@ void PipelineImpl::AllocateRegisters(const RegisterConfiguration* config,
Run<AllocateFPRegistersPhase<LinearScanAllocator>>(); Run<AllocateFPRegistersPhase<LinearScanAllocator>>();
} }
if (info()->is_turbo_preprocess_ranges()) { if (FLAG_turbo_preprocess_ranges) {
Run<MergeSplintersPhase>(); Run<MergeSplintersPhase>();
} }
......
...@@ -55,9 +55,7 @@ class V8_EXPORT_PRIVATE OptimizedCompilationInfo final { ...@@ -55,9 +55,7 @@ class V8_EXPORT_PRIVATE OptimizedCompilationInfo final {
kTraceTurboJson = 1 << 14, kTraceTurboJson = 1 << 14,
kTraceTurboGraph = 1 << 15, kTraceTurboGraph = 1 << 15,
kTraceTurboScheduled = 1 << 16, kTraceTurboScheduled = 1 << 16,
kWasmRuntimeExceptionSupport = 1 << 17, kWasmRuntimeExceptionSupport = 1 << 17
kTurboControlFlowAwareAllocation = 1 << 18,
kTurboPreprocessRanges = 1 << 19
}; };
// Construct a compilation info for optimized compilation. // Construct a compilation info for optimized compilation.
...@@ -86,18 +84,6 @@ class V8_EXPORT_PRIVATE OptimizedCompilationInfo final { ...@@ -86,18 +84,6 @@ class V8_EXPORT_PRIVATE OptimizedCompilationInfo final {
// Flags used by optimized compilation. // Flags used by optimized compilation.
void MarkAsTurboControlFlowAwareAllocation() {
SetFlag(kTurboControlFlowAwareAllocation);
}
bool is_turbo_control_flow_aware_allocation() const {
return GetFlag(kTurboControlFlowAwareAllocation);
}
void MarkAsTurboPreprocessRanges() { SetFlag(kTurboPreprocessRanges); }
bool is_turbo_preprocess_ranges() const {
return GetFlag(kTurboPreprocessRanges);
}
void MarkAsFunctionContextSpecializing() { void MarkAsFunctionContextSpecializing() {
SetFlag(kFunctionContextSpecializing); SetFlag(kFunctionContextSpecializing);
} }
......
...@@ -113,11 +113,6 @@ TEST_F(RegisterAllocatorTest, SimpleLoop) { ...@@ -113,11 +113,6 @@ TEST_F(RegisterAllocatorTest, SimpleLoop) {
// while(true) { i++ } // while(true) { i++ }
StartBlock(); StartBlock();
auto i_reg = DefineConstant(); auto i_reg = DefineConstant();
// Add a branch around the loop to ensure the end-block
// is connected.
EndBlock(Branch(Reg(DefineConstant()), 3, 1));
StartBlock();
EndBlock(); EndBlock();
{ {
...@@ -132,9 +127,6 @@ TEST_F(RegisterAllocatorTest, SimpleLoop) { ...@@ -132,9 +127,6 @@ TEST_F(RegisterAllocatorTest, SimpleLoop) {
EndLoop(); EndLoop();
} }
StartBlock();
EndBlock();
Allocate(); Allocate();
} }
...@@ -625,10 +617,10 @@ TEST_F(RegisterAllocatorTest, SingleDeferredBlockSpill) { ...@@ -625,10 +617,10 @@ TEST_F(RegisterAllocatorTest, SingleDeferredBlockSpill) {
const int var_def_index = 1; const int var_def_index = 1;
const int call_index = 3; const int call_index = 3;
const bool spill_in_deferred = int expect_no_moves =
FLAG_turbo_preprocess_ranges || FLAG_turbo_control_flow_aware_allocation; FLAG_turbo_preprocess_ranges ? var_def_index : call_index;
int expect_no_moves = spill_in_deferred ? var_def_index : call_index; int expect_spill_move =
int expect_spill_move = spill_in_deferred ? call_index : var_def_index; FLAG_turbo_preprocess_ranges ? call_index : var_def_index;
// We should have no parallel moves at the "expect_no_moves" position. // We should have no parallel moves at the "expect_no_moves" position.
EXPECT_EQ( EXPECT_EQ(
...@@ -693,67 +685,6 @@ TEST_F(RegisterAllocatorTest, MultipleDeferredBlockSpills) { ...@@ -693,67 +685,6 @@ TEST_F(RegisterAllocatorTest, MultipleDeferredBlockSpills) {
GetParallelMoveCount(start_of_b3, Instruction::START, sequence())); GetParallelMoveCount(start_of_b3, Instruction::START, sequence()));
} }
TEST_F(RegisterAllocatorTest, ValidMultipleDeferredBlockSpills) {
if (!FLAG_turbo_control_flow_aware_allocation) return;
StartBlock(); // B0
auto var1 = EmitOI(Reg(0));
auto var2 = EmitOI(Reg(1));
auto var3 = EmitOI(Reg(2));
EndBlock(Branch(Reg(var1, 0), 1, 2));
StartBlock(true); // B1
EmitCall(Slot(-2), Slot(var1));
EndBlock(Jump(5));
StartBlock(); // B2
EmitNop();
EndBlock();
StartBlock(); // B3
EmitNop();
EndBlock(Branch(Reg(var2, 0), 1, 2));
StartBlock(true); // B4
EmitCall(Slot(-1), Slot(var2));
EndBlock(Jump(2));
StartBlock(); // B5
EmitNop();
EndBlock();
StartBlock(); // B6
Return(Reg(var3, 2));
EndBlock();
const int def_of_v2 = 2;
const int call_in_b1 = 4;
const int call_in_b4 = 10;
const int end_of_b1 = 5;
const int end_of_b4 = 11;
const int start_of_b6 = 14;
Allocate();
const int var3_reg = 2;
const int var3_slot = 2;
EXPECT_FALSE(IsParallelMovePresent(def_of_v2, Instruction::START, sequence(),
Reg(var3_reg), Slot()));
EXPECT_TRUE(IsParallelMovePresent(call_in_b1, Instruction::START, sequence(),
Reg(var3_reg), Slot(var3_slot)));
EXPECT_TRUE(IsParallelMovePresent(end_of_b1, Instruction::START, sequence(),
Slot(var3_slot), Reg()));
EXPECT_TRUE(IsParallelMovePresent(call_in_b4, Instruction::START, sequence(),
Reg(var3_reg), Slot(var3_slot)));
EXPECT_TRUE(IsParallelMovePresent(end_of_b4, Instruction::START, sequence(),
Slot(var3_slot), Reg()));
EXPECT_EQ(0,
GetParallelMoveCount(start_of_b6, Instruction::START, sequence()));
}
namespace { namespace {
enum class ParameterType { kFixedSlot, kSlot, kRegister, kFixedRegister }; enum class ParameterType { kFixedSlot, kSlot, kRegister, kFixedRegister };
......
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