| Index: src/compiler/register-allocator.cc
|
| diff --git a/src/compiler/register-allocator.cc b/src/compiler/register-allocator.cc
|
| index 1de5773e7fefb59064bc83633bb231e430b008ce..d27519a9060c99da77d0967a0c35d57f57dd3f16 100644
|
| --- a/src/compiler/register-allocator.cc
|
| +++ b/src/compiler/register-allocator.cc
|
| @@ -1415,22 +1415,6 @@ void RegisterAllocator::ResolvePhis() {
|
| }
|
|
|
|
|
| -ParallelMove* RegisterAllocator::GetConnectingParallelMove(
|
| - LifetimePosition pos) {
|
| - int index = pos.InstructionIndex();
|
| - if (code()->IsGapAt(index)) {
|
| - auto gap = code()->GapAt(index);
|
| - return gap->GetOrCreateParallelMove(
|
| - pos.IsInstructionStart() ? GapInstruction::START : GapInstruction::END,
|
| - code_zone());
|
| - }
|
| - int gap_pos = pos.IsInstructionStart() ? (index - 1) : (index + 1);
|
| - return code()->GapAt(gap_pos)->GetOrCreateParallelMove(
|
| - (gap_pos < index) ? GapInstruction::AFTER : GapInstruction::START,
|
| - code_zone());
|
| -}
|
| -
|
| -
|
| const InstructionBlock* RegisterAllocator::GetInstructionBlock(
|
| LifetimePosition pos) {
|
| return code()->GetInstructionBlock(pos.InstructionIndex());
|
| @@ -1438,33 +1422,74 @@ const InstructionBlock* RegisterAllocator::GetInstructionBlock(
|
|
|
|
|
| void RegisterAllocator::ConnectRanges() {
|
| + ZoneMap<std::pair<ParallelMove*, InstructionOperand*>, InstructionOperand*>
|
| + delayed_insertion_map(local_zone());
|
| for (auto first_range : live_ranges()) {
|
| if (first_range == nullptr || first_range->IsChild()) continue;
|
| - auto second_range = first_range->next();
|
| - while (second_range != nullptr) {
|
| + for (auto second_range = first_range->next(); second_range != nullptr;
|
| + first_range = second_range, second_range = second_range->next()) {
|
| auto pos = second_range->Start();
|
| - if (!second_range->IsSpilled()) {
|
| - // Add gap move if the two live ranges touch and there is no block
|
| - // boundary.
|
| - if (first_range->End().Value() == pos.Value()) {
|
| - bool should_insert = true;
|
| - if (IsBlockBoundary(pos)) {
|
| - should_insert =
|
| - CanEagerlyResolveControlFlow(GetInstructionBlock(pos));
|
| - }
|
| - if (should_insert) {
|
| - auto move = GetConnectingParallelMove(pos);
|
| - auto prev_operand =
|
| - first_range->GetAssignedOperand(operand_cache());
|
| - auto cur_operand =
|
| - second_range->GetAssignedOperand(operand_cache());
|
| - move->AddMove(prev_operand, cur_operand, code_zone());
|
| - }
|
| - }
|
| + // Add gap move if the two live ranges touch and there is no block
|
| + // boundary.
|
| + if (second_range->IsSpilled()) continue;
|
| + if (first_range->End().Value() != pos.Value()) continue;
|
| + if (IsBlockBoundary(pos) &&
|
| + !CanEagerlyResolveControlFlow(GetInstructionBlock(pos))) {
|
| + continue;
|
| + }
|
| + auto prev_operand = first_range->GetAssignedOperand(operand_cache());
|
| + auto cur_operand = second_range->GetAssignedOperand(operand_cache());
|
| + if (prev_operand->Equals(cur_operand)) continue;
|
| + int index = pos.InstructionIndex();
|
| + bool delay_insertion = false;
|
| + GapInstruction::InnerPosition gap_pos;
|
| + int gap_index = index;
|
| + if (code()->IsGapAt(index)) {
|
| + gap_pos = pos.IsInstructionStart() ? GapInstruction::START
|
| + : GapInstruction::END;
|
| + } else {
|
| + gap_index = pos.IsInstructionStart() ? (index - 1) : (index + 1);
|
| + delay_insertion = gap_index < index;
|
| + gap_pos = delay_insertion ? GapInstruction::END : GapInstruction::START;
|
| + }
|
| + auto move = code()->GapAt(gap_index)->GetOrCreateParallelMove(
|
| + gap_pos, code_zone());
|
| + if (!delay_insertion) {
|
| + move->AddMove(prev_operand, cur_operand, code_zone());
|
| + } else {
|
| + delayed_insertion_map.insert(
|
| + std::make_pair(std::make_pair(move, prev_operand), cur_operand));
|
| + }
|
| + }
|
| + }
|
| + if (delayed_insertion_map.empty()) return;
|
| + // Insert all the moves which should occur after the stored move.
|
| + ZoneVector<MoveOperands> to_insert(local_zone());
|
| + ZoneVector<MoveOperands*> to_eliminate(local_zone());
|
| + to_insert.reserve(4);
|
| + to_eliminate.reserve(4);
|
| + auto move = delayed_insertion_map.begin()->first.first;
|
| + for (auto it = delayed_insertion_map.begin();; ++it) {
|
| + bool done = it == delayed_insertion_map.end();
|
| + if (done || it->first.first != move) {
|
| + // Commit the MoveOperands for current ParallelMove.
|
| + for (auto move_ops : to_eliminate) {
|
| + move_ops->Eliminate();
|
| + }
|
| + for (auto move_ops : to_insert) {
|
| + move->AddMove(move_ops.source(), move_ops.destination(), code_zone());
|
| }
|
| - first_range = second_range;
|
| - second_range = second_range->next();
|
| + if (done) break;
|
| + // Reset state.
|
| + to_eliminate.clear();
|
| + to_insert.clear();
|
| + move = it->first.first;
|
| }
|
| + // Gather all MoveOperands for a single ParallelMove.
|
| + MoveOperands move_ops(it->first.second, it->second);
|
| + auto eliminate = move->PrepareInsertAfter(&move_ops);
|
| + to_insert.push_back(move_ops);
|
| + if (eliminate != nullptr) to_eliminate.push_back(eliminate);
|
| }
|
| }
|
|
|
|
|