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