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

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

Issue 1391023007: [turbofan] Splinter into one range. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Created 5 years, 2 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/register-allocator.h ('k') | test/unittests/compiler/live-range-unittest.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/compiler/register-allocator.cc
diff --git a/src/compiler/register-allocator.cc b/src/compiler/register-allocator.cc
index da67221621a0d3c36bbf0d2fd1802b9a2562b92c..1dea881fe2b0b19dd00a0ef52a983cf7e145eaa7 100644
--- a/src/compiler/register-allocator.cc
+++ b/src/compiler/register-allocator.cc
@@ -698,7 +698,8 @@ TopLevelLiveRange::TopLevelLiveRange(int vreg, MachineType machine_type)
spilled_in_deferred_blocks_(false),
spill_start_index_(kMaxInt),
last_child_(this),
- last_insertion_point_(this) {
+ last_pos_(nullptr),
+ splinter_(nullptr) {
bits_ |= SpillTypeField::encode(SpillType::kNoSpillType);
}
@@ -845,12 +846,12 @@ AllocatedOperand TopLevelLiveRange::GetSpillRangeOperand() const {
void TopLevelLiveRange::Splinter(LifetimePosition start, LifetimePosition end,
- TopLevelLiveRange* result, Zone* zone) {
+ Zone* zone) {
DCHECK(start != Start() || end != End());
DCHECK(start < end);
- result->set_spill_type(spill_type());
-
+ TopLevelLiveRange splinter_temp(-1, machine_type());
+ UsePosition* last_in_splinter = nullptr;
if (start <= Start()) {
// TODO(mtrofin): here, the TopLevel part is in the deferred range, so we
// may want to continue processing the splinter. However, if the value is
@@ -859,21 +860,21 @@ void TopLevelLiveRange::Splinter(LifetimePosition start, LifetimePosition end,
// should check this, however, this may not be the place, because we don't
// have access to the instruction sequence.
DCHECK(end < End());
- DetachAt(end, result, zone);
+ DetachAt(end, &splinter_temp, zone);
next_ = nullptr;
} else if (end >= End()) {
DCHECK(start > Start());
- DetachAt(start, result, zone);
+ DetachAt(start, &splinter_temp, zone);
next_ = nullptr;
} else {
DCHECK(start < End() && Start() < end);
const int kInvalidId = std::numeric_limits<int>::max();
- UsePosition* last = DetachAt(start, result, zone);
+ UsePosition* last = DetachAt(start, &splinter_temp, zone);
LiveRange end_part(kInvalidId, this->machine_type(), nullptr);
- result->DetachAt(end, &end_part, zone);
+ last_in_splinter = splinter_temp.DetachAt(end, &end_part, zone);
next_ = end_part.next_;
last_interval_->set_next(end_part.first_interval_);
@@ -890,20 +891,39 @@ void TopLevelLiveRange::Splinter(LifetimePosition start, LifetimePosition end,
if (last != nullptr) last->set_next(end_part.first_pos_);
}
}
- result->next_ = nullptr;
- result->top_level_ = result;
- result->SetSplinteredFrom(this);
- // Ensure the result's relative ID is unique within the IDs used for this
- // virtual register's children and splinters.
- result->relative_id_ = GetNextChildId();
+ if (splinter()->IsEmpty()) {
+ splinter()->first_interval_ = splinter_temp.first_interval_;
+ splinter()->last_interval_ = splinter_temp.last_interval_;
+ } else {
+ splinter()->last_interval_->set_next(splinter_temp.first_interval_);
+ splinter()->last_interval_ = splinter_temp.last_interval_;
+ }
+ if (splinter()->first_pos() == nullptr) {
+ splinter()->first_pos_ = splinter_temp.first_pos_;
+ } else {
+ splinter()->last_pos_->set_next(splinter_temp.first_pos_);
+ }
+ if (last_in_splinter != nullptr) {
+ splinter()->last_pos_ = last_in_splinter;
+ } else {
+ if (splinter()->first_pos() != nullptr &&
+ splinter()->last_pos_ == nullptr) {
+ splinter()->last_pos_ = splinter()->first_pos();
+ for (UsePosition* pos = splinter()->first_pos(); pos != nullptr;
+ pos = pos->next()) {
+ splinter()->last_pos_ = pos;
+ }
+ }
+ }
+#if DEBUG
+ Verify();
+ splinter()->Verify();
+#endif
}
void TopLevelLiveRange::SetSplinteredFrom(TopLevelLiveRange* splinter_parent) {
- // The splinter parent is always the original "Top".
- DCHECK(splinter_parent->Start() < Start());
-
splintered_from_ = splinter_parent;
if (!HasSpillOperand() && splinter_parent->spill_range_ != nullptr) {
SetSpillRange(splinter_parent->spill_range_);
@@ -928,43 +948,55 @@ void TopLevelLiveRange::Merge(TopLevelLiveRange* other, Zone* zone) {
DCHECK(Start() < other->Start());
DCHECK(other->splintered_from() == this);
- LiveRange* last_other = other->last_child();
- LiveRange* last_me = last_child();
-
- // Simple case: we just append at the end.
- if (last_me->End() <= other->Start()) return last_me->AppendAsChild(other);
+ LiveRange* first = this;
+ LiveRange* second = other;
+ DCHECK(first->Start() < second->Start());
+ while (first != nullptr && second != nullptr) {
+ DCHECK(first != second);
+ // Make sure the ranges are in order each time we iterate.
+ if (second->Start() < first->Start()) {
+ LiveRange* tmp = second;
+ second = first;
+ first = tmp;
+ continue;
+ }
- DCHECK(last_me->End() > last_other->End());
+ if (first->End() <= second->Start()) {
+ if (first->next() == nullptr ||
+ first->next()->Start() > second->Start()) {
+ // First is in order before second.
+ LiveRange* temp = first->next();
+ first->next_ = second;
+ first = temp;
+ } else {
+ // First is in order before its successor (or second), so advance first.
+ first = first->next();
+ }
+ continue;
+ }
- // In the more general case, we need to find the ranges between which to
- // insert.
- if (other->Start() < last_insertion_point_->Start()) {
- last_insertion_point_ = this;
- }
+ DCHECK(first->Start() < second->Start());
+ // If first and second intersect, split first.
+ if (first->Start() < second->End() && second->Start() < first->End()) {
+ LiveRange* temp = first->SplitAt(second->Start(), zone);
Benedikt Meurer 2015/10/15 13:26:54 I ran into an endless loop here with stress varian
- for (; last_insertion_point_->next() != nullptr &&
- last_insertion_point_->next()->Start() <= other->Start();
- last_insertion_point_ = last_insertion_point_->next()) {
- }
+ temp->set_spilled(first->spilled());
+ if (!temp->spilled())
+ temp->set_assigned_register(first->assigned_register());
- // When we splintered the original range, we reconstituted the original range
- // into one range without children, but with discontinuities. To merge the
- // splinter back in, we need to split the range - or a child obtained after
- // register allocation splitting.
- LiveRange* after = last_insertion_point_->next();
- if (last_insertion_point_->End() > other->Start()) {
- LiveRange* new_after = last_insertion_point_->SplitAt(other->Start(), zone);
- new_after->set_spilled(last_insertion_point_->spilled());
- if (!new_after->spilled())
- new_after->set_assigned_register(
- last_insertion_point_->assigned_register());
- after = new_after;
+ first->next_ = second;
+ first = temp;
+ continue;
+ }
+ DCHECK(first->End() <= second->Start());
}
- last_other->next_ = after;
- last_insertion_point_->next_ = other;
- other->UpdateParentForAllChildren(TopLevel());
+ TopLevel()->UpdateParentForAllChildren(TopLevel());
TopLevel()->UpdateSpillRangePostMerge(other);
+
+#if DEBUG
+ Verify();
+#endif
}
« no previous file with comments | « src/compiler/register-allocator.h ('k') | test/unittests/compiler/live-range-unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698