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

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

Issue 215363004: Support for multiple register values (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 6 years, 8 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
« no previous file with comments | « runtime/vm/flow_graph_allocator.h ('k') | runtime/vm/flow_graph_optimizer.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 16 matching lines...) Expand all
27 } while (0) 27 } while (0)
28 #else 28 #else
29 #define TRACE_ALLOC(statement) 29 #define TRACE_ALLOC(statement)
30 #endif 30 #endif
31 31
32 32
33 static const intptr_t kNoVirtualRegister = -1; 33 static const intptr_t kNoVirtualRegister = -1;
34 static const intptr_t kTempVirtualRegister = -2; 34 static const intptr_t kTempVirtualRegister = -2;
35 static const intptr_t kIllegalPosition = -1; 35 static const intptr_t kIllegalPosition = -1;
36 static const intptr_t kMaxPosition = 0x7FFFFFFF; 36 static const intptr_t kMaxPosition = 0x7FFFFFFF;
37 static const intptr_t kPairVirtualRegisterOffset = 1;
38
39 // Definitions which have pair representations
40 // (kPairOfTagged or kPairOfUnboxedDouble) use two virtual register names.
41 // At SSA index allocation time each definition reserves two SSA indexes,
42 // the second index is only used for pairs. This function maps from the first
43 // SSA index to the second.
44 static intptr_t ToSecondPairVreg(intptr_t vreg) {
45 // Map vreg to its pair vreg.
46 return vreg + kPairVirtualRegisterOffset;
47 }
48
37 49
38 static intptr_t MinPosition(intptr_t a, intptr_t b) { 50 static intptr_t MinPosition(intptr_t a, intptr_t b) {
39 return (a < b) ? a : b; 51 return (a < b) ? a : b;
40 } 52 }
41 53
42 54
43 static bool IsInstructionStartPosition(intptr_t pos) { 55 static bool IsInstructionStartPosition(intptr_t pos) {
44 return (pos & 1) == 0; 56 return (pos & 1) == 0;
45 } 57 }
46 58
(...skipping 20 matching lines...) Expand all
67 block_order_(flow_graph.reverse_postorder()), 79 block_order_(flow_graph.reverse_postorder()),
68 postorder_(flow_graph.postorder()), 80 postorder_(flow_graph.postorder()),
69 liveness_(flow_graph), 81 liveness_(flow_graph),
70 vreg_count_(flow_graph.max_virtual_register_number()), 82 vreg_count_(flow_graph.max_virtual_register_number()),
71 live_ranges_(flow_graph.max_virtual_register_number()), 83 live_ranges_(flow_graph.max_virtual_register_number()),
72 cpu_regs_(), 84 cpu_regs_(),
73 fpu_regs_(), 85 fpu_regs_(),
74 blocked_cpu_registers_(), 86 blocked_cpu_registers_(),
75 blocked_fpu_registers_(), 87 blocked_fpu_registers_(),
76 cpu_spill_slot_count_(0) { 88 cpu_spill_slot_count_(0) {
77 for (intptr_t i = 0; i < vreg_count_; i++) live_ranges_.Add(NULL); 89 for (intptr_t i = 0; i < vreg_count_; i++) {
90 live_ranges_.Add(NULL);
91 }
78 for (intptr_t i = 0; i < vreg_count_; i++) { 92 for (intptr_t i = 0; i < vreg_count_; i++) {
79 value_representations_.Add(kNoRepresentation); 93 value_representations_.Add(kNoRepresentation);
80 } 94 }
81 95
82 // All registers are marked as "not blocked" (array initialized to false). 96 // All registers are marked as "not blocked" (array initialized to false).
83 // Mark the unavailable ones as "blocked" (true). 97 // Mark the unavailable ones as "blocked" (true).
84 for (intptr_t i = 0; i < kFirstFreeCpuRegister; i++) { 98 for (intptr_t i = 0; i < kFirstFreeCpuRegister; i++) {
85 blocked_cpu_registers_[i] = true; 99 blocked_cpu_registers_[i] = true;
86 } 100 }
87 for (intptr_t i = kLastFreeCpuRegister + 1; i < kNumberOfCpuRegisters; i++) { 101 for (intptr_t i = kLastFreeCpuRegister + 1; i < kNumberOfCpuRegisters; i++) {
(...skipping 19 matching lines...) Expand all
107 for (intptr_t i = 0; i < block_count; i++) { 121 for (intptr_t i = 0; i < block_count; i++) {
108 BlockEntryInstr* block = postorder_[i]; 122 BlockEntryInstr* block = postorder_[i];
109 123
110 BitVector* kill = kill_[i]; 124 BitVector* kill = kill_[i];
111 BitVector* live_in = live_in_[i]; 125 BitVector* live_in = live_in_[i];
112 126
113 // Iterate backwards starting at the last instruction. 127 // Iterate backwards starting at the last instruction.
114 for (BackwardInstructionIterator it(block); !it.Done(); it.Advance()) { 128 for (BackwardInstructionIterator it(block); !it.Done(); it.Advance()) {
115 Instruction* current = it.Current(); 129 Instruction* current = it.Current();
116 130
131 // Initialize location summary for instruction.
132 current->InitializeLocationSummary(true); // Optimizing.
133 LocationSummary* locs = current->locs();
134
117 // Handle definitions. 135 // Handle definitions.
118 Definition* current_def = current->AsDefinition(); 136 Definition* current_def = current->AsDefinition();
119 if ((current_def != NULL) && current_def->HasSSATemp()) { 137 if ((current_def != NULL) && current_def->HasSSATemp()) {
120 kill->Add(current_def->ssa_temp_index()); 138 kill->Add(current_def->ssa_temp_index());
121 live_in->Remove(current_def->ssa_temp_index()); 139 live_in->Remove(current_def->ssa_temp_index());
140 if (current_def->HasPairRepresentation()) {
141 kill->Add(ToSecondPairVreg(current_def->ssa_temp_index()));
142 live_in->Remove(ToSecondPairVreg(current_def->ssa_temp_index()));
143 }
122 } 144 }
123 145
124 // Handle uses. 146 // Handle uses.
125 current->InitializeLocationSummary(true); // Optimizing.
126 LocationSummary* locs = current->locs();
127 ASSERT(locs->input_count() == current->InputCount()); 147 ASSERT(locs->input_count() == current->InputCount());
128 for (intptr_t j = 0; j < current->InputCount(); j++) { 148 for (intptr_t j = 0; j < current->InputCount(); j++) {
129 Value* input = current->InputAt(j); 149 Value* input = current->InputAt(j);
130 const intptr_t use = input->definition()->ssa_temp_index();
131 150
132 ASSERT(!locs->in(j).IsConstant() || input->BindsToConstant()); 151 ASSERT(!locs->in(j).IsConstant() || input->BindsToConstant());
133 if (locs->in(j).IsConstant()) continue; 152 if (locs->in(j).IsConstant()) continue;
134 153
135 live_in->Add(use); 154 live_in->Add(input->definition()->ssa_temp_index());
155 if (input->definition()->HasPairRepresentation()) {
156 live_in->Add(ToSecondPairVreg(input->definition()->ssa_temp_index()));
157 }
136 } 158 }
137 159
138 // Add non-argument uses from the deoptimization environment (pushed 160 // Add non-argument uses from the deoptimization environment (pushed
139 // arguments are not allocated by the register allocator). 161 // arguments are not allocated by the register allocator).
140 if (current->env() != NULL) { 162 if (current->env() != NULL) {
141 for (Environment::DeepIterator env_it(current->env()); 163 for (Environment::DeepIterator env_it(current->env());
142 !env_it.Done(); 164 !env_it.Done();
143 env_it.Advance()) { 165 env_it.Advance()) {
144 Definition* defn = env_it.CurrentValue()->definition(); 166 Definition* defn = env_it.CurrentValue()->definition();
145 if (defn->IsMaterializeObject()) { 167 if (defn->IsMaterializeObject()) {
146 // MaterializeObject instruction is not in the graph. 168 // MaterializeObject instruction is not in the graph.
147 // Treat its inputs as part of the environment. 169 // Treat its inputs as part of the environment.
148 for (intptr_t i = 0; i < defn->InputCount(); i++) { 170 for (intptr_t i = 0; i < defn->InputCount(); i++) {
149 if (!defn->InputAt(i)->BindsToConstant()) { 171 if (!defn->InputAt(i)->BindsToConstant()) {
150 live_in->Add(defn->InputAt(i)->definition()->ssa_temp_index()); 172 intptr_t idx = defn->InputAt(i)->definition()->ssa_temp_index();
173 live_in->Add(idx);
151 } 174 }
152 } 175 }
153 } else if (!defn->IsPushArgument() && !defn->IsConstant()) { 176 } else if (!defn->IsPushArgument() && !defn->IsConstant()) {
154 live_in->Add(defn->ssa_temp_index()); 177 live_in->Add(defn->ssa_temp_index());
178 if (defn->HasPairRepresentation()) {
179 live_in->Add(ToSecondPairVreg(defn->ssa_temp_index()));
180 }
155 } 181 }
156 } 182 }
157 } 183 }
158 } 184 }
159 185
160 // Handle phis. 186 // Handle phis.
161 if (block->IsJoinEntry()) { 187 if (block->IsJoinEntry()) {
162 JoinEntryInstr* join = block->AsJoinEntry(); 188 JoinEntryInstr* join = block->AsJoinEntry();
163 for (PhiIterator it(join); !it.Done(); it.Advance()) { 189 for (PhiIterator it(join); !it.Done(); it.Advance()) {
190 // TODO(johnmccutchan): Fix handling of PhiInstr with PairLocation.
164 PhiInstr* phi = it.Current(); 191 PhiInstr* phi = it.Current();
165 ASSERT(phi != NULL); 192 ASSERT(phi != NULL);
166 kill->Add(phi->ssa_temp_index()); 193 kill->Add(phi->ssa_temp_index());
167 live_in->Remove(phi->ssa_temp_index()); 194 live_in->Remove(phi->ssa_temp_index());
168 195
169 // If a phi input is not defined by the corresponding predecessor it 196 // If a phi input is not defined by the corresponding predecessor it
170 // must be marked live-in for that predecessor. 197 // must be marked live-in for that predecessor.
171 for (intptr_t k = 0; k < phi->InputCount(); k++) { 198 for (intptr_t k = 0; k < phi->InputCount(); k++) {
172 Value* val = phi->InputAt(k); 199 Value* val = phi->InputAt(k);
173 if (val->BindsToConstant()) continue; 200 if (val->BindsToConstant()) continue;
174 201
175 BlockEntryInstr* pred = block->PredecessorAt(k); 202 BlockEntryInstr* pred = block->PredecessorAt(k);
176 const intptr_t use = val->definition()->ssa_temp_index(); 203 const intptr_t use = val->definition()->ssa_temp_index();
177 if (!kill_[pred->postorder_number()]->Contains(use)) { 204 if (!kill_[pred->postorder_number()]->Contains(use)) {
178 live_in_[pred->postorder_number()]->Add(use); 205 live_in_[pred->postorder_number()]->Add(use);
179 } 206 }
180 } 207 }
181 } 208 }
182 } else if (block->IsCatchBlockEntry()) { 209 } else if (block->IsCatchBlockEntry()) {
183 // Process initial definitions. 210 // Process initial definitions.
184 CatchBlockEntryInstr* catch_entry = block->AsCatchBlockEntry(); 211 CatchBlockEntryInstr* catch_entry = block->AsCatchBlockEntry();
185 for (intptr_t i = 0; 212 for (intptr_t i = 0;
186 i < catch_entry->initial_definitions()->length(); 213 i < catch_entry->initial_definitions()->length();
187 i++) { 214 i++) {
188 intptr_t vreg = 215 Definition* def = (*catch_entry->initial_definitions())[i];
189 (*catch_entry->initial_definitions())[i]->ssa_temp_index(); 216 const intptr_t vreg = def->ssa_temp_index();
190 kill_[catch_entry->postorder_number()]->Add(vreg); 217 kill_[catch_entry->postorder_number()]->Add(vreg);
191 live_in_[catch_entry->postorder_number()]->Remove(vreg); 218 live_in_[catch_entry->postorder_number()]->Remove(vreg);
192 } 219 }
193 } 220 }
194 } 221 }
195 222
196 // Process initial definitions, ie, constants and incoming parameters. 223 // Process initial definitions, ie, constants and incoming parameters.
197 for (intptr_t i = 0; i < graph_entry_->initial_definitions()->length(); i++) { 224 for (intptr_t i = 0; i < graph_entry_->initial_definitions()->length(); i++) {
198 intptr_t vreg = (*graph_entry_->initial_definitions())[i]->ssa_temp_index(); 225 Definition* def = (*graph_entry_->initial_definitions())[i];
226 const intptr_t vreg = def->ssa_temp_index();
199 kill_[graph_entry_->postorder_number()]->Add(vreg); 227 kill_[graph_entry_->postorder_number()]->Add(vreg);
200 live_in_[graph_entry_->postorder_number()]->Remove(vreg); 228 live_in_[graph_entry_->postorder_number()]->Remove(vreg);
201 } 229 }
202 230
203 // Update initial live_in sets to match live_out sets. Has to be 231 // Update initial live_in sets to match live_out sets. Has to be
204 // done in a separate path because of backwards branches. 232 // done in a separate path because of backwards branches.
205 for (intptr_t i = 0; i < block_count; i++) { 233 for (intptr_t i = 0; i < block_count; i++) {
206 UpdateLiveIn(*postorder_[i]); 234 UpdateLiveIn(*postorder_[i]);
207 } 235 }
208 } 236 }
(...skipping 391 matching lines...) Expand 10 before | Expand all | Expand 10 after
600 return Location::kRegister; 628 return Location::kRegister;
601 } 629 }
602 } 630 }
603 631
604 632
605 static Location::Kind RegisterKindForResult(Instruction* instr) { 633 static Location::Kind RegisterKindForResult(Instruction* instr) {
606 if ((instr->representation() == kUnboxedDouble) || 634 if ((instr->representation() == kUnboxedDouble) ||
607 (instr->representation() == kUnboxedMint) || 635 (instr->representation() == kUnboxedMint) ||
608 (instr->representation() == kUnboxedFloat32x4) || 636 (instr->representation() == kUnboxedFloat32x4) ||
609 (instr->representation() == kUnboxedInt32x4) || 637 (instr->representation() == kUnboxedInt32x4) ||
610 (instr->representation() == kUnboxedFloat64x2)) { 638 (instr->representation() == kUnboxedFloat64x2) ||
639 (instr->representation() == kPairOfUnboxedDouble)) {
611 return Location::kFpuRegister; 640 return Location::kFpuRegister;
612 } else { 641 } else {
613 return Location::kRegister; 642 return Location::kRegister;
614 } 643 }
615 } 644 }
616 645
617 646
618 // 647 //
619 // When describing shape of live ranges in comments below we are going to use 648 // When describing shape of live ranges in comments below we are going to use
620 // the following notation: 649 // the following notation:
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
659 JoinEntryInstr* join = goto_instr->successor(); 688 JoinEntryInstr* join = goto_instr->successor();
660 ASSERT(join != NULL); 689 ASSERT(join != NULL);
661 690
662 // Search for the index of the current block in the predecessors of 691 // Search for the index of the current block in the predecessors of
663 // the join. 692 // the join.
664 const intptr_t pred_idx = join->IndexOfPredecessor(block); 693 const intptr_t pred_idx = join->IndexOfPredecessor(block);
665 694
666 // Record the corresponding phi input use for each phi. 695 // Record the corresponding phi input use for each phi.
667 intptr_t move_idx = 0; 696 intptr_t move_idx = 0;
668 for (PhiIterator it(join); !it.Done(); it.Advance()) { 697 for (PhiIterator it(join); !it.Done(); it.Advance()) {
698 // TODO(johnmccutchan): Fix handling of PhiInstr with PairLocation.
669 PhiInstr* phi = it.Current(); 699 PhiInstr* phi = it.Current();
670 Value* val = phi->InputAt(pred_idx); 700 Value* val = phi->InputAt(pred_idx);
671 MoveOperands* move = parallel_move->MoveOperandsAt(move_idx); 701 MoveOperands* move = parallel_move->MoveOperandsAt(move_idx);
672 702
673 ConstantInstr* constant = val->definition()->AsConstant(); 703 ConstantInstr* constant = val->definition()->AsConstant();
674 if (constant != NULL) { 704 if (constant != NULL) {
675 move->set_src(Location::Constant(constant->value())); 705 move->set_src(Location::Constant(constant->value()));
676 move_idx++; 706 move_idx++;
677 continue; 707 continue;
678 } 708 }
(...skipping 23 matching lines...) Expand all
702 732
703 void FlowGraphAllocator::ConnectIncomingPhiMoves(JoinEntryInstr* join) { 733 void FlowGraphAllocator::ConnectIncomingPhiMoves(JoinEntryInstr* join) {
704 // For join blocks we need to add destinations of phi resolution moves 734 // For join blocks we need to add destinations of phi resolution moves
705 // to phi's live range so that register allocator will fill them with moves. 735 // to phi's live range so that register allocator will fill them with moves.
706 736
707 // All uses are recorded at the start position in the block. 737 // All uses are recorded at the start position in the block.
708 const intptr_t pos = join->start_pos(); 738 const intptr_t pos = join->start_pos();
709 const bool is_loop_header = BlockInfoAt(join->start_pos())->is_loop_header(); 739 const bool is_loop_header = BlockInfoAt(join->start_pos())->is_loop_header();
710 intptr_t move_idx = 0; 740 intptr_t move_idx = 0;
711 for (PhiIterator it(join); !it.Done(); it.Advance()) { 741 for (PhiIterator it(join); !it.Done(); it.Advance()) {
742 // TODO(johnmccutchan): Fix handling of PhiInstr with PairLocation.
712 PhiInstr* phi = it.Current(); 743 PhiInstr* phi = it.Current();
713 ASSERT(phi != NULL); 744 ASSERT(phi != NULL);
714 const intptr_t vreg = phi->ssa_temp_index(); 745 const intptr_t vreg = phi->ssa_temp_index();
715 ASSERT(vreg >= 0); 746 ASSERT(vreg >= 0);
716 747
717 // Expected shape of live range: 748 // Expected shape of live range:
718 // 749 //
719 // B 750 // B
720 // phi [-------- 751 // phi [--------
721 // 752 //
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after
789 MaterializeObjectInstr* mat = def->AsMaterializeObject(); 820 MaterializeObjectInstr* mat = def->AsMaterializeObject();
790 if (mat != NULL) { 821 if (mat != NULL) {
791 // MaterializeObject itself produces no value. But its uses 822 // MaterializeObject itself produces no value. But its uses
792 // are treated as part of the environment: allocated locations 823 // are treated as part of the environment: allocated locations
793 // will be used when building deoptimization data. 824 // will be used when building deoptimization data.
794 locations[i] = Location::NoLocation(); 825 locations[i] = Location::NoLocation();
795 ProcessMaterializationUses(block, block_start_pos, use_pos, mat); 826 ProcessMaterializationUses(block, block_start_pos, use_pos, mat);
796 continue; 827 continue;
797 } 828 }
798 829
799 const intptr_t vreg = def->ssa_temp_index(); 830 LiveRange* range = GetLiveRange(def->ssa_temp_index());
800 LiveRange* range = GetLiveRange(vreg);
801 range->AddUseInterval(block_start_pos, use_pos); 831 range->AddUseInterval(block_start_pos, use_pos);
802 range->AddUse(use_pos, &locations[i]); 832 range->AddUse(use_pos, &locations[i]);
833
834 if (def->HasPairRepresentation()) {
835 LiveRange* range =
836 GetLiveRange(ToSecondPairVreg(def->ssa_temp_index()));
837 range->AddUseInterval(block_start_pos, use_pos);
838 range->AddUse(use_pos, &locations[i]);
839 }
803 } 840 }
804 841
805 env->set_locations(locations); 842 env->set_locations(locations);
806 env = env->outer(); 843 env = env->outer();
807 } 844 }
808 } 845 }
809 846
810 847
811 void FlowGraphAllocator::ProcessMaterializationUses( 848 void FlowGraphAllocator::ProcessMaterializationUses(
812 BlockEntryInstr* block, 849 BlockEntryInstr* block,
(...skipping 14 matching lines...) Expand all
827 Definition* def = mat->InputAt(i)->definition(); 864 Definition* def = mat->InputAt(i)->definition();
828 865
829 ConstantInstr* constant = def->AsConstant(); 866 ConstantInstr* constant = def->AsConstant();
830 if (constant != NULL) { 867 if (constant != NULL) {
831 locations[i] = Location::Constant(constant->value()); 868 locations[i] = Location::Constant(constant->value());
832 continue; 869 continue;
833 } 870 }
834 871
835 locations[i] = Location::Any(); 872 locations[i] = Location::Any();
836 873
837 const intptr_t vreg = def->ssa_temp_index(); 874 LiveRange* range = GetLiveRange(def->ssa_temp_index());
838 LiveRange* range = GetLiveRange(vreg);
839 range->AddUseInterval(block_start_pos, use_pos); 875 range->AddUseInterval(block_start_pos, use_pos);
840 range->AddUse(use_pos, &locations[i]); 876 range->AddUse(use_pos, &locations[i]);
877 if (def->HasPairRepresentation()) {
878 LiveRange* range = GetLiveRange(ToSecondPairVreg(def->ssa_temp_index()));
879 range->AddUseInterval(block_start_pos, use_pos);
880 range->AddUse(use_pos, &locations[i]);
881 }
841 } 882 }
842 883
843 mat->set_locations(locations); 884 mat->set_locations(locations);
844 } 885 }
845 886
846 887
888 void FlowGraphAllocator::ProcessOneInput(BlockEntryInstr* block,
889 intptr_t pos,
890 Location* in_ref,
891 Value* input,
892 intptr_t vreg) {
893 ASSERT(in_ref != NULL);
894 ASSERT(!in_ref->IsPairLocation());
895 ASSERT(input != NULL);
896 ASSERT(block != NULL);
897 LiveRange* range = GetLiveRange(vreg);
898 if (in_ref->IsMachineRegister()) {
899 // Input is expected in a fixed register. Expected shape of
900 // live ranges:
901 //
902 // j' i i'
903 // value --*
904 // register [-----)
905 //
906 MoveOperands* move =
907 AddMoveAt(pos - 1, *in_ref, Location::Any());
908 BlockLocation(*in_ref, pos - 1, pos + 1);
909 range->AddUseInterval(block->start_pos(), pos - 1);
910 range->AddHintedUse(pos - 1, move->src_slot(), in_ref);
911 } else if (in_ref->IsUnallocated()) {
912 if (in_ref->policy() == Location::kWritableRegister) {
913 // Writable unallocated input. Expected shape of
914 // live ranges:
915 //
916 // j' i i'
917 // value --*
918 // temp [------)
919 MoveOperands* move = AddMoveAt(pos - 1,
920 Location::RequiresRegister(),
921 Location::PrefersRegister());
922
923 // Add uses to the live range of the input.
924 range->AddUseInterval(block->start_pos(), pos - 1);
925 range->AddUse(pos - 1, move->src_slot());
926
927 // Create live range for the temporary.
928 LiveRange* temp = MakeLiveRangeForTemporary();
929 temp->AddUseInterval(pos - 1, pos + 1);
930 temp->AddHintedUse(pos - 1, in_ref, move->src_slot());
931 temp->AddUse(pos + 1, move->dest_slot());
932 *in_ref = Location::RequiresRegister();
933 CompleteRange(temp, RegisterKindFromPolicy(*in_ref));
934 } else {
935 // Normal unallocated input. Expected shape of
936 // live ranges:
937 //
938 // i i'
939 // value -----*
940 //
941 range->AddUseInterval(block->start_pos(), pos + 1);
942 range->AddUse(pos + 1, in_ref);
943 }
944 } else {
945 ASSERT(in_ref->IsConstant());
946 }
947 }
948
949
950 void FlowGraphAllocator::ProcessOneOutput(BlockEntryInstr* block,
951 Instruction* current,
952 intptr_t pos,
953 Location* out,
954 Definition* def,
955 intptr_t vreg,
956 bool output_same_as_first_input,
957 Location* in_ref,
958 Definition* input,
959 intptr_t input_vreg,
960 BitVector* interference_set) {
961 ASSERT(out != NULL);
962 ASSERT(!out->IsPairLocation());
963 ASSERT(def != NULL);
964 ASSERT(block != NULL);
965
966 LiveRange* range = vreg >= 0 ?
967 GetLiveRange(vreg) : MakeLiveRangeForTemporary();
968
969 // Process output and finalize its liverange.
970 if (out->IsMachineRegister()) {
971 // Fixed output location. Expected shape of live range:
972 //
973 // i i' j j'
974 // register [--)
975 // output [-------
976 //
977 BlockLocation(*out, pos, pos + 1);
978
979 if (range->vreg() == kTempVirtualRegister) return;
980
981 // We need to emit move connecting fixed register with another location
982 // that will be allocated for this output's live range.
983 // Special case: fixed output followed by a fixed input last use.
984 UsePosition* use = range->first_use();
985
986 // If the value has no uses we don't need to allocate it.
987 if (use == NULL) return;
988
989 if (use->pos() == (pos + 1)) {
990 ASSERT(use->location_slot()->IsUnallocated());
991 *(use->location_slot()) = *out;
992
993 // Remove first use. It was allocated.
994 range->set_first_use(range->first_use()->next());
995 }
996
997 // Shorten live range to the point of definition, this might make the range
998 // empty (if the only use immediately follows). If range is not empty add
999 // move from a fixed register to an unallocated location.
1000 range->DefineAt(pos + 1);
1001 if (range->Start() == range->End()) return;
1002
1003 MoveOperands* move = AddMoveAt(pos + 1, Location::Any(), *out);
1004 range->AddHintedUse(pos + 1, move->dest_slot(), out);
1005 } else if (output_same_as_first_input) {
1006 ASSERT(in_ref != NULL);
1007 ASSERT(input != NULL);
1008 // Output register will contain a value of the first input at instruction's
1009 // start. Expected shape of live ranges:
1010 //
1011 // i i'
1012 // input #0 --*
1013 // output [----
1014 //
1015 ASSERT(in_ref->Equals(Location::RequiresRegister()) ||
1016 in_ref->Equals(Location::RequiresFpuRegister()));
1017
1018 // TODO(johnmccutchan): Without this I get allocated a register instead
1019 // of an FPU register. Figure out why.
1020
1021 *out = *in_ref;
1022 // Create move that will copy value between input and output.
1023 MoveOperands* move = AddMoveAt(pos,
1024 Location::RequiresRegister(),
1025 Location::Any());
1026
1027 // Add uses to the live range of the input.
1028 LiveRange* input_range = GetLiveRange(input_vreg);
1029 input_range->AddUseInterval(block->start_pos(), pos);
1030 input_range->AddUse(pos, move->src_slot());
1031
1032 // Shorten output live range to the point of definition and add both input
1033 // and output uses slots to be filled by allocator.
1034 range->DefineAt(pos);
1035 range->AddHintedUse(pos, out, move->src_slot());
1036 range->AddUse(pos, move->dest_slot());
1037 range->AddUse(pos, in_ref);
1038
1039 if ((interference_set != NULL) &&
1040 (range->vreg() >= 0) &&
1041 interference_set->Contains(range->vreg())) {
1042 interference_set->Add(input->ssa_temp_index());
1043 }
1044 } else {
1045 // Normal unallocated location that requires a register. Expected shape of
1046 // live range:
1047 //
1048 // i i'
1049 // output [-------
1050 //
1051 ASSERT(out->Equals(Location::RequiresRegister()) ||
1052 out->Equals(Location::RequiresFpuRegister()));
1053
1054 // Shorten live range to the point of definition and add use to be filled by
1055 // allocator.
1056 range->DefineAt(pos);
1057 range->AddUse(pos, out);
1058 }
1059
1060 AssignSafepoints(range);
1061 CompleteRange(range, RegisterKindForResult(current));
1062 }
1063
1064
847 // Create and update live ranges corresponding to instruction's inputs, 1065 // Create and update live ranges corresponding to instruction's inputs,
848 // temporaries and output. 1066 // temporaries and output.
849 void FlowGraphAllocator::ProcessOneInstruction(BlockEntryInstr* block, 1067 void FlowGraphAllocator::ProcessOneInstruction(BlockEntryInstr* block,
850 Instruction* current, 1068 Instruction* current,
851 BitVector* interference_set) { 1069 BitVector* interference_set) {
852 LocationSummary* locs = current->locs(); 1070 LocationSummary* locs = current->locs();
853 1071
854 Definition* def = current->AsDefinition(); 1072 Definition* def = current->AsDefinition();
855 if ((def != NULL) && (def->AsConstant() != NULL)) { 1073 if ((def != NULL) && (def->AsConstant() != NULL)) {
1074 ASSERT(!def->HasPairRepresentation());
856 LiveRange* range = (def->ssa_temp_index() != -1) ? 1075 LiveRange* range = (def->ssa_temp_index() != -1) ?
857 GetLiveRange(def->ssa_temp_index()) : NULL; 1076 GetLiveRange(def->ssa_temp_index()) : NULL;
858 1077
859 // Drop definitions of constants that have no uses. 1078 // Drop definitions of constants that have no uses.
860 if ((range == NULL) || (range->first_use() == NULL)) { 1079 if ((range == NULL) || (range->first_use() == NULL)) {
861 locs->set_out(0, Location::NoLocation()); 1080 locs->set_out(0, Location::NoLocation());
862 return; 1081 return;
863 } 1082 }
864 1083
865 // If this constant has only unconstrained uses convert them all 1084 // If this constant has only unconstrained uses convert them all
866 // to use the constant directly and drop this definition. 1085 // to use the constant directly and drop this definition.
867 // TODO(vegorov): improve allocation when we have enough registers to keep 1086 // TODO(vegorov): improve allocation when we have enough registers to keep
868 // constants used in the loop in them. 1087 // constants used in the loop in them.
869 if (HasOnlyUnconstrainedUses(range)) { 1088 if (HasOnlyUnconstrainedUses(range)) {
870 const Object& value = def->AsConstant()->value(); 1089 const Object& value = def->AsConstant()->value();
871 range->set_assigned_location(Location::Constant(value)); 1090 range->set_assigned_location(Location::Constant(value));
872 range->set_spill_slot(Location::Constant(value)); 1091 range->set_spill_slot(Location::Constant(value));
873 range->finger()->Initialize(range); 1092 range->finger()->Initialize(range);
874 ConvertAllUses(range); 1093 ConvertAllUses(range);
875 1094
876 locs->set_out(0, Location::NoLocation()); 1095 locs->set_out(0, Location::NoLocation());
877 return; 1096 return;
878 } 1097 }
879 } 1098 }
880 1099
881 const intptr_t pos = current->lifetime_position(); 1100 const intptr_t pos = current->lifetime_position();
882 ASSERT(IsInstructionStartPosition(pos)); 1101 ASSERT(IsInstructionStartPosition(pos));
883 1102
884 // Number of input locations and number of input operands have to agree.
885 ASSERT(locs->input_count() == current->InputCount()); 1103 ASSERT(locs->input_count() == current->InputCount());
886 1104
887 // Normalize same-as-first-input output if input is specified as 1105 // Normalize same-as-first-input output if input is specified as
888 // fixed register. 1106 // fixed register.
889 if (locs->out(0).IsUnallocated() && 1107 if (locs->out(0).IsUnallocated() &&
890 (locs->out(0).policy() == Location::kSameAsFirstInput) && 1108 (locs->out(0).policy() == Location::kSameAsFirstInput) &&
891 (locs->in(0).IsMachineRegister())) { 1109 (locs->in(0).IsMachineRegister())) {
892 locs->set_out(0, locs->in(0)); 1110 locs->set_out(0, locs->in(0));
893 } 1111 }
894 1112
895 const bool output_same_as_first_input = 1113 const bool output_same_as_first_input =
896 locs->out(0).IsUnallocated() && 1114 locs->out(0).IsUnallocated() &&
897 (locs->out(0).policy() == Location::kSameAsFirstInput); 1115 (locs->out(0).policy() == Location::kSameAsFirstInput);
898 1116
899 // Add uses from the deoptimization environment. 1117 // Add uses from the deoptimization environment.
900 if (current->env() != NULL) ProcessEnvironmentUses(block, current); 1118 if (current->env() != NULL) ProcessEnvironmentUses(block, current);
901 1119
902 // Process inputs. 1120 // Process inputs.
903 // Skip the first input if output is specified with kSameAsFirstInput policy, 1121 // Skip the first input if output is specified with kSameAsFirstInput policy,
904 // they will be processed together at the very end. 1122 // they will be processed together at the very end.
905 for (intptr_t j = output_same_as_first_input ? 1 : 0; 1123 {
906 j < current->InputCount(); 1124 for (intptr_t j = output_same_as_first_input ? 1 : 0;
907 j++) { 1125 j < locs->input_count();
908 Value* input = current->InputAt(j); 1126 j++) {
909 const intptr_t vreg = input->definition()->ssa_temp_index(); 1127 // Determine if we are dealing with a value pair, and if so, whether
910 LiveRange* range = GetLiveRange(vreg); 1128 // the location is the first register or second register.
911 1129 Value* input = current->InputAt(j);
912 Location* in_ref = locs->in_slot(j); 1130 Location* in_ref = locs->in_slot(j);
913 1131 if (in_ref->IsPairLocation()) {
914 if (in_ref->IsMachineRegister()) { 1132 ASSERT(input->definition()->HasPairRepresentation());
915 // Input is expected in a fixed register. Expected shape of 1133 PairLocation* pair = in_ref->AsPairLocation();
916 // live ranges: 1134 const intptr_t vreg = input->definition()->ssa_temp_index();
917 // 1135 // Each element of the pair is assigned it's own virtual register number
918 // j' i i' 1136 // and is allocated its own LiveRange.
919 // value --* 1137 ProcessOneInput(block, pos, pair->SlotAt(0),
920 // register [-----) 1138 input, vreg);
921 // 1139 ProcessOneInput(block, pos, pair->SlotAt(1), input,
922 MoveOperands* move = 1140 ToSecondPairVreg(vreg));
923 AddMoveAt(pos - 1, *in_ref, Location::Any());
924 BlockLocation(*in_ref, pos - 1, pos + 1);
925 range->AddUseInterval(block->start_pos(), pos - 1);
926 range->AddHintedUse(pos - 1, move->src_slot(), in_ref);
927 } else if (in_ref->IsUnallocated()) {
928 if (in_ref->policy() == Location::kWritableRegister) {
929 // Writable unallocated input. Expected shape of
930 // live ranges:
931 //
932 // i i'
933 // value --*
934 // temp [--)
935 MoveOperands* move = AddMoveAt(pos,
936 Location::RequiresRegister(),
937 Location::PrefersRegister());
938
939 // Add uses to the live range of the input.
940 range->AddUseInterval(block->start_pos(), pos);
941 range->AddUse(pos, move->src_slot());
942
943 // Create live range for the temporary.
944 LiveRange* temp = MakeLiveRangeForTemporary();
945 temp->AddUseInterval(pos, pos + 1);
946 temp->AddHintedUse(pos, in_ref, move->src_slot());
947 temp->AddUse(pos, move->dest_slot());
948 *in_ref = Location::RequiresRegister();
949 CompleteRange(temp, RegisterKindFromPolicy(*in_ref));
950 } else { 1141 } else {
951 // Normal unallocated input. Expected shape of 1142 ProcessOneInput(block, pos, in_ref, input,
952 // live ranges: 1143 input->definition()->ssa_temp_index());
953 //
954 // i i'
955 // value -----*
956 //
957 range->AddUseInterval(block->start_pos(), pos + 1);
958 range->AddUse(pos + 1, in_ref);
959 } 1144 }
960 } else {
961 ASSERT(in_ref->IsConstant());
962 } 1145 }
963 } 1146 }
964 1147
965 // Process temps. 1148 // Process temps.
966 for (intptr_t j = 0; j < locs->temp_count(); j++) { 1149 for (intptr_t j = 0; j < locs->temp_count(); j++) {
967 // Expected shape of live range: 1150 // Expected shape of live range:
968 // 1151 //
969 // i i' 1152 // i i'
970 // [--) 1153 // [--)
971 // 1154 //
972 1155
973 Location temp = locs->temp(j); 1156 Location temp = locs->temp(j);
1157 // We do not support pair locations for temporaries.
1158 ASSERT(!temp.IsPairLocation());
974 if (temp.IsMachineRegister()) { 1159 if (temp.IsMachineRegister()) {
975 BlockLocation(temp, pos, pos + 1); 1160 BlockLocation(temp, pos, pos + 1);
976 } else if (temp.IsUnallocated()) { 1161 } else if (temp.IsUnallocated()) {
977 LiveRange* range = MakeLiveRangeForTemporary(); 1162 LiveRange* range = MakeLiveRangeForTemporary();
978 range->AddUseInterval(pos, pos + 1); 1163 range->AddUseInterval(pos, pos + 1);
979 range->AddUse(pos, locs->temp_slot(j)); 1164 range->AddUse(pos, locs->temp_slot(j));
980 CompleteRange(range, RegisterKindFromPolicy(temp)); 1165 CompleteRange(range, RegisterKindFromPolicy(temp));
981 } else { 1166 } else {
982 UNREACHABLE(); 1167 UNREACHABLE();
983 } 1168 }
(...skipping 19 matching lines...) Expand all
1003 pos, 1188 pos,
1004 pos + 1); 1189 pos + 1);
1005 } 1190 }
1006 1191
1007 1192
1008 #if defined(DEBUG) 1193 #if defined(DEBUG)
1009 // Verify that temps, inputs and output were specified as fixed 1194 // Verify that temps, inputs and output were specified as fixed
1010 // locations. Every register is blocked now so attempt to 1195 // locations. Every register is blocked now so attempt to
1011 // allocate will not succeed. 1196 // allocate will not succeed.
1012 for (intptr_t j = 0; j < locs->temp_count(); j++) { 1197 for (intptr_t j = 0; j < locs->temp_count(); j++) {
1198 ASSERT(!locs->temp(j).IsPairLocation());
1013 ASSERT(!locs->temp(j).IsUnallocated()); 1199 ASSERT(!locs->temp(j).IsUnallocated());
1014 } 1200 }
1015 1201
1016 for (intptr_t j = 0; j < locs->input_count(); j++) { 1202 for (intptr_t j = 0; j < locs->input_count(); j++) {
1017 ASSERT(!locs->in(j).IsUnallocated()); 1203 if (locs->in(j).IsPairLocation()) {
1204 PairLocation* pair = locs->in_slot(j)->AsPairLocation();
1205 ASSERT(!pair->At(0).IsUnallocated());
1206 ASSERT(!pair->At(1).IsUnallocated());
1207 } else {
1208 ASSERT(!locs->in(j).IsUnallocated());
1209 }
1018 } 1210 }
1019 1211
1020 ASSERT(!locs->out(0).IsUnallocated()); 1212 if (locs->out(0).IsPairLocation()) {
1213 PairLocation* pair = locs->out_slot(0)->AsPairLocation();
1214 ASSERT(!pair->At(0).IsUnallocated());
1215 ASSERT(!pair->At(1).IsUnallocated());
1216 } else {
1217 ASSERT(!locs->out(0).IsUnallocated());
1218 }
1021 #endif 1219 #endif
1022 } 1220 }
1023 1221
1024 if (locs->can_call()) { 1222 if (locs->can_call()) {
1025 safepoints_.Add(current); 1223 safepoints_.Add(current);
1026 } 1224 }
1027 1225
1028 if (def == NULL) { 1226 if (def == NULL) {
1029 ASSERT(locs->out(0).IsInvalid()); 1227 ASSERT(locs->out(0).IsInvalid());
1030 return; 1228 return;
1031 } 1229 }
1032 1230
1033 if (locs->out(0).IsInvalid()) { 1231 if (locs->out(0).IsInvalid()) {
1034 ASSERT(def->ssa_temp_index() < 0); 1232 ASSERT(def->ssa_temp_index() < 0);
1035 return; 1233 return;
1036 } 1234 }
1037 1235
1038 // We might have a definition without use. We do not assign SSA index to 1236 ASSERT(locs->output_count() == 1);
1039 // such definitions.
1040 LiveRange* range = (def->ssa_temp_index() >= 0) ?
1041 GetLiveRange(def->ssa_temp_index()) :
1042 MakeLiveRangeForTemporary();
1043 Location* out = locs->out_slot(0); 1237 Location* out = locs->out_slot(0);
1044 1238 if (out->IsPairLocation()) {
1045 // Process output and finalize its liverange. 1239 ASSERT(def->HasPairRepresentation());
1046 if (out->IsMachineRegister()) { 1240 PairLocation* pair = out->AsPairLocation();
1047 // Fixed output location. Expected shape of live range: 1241 if (output_same_as_first_input) {
1048 // 1242 ASSERT(locs->in_slot(0)->IsPairLocation());
1049 // i i' j j' 1243 PairLocation* in_pair = locs->in_slot(0)->AsPairLocation();
1050 // register [--) 1244 Definition* input = current->InputAt(0)->definition();
1051 // output [------- 1245 ASSERT(input->HasPairRepresentation());
1052 // 1246 // Each element of the pair is assigned it's own virtual register number
1053 BlockLocation(*out, pos, pos + 1); 1247 // and is allocated its own LiveRange.
1054 1248 ProcessOneOutput(block, current, pos, // BlockEntry, Instruction, seq.
1055 if (range->vreg() == kTempVirtualRegister) return; 1249 pair->SlotAt(0), def, // (output) Location, Definition.
1056 1250 def->ssa_temp_index(), // (output) virtual register.
1057 // We need to emit move connecting fixed register with another location 1251 true, // output mapped to first input.
1058 // that will be allocated for this output's live range. 1252 in_pair->SlotAt(0), input, // (input) Location, Def.
1059 // Special case: fixed output followed by a fixed input last use. 1253 input->ssa_temp_index(), // (input) virtual register.
1060 UsePosition* use = range->first_use(); 1254 interference_set);
1061 1255 ProcessOneOutput(block, current, pos,
1062 // If the value has no uses we don't need to allocate it. 1256 pair->SlotAt(1), def,
1063 if (use == NULL) return; 1257 ToSecondPairVreg(def->ssa_temp_index()),
1064 1258 true,
1065 if (use->pos() == (pos + 1)) { 1259 in_pair->SlotAt(1), input,
1066 ASSERT(use->location_slot()->IsUnallocated()); 1260 ToSecondPairVreg(input->ssa_temp_index()),
1067 *(use->location_slot()) = *out; 1261 interference_set);
1068 1262 } else {
1069 // Remove first use. It was allocated. 1263 // Each element of the pair is assigned it's own virtual register number
1070 range->set_first_use(range->first_use()->next()); 1264 // and is allocated its own LiveRange.
1071 } 1265 ProcessOneOutput(block, current, pos,
1072 1266 pair->SlotAt(0), def,
1073 // Shorten live range to the point of definition, this might make the range 1267 def->ssa_temp_index(),
1074 // empty (if the only use immediately follows). If range is not empty add 1268 false, // output is not mapped to first input.
1075 // move from a fixed register to an unallocated location. 1269 NULL, NULL, -1, // First input not needed.
1076 range->DefineAt(pos + 1); 1270 interference_set);
1077 if (range->Start() == range->End()) return; 1271 ProcessOneOutput(block, current, pos,
1078 1272 pair->SlotAt(1), def,
1079 MoveOperands* move = AddMoveAt(pos + 1, Location::Any(), *out); 1273 ToSecondPairVreg(def->ssa_temp_index()),
1080 range->AddHintedUse(pos + 1, move->dest_slot(), out); 1274 false,
1081 } else if (output_same_as_first_input) { 1275 NULL, NULL, -1,
1082 // Output register will contain a value of the first input at instruction's 1276 interference_set);
1083 // start. Expected shape of live ranges:
1084 //
1085 // i i'
1086 // input #0 --*
1087 // output [----
1088 //
1089 ASSERT(locs->in(0).Equals(Location::RequiresRegister()) ||
1090 locs->in(0).Equals(Location::RequiresFpuRegister()));
1091
1092 // Create move that will copy value between input and output.
1093 locs->set_out(0, Location::RequiresRegister());
1094 MoveOperands* move = AddMoveAt(pos,
1095 Location::RequiresRegister(),
1096 Location::Any());
1097
1098 // Add uses to the live range of the input.
1099 Definition* input = current->InputAt(0)->definition();
1100 LiveRange* input_range =
1101 GetLiveRange(input->ssa_temp_index());
1102 input_range->AddUseInterval(block->start_pos(), pos);
1103 input_range->AddUse(pos, move->src_slot());
1104
1105 // Shorten output live range to the point of definition and add both input
1106 // and output uses slots to be filled by allocator.
1107 range->DefineAt(pos);
1108 range->AddHintedUse(pos, out, move->src_slot());
1109 range->AddUse(pos, move->dest_slot());
1110 range->AddUse(pos, locs->in_slot(0));
1111
1112 if ((interference_set != NULL) &&
1113 (range->vreg() >= 0) &&
1114 interference_set->Contains(range->vreg())) {
1115 interference_set->Add(input->ssa_temp_index());
1116 } 1277 }
1117 } else { 1278 } else {
1118 // Normal unallocated location that requires a register. Expected shape of 1279 if (output_same_as_first_input) {
1119 // live range: 1280 Location* in_ref = locs->in_slot(0);
1120 // 1281 Definition* input = current->InputAt(0)->definition();
1121 // i i' 1282 ASSERT(!in_ref->IsPairLocation());
1122 // output [------- 1283 ProcessOneOutput(block, current, pos, // BlockEntry, Instruction, seq.
1123 // 1284 out, def, // (output) Location, Definition.
1124 ASSERT(locs->out(0).Equals(Location::RequiresRegister()) || 1285 def->ssa_temp_index(), // (output) virtual register.
1125 locs->out(0).Equals(Location::RequiresFpuRegister())); 1286 true, // output mapped to first input.
1126 1287 in_ref, input, // (input) Location, Def.
1127 // Shorten live range to the point of definition and add use to be filled by 1288 input->ssa_temp_index(), // (input) virtual register.
1128 // allocator. 1289 interference_set);
1129 range->DefineAt(pos); 1290 } else {
1130 range->AddUse(pos, out); 1291 ProcessOneOutput(block, current, pos,
1292 out, def,
1293 def->ssa_temp_index(),
1294 false, // output is not mapped to first input.
1295 NULL, NULL, -1, // First input not needed.
1296 interference_set);
1297 }
1131 } 1298 }
1132
1133 AssignSafepoints(range);
1134 CompleteRange(range, RegisterKindForResult(current));
1135 } 1299 }
1136 1300
1137 1301
1138 static ParallelMoveInstr* CreateParallelMoveBefore(Instruction* instr, 1302 static ParallelMoveInstr* CreateParallelMoveBefore(Instruction* instr,
1139 intptr_t pos) { 1303 intptr_t pos) {
1140 ASSERT(pos > 0); 1304 ASSERT(pos > 0);
1141 Instruction* prev = instr->previous(); 1305 Instruction* prev = instr->previous();
1142 ParallelMoveInstr* move = prev->AsParallelMove(); 1306 ParallelMoveInstr* move = prev->AsParallelMove();
1143 if ((move == NULL) || (move->lifetime_position() != pos)) { 1307 if ((move == NULL) || (move->lifetime_position() != pos)) {
1144 move = new ParallelMoveInstr(); 1308 move = new ParallelMoveInstr();
(...skipping 566 matching lines...) Expand 10 before | Expand all | Expand 10 after
1711 const intptr_t pos = FirstIntersection( 1875 const intptr_t pos = FirstIntersection(
1712 unallocated->finger()->first_pending_use_interval(), 1876 unallocated->finger()->first_pending_use_interval(),
1713 allocated_head); 1877 allocated_head);
1714 if (pos < intersection) intersection = pos; 1878 if (pos < intersection) intersection = pos;
1715 } 1879 }
1716 return intersection; 1880 return intersection;
1717 } 1881 }
1718 1882
1719 1883
1720 void ReachingDefs::AddPhi(PhiInstr* phi) { 1884 void ReachingDefs::AddPhi(PhiInstr* phi) {
1885 // TODO(johnmccutchan): Fix handling of PhiInstr with PairLocation.
1721 if (phi->reaching_defs() == NULL) { 1886 if (phi->reaching_defs() == NULL) {
1722 phi->set_reaching_defs( 1887 phi->set_reaching_defs(
1723 new BitVector(flow_graph_.max_virtual_register_number())); 1888 new BitVector(flow_graph_.max_virtual_register_number()));
1724 1889
1725 // Compute initial set reaching defs set. 1890 // Compute initial set reaching defs set.
1726 bool depends_on_phi = false; 1891 bool depends_on_phi = false;
1727 for (intptr_t i = 0; i < phi->InputCount(); i++) { 1892 for (intptr_t i = 0; i < phi->InputCount(); i++) {
1728 Definition* input = phi->InputAt(i)->definition(); 1893 Definition* input = phi->InputAt(i)->definition();
1729 if (input->IsPhi()) { 1894 if (input->IsPhi()) {
1730 depends_on_phi = true; 1895 depends_on_phi = true;
1731 } 1896 }
1732 phi->reaching_defs()->Add(input->ssa_temp_index()); 1897 phi->reaching_defs()->Add(input->ssa_temp_index());
1733 } 1898 }
1734 1899
1735 // If this phi depends on another phi then we need fix point iteration. 1900 // If this phi depends on another phi then we need fix point iteration.
1736 if (depends_on_phi) phis_.Add(phi); 1901 if (depends_on_phi) phis_.Add(phi);
1737 } 1902 }
1738 } 1903 }
1739 1904
1740 1905
1741 void ReachingDefs::Compute() { 1906 void ReachingDefs::Compute() {
1742 // Transitively collect all phis that are used by the given phi. 1907 // Transitively collect all phis that are used by the given phi.
1743 for (intptr_t i = 0; i < phis_.length(); i++) { 1908 for (intptr_t i = 0; i < phis_.length(); i++) {
1909 // TODO(johnmccutchan): Fix handling of PhiInstr with PairLocation.
1744 PhiInstr* phi = phis_[i]; 1910 PhiInstr* phi = phis_[i];
1745 1911
1746 // Add all phis that affect this phi to the list. 1912 // Add all phis that affect this phi to the list.
1747 for (intptr_t i = 0; i < phi->InputCount(); i++) { 1913 for (intptr_t i = 0; i < phi->InputCount(); i++) {
1748 PhiInstr* input_phi = phi->InputAt(i)->definition()->AsPhi(); 1914 PhiInstr* input_phi = phi->InputAt(i)->definition()->AsPhi();
1749 if (input_phi != NULL) { 1915 if (input_phi != NULL) {
1750 AddPhi(input_phi); 1916 AddPhi(input_phi);
1751 } 1917 }
1752 } 1918 }
1753 } 1919 }
(...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after
1837 (loop_header != NULL) && 2003 (loop_header != NULL) &&
1838 (free_until >= loop_header->last_block()->end_pos()) && 2004 (free_until >= loop_header->last_block()->end_pos()) &&
1839 loop_header->backedge_interference()->Contains(unallocated->vreg())) { 2005 loop_header->backedge_interference()->Contains(unallocated->vreg())) {
1840 ASSERT(static_cast<intptr_t>(kNumberOfFpuRegisters) <= 2006 ASSERT(static_cast<intptr_t>(kNumberOfFpuRegisters) <=
1841 kNumberOfCpuRegisters); 2007 kNumberOfCpuRegisters);
1842 bool used_on_backedge[kNumberOfCpuRegisters] = { false }; 2008 bool used_on_backedge[kNumberOfCpuRegisters] = { false };
1843 2009
1844 for (PhiIterator it(loop_header->entry()->AsJoinEntry()); 2010 for (PhiIterator it(loop_header->entry()->AsJoinEntry());
1845 !it.Done(); 2011 !it.Done();
1846 it.Advance()) { 2012 it.Advance()) {
2013 // TODO(johnmccutchan): Fix handling of PhiInstr with PairLocation.
1847 PhiInstr* phi = it.Current(); 2014 PhiInstr* phi = it.Current();
1848 ASSERT(phi->is_alive()); 2015 ASSERT(phi->is_alive());
1849 const intptr_t phi_vreg = phi->ssa_temp_index(); 2016 const intptr_t phi_vreg = phi->ssa_temp_index();
1850 LiveRange* range = GetLiveRange(phi_vreg); 2017 LiveRange* range = GetLiveRange(phi_vreg);
1851 if (range->assigned_location().kind() == register_kind_) { 2018 if (range->assigned_location().kind() == register_kind_) {
1852 const intptr_t reg = range->assigned_location().register_code(); 2019 const intptr_t reg = range->assigned_location().register_code();
1853 2020
1854 if (!reaching_defs_.Get(phi)->Contains(unallocated->vreg())) { 2021 if (!reaching_defs_.Get(phi)->Contains(unallocated->vreg())) {
1855 used_on_backedge[reg] = true; 2022 used_on_backedge[reg] = true;
1856 } 2023 }
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after
1901 registers_[candidate].Add(unallocated); 2068 registers_[candidate].Add(unallocated);
1902 unallocated->set_assigned_location(MakeRegisterLocation(candidate)); 2069 unallocated->set_assigned_location(MakeRegisterLocation(candidate));
1903 2070
1904 return true; 2071 return true;
1905 } 2072 }
1906 2073
1907 2074
1908 bool FlowGraphAllocator::RangeHasOnlyUnconstrainedUsesInLoop(LiveRange* range, 2075 bool FlowGraphAllocator::RangeHasOnlyUnconstrainedUsesInLoop(LiveRange* range,
1909 intptr_t loop_id) { 2076 intptr_t loop_id) {
1910 if (range->vreg() >= 0) { 2077 if (range->vreg() >= 0) {
1911 return GetLiveRange(range->vreg())->HasOnlyUnconstrainedUsesInLoop(loop_id); 2078 LiveRange* parent = GetLiveRange(range->vreg());
2079 return parent->HasOnlyUnconstrainedUsesInLoop(loop_id);
1912 } 2080 }
1913 return false; 2081 return false;
1914 } 2082 }
1915 2083
1916 2084
1917 bool FlowGraphAllocator::IsCheapToEvictRegisterInLoop(BlockInfo* loop, 2085 bool FlowGraphAllocator::IsCheapToEvictRegisterInLoop(BlockInfo* loop,
1918 intptr_t reg) { 2086 intptr_t reg) {
1919 const intptr_t loop_start = loop->entry()->start_pos(); 2087 const intptr_t loop_start = loop->entry()->start_pos();
1920 const intptr_t loop_end = loop->last_block()->end_pos(); 2088 const intptr_t loop_end = loop->last_block()->end_pos();
1921 2089
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after
1982 const intptr_t register_use_pos = 2150 const intptr_t register_use_pos =
1983 (register_use != NULL) ? register_use->pos() 2151 (register_use != NULL) ? register_use->pos()
1984 : unallocated->Start(); 2152 : unallocated->Start();
1985 if (free_until < register_use_pos) { 2153 if (free_until < register_use_pos) {
1986 // Can't acquire free register. Spill until we really need one. 2154 // Can't acquire free register. Spill until we really need one.
1987 ASSERT(unallocated->Start() < ToInstructionStart(register_use_pos)); 2155 ASSERT(unallocated->Start() < ToInstructionStart(register_use_pos));
1988 SpillBetween(unallocated, unallocated->Start(), register_use->pos()); 2156 SpillBetween(unallocated, unallocated->Start(), register_use->pos());
1989 return; 2157 return;
1990 } 2158 }
1991 2159
2160 ASSERT(candidate != kNoRegister);
2161
1992 TRACE_ALLOC(OS::Print("assigning blocked register ")); 2162 TRACE_ALLOC(OS::Print("assigning blocked register "));
1993 TRACE_ALLOC(MakeRegisterLocation(candidate).Print()); 2163 TRACE_ALLOC(MakeRegisterLocation(candidate).Print());
1994 TRACE_ALLOC(OS::Print(" to live range v%" Pd " until %" Pd "\n", 2164 TRACE_ALLOC(OS::Print(" to live range v%" Pd " until %" Pd "\n",
1995 unallocated->vreg(), blocked_at)); 2165 unallocated->vreg(), blocked_at));
1996 2166
1997 if (blocked_at < unallocated->End()) { 2167 if (blocked_at < unallocated->End()) {
1998 // Register is blocked before the end of the live range. Split the range 2168 // Register is blocked before the end of the live range. Split the range
1999 // at latest at blocked_at position. 2169 // at latest at blocked_at position.
2000 LiveRange* tail = SplitBetween(unallocated, 2170 LiveRange* tail = SplitBetween(unallocated,
2001 unallocated->Start(), 2171 unallocated->Start(),
(...skipping 490 matching lines...) Expand 10 before | Expand all | Expand 10 after
2492 } 2662 }
2493 } 2663 }
2494 2664
2495 2665
2496 void FlowGraphAllocator::CollectRepresentations() { 2666 void FlowGraphAllocator::CollectRepresentations() {
2497 // Parameters. 2667 // Parameters.
2498 GraphEntryInstr* graph_entry = flow_graph_.graph_entry(); 2668 GraphEntryInstr* graph_entry = flow_graph_.graph_entry();
2499 for (intptr_t i = 0; i < graph_entry->initial_definitions()->length(); ++i) { 2669 for (intptr_t i = 0; i < graph_entry->initial_definitions()->length(); ++i) {
2500 Definition* def = (*graph_entry->initial_definitions())[i]; 2670 Definition* def = (*graph_entry->initial_definitions())[i];
2501 value_representations_[def->ssa_temp_index()] = def->representation(); 2671 value_representations_[def->ssa_temp_index()] = def->representation();
2672 ASSERT(!def->HasPairRepresentation());
2502 } 2673 }
2503 2674
2504 for (BlockIterator it = flow_graph_.reverse_postorder_iterator(); 2675 for (BlockIterator it = flow_graph_.reverse_postorder_iterator();
2505 !it.Done(); 2676 !it.Done();
2506 it.Advance()) { 2677 it.Advance()) {
2507 BlockEntryInstr* block = it.Current(); 2678 BlockEntryInstr* block = it.Current();
2508 2679
2509 // Catch entry. 2680 // Catch entry.
2510 if (block->IsCatchBlockEntry()) { 2681 if (block->IsCatchBlockEntry()) {
2511 CatchBlockEntryInstr* catch_entry = block->AsCatchBlockEntry(); 2682 CatchBlockEntryInstr* catch_entry = block->AsCatchBlockEntry();
2512 for (intptr_t i = 0; 2683 for (intptr_t i = 0;
2513 i < catch_entry->initial_definitions()->length(); 2684 i < catch_entry->initial_definitions()->length();
2514 ++i) { 2685 ++i) {
2515 Definition* def = (*catch_entry->initial_definitions())[i]; 2686 Definition* def = (*catch_entry->initial_definitions())[i];
2516 value_representations_[def->ssa_temp_index()] = def->representation(); 2687 value_representations_[def->ssa_temp_index()] = def->representation();
2517 } 2688 }
2518 } 2689 }
2519 // Phis. 2690 // Phis.
2520 if (block->IsJoinEntry()) { 2691 if (block->IsJoinEntry()) {
2521 JoinEntryInstr* join = block->AsJoinEntry(); 2692 JoinEntryInstr* join = block->AsJoinEntry();
2522 for (PhiIterator it(join); !it.Done(); it.Advance()) { 2693 for (PhiIterator it(join); !it.Done(); it.Advance()) {
2694 // TODO(johnmccutchan): Fix handling of PhiInstr with PairLocation.
2523 PhiInstr* phi = it.Current(); 2695 PhiInstr* phi = it.Current();
2524 if ((phi != NULL) && (phi->ssa_temp_index() >= 0)) { 2696 if ((phi != NULL) && (phi->ssa_temp_index() >= 0)) {
2525 value_representations_[phi->ssa_temp_index()] = phi->representation(); 2697 value_representations_[phi->ssa_temp_index()] = phi->representation();
2526 } 2698 }
2527 } 2699 }
2528 } 2700 }
2529 // Normal instructions. 2701 // Normal instructions.
2530 for (ForwardInstructionIterator instr_it(block); 2702 for (ForwardInstructionIterator instr_it(block);
2531 !instr_it.Done(); 2703 !instr_it.Done();
2532 instr_it.Advance()) { 2704 instr_it.Advance()) {
2533 Definition* def = instr_it.Current()->AsDefinition(); 2705 Definition* def = instr_it.Current()->AsDefinition();
2534 if ((def != NULL) && (def->ssa_temp_index() >= 0)) { 2706 if ((def != NULL) && (def->ssa_temp_index() >= 0)) {
2535 value_representations_[def->ssa_temp_index()] = def->representation(); 2707 const intptr_t vreg = def->ssa_temp_index();
2708 value_representations_[vreg] = def->representation();
2709 if (def->HasPairRepresentation()) {
2710 value_representations_[ToSecondPairVreg(vreg)] = def->representation();
2711 }
2536 } 2712 }
2537 } 2713 }
2538 } 2714 }
2539 } 2715 }
2540 2716
2541 2717
2542 void FlowGraphAllocator::AllocateRegisters() { 2718 void FlowGraphAllocator::AllocateRegisters() {
2543 CollectRepresentations(); 2719 CollectRepresentations();
2544 2720
2545 liveness_.Analyze(); 2721 liveness_.Analyze();
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after
2605 OS::Print("-- [after ssa allocator] ir [%s] -------------\n", 2781 OS::Print("-- [after ssa allocator] ir [%s] -------------\n",
2606 function.ToFullyQualifiedCString()); 2782 function.ToFullyQualifiedCString());
2607 FlowGraphPrinter printer(flow_graph_, true); 2783 FlowGraphPrinter printer(flow_graph_, true);
2608 printer.PrintBlocks(); 2784 printer.PrintBlocks();
2609 OS::Print("----------------------------------------------\n"); 2785 OS::Print("----------------------------------------------\n");
2610 } 2786 }
2611 } 2787 }
2612 2788
2613 2789
2614 } // namespace dart 2790 } // namespace dart
OLDNEW
« no previous file with comments | « runtime/vm/flow_graph_allocator.h ('k') | runtime/vm/flow_graph_optimizer.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698