Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(61)

Unified Diff: src/compiler/greedy-allocator.cc

Issue 1328783002: [turbofan] Greedy: split around calls heuristic. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Created 5 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « src/compiler/greedy-allocator.h ('k') | src/flag-definitions.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/compiler/greedy-allocator.cc
diff --git a/src/compiler/greedy-allocator.cc b/src/compiler/greedy-allocator.cc
index 444130aa1ea806e2647d7d375f4395384e6e5528..d6f48a2716e2be223b05c46c526dcbc4ca5a7a79 100644
--- a/src/compiler/greedy-allocator.cc
+++ b/src/compiler/greedy-allocator.cc
@@ -390,9 +390,94 @@ void GreedyAllocator::SpillRangeAsLastResort(LiveRange* range) {
}
+LiveRange* GreedyAllocator::GetRemainderAfterSplittingAroundFirstCall(
+ LiveRange* range) {
+ LiveRange* ret = range;
+ for (UseInterval* interval = range->first_interval(); interval != nullptr;
+ interval = interval->next()) {
+ LifetimePosition start = interval->start();
+ LifetimePosition end = interval->end();
+ // If the interval starts at instruction end, then the first instruction
+ // in the interval is the next one.
+ int first_full_instruction = (start.IsGapPosition() || start.IsStart())
+ ? start.ToInstructionIndex()
+ : start.ToInstructionIndex() + 1;
+ // If the interval ends in a gap or at instruction start, then the last
+ // instruction is the previous one.
+ int last_full_instruction = (end.IsGapPosition() || end.IsStart())
+ ? end.ToInstructionIndex() - 1
+ : end.ToInstructionIndex();
+
+ for (int instruction_index = first_full_instruction;
+ instruction_index <= last_full_instruction; ++instruction_index) {
+ if (!code()->InstructionAt(instruction_index)->IsCall()) continue;
+
+ LifetimePosition before =
+ GetSplitPositionForInstruction(range, instruction_index);
+ LiveRange* second_part =
+ before.IsValid() ? Split(range, data(), before) : range;
+
+ if (range != second_part) scheduler().Schedule(range);
+
+ LifetimePosition after =
+ FindSplitPositionAfterCall(second_part, instruction_index);
+
+ if (after.IsValid()) {
+ ret = Split(second_part, data(), after);
+ } else {
+ ret = nullptr;
+ }
+ Spill(second_part);
+ return ret;
+ }
+ }
+ return ret;
+}
+
+
+bool GreedyAllocator::TrySplitAroundCalls(LiveRange* range) {
+ bool modified = false;
+
+ while (range != nullptr) {
+ LiveRange* remainder = GetRemainderAfterSplittingAroundFirstCall(range);
+ // If we performed no modification, we're done.
+ if (remainder == range) {
+ break;
+ }
+ // We performed a modification.
+ modified = true;
+ range = remainder;
+ }
+ // If we have a remainder and we made modifications, it means the remainder
+ // has no calls and we should schedule it for further processing. If we made
+ // no modifications, we will just return false, because we want the algorithm
+ // to make progress by trying some other heuristic.
+ if (modified && range != nullptr) {
+ DCHECK(!range->spilled());
+ DCHECK(!range->HasRegisterAssigned());
+ scheduler().Schedule(range);
+ }
+ return modified;
+}
+
+
+LifetimePosition GreedyAllocator::FindSplitPositionAfterCall(
+ const LiveRange* range, int call_index) {
+ LifetimePosition after_call =
+ Max(range->Start(),
+ LifetimePosition::GapFromInstructionIndex(call_index + 1));
+ UsePosition* next_use = range->NextRegisterPosition(after_call);
+ if (!next_use) return LifetimePosition::Invalid();
+
+ LifetimePosition split_pos = FindOptimalSplitPos(after_call, next_use->pos());
+ split_pos =
+ GetSplitPositionForInstruction(range, split_pos.ToInstructionIndex());
+ return split_pos;
+}
+
+
void GreedyAllocator::SplitOrSpillBlockedRange(LiveRange* range) {
- // TODO(mtrofin): replace the call below with the entry point selecting
- // heuristics, once they exist, out of which GLRSP is the last one.
+ if (TrySplitAroundCalls(range)) return;
auto pos = GetLastResortSplitPosition(range, code());
if (pos.IsValid()) {
LiveRange* tail = Split(range, data(), pos);
« no previous file with comments | « src/compiler/greedy-allocator.h ('k') | src/flag-definitions.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698