| OLD | NEW |
| 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2013, 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 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 65 static intptr_t ToInstructionStart(intptr_t pos) { | 65 static intptr_t ToInstructionStart(intptr_t pos) { |
| 66 return (pos & ~1); | 66 return (pos & ~1); |
| 67 } | 67 } |
| 68 | 68 |
| 69 | 69 |
| 70 static intptr_t ToInstructionEnd(intptr_t pos) { | 70 static intptr_t ToInstructionEnd(intptr_t pos) { |
| 71 return (pos | 1); | 71 return (pos | 1); |
| 72 } | 72 } |
| 73 | 73 |
| 74 | 74 |
| 75 FlowGraphAllocator::FlowGraphAllocator(const FlowGraph& flow_graph) | 75 FlowGraphAllocator::FlowGraphAllocator(const FlowGraph& flow_graph, |
| 76 bool intrinsic_mode) |
| 76 : flow_graph_(flow_graph), | 77 : flow_graph_(flow_graph), |
| 77 reaching_defs_(flow_graph), | 78 reaching_defs_(flow_graph), |
| 78 value_representations_(flow_graph.max_virtual_register_number()), | 79 value_representations_(flow_graph.max_virtual_register_number()), |
| 79 block_order_(flow_graph.reverse_postorder()), | 80 block_order_(flow_graph.reverse_postorder()), |
| 80 postorder_(flow_graph.postorder()), | 81 postorder_(flow_graph.postorder()), |
| 81 liveness_(flow_graph), | 82 liveness_(flow_graph), |
| 82 vreg_count_(flow_graph.max_virtual_register_number()), | 83 vreg_count_(flow_graph.max_virtual_register_number()), |
| 83 live_ranges_(flow_graph.max_virtual_register_number()), | 84 live_ranges_(flow_graph.max_virtual_register_number()), |
| 84 cpu_regs_(), | 85 cpu_regs_(), |
| 85 fpu_regs_(), | 86 fpu_regs_(), |
| 86 blocked_cpu_registers_(), | 87 blocked_cpu_registers_(), |
| 87 blocked_fpu_registers_(), | 88 blocked_fpu_registers_(), |
| 88 number_of_registers_(0), | 89 number_of_registers_(0), |
| 89 registers_(), | 90 registers_(), |
| 90 blocked_registers_(), | 91 blocked_registers_(), |
| 91 cpu_spill_slot_count_(0) { | 92 cpu_spill_slot_count_(0), |
| 93 intrinsic_mode_(intrinsic_mode) { |
| 92 for (intptr_t i = 0; i < vreg_count_; i++) { | 94 for (intptr_t i = 0; i < vreg_count_; i++) { |
| 93 live_ranges_.Add(NULL); | 95 live_ranges_.Add(NULL); |
| 94 } | 96 } |
| 95 for (intptr_t i = 0; i < vreg_count_; i++) { | 97 for (intptr_t i = 0; i < vreg_count_; i++) { |
| 96 value_representations_.Add(kNoRepresentation); | 98 value_representations_.Add(kNoRepresentation); |
| 97 } | 99 } |
| 98 | 100 |
| 99 // All registers are marked as "not blocked" (array initialized to false). | 101 // All registers are marked as "not blocked" (array initialized to false). |
| 100 // Mark the unavailable ones as "blocked" (true). | 102 // Mark the unavailable ones as "blocked" (true). |
| 101 for (intptr_t i = 0; i < kFirstFreeCpuRegister; i++) { | 103 for (intptr_t i = 0; i < kFirstFreeCpuRegister; i++) { |
| (...skipping 10 matching lines...) Expand all Loading... |
| 112 blocked_cpu_registers_[TMP2] = true; | 114 blocked_cpu_registers_[TMP2] = true; |
| 113 } | 115 } |
| 114 if (PP != kNoRegister) { | 116 if (PP != kNoRegister) { |
| 115 blocked_cpu_registers_[PP] = true; | 117 blocked_cpu_registers_[PP] = true; |
| 116 } | 118 } |
| 117 blocked_cpu_registers_[SPREG] = true; | 119 blocked_cpu_registers_[SPREG] = true; |
| 118 blocked_cpu_registers_[FPREG] = true; | 120 blocked_cpu_registers_[FPREG] = true; |
| 119 | 121 |
| 120 // FpuTMP is used as scratch by optimized code and parallel move resolver. | 122 // FpuTMP is used as scratch by optimized code and parallel move resolver. |
| 121 blocked_fpu_registers_[FpuTMP] = true; | 123 blocked_fpu_registers_[FpuTMP] = true; |
| 124 |
| 125 // Block additional registers needed preserved when generating intrinsics. |
| 126 // TODO(fschneider): Handle saving and restoring these registers when |
| 127 // generating intrinsic code. |
| 128 if (intrinsic_mode) { |
| 129 blocked_cpu_registers_[ICREG] = true; |
| 130 blocked_cpu_registers_[ARGS_DESC_REG] = true; |
| 131 } |
| 122 } | 132 } |
| 123 | 133 |
| 124 | 134 |
| 125 static void DeepLiveness(MaterializeObjectInstr* mat, BitVector* live_in) { | 135 static void DeepLiveness(MaterializeObjectInstr* mat, BitVector* live_in) { |
| 126 if (mat->was_visited_for_liveness()) { | 136 if (mat->was_visited_for_liveness()) { |
| 127 return; | 137 return; |
| 128 } | 138 } |
| 129 mat->mark_visited_for_liveness(); | 139 mat->mark_visited_for_liveness(); |
| 130 | 140 |
| 131 for (intptr_t i = 0; i < mat->InputCount(); i++) { | 141 for (intptr_t i = 0; i < mat->InputCount(); i++) { |
| (...skipping 474 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 606 LiveRange* range, | 616 LiveRange* range, |
| 607 BlockEntryInstr* block) { | 617 BlockEntryInstr* block) { |
| 608 // Save the range end because it may change below. | 618 // Save the range end because it may change below. |
| 609 intptr_t range_end = range->End(); | 619 intptr_t range_end = range->End(); |
| 610 if (defn->IsParameter()) { | 620 if (defn->IsParameter()) { |
| 611 ParameterInstr* param = defn->AsParameter(); | 621 ParameterInstr* param = defn->AsParameter(); |
| 612 // Assert that copied and non-copied parameters are mutually exclusive. | 622 // Assert that copied and non-copied parameters are mutually exclusive. |
| 613 // This might change in the future and, if so, the index will be wrong. | 623 // This might change in the future and, if so, the index will be wrong. |
| 614 ASSERT((flow_graph_.num_copied_params() == 0) || | 624 ASSERT((flow_graph_.num_copied_params() == 0) || |
| 615 (flow_graph_.num_non_copied_params() == 0)); | 625 (flow_graph_.num_non_copied_params() == 0)); |
| 616 // Slot index for the leftmost copied parameter is 0. | |
| 617 intptr_t slot_index = param->index(); | 626 intptr_t slot_index = param->index(); |
| 618 // Slot index for the rightmost fixed parameter is -1. | 627 ASSERT(param->base_reg() == FPREG || param->base_reg() == SPREG); |
| 619 slot_index -= flow_graph_.num_non_copied_params(); | 628 if (param->base_reg() == FPREG) { |
| 629 // Slot index for the leftmost copied parameter is 0. |
| 630 // Slot index for the rightmost fixed parameter is -1. |
| 631 slot_index -= flow_graph_.num_non_copied_params(); |
| 632 } |
| 620 | 633 |
| 621 range->set_assigned_location(Location::StackSlot(slot_index)); | 634 range->set_assigned_location(Location::StackSlot(slot_index, |
| 622 range->set_spill_slot(Location::StackSlot(slot_index)); | 635 param->base_reg())); |
| 636 range->set_spill_slot(Location::StackSlot(slot_index, |
| 637 param->base_reg())); |
| 623 } else { | 638 } else { |
| 624 ConstantInstr* constant = defn->AsConstant(); | 639 ConstantInstr* constant = defn->AsConstant(); |
| 625 ASSERT(constant != NULL); | 640 ASSERT(constant != NULL); |
| 626 range->set_assigned_location(Location::Constant(constant)); | 641 range->set_assigned_location(Location::Constant(constant)); |
| 627 range->set_spill_slot(Location::Constant(constant)); | 642 range->set_spill_slot(Location::Constant(constant)); |
| 628 } | 643 } |
| 629 AssignSafepoints(defn, range); | 644 AssignSafepoints(defn, range); |
| 630 range->finger()->Initialize(range); | 645 range->finger()->Initialize(range); |
| 631 UsePosition* use = | 646 UsePosition* use = |
| 632 range->finger()->FirstRegisterBeneficialUse(block->start_pos()); | 647 range->finger()->FirstRegisterBeneficialUse(block->start_pos()); |
| (...skipping 1128 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1761 LiveRange* FlowGraphAllocator::SplitBetween(LiveRange* range, | 1776 LiveRange* FlowGraphAllocator::SplitBetween(LiveRange* range, |
| 1762 intptr_t from, | 1777 intptr_t from, |
| 1763 intptr_t to) { | 1778 intptr_t to) { |
| 1764 TRACE_ALLOC(OS::Print("split v%" Pd " [%" Pd ", %" Pd | 1779 TRACE_ALLOC(OS::Print("split v%" Pd " [%" Pd ", %" Pd |
| 1765 ") between [%" Pd ", %" Pd ")\n", | 1780 ") between [%" Pd ", %" Pd ")\n", |
| 1766 range->vreg(), range->Start(), range->End(), from, to)); | 1781 range->vreg(), range->Start(), range->End(), from, to)); |
| 1767 | 1782 |
| 1768 intptr_t split_pos = kIllegalPosition; | 1783 intptr_t split_pos = kIllegalPosition; |
| 1769 | 1784 |
| 1770 BlockInfo* split_block = BlockInfoAt(to); | 1785 BlockInfo* split_block = BlockInfoAt(to); |
| 1771 if (from < split_block->entry()->lifetime_position()) { | 1786 if (from < split_block->entry()->lifetime_position() && |
| 1787 split_block->loop() != NULL) { |
| 1772 // Interval [from, to) spans multiple blocks. | 1788 // Interval [from, to) spans multiple blocks. |
| 1773 | 1789 |
| 1774 // If last block is inside a loop prefer splitting at outermost loop's | 1790 // If last block is inside a loop prefer splitting at outermost loop's |
| 1775 // header. | 1791 // header. |
| 1776 BlockInfo* loop_header = split_block->loop(); | 1792 BlockInfo* loop_header = split_block->loop(); |
| 1777 while ((loop_header != NULL) && | 1793 while ((loop_header != NULL) && |
| 1778 (from < loop_header->entry()->lifetime_position())) { | 1794 (from < loop_header->entry()->lifetime_position())) { |
| 1779 split_block = loop_header; | 1795 split_block = loop_header; |
| 1780 loop_header = loop_header->loop(); | 1796 loop_header = loop_header->loop(); |
| 1781 } | 1797 } |
| (...skipping 833 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2615 const intptr_t start = range->Start(); | 2631 const intptr_t start = range->Start(); |
| 2616 TRACE_ALLOC(OS::Print("Processing live range for v%" Pd " " | 2632 TRACE_ALLOC(OS::Print("Processing live range for v%" Pd " " |
| 2617 "starting at %" Pd "\n", | 2633 "starting at %" Pd "\n", |
| 2618 range->vreg(), | 2634 range->vreg(), |
| 2619 start)); | 2635 start)); |
| 2620 | 2636 |
| 2621 // TODO(vegorov): eagerly spill liveranges without register uses. | 2637 // TODO(vegorov): eagerly spill liveranges without register uses. |
| 2622 AdvanceActiveIntervals(start); | 2638 AdvanceActiveIntervals(start); |
| 2623 | 2639 |
| 2624 if (!AllocateFreeRegister(range)) { | 2640 if (!AllocateFreeRegister(range)) { |
| 2641 if (intrinsic_mode_) { |
| 2642 // No spilling when compiling intrinsics. |
| 2643 // TODO(fschneider): Handle spilling in intrinsics. For now, the |
| 2644 // IR has to be built so that there are enough free registers. |
| 2645 UNREACHABLE(); |
| 2646 } |
| 2625 AllocateAnyRegister(range); | 2647 AllocateAnyRegister(range); |
| 2626 } | 2648 } |
| 2627 } | 2649 } |
| 2628 | 2650 |
| 2629 // All allocation decisions were done. | 2651 // All allocation decisions were done. |
| 2630 ASSERT(unallocated_.is_empty()); | 2652 ASSERT(unallocated_.is_empty()); |
| 2631 | 2653 |
| 2632 // Finish allocation. | 2654 // Finish allocation. |
| 2633 AdvanceActiveIntervals(kMaxPosition); | 2655 AdvanceActiveIntervals(kMaxPosition); |
| 2634 TRACE_ALLOC(OS::Print("Allocation completed\n")); | 2656 TRACE_ALLOC(OS::Print("Allocation completed\n")); |
| (...skipping 282 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2917 OS::Print("-- [after ssa allocator] ir [%s] -------------\n", | 2939 OS::Print("-- [after ssa allocator] ir [%s] -------------\n", |
| 2918 function.ToFullyQualifiedCString()); | 2940 function.ToFullyQualifiedCString()); |
| 2919 FlowGraphPrinter printer(flow_graph_, true); | 2941 FlowGraphPrinter printer(flow_graph_, true); |
| 2920 printer.PrintBlocks(); | 2942 printer.PrintBlocks(); |
| 2921 OS::Print("----------------------------------------------\n"); | 2943 OS::Print("----------------------------------------------\n"); |
| 2922 } | 2944 } |
| 2923 } | 2945 } |
| 2924 | 2946 |
| 2925 | 2947 |
| 2926 } // namespace dart | 2948 } // namespace dart |
| OLD | NEW |