Commit d5a9dd65 authored by mtrofin's avatar mtrofin Committed by Commit bot

[turbofan] Greedy: smarter last resort splitting.

When all heuristics fail, we run a "last resort" heuristic. Before, it was
splitting at the first found splittable position either before or after a
use position. That turns out to be too naive: it may split in loops, when
alternative split positions exist outside loops.

This change chooses a "before" use case location that is outside the
loop.

Review URL: https://codereview.chromium.org/1372213005

Cr-Commit-Position: refs/heads/master@{#30990}
parent 5a13102d
......@@ -63,53 +63,6 @@ LifetimePosition GetSplitPositionForInstruction(const LiveRange* range,
}
int GetFirstGapIndex(const UseInterval* interval) {
LifetimePosition start = interval->start();
int ret = start.ToInstructionIndex();
return ret;
}
int GetLastGapIndex(const UseInterval* interval) {
LifetimePosition end = interval->end();
return end.ToInstructionIndex();
}
// Basic heuristic for advancing the algorithm, if any other splitting heuristic
// failed.
LifetimePosition GetLastResortSplitPosition(const LiveRange* range,
const InstructionSequence* code) {
if (range->first_interval()->next() != nullptr) {
return range->first_interval()->next()->start();
}
UseInterval* interval = range->first_interval();
int first = GetFirstGapIndex(interval);
int last = GetLastGapIndex(interval);
if (first == last) return LifetimePosition::Invalid();
// TODO(mtrofin:) determine why we can't just split somewhere arbitrary
// within the range, e.g. it's middle.
for (UsePosition* pos = range->first_pos(); pos != nullptr;
pos = pos->next()) {
if (pos->type() != UsePositionType::kRequiresRegister) continue;
LifetimePosition before =
GetSplitPositionForInstruction(range, pos->pos().ToInstructionIndex());
if (before.IsValid()) return before;
LifetimePosition after = GetSplitPositionForInstruction(
range, pos->pos().ToInstructionIndex() + 1);
if (after.IsValid()) return after;
}
return LifetimePosition::Invalid();
}
bool IsProgressPossible(const LiveRange* range,
const InstructionSequence* code) {
return range->CanBeSpilled(range->Start()) ||
GetLastResortSplitPosition(range, code).IsValid();
}
} // namespace
......@@ -556,7 +509,7 @@ void GreedyAllocator::EnsureValidRangeWeight(LiveRange* range) {
range->set_weight(LiveRange::kMaxWeight);
return;
}
if (!IsProgressPossible(range, code())) {
if (!IsProgressPossible(range)) {
range->set_weight(LiveRange::kMaxWeight);
return;
}
......@@ -682,7 +635,7 @@ void GreedyAllocator::SplitOrSpillBlockedRange(LiveRange* range) {
LifetimePosition pos = FindSplitPositionBeforeLoops(range);
if (!pos.IsValid()) pos = GetLastResortSplitPosition(range, code());
if (!pos.IsValid()) pos = GetLastResortSplitPosition(range);
if (pos.IsValid()) {
LiveRange* tail = Split(range, data(), pos);
DCHECK(tail != range);
......@@ -694,6 +647,31 @@ void GreedyAllocator::SplitOrSpillBlockedRange(LiveRange* range) {
}
// Basic heuristic for advancing the algorithm, if any other splitting heuristic
// failed.
LifetimePosition GreedyAllocator::GetLastResortSplitPosition(
const LiveRange* range) {
LifetimePosition previous = range->Start();
for (UsePosition *pos = range->NextRegisterPosition(previous); pos != nullptr;
previous = previous.NextFullStart(),
pos = range->NextRegisterPosition(previous)) {
LifetimePosition optimal = FindOptimalSplitPos(previous, pos->pos());
LifetimePosition before =
GetSplitPositionForInstruction(range, optimal.ToInstructionIndex());
if (before.IsValid()) return before;
LifetimePosition after = GetSplitPositionForInstruction(
range, pos->pos().ToInstructionIndex() + 1);
if (after.IsValid()) return after;
}
return LifetimePosition::Invalid();
}
bool GreedyAllocator::IsProgressPossible(const LiveRange* range) {
return range->CanBeSpilled(range->Start()) ||
GetLastResortSplitPosition(range).IsValid();
}
} // namespace compiler
} // namespace internal
} // namespace v8
......@@ -185,6 +185,10 @@ class GreedyAllocator final : public RegisterAllocator {
// between spill ranges of group members.
void TryReuseSpillRangesForGroups();
LifetimePosition GetLastResortSplitPosition(const LiveRange* range);
bool IsProgressPossible(const LiveRange* range);
// Necessary heuristic: spill when all else failed.
void SpillRangeAsLastResort(LiveRange* range);
......
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