Chromium Code Reviews| 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_[ARGS_DESC_REG] = true; | |
| 130 } | |
| 122 } | 131 } |
| 123 | 132 |
| 124 | 133 |
| 125 static void DeepLiveness(MaterializeObjectInstr* mat, BitVector* live_in) { | 134 static void DeepLiveness(MaterializeObjectInstr* mat, BitVector* live_in) { |
| 126 if (mat->was_visited_for_liveness()) { | 135 if (mat->was_visited_for_liveness()) { |
| 127 return; | 136 return; |
| 128 } | 137 } |
| 129 mat->mark_visited_for_liveness(); | 138 mat->mark_visited_for_liveness(); |
| 130 | 139 |
| 131 for (intptr_t i = 0; i < mat->InputCount(); i++) { | 140 for (intptr_t i = 0; i < mat->InputCount(); i++) { |
| (...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 174 } | 183 } |
| 175 | 184 |
| 176 // Handle uses. | 185 // Handle uses. |
| 177 ASSERT(locs->input_count() == current->InputCount()); | 186 ASSERT(locs->input_count() == current->InputCount()); |
| 178 for (intptr_t j = 0; j < current->InputCount(); j++) { | 187 for (intptr_t j = 0; j < current->InputCount(); j++) { |
| 179 Value* input = current->InputAt(j); | 188 Value* input = current->InputAt(j); |
| 180 | 189 |
| 181 ASSERT(!locs->in(j).IsConstant() || input->BindsToConstant()); | 190 ASSERT(!locs->in(j).IsConstant() || input->BindsToConstant()); |
| 182 if (locs->in(j).IsConstant()) continue; | 191 if (locs->in(j).IsConstant()) continue; |
| 183 | 192 |
| 193 ASSERT(input->definition()->HasSSATemp()); | |
| 184 live_in->Add(input->definition()->ssa_temp_index()); | 194 live_in->Add(input->definition()->ssa_temp_index()); |
| 185 if (input->definition()->HasPairRepresentation()) { | 195 if (input->definition()->HasPairRepresentation()) { |
| 186 live_in->Add(ToSecondPairVreg(input->definition()->ssa_temp_index())); | 196 live_in->Add(ToSecondPairVreg(input->definition()->ssa_temp_index())); |
| 187 } | 197 } |
| 188 } | 198 } |
| 189 | 199 |
| 190 // Add non-argument uses from the deoptimization environment (pushed | 200 // Add non-argument uses from the deoptimization environment (pushed |
| 191 // arguments are not allocated by the register allocator). | 201 // arguments are not allocated by the register allocator). |
| 192 if (current->env() != NULL) { | 202 if (current->env() != NULL) { |
| 193 for (Environment::DeepIterator env_it(current->env()); | 203 for (Environment::DeepIterator env_it(current->env()); |
| (...skipping 415 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 609 LiveRange* range, | 619 LiveRange* range, |
| 610 BlockEntryInstr* block) { | 620 BlockEntryInstr* block) { |
| 611 // Save the range end because it may change below. | 621 // Save the range end because it may change below. |
| 612 intptr_t range_end = range->End(); | 622 intptr_t range_end = range->End(); |
| 613 if (defn->IsParameter()) { | 623 if (defn->IsParameter()) { |
| 614 ParameterInstr* param = defn->AsParameter(); | 624 ParameterInstr* param = defn->AsParameter(); |
| 615 // Assert that copied and non-copied parameters are mutually exclusive. | 625 // Assert that copied and non-copied parameters are mutually exclusive. |
| 616 // This might change in the future and, if so, the index will be wrong. | 626 // This might change in the future and, if so, the index will be wrong. |
| 617 ASSERT((flow_graph_.num_copied_params() == 0) || | 627 ASSERT((flow_graph_.num_copied_params() == 0) || |
| 618 (flow_graph_.num_non_copied_params() == 0)); | 628 (flow_graph_.num_non_copied_params() == 0)); |
| 619 // Slot index for the leftmost copied parameter is 0. | |
| 620 intptr_t slot_index = param->index(); | 629 intptr_t slot_index = param->index(); |
| 621 // Slot index for the rightmost fixed parameter is -1. | 630 ASSERT(param->base_reg() == FPREG || param->base_reg() == SPREG); |
| 622 slot_index -= flow_graph_.num_non_copied_params(); | 631 if (param->base_reg() == FPREG) { |
| 632 // Slot index for the leftmost copied parameter is 0. | |
| 633 // Slot index for the rightmost fixed parameter is -1. | |
| 634 slot_index -= flow_graph_.num_non_copied_params(); | |
| 635 } | |
| 623 | 636 |
| 624 range->set_assigned_location(Location::StackSlot(slot_index)); | 637 range->set_assigned_location(Location::StackSlot(slot_index, |
| 625 range->set_spill_slot(Location::StackSlot(slot_index)); | 638 param->base_reg())); |
| 639 range->set_spill_slot(Location::StackSlot(slot_index, | |
| 640 param->base_reg())); | |
| 626 } else { | 641 } else { |
| 627 ConstantInstr* constant = defn->AsConstant(); | 642 ConstantInstr* constant = defn->AsConstant(); |
| 628 ASSERT(constant != NULL); | 643 ASSERT(constant != NULL); |
| 629 range->set_assigned_location(Location::Constant(constant)); | 644 range->set_assigned_location(Location::Constant(constant)); |
| 630 range->set_spill_slot(Location::Constant(constant)); | 645 range->set_spill_slot(Location::Constant(constant)); |
| 631 } | 646 } |
| 632 AssignSafepoints(defn, range); | 647 AssignSafepoints(defn, range); |
| 633 range->finger()->Initialize(range); | 648 range->finger()->Initialize(range); |
| 634 UsePosition* use = | 649 UsePosition* use = |
| 635 range->finger()->FirstRegisterBeneficialUse(block->start_pos()); | 650 range->finger()->FirstRegisterBeneficialUse(block->start_pos()); |
| (...skipping 1128 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1764 LiveRange* FlowGraphAllocator::SplitBetween(LiveRange* range, | 1779 LiveRange* FlowGraphAllocator::SplitBetween(LiveRange* range, |
| 1765 intptr_t from, | 1780 intptr_t from, |
| 1766 intptr_t to) { | 1781 intptr_t to) { |
| 1767 TRACE_ALLOC(OS::Print("split v%" Pd " [%" Pd ", %" Pd | 1782 TRACE_ALLOC(OS::Print("split v%" Pd " [%" Pd ", %" Pd |
| 1768 ") between [%" Pd ", %" Pd ")\n", | 1783 ") between [%" Pd ", %" Pd ")\n", |
| 1769 range->vreg(), range->Start(), range->End(), from, to)); | 1784 range->vreg(), range->Start(), range->End(), from, to)); |
| 1770 | 1785 |
| 1771 intptr_t split_pos = kIllegalPosition; | 1786 intptr_t split_pos = kIllegalPosition; |
| 1772 | 1787 |
| 1773 BlockInfo* split_block = BlockInfoAt(to); | 1788 BlockInfo* split_block = BlockInfoAt(to); |
| 1774 if (from < split_block->entry()->lifetime_position()) { | 1789 if (from < split_block->entry()->lifetime_position() && |
| 1790 split_block->loop() != NULL) { | |
|
srdjan
2014/09/02 18:48:21
Add parentheses
| |
| 1775 // Interval [from, to) spans multiple blocks. | 1791 // Interval [from, to) spans multiple blocks. |
| 1776 | 1792 |
| 1777 // If last block is inside a loop prefer splitting at outermost loop's | 1793 // If last block is inside a loop prefer splitting at outermost loop's |
| 1778 // header. | 1794 // header. |
| 1779 BlockInfo* loop_header = split_block->loop(); | 1795 BlockInfo* loop_header = split_block->loop(); |
| 1780 while ((loop_header != NULL) && | 1796 while ((loop_header != NULL) && |
| 1781 (from < loop_header->entry()->lifetime_position())) { | 1797 (from < loop_header->entry()->lifetime_position())) { |
| 1782 split_block = loop_header; | 1798 split_block = loop_header; |
| 1783 loop_header = loop_header->loop(); | 1799 loop_header = loop_header->loop(); |
| 1784 } | 1800 } |
| (...skipping 833 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2618 const intptr_t start = range->Start(); | 2634 const intptr_t start = range->Start(); |
| 2619 TRACE_ALLOC(OS::Print("Processing live range for v%" Pd " " | 2635 TRACE_ALLOC(OS::Print("Processing live range for v%" Pd " " |
| 2620 "starting at %" Pd "\n", | 2636 "starting at %" Pd "\n", |
| 2621 range->vreg(), | 2637 range->vreg(), |
| 2622 start)); | 2638 start)); |
| 2623 | 2639 |
| 2624 // TODO(vegorov): eagerly spill liveranges without register uses. | 2640 // TODO(vegorov): eagerly spill liveranges without register uses. |
| 2625 AdvanceActiveIntervals(start); | 2641 AdvanceActiveIntervals(start); |
| 2626 | 2642 |
| 2627 if (!AllocateFreeRegister(range)) { | 2643 if (!AllocateFreeRegister(range)) { |
| 2644 if (intrinsic_mode_) { | |
| 2645 // No spilling when compiling intrinsics. | |
| 2646 // TODO(fschneider): Handle spilling in intrinsics. For now, the | |
| 2647 // IR has to be built so that there are enough free registers. | |
| 2648 UNREACHABLE(); | |
| 2649 } | |
| 2628 AllocateAnyRegister(range); | 2650 AllocateAnyRegister(range); |
| 2629 } | 2651 } |
| 2630 } | 2652 } |
| 2631 | 2653 |
| 2632 // All allocation decisions were done. | 2654 // All allocation decisions were done. |
| 2633 ASSERT(unallocated_.is_empty()); | 2655 ASSERT(unallocated_.is_empty()); |
| 2634 | 2656 |
| 2635 // Finish allocation. | 2657 // Finish allocation. |
| 2636 AdvanceActiveIntervals(kMaxPosition); | 2658 AdvanceActiveIntervals(kMaxPosition); |
| 2637 TRACE_ALLOC(OS::Print("Allocation completed\n")); | 2659 TRACE_ALLOC(OS::Print("Allocation completed\n")); |
| (...skipping 282 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2920 OS::Print("-- [after ssa allocator] ir [%s] -------------\n", | 2942 OS::Print("-- [after ssa allocator] ir [%s] -------------\n", |
| 2921 function.ToFullyQualifiedCString()); | 2943 function.ToFullyQualifiedCString()); |
| 2922 FlowGraphPrinter printer(flow_graph_, true); | 2944 FlowGraphPrinter printer(flow_graph_, true); |
| 2923 printer.PrintBlocks(); | 2945 printer.PrintBlocks(); |
| 2924 OS::Print("----------------------------------------------\n"); | 2946 OS::Print("----------------------------------------------\n"); |
| 2925 } | 2947 } |
| 2926 } | 2948 } |
| 2927 | 2949 |
| 2928 | 2950 |
| 2929 } // namespace dart | 2951 } // namespace dart |
| OLD | NEW |