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,
const InstructionSequence* code = printable_block.code_;
os << "B" << block->rpo_number();
if (block->ao_number().IsValid()) {
os << ": AO#" << block->ao_number();
} else {
os << ": AO#?";
}
os << ": AO#" << block->ao_number();
if (block->IsDeferred()) os << " (deferred)";
if (!block->needs_frame()) os << " (no frame)";
if (block->must_construct_frame()) os << " (construct frame)";
......
......@@ -735,10 +735,10 @@ bool LiveRange::ShouldBeAllocatedBefore(const LiveRange* other) const {
return true;
}
// The other has a smaller hint.
if (controlflow_hint() > other->controlflow_hint()) {
if (other->controlflow_hint() != kUnassignedRegister) {
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* other_pos = other->first_pos();
// To make the order total, handle the case where both positions are null.
......@@ -1478,13 +1478,11 @@ RegisterAllocationData::RegisterAllocationData(
live_out_sets_(code->InstructionBlockCount(), nullptr, allocation_zone()),
live_ranges_(code->VirtualRegisterCount() * 2, nullptr,
allocation_zone()),
fixed_live_ranges_(kNumberOfFixedRangesPerRegister *
this->config()->num_general_registers(),
nullptr, allocation_zone()),
fixed_live_ranges_(this->config()->num_general_registers(), nullptr,
allocation_zone()),
fixed_float_live_ranges_(allocation_zone()),
fixed_double_live_ranges_(kNumberOfFixedRangesPerRegister *
this->config()->num_double_registers(),
nullptr, allocation_zone()),
fixed_double_live_ranges_(this->config()->num_double_registers(), nullptr,
allocation_zone()),
fixed_simd128_live_ranges_(allocation_zone()),
spill_ranges_(code->VirtualRegisterCount(), nullptr, allocation_zone()),
delayed_references_(allocation_zone()),
......@@ -1495,13 +1493,10 @@ RegisterAllocationData::RegisterAllocationData(
spill_state_(code->InstructionBlockCount(), ZoneVector<LiveRange*>(zone),
zone) {
if (!kSimpleFPAliasing) {
fixed_float_live_ranges_.resize(
kNumberOfFixedRangesPerRegister * this->config()->num_float_registers(),
nullptr);
fixed_simd128_live_ranges_.resize(
kNumberOfFixedRangesPerRegister *
this->config()->num_simd128_registers(),
nullptr);
fixed_float_live_ranges_.resize(this->config()->num_float_registers(),
nullptr);
fixed_simd128_live_ranges_.resize(this->config()->num_simd128_registers(),
nullptr);
}
assigned_registers_ = new (code_zone())
......@@ -2077,16 +2072,13 @@ int LiveRangeBuilder::FixedFPLiveRangeID(int index, MachineRepresentation rep) {
int result = -index - 1;
switch (rep) {
case MachineRepresentation::kSimd128:
result -=
kNumberOfFixedRangesPerRegister * config()->num_float_registers();
result -= config()->num_float_registers();
V8_FALLTHROUGH;
case MachineRepresentation::kFloat32:
result -=
kNumberOfFixedRangesPerRegister * config()->num_double_registers();
result -= config()->num_double_registers();
V8_FALLTHROUGH;
case MachineRepresentation::kFloat64:
result -=
kNumberOfFixedRangesPerRegister * config()->num_general_registers();
result -= config()->num_general_registers();
break;
default:
UNREACHABLE();
......@@ -2095,29 +2087,22 @@ int LiveRangeBuilder::FixedFPLiveRangeID(int index, MachineRepresentation rep) {
return result;
}
TopLevelLiveRange* LiveRangeBuilder::FixedLiveRangeFor(int index,
SpillMode spill_mode) {
int offset = spill_mode == SpillMode::kSpillAtDefinition
? 0
: config()->num_general_registers();
TopLevelLiveRange* LiveRangeBuilder::FixedLiveRangeFor(int index) {
DCHECK(index < config()->num_general_registers());
TopLevelLiveRange* result = data()->fixed_live_ranges()[offset + index];
TopLevelLiveRange* result = data()->fixed_live_ranges()[index];
if (result == nullptr) {
MachineRepresentation rep = InstructionSequence::DefaultRepresentation();
result = data()->NewLiveRange(FixedLiveRangeID(offset + index), rep);
result = data()->NewLiveRange(FixedLiveRangeID(index), rep);
DCHECK(result->IsFixed());
result->set_assigned_register(index);
data()->MarkAllocated(rep, index);
if (spill_mode == SpillMode::kSpillDeferred) {
result->set_deferred_fixed();
}
data()->fixed_live_ranges()[offset + index] = result;
data()->fixed_live_ranges()[index] = result;
}
return result;
}
TopLevelLiveRange* LiveRangeBuilder::FixedFPLiveRangeFor(
int index, MachineRepresentation rep, SpillMode spill_mode) {
int index, MachineRepresentation rep) {
int num_regs = config()->num_double_registers();
ZoneVector<TopLevelLiveRange*>* live_ranges =
&data()->fixed_double_live_ranges();
......@@ -2136,26 +2121,20 @@ TopLevelLiveRange* LiveRangeBuilder::FixedFPLiveRangeFor(
}
}
int offset = spill_mode == SpillMode::kSpillAtDefinition ? 0 : num_regs;
DCHECK(index < num_regs);
USE(num_regs);
TopLevelLiveRange* result = (*live_ranges)[offset + index];
TopLevelLiveRange* result = (*live_ranges)[index];
if (result == nullptr) {
result = data()->NewLiveRange(FixedFPLiveRangeID(offset + index, rep), rep);
result = data()->NewLiveRange(FixedFPLiveRangeID(index, rep), rep);
DCHECK(result->IsFixed());
result->set_assigned_register(index);
data()->MarkAllocated(rep, index);
if (spill_mode == SpillMode::kSpillDeferred) {
result->set_deferred_fixed();
}
(*live_ranges)[offset + index] = result;
(*live_ranges)[index] = result;
}
return result;
}
TopLevelLiveRange* LiveRangeBuilder::LiveRangeFor(InstructionOperand* operand,
SpillMode spill_mode) {
TopLevelLiveRange* LiveRangeBuilder::LiveRangeFor(InstructionOperand* operand) {
if (operand->IsUnallocated()) {
return data()->GetOrCreateLiveRangeFor(
UnallocatedOperand::cast(operand)->virtual_register());
......@@ -2164,11 +2143,10 @@ TopLevelLiveRange* LiveRangeBuilder::LiveRangeFor(InstructionOperand* operand,
ConstantOperand::cast(operand)->virtual_register());
} else if (operand->IsRegister()) {
return FixedLiveRangeFor(
LocationOperand::cast(operand)->GetRegister().code(), spill_mode);
LocationOperand::cast(operand)->GetRegister().code());
} else if (operand->IsFPRegister()) {
LocationOperand* op = LocationOperand::cast(operand);
return FixedFPLiveRangeFor(op->register_code(), op->representation(),
spill_mode);
return FixedFPLiveRangeFor(op->register_code(), op->representation());
} else {
return nullptr;
}
......@@ -2183,9 +2161,8 @@ UsePosition* LiveRangeBuilder::NewUsePosition(LifetimePosition pos,
UsePosition* LiveRangeBuilder::Define(LifetimePosition position,
InstructionOperand* operand, void* hint,
UsePositionHintType hint_type,
SpillMode spill_mode) {
TopLevelLiveRange* range = LiveRangeFor(operand, spill_mode);
UsePositionHintType hint_type) {
TopLevelLiveRange* range = LiveRangeFor(operand);
if (range == nullptr) return nullptr;
if (range->IsEmpty() || range->Start() > position) {
......@@ -2206,9 +2183,8 @@ UsePosition* LiveRangeBuilder::Define(LifetimePosition position,
UsePosition* LiveRangeBuilder::Use(LifetimePosition block_start,
LifetimePosition position,
InstructionOperand* operand, void* hint,
UsePositionHintType hint_type,
SpillMode spill_mode) {
TopLevelLiveRange* range = LiveRangeFor(operand, spill_mode);
UsePositionHintType hint_type) {
TopLevelLiveRange* range = LiveRangeFor(operand);
if (range == nullptr) return nullptr;
UsePosition* use_pos = nullptr;
if (operand->IsUnallocated()) {
......@@ -2232,7 +2208,6 @@ void LiveRangeBuilder::ProcessInstructions(const InstructionBlock* block,
fixed_float_live_ranges = (mask & kFloat32Bit) != 0;
fixed_simd128_live_ranges = (mask & kSimd128Bit) != 0;
}
SpillMode spill_mode = SpillModeForBlock(block);
for (int index = block->last_instruction_index(); index >= block_start;
index--) {
......@@ -2261,10 +2236,9 @@ void LiveRangeBuilder::ProcessInstructions(const InstructionBlock* block,
// exception value.
// TODO(mtrofin): should we explore an explicit opcode for
// the first instruction in the handler?
Define(LifetimePosition::GapFromInstructionIndex(index), output,
spill_mode);
Define(LifetimePosition::GapFromInstructionIndex(index), output);
} else {
Define(curr_position, output, spill_mode);
Define(curr_position, output);
}
}
......@@ -2275,7 +2249,7 @@ void LiveRangeBuilder::ProcessInstructions(const InstructionBlock* block,
// is OK because AddUseInterval will just merge it with the existing
// one at the end of the range.
int code = config()->GetAllocatableGeneralCode(i);
TopLevelLiveRange* range = FixedLiveRangeFor(code, spill_mode);
TopLevelLiveRange* range = FixedLiveRangeFor(code);
range->AddUseInterval(curr_position, curr_position.End(),
allocation_zone());
}
......@@ -2286,8 +2260,8 @@ void LiveRangeBuilder::ProcessInstructions(const InstructionBlock* block,
// Add a UseInterval for all DoubleRegisters. See comment above for
// general registers.
int code = config()->GetAllocatableDoubleCode(i);
TopLevelLiveRange* range = FixedFPLiveRangeFor(
code, MachineRepresentation::kFloat64, spill_mode);
TopLevelLiveRange* range =
FixedFPLiveRangeFor(code, MachineRepresentation::kFloat64);
range->AddUseInterval(curr_position, curr_position.End(),
allocation_zone());
}
......@@ -2299,8 +2273,8 @@ void LiveRangeBuilder::ProcessInstructions(const InstructionBlock* block,
// Add a UseInterval for all FloatRegisters. See comment above for
// general registers.
int code = config()->GetAllocatableFloatCode(i);
TopLevelLiveRange* range = FixedFPLiveRangeFor(
code, MachineRepresentation::kFloat32, spill_mode);
TopLevelLiveRange* range =
FixedFPLiveRangeFor(code, MachineRepresentation::kFloat32);
range->AddUseInterval(curr_position, curr_position.End(),
allocation_zone());
}
......@@ -2309,8 +2283,8 @@ void LiveRangeBuilder::ProcessInstructions(const InstructionBlock* block,
for (int i = 0; i < config()->num_allocatable_simd128_registers();
++i) {
int code = config()->GetAllocatableSimd128Code(i);
TopLevelLiveRange* range = FixedFPLiveRangeFor(
code, MachineRepresentation::kSimd128, spill_mode);
TopLevelLiveRange* range =
FixedFPLiveRangeFor(code, MachineRepresentation::kSimd128);
range->AddUseInterval(curr_position, curr_position.End(),
allocation_zone());
}
......@@ -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++) {
......@@ -2364,8 +2338,8 @@ void LiveRangeBuilder::ProcessInstructions(const InstructionBlock* block,
}
}
}
Use(block_start_position, curr_position.End(), temp, spill_mode);
Define(curr_position, temp, spill_mode);
Use(block_start_position, curr_position.End(), temp);
Define(curr_position, temp);
}
// Process the moves of the instruction's gaps, making their sources live.
......@@ -2404,9 +2378,8 @@ void LiveRangeBuilder::ProcessInstructions(const InstructionBlock* block,
}
} else {
if (live->Contains(to_vreg)) {
to_use =
Define(curr_position, &to, &from,
UsePosition::HintTypeForOperand(from), spill_mode);
to_use = Define(curr_position, &to, &from,
UsePosition::HintTypeForOperand(from));
live->Remove(to_vreg);
} else {
cur->Eliminate();
......@@ -2414,10 +2387,10 @@ void LiveRangeBuilder::ProcessInstructions(const InstructionBlock* block,
}
}
} else {
Define(curr_position, &to, spill_mode);
Define(curr_position, &to);
}
UsePosition* from_use = Use(block_start_position, curr_position, &from,
hint, hint_type, spill_mode);
UsePosition* from_use =
Use(block_start_position, curr_position, &from, hint, hint_type);
// Mark range live.
if (from.IsUnallocated()) {
live->Add(UnallocatedOperand::cast(from).virtual_register());
......@@ -2552,8 +2525,7 @@ void LiveRangeBuilder::ProcessPhis(const InstructionBlock* block,
LifetimePosition block_start = LifetimePosition::GapFromInstructionIndex(
block->first_instruction_index());
UsePosition* use_pos = Define(block_start, &phi->output(), hint,
UsePosition::HintTypeForOperand(*hint),
SpillModeForBlock(block));
UsePosition::HintTypeForOperand(*hint));
MapPhiHint(hint, use_pos);
}
}
......@@ -3431,117 +3403,6 @@ bool LinearScanAllocator::ConsiderBlockForControlFlow(
!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(
const InstructionBlock* block) {
if (block->IsDeferred()) return true;
......@@ -3556,14 +3417,6 @@ bool LinearScanAllocator::BlockIsDeferredOrImmediatePredecessorIsNotDeferred(
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() {
DCHECK(unhandled_live_ranges().empty());
DCHECK(active_live_ranges().empty());
......@@ -3591,30 +3444,18 @@ void LinearScanAllocator::AllocateRegisters() {
if (mode() == GENERAL_REGISTERS) {
for (TopLevelLiveRange* current : data()->fixed_live_ranges()) {
if (current != nullptr) {
if (current->IsDeferredFixed()) continue;
AddToInactive(current);
}
if (current != nullptr) AddToInactive(current);
}
} else {
for (TopLevelLiveRange* current : data()->fixed_double_live_ranges()) {
if (current != nullptr) {
if (current->IsDeferredFixed()) continue;
AddToInactive(current);
}
if (current != nullptr) AddToInactive(current);
}
if (!kSimpleFPAliasing && check_fp_aliasing()) {
for (TopLevelLiveRange* current : data()->fixed_float_live_ranges()) {
if (current != nullptr) {
if (current->IsDeferredFixed()) continue;
AddToInactive(current);
}
if (current != nullptr) AddToInactive(current);
}
for (TopLevelLiveRange* current : data()->fixed_simd128_live_ranges()) {
if (current != nullptr) {
if (current->IsDeferredFixed()) continue;
AddToInactive(current);
}
if (current != nullptr) AddToInactive(current);
}
}
}
......@@ -3677,28 +3518,9 @@ void LinearScanAllocator::AllocateRegisters() {
current_block->predecessors()[0].IsNext(
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()
? SpillMode::kSpillDeferred
: 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));
spill_mode = current_block->IsDeferred()
? SpillMode::kSpillDeferred
: SpillMode::kSpillAtDefinition;
if (!fallthrough) {
#ifdef DEBUG
......@@ -4348,14 +4170,6 @@ void LinearScanAllocator::AllocateBlockedReg(LiveRange* current,
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.
if (new_end != current->End()) {
LiveRange* tail = SplitBetween(current, current->Start(), new_end);
......
......@@ -467,12 +467,11 @@ class V8_EXPORT_PRIVATE LiveRange : public NON_EXPORTED_BASE(ZoneObject) {
void VerifyIntervals() const;
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<MachineRepresentation, 13, 8> RepresentationField;
typedef BitField<bool, 21, 1> RecombineField;
typedef BitField<uint8_t, 22, 6> ControlFlowRegisterHint;
// Bit 28 is used by TopLevelLiveRange.
// Unique among children and splinters of the same virtual register.
int relative_id_;
......@@ -570,8 +569,6 @@ class V8_EXPORT_PRIVATE TopLevelLiveRange final : public LiveRange {
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_); }
void set_is_phi(bool value) { bits_ = IsPhiField::update(bits_, value); }
......@@ -781,7 +778,6 @@ class V8_EXPORT_PRIVATE TopLevelLiveRange final : public LiveRange {
typedef BitField<bool, 3, 1> IsPhiField;
typedef BitField<bool, 4, 1> IsNonLoopPhiField;
typedef BitField<SpillType, 5, 2> SpillTypeField;
typedef BitField<bool, 28, 1> DeferredFixedField;
int vreg_;
int last_child_id_;
......@@ -864,8 +860,6 @@ class RegisterAllocationData final : public ZoneObject {
// Encodes whether a spill happens in deferred code (kSpillDeferred) or
// regular code (kSpillAtDefinition).
enum SpillMode { kSpillAtDefinition, kSpillDeferred };
static constexpr int kNumberOfFixedRangesPerRegister = 2;
class PhiMapValue : public ZoneObject {
public:
PhiMapValue(PhiInstruction* phi, const InstructionBlock* block, Zone* zone);
......@@ -1067,8 +1061,6 @@ class LiveRangeBuilder final : public ZoneObject {
private:
using SpillMode = RegisterAllocationData::SpillMode;
static constexpr int kNumberOfFixedRangesPerRegister =
RegisterAllocationData::kNumberOfFixedRangesPerRegister;
RegisterAllocationData* data() const { return data_; }
InstructionSequence* code() const { return data()->code(); }
......@@ -1094,9 +1086,8 @@ class LiveRangeBuilder final : public ZoneObject {
static int FixedLiveRangeID(int index) { return -index - 1; }
int FixedFPLiveRangeID(int index, MachineRepresentation rep);
TopLevelLiveRange* FixedLiveRangeFor(int index, SpillMode spill_mode);
TopLevelLiveRange* FixedFPLiveRangeFor(int index, MachineRepresentation rep,
SpillMode spill_mode);
TopLevelLiveRange* FixedLiveRangeFor(int index);
TopLevelLiveRange* FixedFPLiveRangeFor(int index, MachineRepresentation rep);
void MapPhiHint(InstructionOperand* operand, UsePosition* use_pos);
void ResolvePhiHint(InstructionOperand* operand, UsePosition* use_pos);
......@@ -1106,30 +1097,19 @@ class LiveRangeBuilder final : public ZoneObject {
UsePosition* NewUsePosition(LifetimePosition pos) {
return NewUsePosition(pos, nullptr, nullptr, UsePositionHintType::kNone);
}
TopLevelLiveRange* LiveRangeFor(InstructionOperand* operand,
SpillMode spill_mode);
TopLevelLiveRange* LiveRangeFor(InstructionOperand* operand);
// Helper methods for building intervals.
UsePosition* Define(LifetimePosition position, InstructionOperand* operand,
void* hint, UsePositionHintType hint_type,
SpillMode spill_mode);
void Define(LifetimePosition position, InstructionOperand* operand,
SpillMode spill_mode) {
Define(position, operand, nullptr, UsePositionHintType::kNone, spill_mode);
void* hint, UsePositionHintType hint_type);
void Define(LifetimePosition position, InstructionOperand* operand) {
Define(position, operand, nullptr, UsePositionHintType::kNone);
}
UsePosition* Use(LifetimePosition block_start, LifetimePosition position,
InstructionOperand* operand, void* hint,
UsePositionHintType hint_type, SpillMode spill_mode);
UsePositionHintType hint_type);
void Use(LifetimePosition block_start, LifetimePosition position,
InstructionOperand* operand, SpillMode spill_mode) {
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;
InstructionOperand* operand) {
Use(block_start, position, operand, nullptr, UsePositionHintType::kNone);
}
RegisterAllocationData* const data_;
ZoneMap<InstructionOperand*, UsePosition*> phi_hints_;
......@@ -1265,10 +1245,8 @@ class LinearScanAllocator final : public RegisterAllocator {
void ReloadLiveRanges(RangeWithRegisterSet& to_be_live,
LifetimePosition position);
void UpdateDeferredFixedRanges(SpillMode spill_mode, InstructionBlock* block);
bool BlockIsDeferredOrImmediatePredecessorIsNotDeferred(
const InstructionBlock* block);
bool HasNonDeferredPredecessor(InstructionBlock* block);
struct LiveRangeOrdering {
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")
// Flags for TurboFan.
DEFINE_BOOL(turbo_sp_frame_access, false,
"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")
DEFINE_BOOL(turbo_control_flow_aware_allocation, true,
DEFINE_BOOL(turbo_control_flow_aware_allocation, false,
"consider control flow while allocating registers")
DEFINE_NEG_IMPLICATION(turbo_control_flow_aware_allocation,
turbo_preprocess_ranges)
......
......@@ -113,11 +113,6 @@ TEST_F(RegisterAllocatorTest, SimpleLoop) {
// while(true) { i++ }
StartBlock();
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();
{
......@@ -132,9 +127,6 @@ TEST_F(RegisterAllocatorTest, SimpleLoop) {
EndLoop();
}
StartBlock();
EndBlock();
Allocate();
}
......@@ -625,10 +617,10 @@ TEST_F(RegisterAllocatorTest, SingleDeferredBlockSpill) {
const int var_def_index = 1;
const int call_index = 3;
const bool spill_in_deferred =
FLAG_turbo_preprocess_ranges || FLAG_turbo_control_flow_aware_allocation;
int expect_no_moves = spill_in_deferred ? var_def_index : call_index;
int expect_spill_move = spill_in_deferred ? call_index : var_def_index;
int expect_no_moves =
FLAG_turbo_preprocess_ranges ? var_def_index : call_index;
int expect_spill_move =
FLAG_turbo_preprocess_ranges ? call_index : var_def_index;
// We should have no parallel moves at the "expect_no_moves" position.
EXPECT_EQ(
......@@ -693,67 +685,6 @@ TEST_F(RegisterAllocatorTest, MultipleDeferredBlockSpills) {
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 {
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