Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(23)

Side by Side Diff: runtime/vm/flow_graph_allocator.cc

Issue 513213002: Generate some intrinsics using our IR. (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: addressed latest comments Created 6 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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
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
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
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());
Vyacheslav Egorov (Google) 2014/09/09 21:30:50 This assertion is redundant. There is one in BitVe
Florian Schneider 2014/09/10 14:20:41 Done.
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
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
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)) {
Vyacheslav Egorov (Google) 2014/09/09 21:30:50 We should have landed this change separately to is
Florian Schneider 2014/09/10 14:20:41 I actually planned to factor it out.
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
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
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698