[turbofan] Greedy: smarter last resort splitting.
authormtrofin <mtrofin@chromium.org>
Tue, 29 Sep 2015 03:46:53 +0000 (20:46 -0700)
committerCommit bot <commit-bot@chromium.org>
Tue, 29 Sep 2015 03:47:35 +0000 (03:47 +0000)
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}

src/compiler/greedy-allocator.cc
src/compiler/greedy-allocator.h

index 7852830..e0368bf 100644 (file)
@@ -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
index b7398b3..45bbd87 100644 (file)
@@ -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);