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

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

Issue 1132753005: Greedy allocator: perf work (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: perf try Created 5 years, 7 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
Index: src/compiler/register-allocator.cc
diff --git a/src/compiler/register-allocator.cc b/src/compiler/register-allocator.cc
index 08b71f2e40488181657a064418bff797d9186b9c..1870496629b1ba121723f8a5fe34d3da0f03779e 100644
--- a/src/compiler/register-allocator.cc
+++ b/src/compiler/register-allocator.cc
@@ -47,6 +47,18 @@ const InstructionBlock* GetContainingLoop(const InstructionSequence* sequence,
}
+unsigned GetContainingLoopCount(const InstructionSequence* sequence,
+ const InstructionBlock* block) {
+ if (block->loop_header().IsValid()) return 1;
Jarin 2015/05/13 13:12:56 Can't you use block->IsLoopHeader()?
+
+ if (block->PredecessorCount() == 0)
Jarin 2015/05/13 13:12:56 Style nit: only omit the parentheses if the statem
+ return 0;
+ else
+ return GetContainingLoopCount(
+ sequence, sequence->InstructionBlockAt(block->predecessors()[0]));
Jarin 2015/05/13 13:12:56 Can we get rid of the recursion? More importantly
+}
+
+
const InstructionBlock* GetInstructionBlock(const InstructionSequence* code,
LifetimePosition pos) {
return code->GetInstructionBlock(pos.ToInstructionIndex());
@@ -795,8 +807,12 @@ std::ostream& operator<<(std::ostream& os,
PrintableInstructionOperand pio;
pio.register_configuration_ = printable_range.register_configuration_;
while (use_pos != nullptr) {
- pio.op_ = *use_pos->operand();
- os << pio << use_pos->pos() << " ";
+ if (use_pos->HasOperand()) {
+ pio.op_ = *use_pos->operand();
+ os << pio << use_pos->pos() << " ";
+ } else {
+ os << "<no_op> ";
+ }
use_pos = use_pos->next();
}
os << std::endl;
@@ -1844,6 +1860,8 @@ LifetimePosition RegisterAllocator::FindOptimalSpillingPos(
void RegisterAllocator::Spill(LiveRange* range) {
DCHECK(!range->spilled());
+ stats_.spills++;
+
TRACE("Spilling live range %d\n", range->id());
auto first = range->TopLevel();
if (first->HasNoSpillType()) {
@@ -1871,13 +1889,17 @@ LinearScanAllocator::LinearScanAllocator(RegisterAllocationData* data,
void LinearScanAllocator::AllocateRegisters() {
+ stats_.reset();
+ unsigned range_count = 0;
DCHECK(unhandled_live_ranges().empty());
DCHECK(active_live_ranges().empty());
DCHECK(inactive_live_ranges().empty());
-
+ TRACE("Begin allocating function %s with the Linear Allocator\n",
+ data()->debug_name());
for (auto range : data()->live_ranges()) {
if (range == nullptr) continue;
if (range->kind() == mode()) {
+ range_count++;
AddToUnhandledUnsorted(range);
}
}
@@ -1924,7 +1946,11 @@ void LinearScanAllocator::AllocateRegisters() {
}
}
- if (TryReuseSpillForPhi(current)) continue;
+ bool cont = false;
+ TRACE("Entering TryReuseSpillForPhi with range %d\n", current->id());
+ if (TryReuseSpillForPhi(current)) cont = true;
+ TRACE("Exiting TryReuseSpillForPhi with range %d\n", current->id());
+ if (cont) continue;
for (size_t i = 0; i < active_live_ranges().size(); ++i) {
auto cur_active = active_live_ranges()[i];
@@ -1951,15 +1977,31 @@ void LinearScanAllocator::AllocateRegisters() {
DCHECK(!current->HasRegisterAssigned() && !current->spilled());
bool result = TryAllocateFreeReg(current);
+ TRACE("Failed to allocate free reg for %d\n", current->id());
if (!result) AllocateBlockedReg(current);
if (current->HasRegisterAssigned()) {
AddToActive(current);
- }
+ } else {
+ TRACE("Failed to assign register to %d\n", current->id());
+ }
+ }
+ TRACE("End allocating function %s with the Linear Allocator\n",
+ data()->debug_name());
+ if (FLAG_greedy_stats) {
+ OFStream os(stdout);
+ os << "==================================================" << std::endl;
+ os << "allocation stats for: " << data()->debug_name() << "(" << mode()
+ << ")" << std::endl;
+ os << "input ranges: " << range_count << std::endl;
+ os << "input fixed ranges: " << GetFixedRegisters(data(), mode()).size()
+ << std::endl;
+ os << stats_;
+ os << "==================================================" << std::endl;
}
}
-const char* LinearScanAllocator::RegisterName(int allocation_index) const {
+const char* RegisterAllocator::RegisterName(int allocation_index) const {
if (mode() == GENERAL_REGISTERS) {
return data()->config()->general_register_name(allocation_index);
} else {
@@ -2127,6 +2169,10 @@ bool LinearScanAllocator::TryAllocateFreeReg(LiveRange* current) {
if (pos < current->End()) {
// Register reg is available at the range start but becomes blocked before
// the range end. Split current at position where it becomes blocked.
+ TRACE(
+ "Register %d is available at the range start but becomes blocked "
+ "before range %d end\n",
+ reg, current->id());
auto tail = SplitRangeAt(current, pos);
AddToUnhandledSorted(tail);
}
@@ -2199,6 +2245,8 @@ void LinearScanAllocator::AllocateBlockedReg(LiveRange* current) {
if (pos < register_use->pos()) {
// All registers are blocked before the first use that requires a register.
// Spill starting part of live range up to that use.
+ TRACE("All registers are blocked before the first use for %d\n",
+ current->id());
SpillBetween(current, current->Start(), register_use->pos());
return;
}
@@ -2206,6 +2254,8 @@ void LinearScanAllocator::AllocateBlockedReg(LiveRange* current) {
if (block_pos[reg] < current->End()) {
// Register becomes blocked before the current range end. Split before that
// position.
+ TRACE("Register %d becomes blocked before end of range %d\n", reg,
+ current->id());
LiveRange* tail =
SplitBetween(current, current->Start(), block_pos[reg].Start());
AddToUnhandledSorted(tail);
@@ -2234,6 +2284,8 @@ void LinearScanAllocator::SplitAndSpillIntersecting(LiveRange* current) {
auto next_pos = range->NextRegisterPosition(current->Start());
auto spill_pos = FindOptimalSpillingPos(range, split_pos);
if (next_pos == nullptr) {
+ TRACE("SplitAndSpillIntersecting (1). Range %d, for %d\n", range->id(),
+ current->id());
SpillAfter(range, spill_pos);
} else {
// When spilling between spill_pos and next_pos ensure that the range
@@ -2244,6 +2296,8 @@ void LinearScanAllocator::SplitAndSpillIntersecting(LiveRange* current) {
// live-ranges: ranges are allocated in order of their start positions,
// ranges are retired from active/inactive when the start of the
// current live-range is larger than their end.
+ TRACE("SplitAndSpillIntersecting (2). Range %d, for %d\n", range->id(),
+ current->id());
SpillBetweenUntil(range, spill_pos, current->Start(), next_pos->pos());
}
ActiveToHandled(range);
@@ -2259,9 +2313,13 @@ void LinearScanAllocator::SplitAndSpillIntersecting(LiveRange* current) {
if (next_intersection.IsValid()) {
UsePosition* next_pos = range->NextRegisterPosition(current->Start());
if (next_pos == nullptr) {
+ TRACE("SplitAndSpillIntersecting (3). Range %d, for %d\n",
+ range->id(), current->id());
SpillAfter(range, split_pos);
} else {
next_intersection = Min(next_intersection, next_pos->pos());
+ TRACE("SplitAndSpillIntersecting (4). Range %d, for %d\n",
+ range->id(), current->id());
SpillBetween(range, split_pos, next_intersection);
}
InactiveToHandled(range);
@@ -2470,6 +2528,22 @@ class CoalescedLiveRanges : public ZoneObject {
const std::pair<int, int> CoalescedLiveRanges::Config::kNoKey = {0, 0};
+
+std::ostream& operator<<(std::ostream& os, const AllocatorStats& stats) {
+ os << "losses after eviction: " << stats.losses_after_eviction << std::endl;
+ os << "losses, no eviction: " << stats.losses_no_eviction << std::endl;
+ os << "spills: " << stats.spills << std::endl;
+ os << "wins: " << stats.wins << std::endl;
+ os << "split attempts: " << stats.good_split_attempts << std::endl;
+ os << "split successes: " << stats.good_split_successes << std::endl;
+ os << "splits above: " << stats.good_split_above << std::endl;
+ os << "splits below: " << stats.good_split_below << std::endl;
+ os << "smart splits above: " << stats.good_split_smart_above << std::endl;
+ os << "smart splits below: " << stats.good_split_smart_below << std::endl;
+ return os;
+}
+
+
GreedyAllocator::GreedyAllocator(RegisterAllocationData* data,
RegisterKind kind, Zone* local_zone)
: RegisterAllocator(data, kind),
@@ -2478,17 +2552,15 @@ GreedyAllocator::GreedyAllocator(RegisterAllocationData* data,
queue_(local_zone) {}
-unsigned GreedyAllocator::GetLiveRangeSize(LiveRange* range) {
- auto interval = range->first_interval();
- if (interval == nullptr) return 0;
+unsigned GreedyAllocator::GetLiveRangeSize(LiveRange* range,
+ LifetimePosition start,
+ LifetimePosition end) {
+ return (end.value() - start.value());
+}
- unsigned size = 0;
- while (interval != nullptr) {
- size += (interval->end().value() - interval->start().value());
- interval = interval->next();
- }
- return size;
+unsigned GreedyAllocator::GetLiveRangeSize(LiveRange* range) {
+ return GetLiveRangeSize(range, range->Start(), range->End());
}
@@ -2498,6 +2570,7 @@ void GreedyAllocator::AssignRangeToRegister(int reg_id, LiveRange* range) {
DCHECK_EQ(reg_id, range->assigned_register());
return;
}
+ TRACE("Assigning %s to range %d\n", RegisterName(reg_id), range->id());
range->set_assigned_register(reg_id);
range->SetUseHints(reg_id);
if (range->is_phi()) {
@@ -2507,47 +2580,62 @@ void GreedyAllocator::AssignRangeToRegister(int reg_id, LiveRange* range) {
float GreedyAllocator::CalculateSpillWeight(LiveRange* range) {
- InstructionOperand* first_hint = nullptr;
- if (range->FirstHintPosition() != nullptr) {
- first_hint = range->FirstHintPosition()->operand();
- }
+ return CalculateSpillWeight(range, range->Start(), range->End());
+}
+
+// Local definition of integer power, to avoid casting std::pow.
+unsigned ipow(unsigned b, unsigned e) {
+ if (e == 0) return 1;
+ if (e == 1) return b;
+ auto odd = e & 1;
+ auto rem = e >> 1;
+ auto half = ipow(b, rem);
Jarin 2015/05/13 13:12:57 If you wrote this function for efficiency, then yo
+ auto ret = half * half;
+ if (odd) ret *= b;
+ return ret;
+}
+
+
+float GreedyAllocator::CalculateSpillWeight(LiveRange* range,
+ LifetimePosition start,
+ LifetimePosition end) {
if (range->IsFixed()) return std::numeric_limits<float>::max();
- bool spill;
- if (!FindProgressingSplitPosition(range, &spill).IsValid())
+
+ if (!RangeHasSplitOrSpillPosition(range, start, end))
return std::numeric_limits<float>::max();
- float multiplier = 1.0;
- if (first_hint != nullptr && first_hint->IsRegister()) {
- multiplier = 3.0;
- }
unsigned use_count = 0;
auto* pos = range->first_pos();
- while (pos != nullptr) {
- use_count++;
- pos = pos->next();
+ const InstructionBlock* last_block = nullptr;
+
+ unsigned last_loop_count = 0;
+ unsigned last_use_count = 0;
+ for (; pos != nullptr; pos = pos->next()) {
+ if (pos->pos() < start) continue;
+ if (pos->pos() > end) break;
+
+ auto block = GetInstructionBlock(code(), pos->pos());
+ if (block != last_block) {
+ last_block = block;
+ use_count += last_use_count * ipow(2, last_loop_count);
Jarin 2015/05/13 13:12:56 ipow(2, x) --> 1 << x?
+ last_loop_count = GetContainingLoopCount(code(), block);
+ last_use_count = 0;
+ }
+ if (pos->RegisterIsBeneficial()) last_use_count++;
}
+ use_count += last_use_count * ipow(2, last_loop_count);
Jarin 2015/05/13 13:12:56 ipow(2, x) --> 1 << x?
- unsigned range_size = GetLiveRangeSize(range);
+ unsigned range_size = GetLiveRangeSize(range, start, end);
DCHECK_NE(0U, range_size);
- return multiplier * static_cast<float>(use_count) /
- static_cast<float>(range_size);
-}
-
-
-float GreedyAllocator::CalculateMaxSpillWeight(
- const ZoneSet<LiveRange*>& ranges) {
- float max = 0.0;
- for (auto* r : ranges) {
- max = std::max(max, CalculateSpillWeight(r));
- }
- return max;
+ return static_cast<float>(use_count) / static_cast<float>(range_size);
}
void GreedyAllocator::Evict(LiveRange* range) {
+ TRACE("Evicting range %d\n", range->id());
bool removed = allocations_[range->assigned_register()]->Remove(range);
CHECK(removed);
range->UnsetUseHints();
@@ -2651,7 +2739,7 @@ LiveRange* GreedyAllocator::SpillBetweenUntil(LiveRange* range,
void GreedyAllocator::Enqueue(LiveRange* range) {
if (range == nullptr || range->IsEmpty()) return;
unsigned size = GetLiveRangeSize(range);
- TRACE("Enqueuing range %d\n", range->id());
+ TRACE("Enqueuing range %d size %d\n", range->id(), size);
queue_.push(std::make_pair(size, range));
}
@@ -2680,17 +2768,25 @@ bool GreedyAllocator::HandleSpillOperands(LiveRange* range) {
return true;
}
}
- return TryReuseSpillForPhi(range);
+ TRACE("Entering TryReuseSpillForPhi with range %d\n", range->id());
+ bool ret = TryReuseSpillForPhi(range);
+ TRACE("Exiting TryReuseSpillForPhi with range %d\n", range->id());
+ return ret;
}
void GreedyAllocator::AllocateRegisters() {
+ stats_.reset();
+ unsigned range_count = 0;
+ TRACE("Begin allocating function %s with the Greedy Allocator\n",
+ data()->debug_name());
for (auto range : data()->live_ranges()) {
if (range == nullptr) continue;
if (range->kind() == mode()) {
DCHECK(!range->HasRegisterAssigned() && !range->spilled());
TRACE("Enqueueing live range %d to priority queue \n", range->id());
Enqueue(range);
+ range_count++;
}
}
@@ -2712,23 +2808,21 @@ void GreedyAllocator::AllocateRegisters() {
auto current_pair = queue_.top();
queue_.pop();
auto current = current_pair.second;
+ TRACE("Processing interval %d of size %d\n", current->id(),
+ current_pair.first);
if (HandleSpillOperands(current)) {
continue;
}
- bool spill = false;
+
ZoneSet<LiveRange*> conflicting(local_zone());
if (!TryAllocate(current, &conflicting)) {
DCHECK(!conflicting.empty());
- float this_weight = std::numeric_limits<float>::max();
- LifetimePosition split_pos =
- FindProgressingSplitPosition(current, &spill);
- if (split_pos.IsValid()) {
- this_weight = CalculateSpillWeight(current);
- }
+ float this_weight = CalculateSpillWeight(current);
bool evicted = false;
for (auto* conflict : conflicting) {
- if (CalculateSpillWeight(conflict) < this_weight) {
+ float conflict_weight = CalculateSpillWeight(conflict);
+ if (conflict_weight < this_weight) {
Evict(conflict);
Enqueue(conflict);
evicted = true;
@@ -2737,11 +2831,19 @@ void GreedyAllocator::AllocateRegisters() {
if (evicted) {
conflicting.clear();
TryAllocate(current, &conflicting);
+ if (conflicting.size() == 0) {
+ stats_.wins++;
+ } else {
+ stats_.losses_after_eviction++;
+ }
+ } else {
+ stats_.losses_no_eviction++;
}
- if (!conflicting.empty()) {
+ if (conflicting.size() > 0) {
+ TRACE("Could evict for range %d\n", current->id());
DCHECK(!current->IsFixed() || current->CanBeSpilled(current->Start()));
- DCHECK(split_pos.IsValid());
- AllocateBlockedRange(current, split_pos, spill);
+ // DCHECK(split_pos.IsValid());
Jarin 2015/05/13 13:12:57 Remove.
+ AllocateBlockedRange(current, conflicting);
}
}
}
@@ -2751,90 +2853,215 @@ void GreedyAllocator::AllocateRegisters() {
data()->MarkAllocated(mode(), static_cast<int>(i));
}
}
+ TRACE("End allocating function %s with the Greedy Allocator\n",
+ data()->debug_name());
+ if (FLAG_greedy_stats) {
+ OFStream os(stdout);
+ os << "==================================================" << std::endl;
+ os << "allocation stats for: " << data()->debug_name() << "(" << mode()
+ << ")" << std::endl;
+ os << "input ranges: " << range_count << std::endl;
+ os << "input fixed ranges: " << GetFixedRegisters(data(), mode()).size()
+ << std::endl;
+ os << stats_;
+ os << "==================================================" << std::endl;
+ }
}
-LifetimePosition GreedyAllocator::GetSplittablePos(LifetimePosition pos) {
- auto ret = pos.PrevStart().End();
+LifetimePosition GreedyAllocator::GetCorrectSplitPos(LifetimePosition pos) {
+ LifetimePosition ret;
if (IsBlockBoundary(code(), pos.Start())) {
ret = pos.Start();
+ } else {
+ ret = pos.PrevStart().End();
}
DCHECK(ret <= pos);
return ret;
}
-LifetimePosition GreedyAllocator::FindProgressingSplitPosition(
- LiveRange* range, bool* is_spill_pos) {
+LifetimePosition GreedyAllocator::GetSplittablePos(UsePosition* use_pos,
+ LiveRange* range) {
+ DCHECK(use_pos != nullptr);
auto start = range->Start();
auto end = range->End();
- UsePosition* next_reg_use = range->first_pos();
- while (next_reg_use != nullptr &&
- next_reg_use->type() != UsePositionType::kRequiresRegister) {
- next_reg_use = next_reg_use->next();
+ auto pos = GetCorrectSplitPos(use_pos->pos());
+ if (start < pos && pos < end) {
+ return pos;
}
- if (next_reg_use == nullptr) {
- *is_spill_pos = true;
- auto ret = FindOptimalSpillingPos(range, start);
- DCHECK(ret.IsValid());
- return ret;
+ if (pos >= end) {
+ return LifetimePosition::Invalid();
Jarin 2015/05/13 13:12:56 How can this happen?
}
- *is_spill_pos = false;
- auto reg_pos = next_reg_use->pos();
- auto correct_pos = GetSplittablePos(reg_pos);
- if (start < correct_pos && correct_pos < end) {
- return correct_pos;
+ auto after = pos.NextFullStart();
+ if (start < after && after < end) {
+ return after;
}
+ if (use_pos->next() != nullptr) {
+ return GetSplittablePos(use_pos->next(), range);
+ }
+ return LifetimePosition::Invalid();
+}
- if (correct_pos >= end) {
- return LifetimePosition::Invalid();
+bool GreedyAllocator::RangeHasSplitOrSpillPosition(LiveRange* range,
+ LifetimePosition start,
+ LifetimePosition end) {
+ UsePosition* next_reg_use = range->first_pos();
+ for (; next_reg_use != nullptr; next_reg_use = next_reg_use->next()) {
+ if (next_reg_use->pos() > end) break;
+ if (next_reg_use->pos() < start) continue;
+ if (next_reg_use->type() == UsePositionType::kRequiresRegister) break;
}
- // Correct_pos must be at or before start. Find the next use position.
- next_reg_use = next_reg_use->next();
- auto reference = reg_pos;
- while (next_reg_use != nullptr) {
- auto pos = next_reg_use->pos();
- // Skip over tight successive uses.
- if (reference.NextStart() < pos) {
- break;
- }
- reference = pos;
+ if (next_reg_use == nullptr || next_reg_use->pos() > end) {
+ auto ret = FindOptimalSpillingPos(range, start);
+ CHECK(ret.IsValid());
+ return true;
+ }
+ auto pos = GetCorrectSplitPos(next_reg_use->pos());
+ if (start < pos && pos < end) return true;
+ while (next_reg_use->next() != nullptr &&
+ next_reg_use->pos().NextFullStart() > next_reg_use->next()->pos()) {
next_reg_use = next_reg_use->next();
}
+ CHECK(next_reg_use != nullptr);
+ pos = next_reg_use->pos().NextFullStart();
+ if (start < pos && pos < end) return true;
Jarin 2015/05/13 13:12:56 return start < pos && pos < end;
+ return false;
+}
- if (next_reg_use == nullptr) {
- // While there may not be another use, we may still have space in the range
- // to clip off.
- correct_pos = reference.NextStart();
- if (start < correct_pos && correct_pos < end) {
- return correct_pos;
+bool GreedyAllocator::FindGoodSplitPoint(LiveRange* range,
+ const ZoneSet<LiveRange*>& conflicts) {
+ auto start = range->Start();
+ auto end = range->End();
+ end = end.IsInstructionPosition() ? end.End() : end.PrevStart().End();
+ auto pos = LifetimePosition::Invalid();
+ float heaviest = 0.0;
+ stats_.good_split_attempts++;
+
+ bool winner_is_smart = false;
+ bool winner_is_above = false;
+ for (auto conflict : conflicts) {
+ bool upper_is_freed = false;
+ bool using_smart = false;
+ auto first_intersection = range->FirstIntersection(conflict);
+ DCHECK(first_intersection.IsValid());
+ DCHECK(conflict->HasRegisterAssigned());
+ if (first_intersection == start && FLAG_greedy_below) {
+ first_intersection = conflict->End();
+ } else {
+ upper_is_freed = true;
+ }
+ auto corrected_pos = GetCorrectSplitPos(first_intersection);
+ if (start >= corrected_pos || corrected_pos >= end) continue;
+ auto candidate_pos =
+ FLAG_greedy_smart
+ ? (upper_is_freed ? FindOptimalSplitPos(start, corrected_pos)
+ : FindOptimalSplitPos(corrected_pos, end))
+ : corrected_pos;
+
+ if (start >= candidate_pos || candidate_pos >= end) {
+ if (FLAG_greedy_alternative && start < corrected_pos &&
+ corrected_pos < end) {
+ candidate_pos = corrected_pos;
+ } else {
+ continue;
+ }
+ }
+ using_smart = (candidate_pos != corrected_pos);
+
+ float this_weight = 0.0;
+ if (upper_is_freed) {
+ this_weight = CalculateSpillWeight(range, start, candidate_pos);
+ } else {
+ this_weight = CalculateSpillWeight(range, candidate_pos, end);
+ }
+
+ if (FLAG_greedy_split_longest) {
+ pos = Max(pos, candidate_pos);
+ } else if (this_weight > heaviest) {
+ pos = candidate_pos;
+ heaviest = this_weight;
+ winner_is_smart = using_smart;
+ winner_is_above = upper_is_freed;
}
- return LifetimePosition::Invalid();
}
- correct_pos = GetSplittablePos(next_reg_use->pos());
- if (start < correct_pos && correct_pos < end) {
- DCHECK(reference < correct_pos);
- return correct_pos;
+ if (!pos.IsValid()) {
+ // All registers are blocked.
+ TRACE("All registers are blocked for range %d\n", range->id());
+ return false;
}
- return LifetimePosition::Invalid();
+ CHECK(FLAG_greedy_split_longest || heaviest > 0.0);
+
+ // Register reg is available at the range start but becomes blocked before
+ // the range end. Split current at position where it becomes blocked.
+ TRACE("Splitting range %d at position %d where the length is %f", range->id(),
+ pos.value(), heaviest);
+
+ LiveRange* tail = SplitRangeAt(range, pos);
+ CHECK(tail != range);
+ Enqueue(tail);
+ Enqueue(range);
+ if (winner_is_smart) {
+ if (winner_is_above) {
+ stats_.good_split_smart_above++;
+ } else {
+ stats_.good_split_smart_below++;
+ }
+ } else {
+ if (winner_is_above) {
+ stats_.good_split_above++;
+ } else {
+ stats_.good_split_below++;
+ }
+ }
+ stats_.good_split_successes++;
+ return true;
}
+void GreedyAllocator::AllocateBlockedRange(
+ LiveRange* current, const ZoneSet<LiveRange*>& conflicts) {
+ auto start = current->Start();
+ auto end = current->End();
+
+ UsePosition* next_reg_use = current->first_pos();
+ while (next_reg_use != nullptr &&
+ next_reg_use->type() != UsePositionType::kRequiresRegister) {
+ next_reg_use = next_reg_use->next();
+ }
-void GreedyAllocator::AllocateBlockedRange(LiveRange* current,
- LifetimePosition pos, bool spill) {
- auto tail = SplitRangeAt(current, pos);
- if (spill) {
+ if (next_reg_use == nullptr) {
+ auto pos = FindOptimalSpillingPos(current, start);
+ DCHECK(pos.IsValid());
+ auto tail = SplitRangeAt(current, pos);
Spill(tail);
- } else {
- Enqueue(tail);
+ if (tail != current) {
+ Enqueue(current);
+ }
+ return;
}
- if (tail != current) {
- Enqueue(current);
+
+ if (FindGoodSplitPoint(current, conflicts)) return;
+ auto alternate = GetCorrectSplitPos(next_reg_use->pos());
+ if (start >= alternate || alternate >= end) {
+ auto reg_use_backup = next_reg_use;
+ for (; next_reg_use != nullptr; next_reg_use = next_reg_use->next()) {
+ if (next_reg_use->type() == UsePositionType::kRequiresRegister) {
+ alternate = next_reg_use->pos();
+ }
+ }
+ alternate = alternate.NextStart();
+ if (start >= alternate || alternate >= end) {
+ alternate = GetSplittablePos(reg_use_backup, current);
+ CHECK(alternate.IsValid());
+ }
}
+ auto tail = SplitRangeAt(current, alternate);
+ Enqueue(tail);
+ Enqueue(current);
}
@@ -2860,7 +3087,6 @@ void SpillSlotLocator::LocateSpillSlots() {
bool GreedyAllocator::TryReuseSpillForPhi(LiveRange* range) {
if (range->IsChild() || !range->is_phi()) return false;
DCHECK(!range->HasSpillOperand());
-
auto phi_map_value = data()->GetPhiMapValueFor(range->id());
auto phi = phi_map_value->phi();
auto block = phi_map_value->block();
@@ -3320,6 +3546,7 @@ void LiveRangeConnector::ResolveControlFlow(const InstructionBlock* block,
void LiveRangeConnector::ConnectRanges(Zone* local_zone) {
DelayedInsertionMap delayed_insertion_map(local_zone);
+ unsigned moves_counter = 0;
for (auto first_range : data()->live_ranges()) {
if (first_range == nullptr || first_range->IsChild()) continue;
for (auto second_range = first_range->next(); second_range != nullptr;
@@ -3351,6 +3578,7 @@ void LiveRangeConnector::ConnectRanges(Zone* local_zone) {
}
auto move = code()->InstructionAt(gap_index)->GetOrCreateParallelMove(
gap_pos, code_zone());
+ moves_counter++;
if (!delay_insertion) {
move->AddMove(prev_operand, cur_operand);
} else {
@@ -3359,6 +3587,10 @@ void LiveRangeConnector::ConnectRanges(Zone* local_zone) {
}
}
}
+ if (FLAG_greedy_stats) {
+ OFStream os(stdout);
+ os << "Moves: " << moves_counter << std::endl;
+ }
if (delayed_insertion_map.empty()) return;
// Insert all the moves which should occur after the stored move.
ZoneVector<MoveOperands*> to_insert(local_zone);
@@ -3390,6 +3622,7 @@ void LiveRangeConnector::ConnectRanges(Zone* local_zone) {
}
}
+ // #include "../prints.inc"
Jarin 2015/05/13 13:12:56 Remove this line.
} // namespace compiler
} // namespace internal

Powered by Google App Engine
This is Rietveld 408576698