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

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
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 56 matching lines...) Expand 10 before | Expand all | Expand 10 after
67 block_order_(flow_graph.reverse_postorder()), 67 block_order_(flow_graph.reverse_postorder()),
68 postorder_(flow_graph.postorder()), 68 postorder_(flow_graph.postorder()),
69 liveness_(flow_graph), 69 liveness_(flow_graph),
70 vreg_count_(flow_graph.max_virtual_register_number()), 70 vreg_count_(flow_graph.max_virtual_register_number()),
71 live_ranges_(flow_graph.max_virtual_register_number()), 71 live_ranges_(flow_graph.max_virtual_register_number()),
72 cpu_regs_(), 72 cpu_regs_(),
73 fpu_regs_(), 73 fpu_regs_(),
74 blocked_cpu_registers_(), 74 blocked_cpu_registers_(),
75 blocked_fpu_registers_(), 75 blocked_fpu_registers_(),
76 cpu_spill_slot_count_(0) { 76 cpu_spill_slot_count_(0) {
77 for (intptr_t i = 0; i < vreg_count_; i++) live_ranges_.Add(NULL); 77 for (intptr_t i = 0; i < vreg_count_; i++) {
78 live_ranges_.Add(NULL);
79 }
78 for (intptr_t i = 0; i < vreg_count_; i++) { 80 for (intptr_t i = 0; i < vreg_count_; i++) {
79 value_representations_.Add(kNoRepresentation); 81 value_representations_.Add(kNoRepresentation);
80 } 82 }
81 83
82 // All registers are marked as "not blocked" (array initialized to false). 84 // All registers are marked as "not blocked" (array initialized to false).
83 // Mark the unavailable ones as "blocked" (true). 85 // Mark the unavailable ones as "blocked" (true).
84 for (intptr_t i = 0; i < kFirstFreeCpuRegister; i++) { 86 for (intptr_t i = 0; i < kFirstFreeCpuRegister; i++) {
85 blocked_cpu_registers_[i] = true; 87 blocked_cpu_registers_[i] = true;
86 } 88 }
87 for (intptr_t i = kLastFreeCpuRegister + 1; i < kNumberOfCpuRegisters; i++) { 89 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++) { 109 for (intptr_t i = 0; i < block_count; i++) {
108 BlockEntryInstr* block = postorder_[i]; 110 BlockEntryInstr* block = postorder_[i];
109 111
110 BitVector* kill = kill_[i]; 112 BitVector* kill = kill_[i];
111 BitVector* live_in = live_in_[i]; 113 BitVector* live_in = live_in_[i];
112 114
113 // Iterate backwards starting at the last instruction. 115 // Iterate backwards starting at the last instruction.
114 for (BackwardInstructionIterator it(block); !it.Done(); it.Advance()) { 116 for (BackwardInstructionIterator it(block); !it.Done(); it.Advance()) {
115 Instruction* current = it.Current(); 117 Instruction* current = it.Current();
116 118
119 // Initialize location summary for instruction.
120 current->InitializeLocationSummary(true); // Optimizing.
121 LocationSummary* locs = current->locs();
122
117 // Handle definitions. 123 // Handle definitions.
118 Definition* current_def = current->AsDefinition(); 124 Definition* current_def = current->AsDefinition();
119 if ((current_def != NULL) && current_def->HasSSATemp()) { 125 if ((current_def != NULL) && current_def->HasSSATemp()) {
120 kill->Add(current_def->ssa_temp_index()); 126 kill->Add(current_def->ssa_temp_index());
121 live_in->Remove(current_def->ssa_temp_index()); 127 live_in->Remove(current_def->ssa_temp_index());
128 if (current_def->RequiresPairSSAIndex()) {
129 kill->Add(current_def->pair_ssa_index());
130 live_in->Remove(current_def->pair_ssa_index());
131 }
122 } 132 }
123 133
124 // Handle uses. 134 // Handle uses.
125 current->InitializeLocationSummary(true); // Optimizing.
126 LocationSummary* locs = current->locs();
127 ASSERT(locs->input_count() == current->InputCount()); 135 ASSERT(locs->input_count() == current->InputCount());
128 for (intptr_t j = 0; j < current->InputCount(); j++) { 136 for (intptr_t j = 0; j < current->InputCount(); j++) {
129 Value* input = current->InputAt(j); 137 Value* input = current->InputAt(j);
130 const intptr_t use = input->definition()->ssa_temp_index();
131 138
132 ASSERT(!locs->in(j).IsConstant() || input->BindsToConstant()); 139 ASSERT(!locs->in(j).IsConstant() || input->BindsToConstant());
133 if (locs->in(j).IsConstant()) continue; 140 if (locs->in(j).IsConstant()) continue;
134 141
135 live_in->Add(use); 142 live_in->Add(input->definition()->ssa_temp_index());
143 if (input->definition()->RequiresPairSSAIndex()) {
144 live_in->Add(input->definition()->pair_ssa_index());
145 }
136 } 146 }
137 147
138 // Add non-argument uses from the deoptimization environment (pushed 148 // Add non-argument uses from the deoptimization environment (pushed
139 // arguments are not allocated by the register allocator). 149 // arguments are not allocated by the register allocator).
140 if (current->env() != NULL) { 150 if (current->env() != NULL) {
141 for (Environment::DeepIterator env_it(current->env()); 151 for (Environment::DeepIterator env_it(current->env());
142 !env_it.Done(); 152 !env_it.Done();
143 env_it.Advance()) { 153 env_it.Advance()) {
144 Definition* defn = env_it.CurrentValue()->definition(); 154 Definition* defn = env_it.CurrentValue()->definition();
145 if (defn->IsMaterializeObject()) { 155 if (defn->IsMaterializeObject()) {
146 // MaterializeObject instruction is not in the graph. 156 // MaterializeObject instruction is not in the graph.
147 // Treat its inputs as part of the environment. 157 // Treat its inputs as part of the environment.
148 for (intptr_t i = 0; i < defn->InputCount(); i++) { 158 for (intptr_t i = 0; i < defn->InputCount(); i++) {
149 if (!defn->InputAt(i)->BindsToConstant()) { 159 if (!defn->InputAt(i)->BindsToConstant()) {
150 live_in->Add(defn->InputAt(i)->definition()->ssa_temp_index()); 160 intptr_t idx = defn->InputAt(i)->definition()->ssa_temp_index();
161 live_in->Add(idx);
151 } 162 }
152 } 163 }
153 } else if (!defn->IsPushArgument() && !defn->IsConstant()) { 164 } else if (!defn->IsPushArgument() && !defn->IsConstant()) {
154 live_in->Add(defn->ssa_temp_index()); 165 live_in->Add(defn->ssa_temp_index());
166 if (defn->RequiresPairSSAIndex()) {
167 live_in->Add(defn->pair_ssa_index());
168 }
155 } 169 }
156 } 170 }
157 } 171 }
158 } 172 }
159 173
160 // Handle phis. 174 // Handle phis.
161 if (block->IsJoinEntry()) { 175 if (block->IsJoinEntry()) {
162 JoinEntryInstr* join = block->AsJoinEntry(); 176 JoinEntryInstr* join = block->AsJoinEntry();
163 for (PhiIterator it(join); !it.Done(); it.Advance()) { 177 for (PhiIterator it(join); !it.Done(); it.Advance()) {
178 // TODO(johnmccutchan): Fix handling of PhiInstr with PairLocation.
164 PhiInstr* phi = it.Current(); 179 PhiInstr* phi = it.Current();
165 ASSERT(phi != NULL); 180 ASSERT(phi != NULL);
166 kill->Add(phi->ssa_temp_index()); 181 kill->Add(phi->ssa_temp_index());
167 live_in->Remove(phi->ssa_temp_index()); 182 live_in->Remove(phi->ssa_temp_index());
168 183
169 // If a phi input is not defined by the corresponding predecessor it 184 // If a phi input is not defined by the corresponding predecessor it
170 // must be marked live-in for that predecessor. 185 // must be marked live-in for that predecessor.
171 for (intptr_t k = 0; k < phi->InputCount(); k++) { 186 for (intptr_t k = 0; k < phi->InputCount(); k++) {
172 Value* val = phi->InputAt(k); 187 Value* val = phi->InputAt(k);
173 if (val->BindsToConstant()) continue; 188 if (val->BindsToConstant()) continue;
174 189
175 BlockEntryInstr* pred = block->PredecessorAt(k); 190 BlockEntryInstr* pred = block->PredecessorAt(k);
176 const intptr_t use = val->definition()->ssa_temp_index(); 191 const intptr_t use = val->definition()->ssa_temp_index();
177 if (!kill_[pred->postorder_number()]->Contains(use)) { 192 if (!kill_[pred->postorder_number()]->Contains(use)) {
178 live_in_[pred->postorder_number()]->Add(use); 193 live_in_[pred->postorder_number()]->Add(use);
179 } 194 }
180 } 195 }
181 } 196 }
182 } else if (block->IsCatchBlockEntry()) { 197 } else if (block->IsCatchBlockEntry()) {
183 // Process initial definitions. 198 // Process initial definitions.
184 CatchBlockEntryInstr* catch_entry = block->AsCatchBlockEntry(); 199 CatchBlockEntryInstr* catch_entry = block->AsCatchBlockEntry();
185 for (intptr_t i = 0; 200 for (intptr_t i = 0;
186 i < catch_entry->initial_definitions()->length(); 201 i < catch_entry->initial_definitions()->length();
187 i++) { 202 i++) {
188 intptr_t vreg = 203 Definition* def = (*catch_entry->initial_definitions())[i];
189 (*catch_entry->initial_definitions())[i]->ssa_temp_index(); 204 const intptr_t vreg = def->ssa_temp_index();
190 kill_[catch_entry->postorder_number()]->Add(vreg); 205 kill_[catch_entry->postorder_number()]->Add(vreg);
191 live_in_[catch_entry->postorder_number()]->Remove(vreg); 206 live_in_[catch_entry->postorder_number()]->Remove(vreg);
192 } 207 }
193 } 208 }
194 } 209 }
195 210
196 // Process initial definitions, ie, constants and incoming parameters. 211 // Process initial definitions, ie, constants and incoming parameters.
197 for (intptr_t i = 0; i < graph_entry_->initial_definitions()->length(); i++) { 212 for (intptr_t i = 0; i < graph_entry_->initial_definitions()->length(); i++) {
198 intptr_t vreg = (*graph_entry_->initial_definitions())[i]->ssa_temp_index(); 213 Definition* def = (*graph_entry_->initial_definitions())[i];
214 const intptr_t vreg = def->ssa_temp_index();
199 kill_[graph_entry_->postorder_number()]->Add(vreg); 215 kill_[graph_entry_->postorder_number()]->Add(vreg);
200 live_in_[graph_entry_->postorder_number()]->Remove(vreg); 216 live_in_[graph_entry_->postorder_number()]->Remove(vreg);
201 } 217 }
202 218
203 // Update initial live_in sets to match live_out sets. Has to be 219 // Update initial live_in sets to match live_out sets. Has to be
204 // done in a separate path because of backwards branches. 220 // done in a separate path because of backwards branches.
205 for (intptr_t i = 0; i < block_count; i++) { 221 for (intptr_t i = 0; i < block_count; i++) {
206 UpdateLiveIn(*postorder_[i]); 222 UpdateLiveIn(*postorder_[i]);
207 } 223 }
208 } 224 }
(...skipping 391 matching lines...) Expand 10 before | Expand all | Expand 10 after
600 return Location::kRegister; 616 return Location::kRegister;
601 } 617 }
602 } 618 }
603 619
604 620
605 static Location::Kind RegisterKindForResult(Instruction* instr) { 621 static Location::Kind RegisterKindForResult(Instruction* instr) {
606 if ((instr->representation() == kUnboxedDouble) || 622 if ((instr->representation() == kUnboxedDouble) ||
607 (instr->representation() == kUnboxedMint) || 623 (instr->representation() == kUnboxedMint) ||
608 (instr->representation() == kUnboxedFloat32x4) || 624 (instr->representation() == kUnboxedFloat32x4) ||
609 (instr->representation() == kUnboxedInt32x4) || 625 (instr->representation() == kUnboxedInt32x4) ||
610 (instr->representation() == kUnboxedFloat64x2)) { 626 (instr->representation() == kUnboxedFloat64x2) ||
627 (instr->representation() == kPairOfUnboxedDouble)) {
611 return Location::kFpuRegister; 628 return Location::kFpuRegister;
612 } else { 629 } else {
613 return Location::kRegister; 630 return Location::kRegister;
614 } 631 }
615 } 632 }
616 633
617 634
618 // 635 //
619 // When describing shape of live ranges in comments below we are going to use 636 // When describing shape of live ranges in comments below we are going to use
620 // the following notation: 637 // the following notation:
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
659 JoinEntryInstr* join = goto_instr->successor(); 676 JoinEntryInstr* join = goto_instr->successor();
660 ASSERT(join != NULL); 677 ASSERT(join != NULL);
661 678
662 // Search for the index of the current block in the predecessors of 679 // Search for the index of the current block in the predecessors of
663 // the join. 680 // the join.
664 const intptr_t pred_idx = join->IndexOfPredecessor(block); 681 const intptr_t pred_idx = join->IndexOfPredecessor(block);
665 682
666 // Record the corresponding phi input use for each phi. 683 // Record the corresponding phi input use for each phi.
667 intptr_t move_idx = 0; 684 intptr_t move_idx = 0;
668 for (PhiIterator it(join); !it.Done(); it.Advance()) { 685 for (PhiIterator it(join); !it.Done(); it.Advance()) {
686 // TODO(johnmccutchan): Fix handling of PhiInstr with PairLocation.
669 PhiInstr* phi = it.Current(); 687 PhiInstr* phi = it.Current();
670 Value* val = phi->InputAt(pred_idx); 688 Value* val = phi->InputAt(pred_idx);
671 MoveOperands* move = parallel_move->MoveOperandsAt(move_idx); 689 MoveOperands* move = parallel_move->MoveOperandsAt(move_idx);
672 690
673 ConstantInstr* constant = val->definition()->AsConstant(); 691 ConstantInstr* constant = val->definition()->AsConstant();
674 if (constant != NULL) { 692 if (constant != NULL) {
675 move->set_src(Location::Constant(constant->value())); 693 move->set_src(Location::Constant(constant->value()));
676 move_idx++; 694 move_idx++;
677 continue; 695 continue;
678 } 696 }
(...skipping 23 matching lines...) Expand all
702 720
703 void FlowGraphAllocator::ConnectIncomingPhiMoves(JoinEntryInstr* join) { 721 void FlowGraphAllocator::ConnectIncomingPhiMoves(JoinEntryInstr* join) {
704 // For join blocks we need to add destinations of phi resolution moves 722 // 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. 723 // to phi's live range so that register allocator will fill them with moves.
706 724
707 // All uses are recorded at the start position in the block. 725 // All uses are recorded at the start position in the block.
708 const intptr_t pos = join->start_pos(); 726 const intptr_t pos = join->start_pos();
709 const bool is_loop_header = BlockInfoAt(join->start_pos())->is_loop_header(); 727 const bool is_loop_header = BlockInfoAt(join->start_pos())->is_loop_header();
710 intptr_t move_idx = 0; 728 intptr_t move_idx = 0;
711 for (PhiIterator it(join); !it.Done(); it.Advance()) { 729 for (PhiIterator it(join); !it.Done(); it.Advance()) {
730 // TODO(johnmccutchan): Fix handling of PhiInstr with PairLocation.
712 PhiInstr* phi = it.Current(); 731 PhiInstr* phi = it.Current();
713 ASSERT(phi != NULL); 732 ASSERT(phi != NULL);
714 const intptr_t vreg = phi->ssa_temp_index(); 733 const intptr_t vreg = phi->ssa_temp_index();
715 ASSERT(vreg >= 0); 734 ASSERT(vreg >= 0);
716 735
717 // Expected shape of live range: 736 // Expected shape of live range:
718 // 737 //
719 // B 738 // B
720 // phi [-------- 739 // phi [--------
721 // 740 //
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after
789 MaterializeObjectInstr* mat = def->AsMaterializeObject(); 808 MaterializeObjectInstr* mat = def->AsMaterializeObject();
790 if (mat != NULL) { 809 if (mat != NULL) {
791 // MaterializeObject itself produces no value. But its uses 810 // MaterializeObject itself produces no value. But its uses
792 // are treated as part of the environment: allocated locations 811 // are treated as part of the environment: allocated locations
793 // will be used when building deoptimization data. 812 // will be used when building deoptimization data.
794 locations[i] = Location::NoLocation(); 813 locations[i] = Location::NoLocation();
795 ProcessMaterializationUses(block, block_start_pos, use_pos, mat); 814 ProcessMaterializationUses(block, block_start_pos, use_pos, mat);
796 continue; 815 continue;
797 } 816 }
798 817
799 const intptr_t vreg = def->ssa_temp_index(); 818 LiveRange* range = GetLiveRange(def->ssa_temp_index());
800 LiveRange* range = GetLiveRange(vreg);
801 range->AddUseInterval(block_start_pos, use_pos); 819 range->AddUseInterval(block_start_pos, use_pos);
802 range->AddUse(use_pos, &locations[i]); 820 range->AddUse(use_pos, &locations[i]);
821
822 if (def->RequiresPairSSAIndex()) {
823 LiveRange* range = GetLiveRange(def->pair_ssa_index());
824 range->AddUseInterval(block_start_pos, use_pos);
825 range->AddUse(use_pos, &locations[i]);
826 }
803 } 827 }
804 828
805 env->set_locations(locations); 829 env->set_locations(locations);
806 env = env->outer(); 830 env = env->outer();
807 } 831 }
808 } 832 }
809 833
810 834
811 void FlowGraphAllocator::ProcessMaterializationUses( 835 void FlowGraphAllocator::ProcessMaterializationUses(
812 BlockEntryInstr* block, 836 BlockEntryInstr* block,
(...skipping 14 matching lines...) Expand all
827 Definition* def = mat->InputAt(i)->definition(); 851 Definition* def = mat->InputAt(i)->definition();
828 852
829 ConstantInstr* constant = def->AsConstant(); 853 ConstantInstr* constant = def->AsConstant();
830 if (constant != NULL) { 854 if (constant != NULL) {
831 locations[i] = Location::Constant(constant->value()); 855 locations[i] = Location::Constant(constant->value());
832 continue; 856 continue;
833 } 857 }
834 858
835 locations[i] = Location::Any(); 859 locations[i] = Location::Any();
836 860
837 const intptr_t vreg = def->ssa_temp_index(); 861 LiveRange* range = GetLiveRange(def->ssa_temp_index());
838 LiveRange* range = GetLiveRange(vreg);
839 range->AddUseInterval(block_start_pos, use_pos); 862 range->AddUseInterval(block_start_pos, use_pos);
840 range->AddUse(use_pos, &locations[i]); 863 range->AddUse(use_pos, &locations[i]);
864 if (def->RequiresPairSSAIndex()) {
865 LiveRange* range = GetLiveRange(def->pair_ssa_index());
866 range->AddUseInterval(block_start_pos, use_pos);
867 range->AddUse(use_pos, &locations[i]);
868 }
841 } 869 }
842 870
843 mat->set_locations(locations); 871 mat->set_locations(locations);
844 } 872 }
845 873
846 874
875 void FlowGraphAllocator::ProcessOneInput(BlockEntryInstr* block,
876 intptr_t pos,
877 Location* in_ref,
878 Value* input,
879 intptr_t vreg) {
880 ASSERT(in_ref != NULL);
881 ASSERT(!in_ref->IsPairLocation());
882 ASSERT(input != NULL);
883 ASSERT(block != NULL);
884 LiveRange* range = GetLiveRange(vreg);
885 if (in_ref->IsMachineRegister()) {
886 // Input is expected in a fixed register. Expected shape of
887 // live ranges:
888 //
889 // j' i i'
890 // value --*
891 // register [-----)
892 //
893 MoveOperands* move =
894 AddMoveAt(pos - 1, *in_ref, Location::Any());
895 BlockLocation(*in_ref, pos - 1, pos + 1);
896 range->AddUseInterval(block->start_pos(), pos - 1);
897 range->AddHintedUse(pos - 1, move->src_slot(), in_ref);
898 } else if (in_ref->IsUnallocated()) {
899 if (in_ref->policy() == Location::kWritableRegister) {
900 // Writable unallocated input. Expected shape of
901 // live ranges:
902 //
903 // j' i i'
904 // value --*
905 // temp [------)
906 MoveOperands* move = AddMoveAt(pos - 1,
907 Location::RequiresRegister(),
908 Location::PrefersRegister());
909
910 // Add uses to the live range of the input.
911 range->AddUseInterval(block->start_pos(), pos - 1);
912 range->AddUse(pos - 1, move->src_slot());
913
914 // Create live range for the temporary.
915 LiveRange* temp = MakeLiveRangeForTemporary();
916 temp->AddUseInterval(pos - 1, pos + 1);
917 temp->AddHintedUse(pos - 1, in_ref, move->src_slot());
918 temp->AddUse(pos + 1, move->dest_slot());
919 *in_ref = Location::RequiresRegister();
920 CompleteRange(temp, RegisterKindFromPolicy(*in_ref));
921 } else {
922 // Normal unallocated input. Expected shape of
923 // live ranges:
924 //
925 // i i'
926 // value -----*
927 //
928 range->AddUseInterval(block->start_pos(), pos + 1);
929 range->AddUse(pos + 1, in_ref);
930 }
931 } else {
932 ASSERT(in_ref->IsConstant());
933 }
934 }
935
936 void FlowGraphAllocator::ProcessOneOutput(BlockEntryInstr* block,
937 Instruction* current,
938 intptr_t pos,
939 Location* out,
940 Definition* def,
941 intptr_t vreg,
942 bool output_same_as_first_input,
943 Location* in_ref,
944 Definition* input,
945 intptr_t input_vreg,
946 BitVector* interference_set) {
947 ASSERT(out != NULL);
948 ASSERT(!out->IsPairLocation());
949 ASSERT(def != NULL);
950 ASSERT(block != NULL);
951
952 LiveRange* range = vreg >= 0 ?
953 GetLiveRange(vreg) : MakeLiveRangeForTemporary();
954
955 // Process output and finalize its liverange.
956 if (out->IsMachineRegister()) {
957 // Fixed output location. Expected shape of live range:
958 //
959 // i i' j j'
960 // register [--)
961 // output [-------
962 //
963 BlockLocation(*out, pos, pos + 1);
964
965 if (range->vreg() == kTempVirtualRegister) return;
966
967 // We need to emit move connecting fixed register with another location
968 // that will be allocated for this output's live range.
969 // Special case: fixed output followed by a fixed input last use.
970 UsePosition* use = range->first_use();
971
972 // If the value has no uses we don't need to allocate it.
973 if (use == NULL) return;
974
975 if (use->pos() == (pos + 1)) {
976 ASSERT(use->location_slot()->IsUnallocated());
977 *(use->location_slot()) = *out;
978
979 // Remove first use. It was allocated.
980 range->set_first_use(range->first_use()->next());
981 }
982
983 // Shorten live range to the point of definition, this might make the range
984 // empty (if the only use immediately follows). If range is not empty add
985 // move from a fixed register to an unallocated location.
986 range->DefineAt(pos + 1);
987 if (range->Start() == range->End()) return;
988
989 MoveOperands* move = AddMoveAt(pos + 1, Location::Any(), *out);
990 range->AddHintedUse(pos + 1, move->dest_slot(), out);
991 } else if (output_same_as_first_input) {
992 ASSERT(in_ref != NULL);
993 ASSERT(input != NULL);
994 // Output register will contain a value of the first input at instruction's
995 // start. Expected shape of live ranges:
996 //
997 // i i'
998 // input #0 --*
999 // output [----
1000 //
1001 ASSERT(in_ref->Equals(Location::RequiresRegister()) ||
1002 in_ref->Equals(Location::RequiresFpuRegister()));
1003
1004 // TODO(johnmccutchan): Without this I get allocated a register instead
1005 // of an FPU register. Figure out why.
1006
1007 *out = *in_ref;
1008 // Create move that will copy value between input and output.
1009 MoveOperands* move = AddMoveAt(pos,
1010 Location::RequiresRegister(),
1011 Location::Any());
1012
1013 // Add uses to the live range of the input.
1014 LiveRange* input_range = GetLiveRange(input_vreg);
1015 input_range->AddUseInterval(block->start_pos(), pos);
1016 input_range->AddUse(pos, move->src_slot());
1017
1018 // Shorten output live range to the point of definition and add both input
1019 // and output uses slots to be filled by allocator.
1020 range->DefineAt(pos);
1021 range->AddHintedUse(pos, out, move->src_slot());
1022 range->AddUse(pos, move->dest_slot());
1023 range->AddUse(pos, in_ref);
1024
1025 if ((interference_set != NULL) &&
1026 (range->vreg() >= 0) &&
1027 interference_set->Contains(range->vreg())) {
1028 interference_set->Add(input->ssa_temp_index());
1029 }
1030 } else {
1031 // Normal unallocated location that requires a register. Expected shape of
1032 // live range:
1033 //
1034 // i i'
1035 // output [-------
1036 //
1037 ASSERT(out->Equals(Location::RequiresRegister()) ||
1038 out->Equals(Location::RequiresFpuRegister()));
1039
1040 // Shorten live range to the point of definition and add use to be filled by
1041 // allocator.
1042 range->DefineAt(pos);
1043 range->AddUse(pos, out);
1044 }
1045
1046 AssignSafepoints(range);
1047 CompleteRange(range, RegisterKindForResult(current));
1048 }
1049
1050
847 // Create and update live ranges corresponding to instruction's inputs, 1051 // Create and update live ranges corresponding to instruction's inputs,
848 // temporaries and output. 1052 // temporaries and output.
849 void FlowGraphAllocator::ProcessOneInstruction(BlockEntryInstr* block, 1053 void FlowGraphAllocator::ProcessOneInstruction(BlockEntryInstr* block,
850 Instruction* current, 1054 Instruction* current,
851 BitVector* interference_set) { 1055 BitVector* interference_set) {
852 LocationSummary* locs = current->locs(); 1056 LocationSummary* locs = current->locs();
853 1057
854 Definition* def = current->AsDefinition(); 1058 Definition* def = current->AsDefinition();
855 if ((def != NULL) && (def->AsConstant() != NULL)) { 1059 if ((def != NULL) && (def->AsConstant() != NULL)) {
1060 ASSERT(!def->RequiresPairSSAIndex());
856 LiveRange* range = (def->ssa_temp_index() != -1) ? 1061 LiveRange* range = (def->ssa_temp_index() != -1) ?
857 GetLiveRange(def->ssa_temp_index()) : NULL; 1062 GetLiveRange(def->ssa_temp_index()) : NULL;
858 1063
859 // Drop definitions of constants that have no uses. 1064 // Drop definitions of constants that have no uses.
860 if ((range == NULL) || (range->first_use() == NULL)) { 1065 if ((range == NULL) || (range->first_use() == NULL)) {
861 locs->set_out(0, Location::NoLocation()); 1066 locs->set_out(0, Location::NoLocation());
862 return; 1067 return;
863 } 1068 }
864 1069
865 // If this constant has only unconstrained uses convert them all 1070 // If this constant has only unconstrained uses convert them all
866 // to use the constant directly and drop this definition. 1071 // to use the constant directly and drop this definition.
867 // TODO(vegorov): improve allocation when we have enough registers to keep 1072 // TODO(vegorov): improve allocation when we have enough registers to keep
868 // constants used in the loop in them. 1073 // constants used in the loop in them.
869 if (HasOnlyUnconstrainedUses(range)) { 1074 if (HasOnlyUnconstrainedUses(range)) {
870 const Object& value = def->AsConstant()->value(); 1075 const Object& value = def->AsConstant()->value();
871 range->set_assigned_location(Location::Constant(value)); 1076 range->set_assigned_location(Location::Constant(value));
872 range->set_spill_slot(Location::Constant(value)); 1077 range->set_spill_slot(Location::Constant(value));
873 range->finger()->Initialize(range); 1078 range->finger()->Initialize(range);
874 ConvertAllUses(range); 1079 ConvertAllUses(range);
875 1080
876 locs->set_out(0, Location::NoLocation()); 1081 locs->set_out(0, Location::NoLocation());
877 return; 1082 return;
878 } 1083 }
879 } 1084 }
880 1085
881 const intptr_t pos = current->lifetime_position(); 1086 const intptr_t pos = current->lifetime_position();
882 ASSERT(IsInstructionStartPosition(pos)); 1087 ASSERT(IsInstructionStartPosition(pos));
883 1088
884 // Number of input locations and number of input operands have to agree.
885 ASSERT(locs->input_count() == current->InputCount()); 1089 ASSERT(locs->input_count() == current->InputCount());
886 1090
887 // Normalize same-as-first-input output if input is specified as 1091 // Normalize same-as-first-input output if input is specified as
888 // fixed register. 1092 // fixed register.
889 if (locs->out(0).IsUnallocated() && 1093 if (locs->out(0).IsUnallocated() &&
890 (locs->out(0).policy() == Location::kSameAsFirstInput) && 1094 (locs->out(0).policy() == Location::kSameAsFirstInput) &&
891 (locs->in(0).IsMachineRegister())) { 1095 (locs->in(0).IsMachineRegister())) {
892 locs->set_out(0, locs->in(0)); 1096 locs->set_out(0, locs->in(0));
893 } 1097 }
894 1098
895 const bool output_same_as_first_input = 1099 const bool output_same_as_first_input =
896 locs->out(0).IsUnallocated() && 1100 locs->out(0).IsUnallocated() &&
897 (locs->out(0).policy() == Location::kSameAsFirstInput); 1101 (locs->out(0).policy() == Location::kSameAsFirstInput);
898 1102
899 // Add uses from the deoptimization environment. 1103 // Add uses from the deoptimization environment.
900 if (current->env() != NULL) ProcessEnvironmentUses(block, current); 1104 if (current->env() != NULL) ProcessEnvironmentUses(block, current);
901 1105
902 // Process inputs. 1106 // Process inputs.
903 // Skip the first input if output is specified with kSameAsFirstInput policy, 1107 // Skip the first input if output is specified with kSameAsFirstInput policy,
904 // they will be processed together at the very end. 1108 // they will be processed together at the very end.
905 for (intptr_t j = output_same_as_first_input ? 1 : 0; 1109 {
906 j < current->InputCount(); 1110 for (intptr_t j = output_same_as_first_input ? 1 : 0;
907 j++) { 1111 j < locs->input_count();
908 Value* input = current->InputAt(j); 1112 j++) {
909 const intptr_t vreg = input->definition()->ssa_temp_index(); 1113 // Determine if we are dealing with a value pair, and if so, whether
910 LiveRange* range = GetLiveRange(vreg); 1114 // the location is the first register or second register.
911 1115 Value* input = current->InputAt(j);
912 Location* in_ref = locs->in_slot(j); 1116 Location* in_ref = locs->in_slot(j);
913 1117 if (in_ref->IsPairLocation()) {
914 if (in_ref->IsMachineRegister()) { 1118 ASSERT(input->definition()->RequiresPairSSAIndex());
915 // Input is expected in a fixed register. Expected shape of 1119 PairLocation* pair = in_ref->AsPairLocation();
916 // live ranges: 1120 ProcessOneInput(block, pos, pair->SlotAt(0),
917 // 1121 input, input->definition()->ssa_temp_index());
918 // j' i i' 1122 ProcessOneInput(block, pos, pair->SlotAt(1), input,
919 // value --* 1123 input->definition()->pair_ssa_index());
920 // register [-----)
921 //
922 MoveOperands* move =
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 { 1124 } else {
951 // Normal unallocated input. Expected shape of 1125 ProcessOneInput(block, pos, in_ref, input,
952 // live ranges: 1126 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 } 1127 }
960 } else {
961 ASSERT(in_ref->IsConstant());
962 } 1128 }
963 } 1129 }
964 1130
1131
Florian Schneider 2014/04/04 11:52:46 No need for extra \n.
Cutch 2014/04/04 16:34:46 Done.
965 // Process temps. 1132 // Process temps.
966 for (intptr_t j = 0; j < locs->temp_count(); j++) { 1133 for (intptr_t j = 0; j < locs->temp_count(); j++) {
967 // Expected shape of live range: 1134 // Expected shape of live range:
968 // 1135 //
969 // i i' 1136 // i i'
970 // [--) 1137 // [--)
971 // 1138 //
972 1139
973 Location temp = locs->temp(j); 1140 Location temp = locs->temp(j);
1141 ASSERT(!temp.IsPairLocation());
974 if (temp.IsMachineRegister()) { 1142 if (temp.IsMachineRegister()) {
975 BlockLocation(temp, pos, pos + 1); 1143 BlockLocation(temp, pos, pos + 1);
976 } else if (temp.IsUnallocated()) { 1144 } else if (temp.IsUnallocated()) {
977 LiveRange* range = MakeLiveRangeForTemporary(); 1145 LiveRange* range = MakeLiveRangeForTemporary();
978 range->AddUseInterval(pos, pos + 1); 1146 range->AddUseInterval(pos, pos + 1);
979 range->AddUse(pos, locs->temp_slot(j)); 1147 range->AddUse(pos, locs->temp_slot(j));
980 CompleteRange(range, RegisterKindFromPolicy(temp)); 1148 CompleteRange(range, RegisterKindFromPolicy(temp));
981 } else { 1149 } else {
982 UNREACHABLE(); 1150 UNREACHABLE();
983 } 1151 }
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after
1028 if (def == NULL) { 1196 if (def == NULL) {
1029 ASSERT(locs->out(0).IsInvalid()); 1197 ASSERT(locs->out(0).IsInvalid());
1030 return; 1198 return;
1031 } 1199 }
1032 1200
1033 if (locs->out(0).IsInvalid()) { 1201 if (locs->out(0).IsInvalid()) {
1034 ASSERT(def->ssa_temp_index() < 0); 1202 ASSERT(def->ssa_temp_index() < 0);
1035 return; 1203 return;
1036 } 1204 }
1037 1205
1038 // We might have a definition without use. We do not assign SSA index to 1206 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); 1207 Location* out = locs->out_slot(0);
1044 1208 if (out->IsPairLocation()) {
1045 // Process output and finalize its liverange. 1209 ASSERT(def->RequiresPairSSAIndex());
1046 if (out->IsMachineRegister()) { 1210 PairLocation* pair = out->AsPairLocation();
1047 // Fixed output location. Expected shape of live range: 1211 if (output_same_as_first_input) {
1048 // 1212 ASSERT(locs->in_slot(0)->IsPairLocation());
1049 // i i' j j' 1213 PairLocation* in_pair = locs->in_slot(0)->AsPairLocation();
1050 // register [--) 1214 Definition* input = current->InputAt(0)->definition();
1051 // output [------- 1215 ASSERT(input->RequiresPairSSAIndex());
1052 // 1216 ProcessOneOutput(block, current, pos,
1053 BlockLocation(*out, pos, pos + 1); 1217 pair->SlotAt(0), def, def->ssa_temp_index(),
1054 1218 true,
1055 if (range->vreg() == kTempVirtualRegister) return; 1219 in_pair->SlotAt(0), input, input->ssa_temp_index(),
1056 1220 interference_set);
1057 // We need to emit move connecting fixed register with another location 1221 ProcessOneOutput(block, current, pos,
1058 // that will be allocated for this output's live range. 1222 pair->SlotAt(1), def, def->pair_ssa_index(),
1059 // Special case: fixed output followed by a fixed input last use. 1223 true,
1060 UsePosition* use = range->first_use(); 1224 in_pair->SlotAt(1), input, input->pair_ssa_index(),
1061 1225 interference_set);
1062 // If the value has no uses we don't need to allocate it. 1226 } else {
1063 if (use == NULL) return; 1227 ProcessOneOutput(block, current, pos,
1064 1228 pair->SlotAt(0), def, def->ssa_temp_index(),
1065 if (use->pos() == (pos + 1)) { 1229 false,
1066 ASSERT(use->location_slot()->IsUnallocated()); 1230 NULL, NULL, -1,
1067 *(use->location_slot()) = *out; 1231 interference_set);
1068 1232 ProcessOneOutput(block, current, pos,
1069 // Remove first use. It was allocated. 1233 pair->SlotAt(1), def, def->pair_ssa_index(),
1070 range->set_first_use(range->first_use()->next()); 1234 false,
1071 } 1235 NULL, NULL, -1,
1072 1236 interference_set);
1073 // Shorten live range to the point of definition, this might make the range
1074 // empty (if the only use immediately follows). If range is not empty add
1075 // move from a fixed register to an unallocated location.
1076 range->DefineAt(pos + 1);
1077 if (range->Start() == range->End()) return;
1078
1079 MoveOperands* move = AddMoveAt(pos + 1, Location::Any(), *out);
1080 range->AddHintedUse(pos + 1, move->dest_slot(), out);
1081 } else if (output_same_as_first_input) {
1082 // Output register will contain a value of the first input at instruction's
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 } 1237 }
1117 } else { 1238 } else {
1118 // Normal unallocated location that requires a register. Expected shape of 1239 if (output_same_as_first_input) {
1119 // live range: 1240 Location* in_ref = locs->in_slot(0);
1120 // 1241 Definition* input = current->InputAt(0)->definition();
1121 // i i' 1242 ASSERT(!in_ref->IsPairLocation());
1122 // output [------- 1243 ProcessOneOutput(block, current, pos,
1123 // 1244 out, def, def->ssa_temp_index(),
1124 ASSERT(locs->out(0).Equals(Location::RequiresRegister()) || 1245 true,
1125 locs->out(0).Equals(Location::RequiresFpuRegister())); 1246 in_ref, input, input->ssa_temp_index(),
1126 1247 interference_set);
1127 // Shorten live range to the point of definition and add use to be filled by 1248 } else {
1128 // allocator. 1249 ProcessOneOutput(block, current, pos,
1129 range->DefineAt(pos); 1250 out, def, def->ssa_temp_index(),
1130 range->AddUse(pos, out); 1251 false,
1252 NULL, NULL, -1,
1253 interference_set);
1254 }
1131 } 1255 }
1132
1133 AssignSafepoints(range);
1134 CompleteRange(range, RegisterKindForResult(current));
1135 } 1256 }
1136 1257
1137 1258
1138 static ParallelMoveInstr* CreateParallelMoveBefore(Instruction* instr, 1259 static ParallelMoveInstr* CreateParallelMoveBefore(Instruction* instr,
1139 intptr_t pos) { 1260 intptr_t pos) {
1140 ASSERT(pos > 0); 1261 ASSERT(pos > 0);
1141 Instruction* prev = instr->previous(); 1262 Instruction* prev = instr->previous();
1142 ParallelMoveInstr* move = prev->AsParallelMove(); 1263 ParallelMoveInstr* move = prev->AsParallelMove();
1143 if ((move == NULL) || (move->lifetime_position() != pos)) { 1264 if ((move == NULL) || (move->lifetime_position() != pos)) {
1144 move = new ParallelMoveInstr(); 1265 move = new ParallelMoveInstr();
(...skipping 566 matching lines...) Expand 10 before | Expand all | Expand 10 after
1711 const intptr_t pos = FirstIntersection( 1832 const intptr_t pos = FirstIntersection(
1712 unallocated->finger()->first_pending_use_interval(), 1833 unallocated->finger()->first_pending_use_interval(),
1713 allocated_head); 1834 allocated_head);
1714 if (pos < intersection) intersection = pos; 1835 if (pos < intersection) intersection = pos;
1715 } 1836 }
1716 return intersection; 1837 return intersection;
1717 } 1838 }
1718 1839
1719 1840
1720 void ReachingDefs::AddPhi(PhiInstr* phi) { 1841 void ReachingDefs::AddPhi(PhiInstr* phi) {
1842 // TODO(johnmccutchan): Fix handling of PhiInstr with PairLocation.
1721 if (phi->reaching_defs() == NULL) { 1843 if (phi->reaching_defs() == NULL) {
1722 phi->set_reaching_defs( 1844 phi->set_reaching_defs(
1723 new BitVector(flow_graph_.max_virtual_register_number())); 1845 new BitVector(flow_graph_.max_virtual_register_number()));
1724 1846
1725 // Compute initial set reaching defs set. 1847 // Compute initial set reaching defs set.
1726 bool depends_on_phi = false; 1848 bool depends_on_phi = false;
1727 for (intptr_t i = 0; i < phi->InputCount(); i++) { 1849 for (intptr_t i = 0; i < phi->InputCount(); i++) {
1728 Definition* input = phi->InputAt(i)->definition(); 1850 Definition* input = phi->InputAt(i)->definition();
1729 if (input->IsPhi()) { 1851 if (input->IsPhi()) {
1730 depends_on_phi = true; 1852 depends_on_phi = true;
1731 } 1853 }
1732 phi->reaching_defs()->Add(input->ssa_temp_index()); 1854 phi->reaching_defs()->Add(input->ssa_temp_index());
1733 } 1855 }
1734 1856
1735 // If this phi depends on another phi then we need fix point iteration. 1857 // If this phi depends on another phi then we need fix point iteration.
1736 if (depends_on_phi) phis_.Add(phi); 1858 if (depends_on_phi) phis_.Add(phi);
1737 } 1859 }
1738 } 1860 }
1739 1861
1740 1862
1741 void ReachingDefs::Compute() { 1863 void ReachingDefs::Compute() {
1742 // Transitively collect all phis that are used by the given phi. 1864 // Transitively collect all phis that are used by the given phi.
1743 for (intptr_t i = 0; i < phis_.length(); i++) { 1865 for (intptr_t i = 0; i < phis_.length(); i++) {
1866 // TODO(johnmccutchan): Fix handling of PhiInstr with PairLocation.
1744 PhiInstr* phi = phis_[i]; 1867 PhiInstr* phi = phis_[i];
1745 1868
1746 // Add all phis that affect this phi to the list. 1869 // Add all phis that affect this phi to the list.
1747 for (intptr_t i = 0; i < phi->InputCount(); i++) { 1870 for (intptr_t i = 0; i < phi->InputCount(); i++) {
1748 PhiInstr* input_phi = phi->InputAt(i)->definition()->AsPhi(); 1871 PhiInstr* input_phi = phi->InputAt(i)->definition()->AsPhi();
1749 if (input_phi != NULL) { 1872 if (input_phi != NULL) {
1750 AddPhi(input_phi); 1873 AddPhi(input_phi);
1751 } 1874 }
1752 } 1875 }
1753 } 1876 }
(...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after
1837 (loop_header != NULL) && 1960 (loop_header != NULL) &&
1838 (free_until >= loop_header->last_block()->end_pos()) && 1961 (free_until >= loop_header->last_block()->end_pos()) &&
1839 loop_header->backedge_interference()->Contains(unallocated->vreg())) { 1962 loop_header->backedge_interference()->Contains(unallocated->vreg())) {
1840 ASSERT(static_cast<intptr_t>(kNumberOfFpuRegisters) <= 1963 ASSERT(static_cast<intptr_t>(kNumberOfFpuRegisters) <=
1841 kNumberOfCpuRegisters); 1964 kNumberOfCpuRegisters);
1842 bool used_on_backedge[kNumberOfCpuRegisters] = { false }; 1965 bool used_on_backedge[kNumberOfCpuRegisters] = { false };
1843 1966
1844 for (PhiIterator it(loop_header->entry()->AsJoinEntry()); 1967 for (PhiIterator it(loop_header->entry()->AsJoinEntry());
1845 !it.Done(); 1968 !it.Done();
1846 it.Advance()) { 1969 it.Advance()) {
1970 // TODO(johnmccutchan): Fix handling of PhiInstr with PairLocation.
1847 PhiInstr* phi = it.Current(); 1971 PhiInstr* phi = it.Current();
1848 ASSERT(phi->is_alive()); 1972 ASSERT(phi->is_alive());
1849 const intptr_t phi_vreg = phi->ssa_temp_index(); 1973 const intptr_t phi_vreg = phi->ssa_temp_index();
1850 LiveRange* range = GetLiveRange(phi_vreg); 1974 LiveRange* range = GetLiveRange(phi_vreg);
1851 if (range->assigned_location().kind() == register_kind_) { 1975 if (range->assigned_location().kind() == register_kind_) {
1852 const intptr_t reg = range->assigned_location().register_code(); 1976 const intptr_t reg = range->assigned_location().register_code();
1853 1977
1854 if (!reaching_defs_.Get(phi)->Contains(unallocated->vreg())) { 1978 if (!reaching_defs_.Get(phi)->Contains(unallocated->vreg())) {
1855 used_on_backedge[reg] = true; 1979 used_on_backedge[reg] = true;
1856 } 1980 }
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after
1901 registers_[candidate].Add(unallocated); 2025 registers_[candidate].Add(unallocated);
1902 unallocated->set_assigned_location(MakeRegisterLocation(candidate)); 2026 unallocated->set_assigned_location(MakeRegisterLocation(candidate));
1903 2027
1904 return true; 2028 return true;
1905 } 2029 }
1906 2030
1907 2031
1908 bool FlowGraphAllocator::RangeHasOnlyUnconstrainedUsesInLoop(LiveRange* range, 2032 bool FlowGraphAllocator::RangeHasOnlyUnconstrainedUsesInLoop(LiveRange* range,
1909 intptr_t loop_id) { 2033 intptr_t loop_id) {
1910 if (range->vreg() >= 0) { 2034 if (range->vreg() >= 0) {
1911 return GetLiveRange(range->vreg())->HasOnlyUnconstrainedUsesInLoop(loop_id); 2035 LiveRange* parent = GetLiveRange(range->vreg());
2036 return parent->HasOnlyUnconstrainedUsesInLoop(loop_id);
1912 } 2037 }
1913 return false; 2038 return false;
1914 } 2039 }
1915 2040
1916 2041
1917 bool FlowGraphAllocator::IsCheapToEvictRegisterInLoop(BlockInfo* loop, 2042 bool FlowGraphAllocator::IsCheapToEvictRegisterInLoop(BlockInfo* loop,
1918 intptr_t reg) { 2043 intptr_t reg) {
1919 const intptr_t loop_start = loop->entry()->start_pos(); 2044 const intptr_t loop_start = loop->entry()->start_pos();
1920 const intptr_t loop_end = loop->last_block()->end_pos(); 2045 const intptr_t loop_end = loop->last_block()->end_pos();
1921 2046
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after
1982 const intptr_t register_use_pos = 2107 const intptr_t register_use_pos =
1983 (register_use != NULL) ? register_use->pos() 2108 (register_use != NULL) ? register_use->pos()
1984 : unallocated->Start(); 2109 : unallocated->Start();
1985 if (free_until < register_use_pos) { 2110 if (free_until < register_use_pos) {
1986 // Can't acquire free register. Spill until we really need one. 2111 // Can't acquire free register. Spill until we really need one.
1987 ASSERT(unallocated->Start() < ToInstructionStart(register_use_pos)); 2112 ASSERT(unallocated->Start() < ToInstructionStart(register_use_pos));
1988 SpillBetween(unallocated, unallocated->Start(), register_use->pos()); 2113 SpillBetween(unallocated, unallocated->Start(), register_use->pos());
1989 return; 2114 return;
1990 } 2115 }
1991 2116
2117 ASSERT(candidate != kNoRegister);
2118
1992 TRACE_ALLOC(OS::Print("assigning blocked register ")); 2119 TRACE_ALLOC(OS::Print("assigning blocked register "));
1993 TRACE_ALLOC(MakeRegisterLocation(candidate).Print()); 2120 TRACE_ALLOC(MakeRegisterLocation(candidate).Print());
1994 TRACE_ALLOC(OS::Print(" to live range v%" Pd " until %" Pd "\n", 2121 TRACE_ALLOC(OS::Print(" to live range v%" Pd " until %" Pd "\n",
1995 unallocated->vreg(), blocked_at)); 2122 unallocated->vreg(), blocked_at));
1996 2123
1997 if (blocked_at < unallocated->End()) { 2124 if (blocked_at < unallocated->End()) {
1998 // Register is blocked before the end of the live range. Split the range 2125 // Register is blocked before the end of the live range. Split the range
1999 // at latest at blocked_at position. 2126 // at latest at blocked_at position.
2000 LiveRange* tail = SplitBetween(unallocated, 2127 LiveRange* tail = SplitBetween(unallocated,
2001 unallocated->Start(), 2128 unallocated->Start(),
(...skipping 345 matching lines...) Expand 10 before | Expand all | Expand 10 after
2347 AdvanceActiveIntervals(kMaxPosition); 2474 AdvanceActiveIntervals(kMaxPosition);
2348 TRACE_ALLOC(OS::Print("Allocation completed\n")); 2475 TRACE_ALLOC(OS::Print("Allocation completed\n"));
2349 } 2476 }
2350 2477
2351 2478
2352 bool FlowGraphAllocator::TargetLocationIsSpillSlot(LiveRange* range, 2479 bool FlowGraphAllocator::TargetLocationIsSpillSlot(LiveRange* range,
2353 Location target) { 2480 Location target) {
2354 if (target.IsStackSlot() || 2481 if (target.IsStackSlot() ||
2355 target.IsDoubleStackSlot() || 2482 target.IsDoubleStackSlot() ||
2356 target.IsConstant()) { 2483 target.IsConstant()) {
2357 ASSERT(GetLiveRange(range->vreg())->spill_slot().Equals(target)); 2484 LiveRange* parent = GetLiveRange(range->vreg());
Florian Schneider 2014/04/04 11:52:46 Unintended change?
Cutch 2014/04/04 16:34:46 Done.
2485 ASSERT(parent->spill_slot().Equals(target));
2358 return true; 2486 return true;
2359 } 2487 }
2360 return false; 2488 return false;
2361 } 2489 }
2362 2490
2363 2491
2364 void FlowGraphAllocator::ConnectSplitSiblings(LiveRange* parent, 2492 void FlowGraphAllocator::ConnectSplitSiblings(LiveRange* parent,
2365 BlockEntryInstr* source_block, 2493 BlockEntryInstr* source_block,
2366 BlockEntryInstr* target_block) { 2494 BlockEntryInstr* target_block) {
2367 TRACE_ALLOC(OS::Print("Connect v%" Pd " on the edge B%" Pd " -> B%" Pd "\n", 2495 TRACE_ALLOC(OS::Print("Connect v%" Pd " on the edge B%" Pd " -> B%" Pd "\n",
(...skipping 124 matching lines...) Expand 10 before | Expand all | Expand 10 after
2492 } 2620 }
2493 } 2621 }
2494 2622
2495 2623
2496 void FlowGraphAllocator::CollectRepresentations() { 2624 void FlowGraphAllocator::CollectRepresentations() {
2497 // Parameters. 2625 // Parameters.
2498 GraphEntryInstr* graph_entry = flow_graph_.graph_entry(); 2626 GraphEntryInstr* graph_entry = flow_graph_.graph_entry();
2499 for (intptr_t i = 0; i < graph_entry->initial_definitions()->length(); ++i) { 2627 for (intptr_t i = 0; i < graph_entry->initial_definitions()->length(); ++i) {
2500 Definition* def = (*graph_entry->initial_definitions())[i]; 2628 Definition* def = (*graph_entry->initial_definitions())[i];
2501 value_representations_[def->ssa_temp_index()] = def->representation(); 2629 value_representations_[def->ssa_temp_index()] = def->representation();
2630 if (def->RequiresPairSSAIndex()) {
Florian Schneider 2014/04/04 11:52:46 Can the initial_definitions of the GraphEntry ever
Cutch 2014/04/04 16:34:46 Done.
2631 value_representations_[def->pair_ssa_index()] = def->representation();
2632 }
2502 } 2633 }
2503 2634
2504 for (BlockIterator it = flow_graph_.reverse_postorder_iterator(); 2635 for (BlockIterator it = flow_graph_.reverse_postorder_iterator();
2505 !it.Done(); 2636 !it.Done();
2506 it.Advance()) { 2637 it.Advance()) {
2507 BlockEntryInstr* block = it.Current(); 2638 BlockEntryInstr* block = it.Current();
2508 2639
2509 // Catch entry. 2640 // Catch entry.
2510 if (block->IsCatchBlockEntry()) { 2641 if (block->IsCatchBlockEntry()) {
2511 CatchBlockEntryInstr* catch_entry = block->AsCatchBlockEntry(); 2642 CatchBlockEntryInstr* catch_entry = block->AsCatchBlockEntry();
2512 for (intptr_t i = 0; 2643 for (intptr_t i = 0;
2513 i < catch_entry->initial_definitions()->length(); 2644 i < catch_entry->initial_definitions()->length();
2514 ++i) { 2645 ++i) {
2515 Definition* def = (*catch_entry->initial_definitions())[i]; 2646 Definition* def = (*catch_entry->initial_definitions())[i];
2516 value_representations_[def->ssa_temp_index()] = def->representation(); 2647 value_representations_[def->ssa_temp_index()] = def->representation();
2517 } 2648 }
2518 } 2649 }
2519 // Phis. 2650 // Phis.
2520 if (block->IsJoinEntry()) { 2651 if (block->IsJoinEntry()) {
2521 JoinEntryInstr* join = block->AsJoinEntry(); 2652 JoinEntryInstr* join = block->AsJoinEntry();
2522 for (PhiIterator it(join); !it.Done(); it.Advance()) { 2653 for (PhiIterator it(join); !it.Done(); it.Advance()) {
2654 // TODO(johnmccutchan): Fix handling of PhiInstr with PairLocation.
2523 PhiInstr* phi = it.Current(); 2655 PhiInstr* phi = it.Current();
2524 if ((phi != NULL) && (phi->ssa_temp_index() >= 0)) { 2656 if ((phi != NULL) && (phi->ssa_temp_index() >= 0)) {
2525 value_representations_[phi->ssa_temp_index()] = phi->representation(); 2657 value_representations_[phi->ssa_temp_index()] = phi->representation();
2526 } 2658 }
2527 } 2659 }
2528 } 2660 }
2529 // Normal instructions. 2661 // Normal instructions.
2530 for (ForwardInstructionIterator instr_it(block); 2662 for (ForwardInstructionIterator instr_it(block);
2531 !instr_it.Done(); 2663 !instr_it.Done();
2532 instr_it.Advance()) { 2664 instr_it.Advance()) {
2533 Definition* def = instr_it.Current()->AsDefinition(); 2665 Definition* def = instr_it.Current()->AsDefinition();
2534 if ((def != NULL) && (def->ssa_temp_index() >= 0)) { 2666 if ((def != NULL) && (def->ssa_temp_index() >= 0)) {
2535 value_representations_[def->ssa_temp_index()] = def->representation(); 2667 value_representations_[def->ssa_temp_index()] = def->representation();
2668 if (def->RequiresPairSSAIndex()) {
2669 value_representations_[def->pair_ssa_index()] = def->representation();
2670 }
2536 } 2671 }
2537 } 2672 }
2538 } 2673 }
2539 } 2674 }
2540 2675
2541 2676
2542 void FlowGraphAllocator::AllocateRegisters() { 2677 void FlowGraphAllocator::AllocateRegisters() {
2543 CollectRepresentations(); 2678 CollectRepresentations();
2544 2679
2545 liveness_.Analyze(); 2680 liveness_.Analyze();
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after
2605 OS::Print("-- [after ssa allocator] ir [%s] -------------\n", 2740 OS::Print("-- [after ssa allocator] ir [%s] -------------\n",
2606 function.ToFullyQualifiedCString()); 2741 function.ToFullyQualifiedCString());
2607 FlowGraphPrinter printer(flow_graph_, true); 2742 FlowGraphPrinter printer(flow_graph_, true);
2608 printer.PrintBlocks(); 2743 printer.PrintBlocks();
2609 OS::Print("----------------------------------------------\n"); 2744 OS::Print("----------------------------------------------\n");
2610 } 2745 }
2611 } 2746 }
2612 2747
2613 2748
2614 } // namespace dart 2749 } // namespace dart
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698