| Index: src/compiler/register-allocator.cc
|
| diff --git a/src/compiler/register-allocator.cc b/src/compiler/register-allocator.cc
|
| index da67221621a0d3c36bbf0d2fd1802b9a2562b92c..2f6406681fc38d6e9009304565b51d8c5d81c92d 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);
|
| -
|
| - DCHECK(last_me->End() > last_other->End());
|
| + 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;
|
| + }
|
|
|
| - // 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;
|
| - }
|
| + 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;
|
| + }
|
|
|
| - for (; last_insertion_point_->next() != nullptr &&
|
| - last_insertion_point_->next()->Start() <= other->Start();
|
| - last_insertion_point_ = last_insertion_point_->next()) {
|
| - }
|
| + 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);
|
| + CHECK(temp != first);
|
| + 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
|
| }
|
|
|
|
|
|
|