| 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 477 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 609 LiveRange* range, | 618 LiveRange* range, |
| 610 BlockEntryInstr* block) { | 619 BlockEntryInstr* block) { |
| 611 // Save the range end because it may change below. | 620 // Save the range end because it may change below. |
| 612 intptr_t range_end = range->End(); | 621 intptr_t range_end = range->End(); |
| 613 if (defn->IsParameter()) { | 622 if (defn->IsParameter()) { |
| 614 ParameterInstr* param = defn->AsParameter(); | 623 ParameterInstr* param = defn->AsParameter(); |
| 615 // Assert that copied and non-copied parameters are mutually exclusive. | 624 // 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. | 625 // This might change in the future and, if so, the index will be wrong. |
| 617 ASSERT((flow_graph_.num_copied_params() == 0) || | 626 ASSERT((flow_graph_.num_copied_params() == 0) || |
| 618 (flow_graph_.num_non_copied_params() == 0)); | 627 (flow_graph_.num_non_copied_params() == 0)); |
| 619 // Slot index for the leftmost copied parameter is 0. | |
| 620 intptr_t slot_index = param->index(); | 628 intptr_t slot_index = param->index(); |
| 621 // Slot index for the rightmost fixed parameter is -1. | 629 ASSERT((param->base_reg() == FPREG) || (param->base_reg() == SPREG)); |
| 622 slot_index -= flow_graph_.num_non_copied_params(); | 630 if (param->base_reg() == FPREG) { |
| 631 // Slot index for the leftmost copied parameter is 0. |
| 632 // Slot index for the rightmost fixed parameter is -1. |
| 633 slot_index -= flow_graph_.num_non_copied_params(); |
| 634 } |
| 623 | 635 |
| 624 range->set_assigned_location(Location::StackSlot(slot_index)); | 636 range->set_assigned_location(Location::StackSlot(slot_index, |
| 625 range->set_spill_slot(Location::StackSlot(slot_index)); | 637 param->base_reg())); |
| 638 range->set_spill_slot(Location::StackSlot(slot_index, |
| 639 param->base_reg())); |
| 626 } else { | 640 } else { |
| 627 ConstantInstr* constant = defn->AsConstant(); | 641 ConstantInstr* constant = defn->AsConstant(); |
| 628 ASSERT(constant != NULL); | 642 ASSERT(constant != NULL); |
| 629 range->set_assigned_location(Location::Constant(constant)); | 643 range->set_assigned_location(Location::Constant(constant)); |
| 630 range->set_spill_slot(Location::Constant(constant)); | 644 range->set_spill_slot(Location::Constant(constant)); |
| 631 } | 645 } |
| 632 AssignSafepoints(defn, range); | 646 AssignSafepoints(defn, range); |
| 633 range->finger()->Initialize(range); | 647 range->finger()->Initialize(range); |
| 634 UsePosition* use = | 648 UsePosition* use = |
| 635 range->finger()->FirstRegisterBeneficialUse(block->start_pos()); | 649 range->finger()->FirstRegisterBeneficialUse(block->start_pos()); |
| (...skipping 1982 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2618 const intptr_t start = range->Start(); | 2632 const intptr_t start = range->Start(); |
| 2619 TRACE_ALLOC(OS::Print("Processing live range for v%" Pd " " | 2633 TRACE_ALLOC(OS::Print("Processing live range for v%" Pd " " |
| 2620 "starting at %" Pd "\n", | 2634 "starting at %" Pd "\n", |
| 2621 range->vreg(), | 2635 range->vreg(), |
| 2622 start)); | 2636 start)); |
| 2623 | 2637 |
| 2624 // TODO(vegorov): eagerly spill liveranges without register uses. | 2638 // TODO(vegorov): eagerly spill liveranges without register uses. |
| 2625 AdvanceActiveIntervals(start); | 2639 AdvanceActiveIntervals(start); |
| 2626 | 2640 |
| 2627 if (!AllocateFreeRegister(range)) { | 2641 if (!AllocateFreeRegister(range)) { |
| 2642 if (intrinsic_mode_) { |
| 2643 // No spilling when compiling intrinsics. |
| 2644 // TODO(fschneider): Handle spilling in intrinsics. For now, the |
| 2645 // IR has to be built so that there are enough free registers. |
| 2646 UNREACHABLE(); |
| 2647 } |
| 2628 AllocateAnyRegister(range); | 2648 AllocateAnyRegister(range); |
| 2629 } | 2649 } |
| 2630 } | 2650 } |
| 2631 | 2651 |
| 2632 // All allocation decisions were done. | 2652 // All allocation decisions were done. |
| 2633 ASSERT(unallocated_.is_empty()); | 2653 ASSERT(unallocated_.is_empty()); |
| 2634 | 2654 |
| 2635 // Finish allocation. | 2655 // Finish allocation. |
| 2636 AdvanceActiveIntervals(kMaxPosition); | 2656 AdvanceActiveIntervals(kMaxPosition); |
| 2637 TRACE_ALLOC(OS::Print("Allocation completed\n")); | 2657 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", | 2940 OS::Print("-- [after ssa allocator] ir [%s] -------------\n", |
| 2921 function.ToFullyQualifiedCString()); | 2941 function.ToFullyQualifiedCString()); |
| 2922 FlowGraphPrinter printer(flow_graph_, true); | 2942 FlowGraphPrinter printer(flow_graph_, true); |
| 2923 printer.PrintBlocks(); | 2943 printer.PrintBlocks(); |
| 2924 OS::Print("----------------------------------------------\n"); | 2944 OS::Print("----------------------------------------------\n"); |
| 2925 } | 2945 } |
| 2926 } | 2946 } |
| 2927 | 2947 |
| 2928 | 2948 |
| 2929 } // namespace dart | 2949 } // namespace dart |
| OLD | NEW |