OLD | NEW |
1 // Copyright 2014 the V8 project authors. All rights reserved. | 1 // Copyright 2014 the V8 project authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "src/compiler/linkage.h" | 5 #include "src/compiler/linkage.h" |
6 #include "src/compiler/register-allocator.h" | 6 #include "src/compiler/register-allocator.h" |
7 #include "src/string-stream.h" | 7 #include "src/string-stream.h" |
8 | 8 |
9 namespace v8 { | 9 namespace v8 { |
10 namespace internal { | 10 namespace internal { |
(...skipping 1397 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1408 | 1408 |
1409 void RegisterAllocator::ResolvePhis() { | 1409 void RegisterAllocator::ResolvePhis() { |
1410 // Process the blocks in reverse order. | 1410 // Process the blocks in reverse order. |
1411 for (auto i = code()->instruction_blocks().rbegin(); | 1411 for (auto i = code()->instruction_blocks().rbegin(); |
1412 i != code()->instruction_blocks().rend(); ++i) { | 1412 i != code()->instruction_blocks().rend(); ++i) { |
1413 ResolvePhis(*i); | 1413 ResolvePhis(*i); |
1414 } | 1414 } |
1415 } | 1415 } |
1416 | 1416 |
1417 | 1417 |
1418 ParallelMove* RegisterAllocator::GetConnectingParallelMove( | |
1419 LifetimePosition pos) { | |
1420 int index = pos.InstructionIndex(); | |
1421 if (code()->IsGapAt(index)) { | |
1422 auto gap = code()->GapAt(index); | |
1423 return gap->GetOrCreateParallelMove( | |
1424 pos.IsInstructionStart() ? GapInstruction::START : GapInstruction::END, | |
1425 code_zone()); | |
1426 } | |
1427 int gap_pos = pos.IsInstructionStart() ? (index - 1) : (index + 1); | |
1428 return code()->GapAt(gap_pos)->GetOrCreateParallelMove( | |
1429 (gap_pos < index) ? GapInstruction::AFTER : GapInstruction::START, | |
1430 code_zone()); | |
1431 } | |
1432 | |
1433 | |
1434 const InstructionBlock* RegisterAllocator::GetInstructionBlock( | 1418 const InstructionBlock* RegisterAllocator::GetInstructionBlock( |
1435 LifetimePosition pos) { | 1419 LifetimePosition pos) { |
1436 return code()->GetInstructionBlock(pos.InstructionIndex()); | 1420 return code()->GetInstructionBlock(pos.InstructionIndex()); |
1437 } | 1421 } |
1438 | 1422 |
1439 | 1423 |
1440 void RegisterAllocator::ConnectRanges() { | 1424 void RegisterAllocator::ConnectRanges() { |
| 1425 ZoneMap<std::pair<ParallelMove*, InstructionOperand*>, InstructionOperand*> |
| 1426 delayed_insertion_map(local_zone()); |
1441 for (auto first_range : live_ranges()) { | 1427 for (auto first_range : live_ranges()) { |
1442 if (first_range == nullptr || first_range->IsChild()) continue; | 1428 if (first_range == nullptr || first_range->IsChild()) continue; |
1443 auto second_range = first_range->next(); | 1429 for (auto second_range = first_range->next(); second_range != nullptr; |
1444 while (second_range != nullptr) { | 1430 first_range = second_range, second_range = second_range->next()) { |
1445 auto pos = second_range->Start(); | 1431 auto pos = second_range->Start(); |
1446 if (!second_range->IsSpilled()) { | 1432 // Add gap move if the two live ranges touch and there is no block |
1447 // Add gap move if the two live ranges touch and there is no block | 1433 // boundary. |
1448 // boundary. | 1434 if (second_range->IsSpilled()) continue; |
1449 if (first_range->End().Value() == pos.Value()) { | 1435 if (first_range->End().Value() != pos.Value()) continue; |
1450 bool should_insert = true; | 1436 if (IsBlockBoundary(pos) && |
1451 if (IsBlockBoundary(pos)) { | 1437 !CanEagerlyResolveControlFlow(GetInstructionBlock(pos))) { |
1452 should_insert = | 1438 continue; |
1453 CanEagerlyResolveControlFlow(GetInstructionBlock(pos)); | |
1454 } | |
1455 if (should_insert) { | |
1456 auto move = GetConnectingParallelMove(pos); | |
1457 auto prev_operand = | |
1458 first_range->GetAssignedOperand(operand_cache()); | |
1459 auto cur_operand = | |
1460 second_range->GetAssignedOperand(operand_cache()); | |
1461 move->AddMove(prev_operand, cur_operand, code_zone()); | |
1462 } | |
1463 } | |
1464 } | 1439 } |
1465 first_range = second_range; | 1440 auto prev_operand = first_range->GetAssignedOperand(operand_cache()); |
1466 second_range = second_range->next(); | 1441 auto cur_operand = second_range->GetAssignedOperand(operand_cache()); |
| 1442 if (prev_operand->Equals(cur_operand)) continue; |
| 1443 int index = pos.InstructionIndex(); |
| 1444 bool delay_insertion = false; |
| 1445 GapInstruction::InnerPosition gap_pos; |
| 1446 int gap_index = index; |
| 1447 if (code()->IsGapAt(index)) { |
| 1448 gap_pos = pos.IsInstructionStart() ? GapInstruction::START |
| 1449 : GapInstruction::END; |
| 1450 } else { |
| 1451 gap_index = pos.IsInstructionStart() ? (index - 1) : (index + 1); |
| 1452 delay_insertion = gap_index < index; |
| 1453 gap_pos = delay_insertion ? GapInstruction::END : GapInstruction::START; |
| 1454 } |
| 1455 auto move = code()->GapAt(gap_index)->GetOrCreateParallelMove( |
| 1456 gap_pos, code_zone()); |
| 1457 if (!delay_insertion) { |
| 1458 move->AddMove(prev_operand, cur_operand, code_zone()); |
| 1459 } else { |
| 1460 delayed_insertion_map.insert( |
| 1461 std::make_pair(std::make_pair(move, prev_operand), cur_operand)); |
| 1462 } |
1467 } | 1463 } |
1468 } | 1464 } |
| 1465 if (delayed_insertion_map.empty()) return; |
| 1466 // Insert all the moves which should occur after the stored move. |
| 1467 ZoneVector<MoveOperands> to_insert(local_zone()); |
| 1468 ZoneVector<MoveOperands*> to_eliminate(local_zone()); |
| 1469 to_insert.reserve(4); |
| 1470 to_eliminate.reserve(4); |
| 1471 auto move = delayed_insertion_map.begin()->first.first; |
| 1472 for (auto it = delayed_insertion_map.begin();; ++it) { |
| 1473 bool done = it == delayed_insertion_map.end(); |
| 1474 if (done || it->first.first != move) { |
| 1475 // Commit the MoveOperands for current ParallelMove. |
| 1476 for (auto move_ops : to_eliminate) { |
| 1477 move_ops->Eliminate(); |
| 1478 } |
| 1479 for (auto move_ops : to_insert) { |
| 1480 move->AddMove(move_ops.source(), move_ops.destination(), code_zone()); |
| 1481 } |
| 1482 if (done) break; |
| 1483 // Reset state. |
| 1484 to_eliminate.clear(); |
| 1485 to_insert.clear(); |
| 1486 move = it->first.first; |
| 1487 } |
| 1488 // Gather all MoveOperands for a single ParallelMove. |
| 1489 MoveOperands move_ops(it->first.second, it->second); |
| 1490 auto eliminate = move->PrepareInsertAfter(&move_ops); |
| 1491 to_insert.push_back(move_ops); |
| 1492 if (eliminate != nullptr) to_eliminate.push_back(eliminate); |
| 1493 } |
1469 } | 1494 } |
1470 | 1495 |
1471 | 1496 |
1472 bool RegisterAllocator::CanEagerlyResolveControlFlow( | 1497 bool RegisterAllocator::CanEagerlyResolveControlFlow( |
1473 const InstructionBlock* block) const { | 1498 const InstructionBlock* block) const { |
1474 if (block->PredecessorCount() != 1) return false; | 1499 if (block->PredecessorCount() != 1) return false; |
1475 return block->predecessors()[0].IsNext(block->rpo_number()); | 1500 return block->predecessors()[0].IsNext(block->rpo_number()); |
1476 } | 1501 } |
1477 | 1502 |
1478 | 1503 |
(...skipping 1025 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2504 } else { | 2529 } else { |
2505 DCHECK(range->Kind() == GENERAL_REGISTERS); | 2530 DCHECK(range->Kind() == GENERAL_REGISTERS); |
2506 assigned_registers_->Add(reg); | 2531 assigned_registers_->Add(reg); |
2507 } | 2532 } |
2508 range->set_assigned_register(reg, operand_cache()); | 2533 range->set_assigned_register(reg, operand_cache()); |
2509 } | 2534 } |
2510 | 2535 |
2511 } // namespace compiler | 2536 } // namespace compiler |
2512 } // namespace internal | 2537 } // namespace internal |
2513 } // namespace v8 | 2538 } // namespace v8 |
OLD | NEW |