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 |