Commit 4f719cca authored by Leszek Swirski's avatar Leszek Swirski Committed by Commit Bot

Revert "[regalloc] Introduce deferred fixed ranges"

This reverts commit b1769313.

Reason for revert: Flag access breaks TSAN (not an issue with this
CL as such, but we need to revert to re-open the tree).

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}

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

Change-Id: I5675a96acf0b5e5f7d63c60a742d2971b6d0d34d
No-Presubmit: true
No-Tree-Checks: true
No-Try: true
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/1530803Reviewed-by: 's avatarLeszek Swirski <leszeks@chromium.org>
Commit-Queue: Leszek Swirski <leszeks@chromium.org>
Cr-Commit-Position: refs/heads/master@{#60324}
parent a6d32847
...@@ -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)";
......
...@@ -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.
...@@ -1478,13 +1478,11 @@ RegisterAllocationData::RegisterAllocationData( ...@@ -1478,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()),
...@@ -1495,12 +1493,9 @@ RegisterAllocationData::RegisterAllocationData( ...@@ -1495,12 +1493,9 @@ RegisterAllocationData::RegisterAllocationData(
spill_state_(code->InstructionBlockCount(), ZoneVector<LiveRange*>(zone), spill_state_(code->InstructionBlockCount(), ZoneVector<LiveRange*>(zone),
zone) { zone) {
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);
} }
...@@ -2077,16 +2072,13 @@ int LiveRangeBuilder::FixedFPLiveRangeID(int index, MachineRepresentation rep) { ...@@ -2077,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();
...@@ -2095,29 +2087,22 @@ int LiveRangeBuilder::FixedFPLiveRangeID(int index, MachineRepresentation rep) { ...@@ -2095,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();
...@@ -2136,26 +2121,20 @@ TopLevelLiveRange* LiveRangeBuilder::FixedFPLiveRangeFor( ...@@ -2136,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());
...@@ -2164,11 +2143,10 @@ TopLevelLiveRange* LiveRangeBuilder::LiveRangeFor(InstructionOperand* operand, ...@@ -2164,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;
} }
...@@ -2183,9 +2161,8 @@ UsePosition* LiveRangeBuilder::NewUsePosition(LifetimePosition pos, ...@@ -2183,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) {
...@@ -2206,9 +2183,8 @@ UsePosition* LiveRangeBuilder::Define(LifetimePosition position, ...@@ -2206,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()) {
...@@ -2232,7 +2208,6 @@ void LiveRangeBuilder::ProcessInstructions(const InstructionBlock* block, ...@@ -2232,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--) {
...@@ -2261,10 +2236,9 @@ void LiveRangeBuilder::ProcessInstructions(const InstructionBlock* block, ...@@ -2261,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);
} }
} }
...@@ -2275,7 +2249,7 @@ void LiveRangeBuilder::ProcessInstructions(const InstructionBlock* block, ...@@ -2275,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());
} }
...@@ -2286,8 +2260,8 @@ void LiveRangeBuilder::ProcessInstructions(const InstructionBlock* block, ...@@ -2286,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());
} }
...@@ -2299,8 +2273,8 @@ void LiveRangeBuilder::ProcessInstructions(const InstructionBlock* block, ...@@ -2299,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());
} }
...@@ -2309,8 +2283,8 @@ void LiveRangeBuilder::ProcessInstructions(const InstructionBlock* block, ...@@ -2309,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());
} }
...@@ -2347,7 +2321,7 @@ void LiveRangeBuilder::ProcessInstructions(const InstructionBlock* block, ...@@ -2347,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++) {
...@@ -2364,8 +2338,8 @@ void LiveRangeBuilder::ProcessInstructions(const InstructionBlock* block, ...@@ -2364,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.
...@@ -2404,9 +2378,8 @@ void LiveRangeBuilder::ProcessInstructions(const InstructionBlock* block, ...@@ -2404,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();
...@@ -2414,10 +2387,10 @@ void LiveRangeBuilder::ProcessInstructions(const InstructionBlock* block, ...@@ -2414,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());
...@@ -2552,8 +2525,7 @@ void LiveRangeBuilder::ProcessPhis(const InstructionBlock* block, ...@@ -2552,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);
} }
} }
...@@ -3431,117 +3403,6 @@ bool LinearScanAllocator::ConsiderBlockForControlFlow( ...@@ -3431,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;
...@@ -3556,14 +3417,6 @@ bool LinearScanAllocator::BlockIsDeferredOrImmediatePredecessorIsNotDeferred( ...@@ -3556,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());
...@@ -3591,30 +3444,18 @@ void LinearScanAllocator::AllocateRegisters() { ...@@ -3591,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);
}
} }
} }
} }
...@@ -3677,29 +3518,10 @@ void LinearScanAllocator::AllocateRegisters() { ...@@ -3677,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.
...@@ -4348,14 +4170,6 @@ void LinearScanAllocator::AllocateBlockedReg(LiveRange* current, ...@@ -4348,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);
......
...@@ -467,12 +467,11 @@ class V8_EXPORT_PRIVATE LiveRange : public NON_EXPORTED_BASE(ZoneObject) { ...@@ -467,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_;
...@@ -570,8 +569,6 @@ class V8_EXPORT_PRIVATE TopLevelLiveRange final : public LiveRange { ...@@ -570,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); }
...@@ -781,7 +778,6 @@ class V8_EXPORT_PRIVATE TopLevelLiveRange final : public LiveRange { ...@@ -781,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_;
...@@ -864,8 +860,6 @@ class RegisterAllocationData final : public ZoneObject { ...@@ -864,8 +860,6 @@ class RegisterAllocationData final : public ZoneObject {
// Encodes whether a spill happens in deferred code (kSpillDeferred) or // Encodes whether a spill happens in deferred code (kSpillDeferred) or
// regular code (kSpillAtDefinition). // regular code (kSpillAtDefinition).
enum SpillMode { kSpillAtDefinition, kSpillDeferred }; enum SpillMode { kSpillAtDefinition, kSpillDeferred };
static constexpr int kNumberOfFixedRangesPerRegister = 2;
class PhiMapValue : public ZoneObject { class PhiMapValue : public ZoneObject {
public: public:
PhiMapValue(PhiInstruction* phi, const InstructionBlock* block, Zone* zone); PhiMapValue(PhiInstruction* phi, const InstructionBlock* block, Zone* zone);
...@@ -1067,8 +1061,6 @@ class LiveRangeBuilder final : public ZoneObject { ...@@ -1067,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(); }
...@@ -1094,9 +1086,8 @@ class LiveRangeBuilder final : public ZoneObject { ...@@ -1094,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);
...@@ -1106,30 +1097,19 @@ class LiveRangeBuilder final : public ZoneObject { ...@@ -1106,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 (FLAG_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_;
...@@ -1265,10 +1245,8 @@ class LinearScanAllocator final : public RegisterAllocator { ...@@ -1265,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 {
......
...@@ -419,9 +419,9 @@ DEFINE_BOOL(print_deopt_stress, false, "print number of possible deopt points") ...@@ -419,9 +419,9 @@ DEFINE_BOOL(print_deopt_stress, false, "print number of possible deopt points")
// Flags for TurboFan. // Flags for TurboFan.
DEFINE_BOOL(turbo_sp_frame_access, false, DEFINE_BOOL(turbo_sp_frame_access, false,
"use stack pointer-relative access to frame wherever possible") "use stack pointer-relative access to frame wherever possible")
DEFINE_BOOL(turbo_preprocess_ranges, false, DEFINE_BOOL(turbo_preprocess_ranges, true,
"run pre-register allocation heuristics") "run pre-register allocation heuristics")
DEFINE_BOOL(turbo_control_flow_aware_allocation, true, DEFINE_BOOL(turbo_control_flow_aware_allocation, false,
"consider control flow while allocating registers") "consider control flow while allocating registers")
DEFINE_NEG_IMPLICATION(turbo_control_flow_aware_allocation, DEFINE_NEG_IMPLICATION(turbo_control_flow_aware_allocation,
turbo_preprocess_ranges) turbo_preprocess_ranges)
......
...@@ -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