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

Side by Side Diff: src/compiler/greedy-allocator.cc

Issue 1242123006: [turbofan] Deferred block spilling heuristic - first step. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Created 5 years, 5 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 unified diff | Download patch
« no previous file with comments | « no previous file | src/compiler/register-allocator.h » ('j') | src/compiler/register-allocator.cc » ('J')
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2015 the V8 project authors. All rights reserved. 1 // Copyright 2015 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "src/compiler/greedy-allocator.h" 5 #include "src/compiler/greedy-allocator.h"
6 #include "src/compiler/register-allocator.h" 6 #include "src/compiler/register-allocator.h"
7 7
8 namespace v8 { 8 namespace v8 {
9 namespace internal { 9 namespace internal {
10 namespace compiler { 10 namespace compiler {
(...skipping 22 matching lines...) Expand all
33 DCHECK(pos.IsStart() || pos.IsGapPosition() || 33 DCHECK(pos.IsStart() || pos.IsGapPosition() ||
34 (data->code() 34 (data->code()
35 ->GetInstructionBlock(pos.ToInstructionIndex()) 35 ->GetInstructionBlock(pos.ToInstructionIndex())
36 ->last_instruction_index() != pos.ToInstructionIndex())); 36 ->last_instruction_index() != pos.ToInstructionIndex()));
37 LiveRange* result = data->NewChildRangeFor(range); 37 LiveRange* result = data->NewChildRangeFor(range);
38 range->SplitAt(pos, result, data->allocation_zone()); 38 range->SplitAt(pos, result, data->allocation_zone());
39 return result; 39 return result;
40 } 40 }
41 41
42 42
43 void SpillToStackSlot(LiveRange* range, RegisterAllocationData* data) {
44 DCHECK(!range->spilled());
45 TRACE("Spilling live range %d\n", range->id());
46 auto first = range->TopLevel();
47 if (first->HasNoSpillType()) {
48 data->AssignSpillRangeToLiveRange(first);
49 }
50 range->Spill();
51 }
52
53
43 // TODO(mtrofin): explain why splitting in gap START is always OK. 54 // TODO(mtrofin): explain why splitting in gap START is always OK.
44 LifetimePosition GetSplitPositionForInstruction(const LiveRange* range, 55 LifetimePosition GetSplitPositionForInstruction(const LiveRange* range,
45 const InstructionSequence* code, 56 const InstructionSequence* code,
46 int instruction_index) { 57 int instruction_index) {
47 LifetimePosition ret = LifetimePosition::Invalid(); 58 LifetimePosition ret = LifetimePosition::Invalid();
48 59
49 ret = LifetimePosition::GapFromInstructionIndex(instruction_index); 60 ret = LifetimePosition::GapFromInstructionIndex(instruction_index);
50 if (range->Start() >= ret || ret >= range->End()) { 61 if (range->Start() >= ret || ret >= range->End()) {
51 return LifetimePosition::Invalid(); 62 return LifetimePosition::Invalid();
52 } 63 }
53 return ret; 64 return ret;
54 } 65 }
55 66
56 67
57 int GetFirstGapIndex(const UseInterval* interval) { 68 int GetFirstGapIndex(const UseInterval* interval) {
58 LifetimePosition start = interval->start(); 69 LifetimePosition start = interval->start();
59 int ret = start.ToInstructionIndex(); 70 int ret = start.ToInstructionIndex();
60 return ret; 71 return ret;
61 } 72 }
62 73
63 74
64 int GetLastGapIndex(const UseInterval* interval) { 75 int GetLastGapIndex(const UseInterval* interval) {
65 LifetimePosition end = interval->end(); 76 LifetimePosition end = interval->end();
66 return end.ToInstructionIndex(); 77 return end.ToInstructionIndex();
67 } 78 }
68 79
69 80
81 // Split before a call that requires parameters on stack, and spill until
82 // the first position requiring the parameter back in a register.
83 bool TrySplittingAroundCalls(LiveRange* range, RegisterAllocationData* data,
84 AllocationScheduler* scheduler) {
85 for (auto use = range->first_pos(); use != nullptr; use = use->next()) {
86 int index = use->pos().ToInstructionIndex();
87 auto instr = data->code()->InstructionAt(index);
Jarin 2015/07/22 12:59:35 Expand 'auto', please.
88 if (!instr->IsCall()) continue;
Jarin 2015/07/22 12:59:35 This does not really work because live ranges can
Mircea Trofin 2015/07/23 02:20:04 I see. OK, so we need to iterate over each instruc
89 if (use->type() != UsePositionType::kRequiresSlot) continue;
90
91 LifetimePosition at_call =
92 GetSplitPositionForInstruction(range, data->code(), index);
93 if (!at_call.IsValid()) continue;
94 LiveRange* call_part = Split(range, data, at_call);
95 scheduler->Schedule(range);
96
97 use = use->next();
98 LifetimePosition next_split = LifetimePosition::Invalid();
99 for (; use != nullptr && !next_split.IsValid(); use = use->next()) {
100 next_split = GetSplitPositionForInstruction(
101 call_part, data->code(), use->pos().ToInstructionIndex());
102 }
Jarin 2015/07/22 12:59:35 Why do we have the loop here? Cannot it happen tha
Mircea Trofin 2015/07/23 02:20:04 If we fall on to a different block, that's fine, c
103 if (next_split.IsValid()) {
104 LiveRange* keep = Split(call_part, data, next_split);
105 scheduler->Schedule(keep);
106 }
107
108 SpillToStackSlot(call_part, data);
109 return true;
110 }
111 return false;
112 }
113
114
70 // Basic heuristic for advancing the algorithm, if any other splitting heuristic 115 // Basic heuristic for advancing the algorithm, if any other splitting heuristic
71 // failed. 116 // failed.
72 LifetimePosition GetLastResortSplitPosition(const LiveRange* range, 117 LifetimePosition GetLastResortSplitPosition(const LiveRange* range,
73 const InstructionSequence* code) { 118 const InstructionSequence* code) {
74 if (range->first_interval()->next() != nullptr) { 119 if (range->first_interval()->next() != nullptr) {
75 return range->first_interval()->next()->start(); 120 return range->first_interval()->next()->start();
76 } 121 }
77 122
78 UseInterval* interval = range->first_interval(); 123 UseInterval* interval = range->first_interval();
79 int first = GetFirstGapIndex(interval); 124 int first = GetFirstGapIndex(interval);
(...skipping 157 matching lines...) Expand 10 before | Expand all | Expand 10 after
237 LifetimePosition start = range->Start(); 282 LifetimePosition start = range->Start();
238 TRACE("Live range %d is defined by a spill operand.\n", range->id()); 283 TRACE("Live range %d is defined by a spill operand.\n", range->id());
239 auto next_pos = start; 284 auto next_pos = start;
240 if (next_pos.IsGapPosition()) { 285 if (next_pos.IsGapPosition()) {
241 next_pos = next_pos.NextStart(); 286 next_pos = next_pos.NextStart();
242 } 287 }
243 auto pos = range->NextUsePositionRegisterIsBeneficial(next_pos); 288 auto pos = range->NextUsePositionRegisterIsBeneficial(next_pos);
244 // If the range already has a spill operand and it doesn't need a 289 // If the range already has a spill operand and it doesn't need a
245 // register immediately, split it and spill the first part of the range. 290 // register immediately, split it and spill the first part of the range.
246 if (pos == nullptr) { 291 if (pos == nullptr) {
247 Spill(range); 292 SpillToStackSlot(range, data());
248 } else if (pos->pos() > range->Start().NextStart()) { 293 } else if (pos->pos() > range->Start().NextStart()) {
249 // Do not spill live range eagerly if use position that can benefit from 294 // Do not spill live range eagerly if use position that can benefit from
250 // the register is too close to the start of live range. 295 // the register is too close to the start of live range.
251 auto split_pos = pos->pos(); 296 auto split_pos = GetSplitPositionForInstruction(
252 if (data()->IsBlockBoundary(split_pos.Start())) { 297 range, code(), pos->pos().ToInstructionIndex());
253 split_pos = split_pos.Start(); 298 if (split_pos.IsValid()) {
254 } else { 299 Split(range, data(), split_pos);
255 split_pos = split_pos.PrevStart().End(); 300 SpillToStackSlot(range, data());
256 } 301 }
257 Split(range, data(), split_pos);
258 Spill(range);
259 } 302 }
260 } 303 }
261 } 304 }
262 305
263 306
264 void GreedyAllocator::AllocateRegisters() { 307 void GreedyAllocator::AllocateRegisters() {
265 CHECK(scheduler().empty()); 308 CHECK(scheduler().empty());
266 CHECK(allocations_.empty()); 309 CHECK(allocations_.empty());
267 310
268 TRACE("Begin allocating function %s with the Greedy Allocator\n", 311 TRACE("Begin allocating function %s with the Greedy Allocator\n",
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after
319 } 362 }
320 range->set_weight(use_count / static_cast<float>(range->GetSize())); 363 range->set_weight(use_count / static_cast<float>(range->GetSize()));
321 } 364 }
322 365
323 366
324 void GreedyAllocator::SpillRangeAsLastResort(LiveRange* range) { 367 void GreedyAllocator::SpillRangeAsLastResort(LiveRange* range) {
325 LifetimePosition start = range->Start(); 368 LifetimePosition start = range->Start();
326 CHECK(range->CanBeSpilled(start)); 369 CHECK(range->CanBeSpilled(start));
327 370
328 DCHECK(range->NextRegisterPosition(start) == nullptr); 371 DCHECK(range->NextRegisterPosition(start) == nullptr);
329 Spill(range); 372 SpillToStackSlot(range, data());
330 } 373 }
331 374
332 375
333 void GreedyAllocator::SplitOrSpillBlockedRange(LiveRange* range) { 376 void GreedyAllocator::SplitOrSpillBlockedRange(LiveRange* range) {
377 if (TrySplittingAroundCalls(range, data(), &scheduler())) return;
378
334 // TODO(mtrofin): replace the call below with the entry point selecting 379 // TODO(mtrofin): replace the call below with the entry point selecting
335 // heuristics, once they exist, out of which GLRSP is the last one. 380 // heuristics, once they exist, out of which GLRSP is the last one.
336 auto pos = GetLastResortSplitPosition(range, code()); 381 auto pos = GetLastResortSplitPosition(range, code());
337 if (pos.IsValid()) { 382 if (pos.IsValid()) {
338 LiveRange* tail = Split(range, data(), pos); 383 LiveRange* tail = Split(range, data(), pos);
339 DCHECK(tail != range); 384 DCHECK(tail != range);
340 scheduler().Schedule(tail); 385 scheduler().Schedule(tail);
341 scheduler().Schedule(range); 386 scheduler().Schedule(range);
342 return; 387 return;
343 } 388 }
344 SpillRangeAsLastResort(range); 389 SpillRangeAsLastResort(range);
345 } 390 }
346 391
347 392
348 } // namespace compiler 393 } // namespace compiler
349 } // namespace internal 394 } // namespace internal
350 } // namespace v8 395 } // namespace v8
OLDNEW
« no previous file with comments | « no previous file | src/compiler/register-allocator.h » ('j') | src/compiler/register-allocator.cc » ('J')

Powered by Google App Engine
This is Rietveld 408576698