| OLD | NEW |
| 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file |
| 2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
| 3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
| 4 | 4 |
| 5 #include "vm/flow_graph_allocator.h" | 5 #include "vm/flow_graph_allocator.h" |
| 6 | 6 |
| 7 #include "vm/bit_vector.h" | 7 #include "vm/bit_vector.h" |
| 8 #include "vm/intermediate_language.h" | 8 #include "vm/intermediate_language.h" |
| 9 #include "vm/il_printer.h" | 9 #include "vm/il_printer.h" |
| 10 #include "vm/flow_graph.h" | 10 #include "vm/flow_graph.h" |
| (...skipping 562 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 573 UsePosition* use = | 573 UsePosition* use = |
| 574 range->finger()->FirstRegisterBeneficialUse(graph_entry->start_pos()); | 574 range->finger()->FirstRegisterBeneficialUse(graph_entry->start_pos()); |
| 575 if (use != NULL) { | 575 if (use != NULL) { |
| 576 LiveRange* tail = SplitBetween(range, graph_entry->start_pos(), use->pos()); | 576 LiveRange* tail = SplitBetween(range, graph_entry->start_pos(), use->pos()); |
| 577 CompleteRange(tail, Location::kRegister); | 577 CompleteRange(tail, Location::kRegister); |
| 578 } | 578 } |
| 579 ConvertAllUses(range); | 579 ConvertAllUses(range); |
| 580 } | 580 } |
| 581 | 581 |
| 582 | 582 |
| 583 static Location::Kind RegisterKindFromPolicy(Location loc) { |
| 584 if (loc.policy() == Location::kRequiresXmmRegister) { |
| 585 return Location::kXmmRegister; |
| 586 } else { |
| 587 return Location::kRegister; |
| 588 } |
| 589 } |
| 590 |
| 591 |
| 592 static Location::Kind RegisterKindForResult(Instruction* instr) { |
| 593 if (instr->representation() == kUnboxedDouble) { |
| 594 return Location::kXmmRegister; |
| 595 } else { |
| 596 return Location::kRegister; |
| 597 } |
| 598 } |
| 599 |
| 600 |
| 583 // | 601 // |
| 584 // When describing shape of live ranges in comments below we are going to use | 602 // When describing shape of live ranges in comments below we are going to use |
| 585 // the following notation: | 603 // the following notation: |
| 586 // | 604 // |
| 587 // B block entry | 605 // B block entry |
| 588 // g g' start and end of goto instruction | 606 // g g' start and end of goto instruction |
| 589 // i i' start and end of any other instruction | 607 // i i' start and end of any other instruction |
| 590 // j j' start and end of any other instruction | 608 // j j' start and end of any other instruction |
| 591 | 609 |
| 592 // - body of a use interval | 610 // - body of a use interval |
| (...skipping 100 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 693 MoveOperands* move = | 711 MoveOperands* move = |
| 694 goto_instr->parallel_move()->MoveOperandsAt(move_idx); | 712 goto_instr->parallel_move()->MoveOperandsAt(move_idx); |
| 695 move->set_dest(Location::PrefersRegister()); | 713 move->set_dest(Location::PrefersRegister()); |
| 696 range->AddUse(pos, move->dest_slot()); | 714 range->AddUse(pos, move->dest_slot()); |
| 697 } | 715 } |
| 698 | 716 |
| 699 // All phi resolution moves are connected. Phi's live range is | 717 // All phi resolution moves are connected. Phi's live range is |
| 700 // complete. | 718 // complete. |
| 701 AssignSafepoints(range); | 719 AssignSafepoints(range); |
| 702 | 720 |
| 703 // TODO(vegorov): unboxed double phis. | 721 CompleteRange(range, RegisterKindForResult(phi)); |
| 704 CompleteRange(range, Location::kRegister); | |
| 705 | 722 |
| 706 move_idx++; | 723 move_idx++; |
| 707 } | 724 } |
| 708 } | 725 } |
| 709 } | 726 } |
| 710 | 727 |
| 711 | 728 |
| 712 void FlowGraphAllocator::ProcessEnvironmentUses(BlockEntryInstr* block, | 729 void FlowGraphAllocator::ProcessEnvironmentUses(BlockEntryInstr* block, |
| 713 Instruction* current) { | 730 Instruction* current) { |
| 714 ASSERT(current->env() != NULL); | 731 ASSERT(current->env() != NULL); |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 746 const intptr_t vreg = def->ssa_temp_index(); | 763 const intptr_t vreg = def->ssa_temp_index(); |
| 747 LiveRange* range = GetLiveRange(vreg); | 764 LiveRange* range = GetLiveRange(vreg); |
| 748 range->AddUseInterval(block_start_pos, use_pos); | 765 range->AddUseInterval(block_start_pos, use_pos); |
| 749 range->AddUse(use_pos, &locations[i]); | 766 range->AddUse(use_pos, &locations[i]); |
| 750 } | 767 } |
| 751 | 768 |
| 752 env->set_locations(locations); | 769 env->set_locations(locations); |
| 753 } | 770 } |
| 754 | 771 |
| 755 | 772 |
| 756 static Location::Kind RegisterKindFromPolicy(Location loc) { | |
| 757 if (loc.policy() == Location::kRequiresXmmRegister) { | |
| 758 return Location::kXmmRegister; | |
| 759 } else { | |
| 760 return Location::kRegister; | |
| 761 } | |
| 762 } | |
| 763 | |
| 764 | |
| 765 static Location::Kind RegisterKindForResult(Instruction* instr) { | |
| 766 if (instr->representation() == kUnboxedDouble) { | |
| 767 return Location::kXmmRegister; | |
| 768 } else { | |
| 769 return Location::kRegister; | |
| 770 } | |
| 771 } | |
| 772 | |
| 773 | |
| 774 // Create and update live ranges corresponding to instruction's inputs, | 773 // Create and update live ranges corresponding to instruction's inputs, |
| 775 // temporaries and output. | 774 // temporaries and output. |
| 776 void FlowGraphAllocator::ProcessOneInstruction(BlockEntryInstr* block, | 775 void FlowGraphAllocator::ProcessOneInstruction(BlockEntryInstr* block, |
| 777 Instruction* current) { | 776 Instruction* current) { |
| 778 const intptr_t pos = current->lifetime_position(); | 777 const intptr_t pos = current->lifetime_position(); |
| 779 ASSERT(IsInstructionStartPosition(pos)); | 778 ASSERT(IsInstructionStartPosition(pos)); |
| 780 | 779 |
| 781 LocationSummary* locs = current->locs(); | 780 LocationSummary* locs = current->locs(); |
| 782 | 781 |
| 783 // Number of input locations and number of input operands have to agree. | 782 // Number of input locations and number of input operands have to agree. |
| (...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 864 // i i' | 863 // i i' |
| 865 // [--) | 864 // [--) |
| 866 // | 865 // |
| 867 // The stack bitmap describes the position i. | 866 // The stack bitmap describes the position i. |
| 868 for (intptr_t reg = 0; reg < kNumberOfCpuRegisters; reg++) { | 867 for (intptr_t reg = 0; reg < kNumberOfCpuRegisters; reg++) { |
| 869 BlockLocation(Location::RegisterLocation(static_cast<Register>(reg)), | 868 BlockLocation(Location::RegisterLocation(static_cast<Register>(reg)), |
| 870 pos, | 869 pos, |
| 871 pos + 1); | 870 pos + 1); |
| 872 } | 871 } |
| 873 | 872 |
| 873 for (intptr_t reg = 0; reg < kNumberOfXmmRegisters; reg++) { |
| 874 BlockLocation( |
| 875 Location::XmmRegisterLocation(static_cast<XmmRegister>(reg)), |
| 876 pos, |
| 877 pos + 1); |
| 878 } |
| 879 |
| 880 |
| 874 #if defined(DEBUG) | 881 #if defined(DEBUG) |
| 875 // Verify that temps, inputs and output were specified as fixed | 882 // Verify that temps, inputs and output were specified as fixed |
| 876 // locations. Every register is blocked now so attempt to | 883 // locations. Every register is blocked now so attempt to |
| 877 // allocate will not succeed. | 884 // allocate will not succeed. |
| 878 for (intptr_t j = 0; j < locs->temp_count(); j++) { | 885 for (intptr_t j = 0; j < locs->temp_count(); j++) { |
| 879 ASSERT(!locs->temp(j).IsUnallocated()); | 886 ASSERT(!locs->temp(j).IsUnallocated()); |
| 880 } | 887 } |
| 881 | 888 |
| 882 for (intptr_t j = 0; j < locs->input_count(); j++) { | 889 for (intptr_t j = 0; j < locs->input_count(); j++) { |
| 883 ASSERT(!locs->in(j).IsUnallocated()); | 890 ASSERT(!locs->in(j).IsUnallocated()); |
| (...skipping 297 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1181 return use; | 1188 return use; |
| 1182 } | 1189 } |
| 1183 | 1190 |
| 1184 | 1191 |
| 1185 UsePosition* AllocationFinger::FirstRegisterUse(intptr_t after) { | 1192 UsePosition* AllocationFinger::FirstRegisterUse(intptr_t after) { |
| 1186 for (UsePosition* use = FirstUseAfter(first_register_use_, after); | 1193 for (UsePosition* use = FirstUseAfter(first_register_use_, after); |
| 1187 use != NULL; | 1194 use != NULL; |
| 1188 use = use->next()) { | 1195 use = use->next()) { |
| 1189 Location* loc = use->location_slot(); | 1196 Location* loc = use->location_slot(); |
| 1190 if (loc->IsUnallocated() && | 1197 if (loc->IsUnallocated() && |
| 1191 (loc->policy() == Location::kRequiresRegister)) { | 1198 ((loc->policy() == Location::kRequiresRegister) || |
| 1199 (loc->policy() == Location::kRequiresXmmRegister))) { |
| 1192 first_register_use_ = use; | 1200 first_register_use_ = use; |
| 1193 return use; | 1201 return use; |
| 1194 } | 1202 } |
| 1195 } | 1203 } |
| 1196 return NULL; | 1204 return NULL; |
| 1197 } | 1205 } |
| 1198 | 1206 |
| 1199 | 1207 |
| 1200 UsePosition* AllocationFinger::FirstRegisterBeneficialUse(intptr_t after) { | 1208 UsePosition* AllocationFinger::FirstRegisterBeneficialUse(intptr_t after) { |
| 1201 for (UsePosition* use = FirstUseAfter(first_register_beneficial_use_, after); | 1209 for (UsePosition* use = FirstUseAfter(first_register_beneficial_use_, after); |
| (...skipping 225 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1427 LiveRange* last_sibling = range; | 1435 LiveRange* last_sibling = range; |
| 1428 while (last_sibling->next_sibling() != NULL) { | 1436 while (last_sibling->next_sibling() != NULL) { |
| 1429 last_sibling = last_sibling->next_sibling(); | 1437 last_sibling = last_sibling->next_sibling(); |
| 1430 } | 1438 } |
| 1431 | 1439 |
| 1432 spill_slots_[idx] = last_sibling->End(); | 1440 spill_slots_[idx] = last_sibling->End(); |
| 1433 | 1441 |
| 1434 if (register_kind_ == Location::kRegister) { | 1442 if (register_kind_ == Location::kRegister) { |
| 1435 range->set_spill_slot(Location::StackSlot(idx)); | 1443 range->set_spill_slot(Location::StackSlot(idx)); |
| 1436 } else { | 1444 } else { |
| 1445 // Double spill slots are essentially one (x64) or two (ia32) normal |
| 1446 // word size spill slots. We use the index of the slot with the lowest |
| 1447 // address as an index for the double spill slot. In terms of indexes |
| 1448 // this relation is inverted: so we have to take the highest index. |
| 1449 const intptr_t slot_idx = |
| 1450 idx * kDoubleSpillSlotFactor + (kDoubleSpillSlotFactor - 1); |
| 1437 range->set_spill_slot( | 1451 range->set_spill_slot( |
| 1438 Location::DoubleStackSlot( | 1452 Location::DoubleStackSlot( |
| 1439 cpu_spill_slot_count_ + idx * kDoubleSpillSlotFactor)); | 1453 cpu_spill_slot_count_ + slot_idx)); |
| 1440 } | 1454 } |
| 1441 | 1455 |
| 1442 spilled_.Add(range); | 1456 spilled_.Add(range); |
| 1443 } | 1457 } |
| 1444 | 1458 |
| 1445 | 1459 |
| 1446 void FlowGraphAllocator::MarkAsObjectAtSafepoints(LiveRange* range) { | 1460 void FlowGraphAllocator::MarkAsObjectAtSafepoints(LiveRange* range) { |
| 1447 intptr_t stack_index = range->spill_slot().stack_index(); | 1461 intptr_t stack_index = range->spill_slot().stack_index(); |
| 1448 ASSERT(stack_index >= 0); | 1462 ASSERT(stack_index >= 0); |
| 1449 | 1463 |
| (...skipping 217 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1667 | 1681 |
| 1668 | 1682 |
| 1669 void FlowGraphAllocator::AssignNonFreeRegister(LiveRange* unallocated, | 1683 void FlowGraphAllocator::AssignNonFreeRegister(LiveRange* unallocated, |
| 1670 intptr_t reg) { | 1684 intptr_t reg) { |
| 1671 intptr_t first_evicted = -1; | 1685 intptr_t first_evicted = -1; |
| 1672 for (intptr_t i = registers_[reg].length() - 1; i >= 0; i--) { | 1686 for (intptr_t i = registers_[reg].length() - 1; i >= 0; i--) { |
| 1673 LiveRange* allocated = registers_[reg][i]; | 1687 LiveRange* allocated = registers_[reg][i]; |
| 1674 if (allocated->vreg() < 0) continue; // Can't be evicted. | 1688 if (allocated->vreg() < 0) continue; // Can't be evicted. |
| 1675 if (EvictIntersection(allocated, unallocated)) { | 1689 if (EvictIntersection(allocated, unallocated)) { |
| 1676 // If allocated was not spilled convert all pending uses. | 1690 // If allocated was not spilled convert all pending uses. |
| 1677 if (allocated->assigned_location().IsRegister()) { | 1691 if (allocated->assigned_location().IsMachineRegister()) { |
| 1678 ASSERT(allocated->End() <= unallocated->Start()); | 1692 ASSERT(allocated->End() <= unallocated->Start()); |
| 1679 ConvertAllUses(allocated); | 1693 ConvertAllUses(allocated); |
| 1680 } | 1694 } |
| 1681 registers_[reg][i] = NULL; | 1695 registers_[reg][i] = NULL; |
| 1682 first_evicted = i; | 1696 first_evicted = i; |
| 1683 } | 1697 } |
| 1684 } | 1698 } |
| 1685 | 1699 |
| 1686 // Remove evicted ranges from the array. | 1700 // Remove evicted ranges from the array. |
| 1687 if (first_evicted != -1) RemoveEvicted(reg, first_evicted); | 1701 if (first_evicted != -1) RemoveEvicted(reg, first_evicted); |
| (...skipping 443 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2131 OS::Print("-- [after ssa allocator] ir [%s] -------------\n", | 2145 OS::Print("-- [after ssa allocator] ir [%s] -------------\n", |
| 2132 function.ToFullyQualifiedCString()); | 2146 function.ToFullyQualifiedCString()); |
| 2133 FlowGraphPrinter printer(flow_graph_, true); | 2147 FlowGraphPrinter printer(flow_graph_, true); |
| 2134 printer.PrintBlocks(); | 2148 printer.PrintBlocks(); |
| 2135 OS::Print("----------------------------------------------\n"); | 2149 OS::Print("----------------------------------------------\n"); |
| 2136 } | 2150 } |
| 2137 } | 2151 } |
| 2138 | 2152 |
| 2139 | 2153 |
| 2140 } // namespace dart | 2154 } // namespace dart |
| OLD | NEW |