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 |
} |