Index: src/compiler/register-allocator.cc |
diff --git a/src/compiler/register-allocator.cc b/src/compiler/register-allocator.cc |
index 49ae35b63da63e85a1be1a478182782f5b719286..fdd2538089cf521adb74b9620a44fb9e83f56326 100644 |
--- a/src/compiler/register-allocator.cc |
+++ b/src/compiler/register-allocator.cc |
@@ -3174,8 +3174,8 @@ namespace { |
class LiveRangeBound { |
public: |
- explicit LiveRangeBound(const LiveRange* range) |
- : range_(range), start_(range->Start()), end_(range->End()) { |
+ explicit LiveRangeBound(const LiveRange* range, bool skip) |
+ : range_(range), start_(range->Start()), end_(range->End()), skip_(skip) { |
DCHECK(!range->IsEmpty()); |
} |
@@ -3186,6 +3186,7 @@ class LiveRangeBound { |
const LiveRange* const range_; |
const LifetimePosition start_; |
const LifetimePosition end_; |
+ const bool skip_; |
private: |
DISALLOW_COPY_AND_ASSIGN(LiveRangeBound); |
@@ -3204,14 +3205,17 @@ class LiveRangeBoundArray { |
bool ShouldInitialize() { return start_ == nullptr; } |
- void Initialize(Zone* zone, const LiveRange* const range) { |
- size_t length = 0; |
- for (auto i = range; i != nullptr; i = i->next()) length++; |
- start_ = zone->NewArray<LiveRangeBound>(length); |
- length_ = length; |
- auto curr = start_; |
- for (auto i = range; i != nullptr; i = i->next(), ++curr) { |
- new (curr) LiveRangeBound(i); |
+ void Initialize(Zone* zone, const TopLevelLiveRange* const range) { |
+ length_ = range->GetChildCount(); |
+ |
+ start_ = zone->NewArray<LiveRangeBound>(length_); |
+ LiveRangeBound* curr = start_; |
+ // Normally, spilled ranges do not need connecting moves, because the spill |
+ // location has been assigned at definition. For ranges spilled in deferred |
+ // blocks, that is not the case, so we need to connect the spilled children. |
+ bool spilled_in_blocks = range->IsSpilledOnlyInDeferredBlocks(); |
+ for (const LiveRange *i = range; i != nullptr; i = i->next(), ++curr) { |
+ new (curr) LiveRangeBound(i, !spilled_in_blocks && i->spilled()); |
} |
} |
@@ -3244,21 +3248,29 @@ class LiveRangeBoundArray { |
return Find(succ_start); |
} |
- void Find(const InstructionBlock* block, const InstructionBlock* pred, |
- FindResult* result) const { |
- auto pred_end = LifetimePosition::InstructionFromInstructionIndex( |
- pred->last_instruction_index()); |
- auto bound = Find(pred_end); |
+ bool FindConnectableSubranges(const InstructionBlock* block, |
+ const InstructionBlock* pred, |
+ FindResult* result) const { |
+ LifetimePosition pred_end = |
+ LifetimePosition::InstructionFromInstructionIndex( |
+ pred->last_instruction_index()); |
+ LiveRangeBound* bound = Find(pred_end); |
result->pred_cover_ = bound->range_; |
- auto cur_start = LifetimePosition::GapFromInstructionIndex( |
+ LifetimePosition cur_start = LifetimePosition::GapFromInstructionIndex( |
block->first_instruction_index()); |
- // Common case. |
+ |
if (bound->CanCover(cur_start)) { |
- result->cur_cover_ = bound->range_; |
- return; |
+ // Both blocks are covered by the same range, so there is nothing to |
+ // connect. |
+ return false; |
+ } |
+ bound = Find(cur_start); |
+ if (bound->skip_) { |
+ return false; |
} |
- result->cur_cover_ = Find(cur_start)->range_; |
+ result->cur_cover_ = bound->range_; |
DCHECK(result->pred_cover_ != nullptr && result->cur_cover_ != nullptr); |
+ return (result->cur_cover_ != result->pred_cover_); |
} |
private: |
@@ -3346,11 +3358,9 @@ void LiveRangeConnector::ResolveControlFlow(Zone* local_zone) { |
for (auto pred : block->predecessors()) { |
FindResult result; |
const auto* pred_block = code()->InstructionBlockAt(pred); |
- array->Find(block, pred_block, &result); |
- if (result.cur_cover_ == result.pred_cover_ || |
- (!result.cur_cover_->TopLevel()->IsSpilledOnlyInDeferredBlocks() && |
- result.cur_cover_->spilled())) |
+ if (!array->FindConnectableSubranges(block, pred_block, &result)) { |
continue; |
+ } |
auto pred_op = result.pred_cover_->GetAssignedOperand(); |
auto cur_op = result.cur_cover_->GetAssignedOperand(); |
if (pred_op.Equals(cur_op)) continue; |