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

Side by Side Diff: src/compiler/register-allocator.cc

Issue 1081373002: [turbofan] cleanup ParallelMove (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Created 5 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
« no previous file with comments | « src/compiler/register-allocator.h ('k') | src/compiler/register-allocator-verifier.cc » ('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 2014 the V8 project authors. All rights reserved. 1 // Copyright 2014 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "src/compiler/linkage.h" 5 #include "src/compiler/linkage.h"
6 #include "src/compiler/register-allocator.h" 6 #include "src/compiler/register-allocator.h"
7 #include "src/string-stream.h" 7 #include "src/string-stream.h"
8 8
9 namespace v8 { 9 namespace v8 {
10 namespace internal { 10 namespace internal {
(...skipping 122 matching lines...) Expand 10 before | Expand all | Expand 10 after
133 current_hint_operand_(nullptr), 133 current_hint_operand_(nullptr),
134 spill_start_index_(kMaxInt), 134 spill_start_index_(kMaxInt),
135 spill_type_(SpillType::kNoSpillType), 135 spill_type_(SpillType::kNoSpillType),
136 spill_operand_(nullptr), 136 spill_operand_(nullptr),
137 spills_at_definition_(nullptr) {} 137 spills_at_definition_(nullptr) {}
138 138
139 139
140 void LiveRange::set_assigned_register(int reg) { 140 void LiveRange::set_assigned_register(int reg) {
141 DCHECK(!HasRegisterAssigned() && !IsSpilled()); 141 DCHECK(!HasRegisterAssigned() && !IsSpilled());
142 assigned_register_ = reg; 142 assigned_register_ = reg;
143 // TODO(dcarney): stop aliasing hint operands.
144 ConvertUsesToOperand(GetAssignedOperand(), nullptr);
145 } 143 }
146 144
147 145
148 void LiveRange::MakeSpilled() { 146 void LiveRange::MakeSpilled() {
149 DCHECK(!IsSpilled()); 147 DCHECK(!IsSpilled());
150 DCHECK(!TopLevel()->HasNoSpillType()); 148 DCHECK(!TopLevel()->HasNoSpillType());
151 spilled_ = true; 149 spilled_ = true;
152 assigned_register_ = kInvalidAssignment; 150 assigned_register_ = kInvalidAssignment;
153 } 151 }
154 152
(...skipping 13 matching lines...) Expand all
168 DCHECK(!IsChild()); 166 DCHECK(!IsChild());
169 auto zone = sequence->zone(); 167 auto zone = sequence->zone();
170 for (auto to_spill = spills_at_definition_; to_spill != nullptr; 168 for (auto to_spill = spills_at_definition_; to_spill != nullptr;
171 to_spill = to_spill->next) { 169 to_spill = to_spill->next) {
172 auto instr = sequence->InstructionAt(to_spill->gap_index); 170 auto instr = sequence->InstructionAt(to_spill->gap_index);
173 auto move = instr->GetOrCreateParallelMove(Instruction::START, zone); 171 auto move = instr->GetOrCreateParallelMove(Instruction::START, zone);
174 // Skip insertion if it's possible that the move exists already as a 172 // Skip insertion if it's possible that the move exists already as a
175 // constraint move from a fixed output register to a slot. 173 // constraint move from a fixed output register to a slot.
176 if (might_be_duplicated) { 174 if (might_be_duplicated) {
177 bool found = false; 175 bool found = false;
178 auto move_ops = move->move_operands(); 176 for (auto move_op : *move) {
179 for (auto move_op = move_ops->begin(); move_op != move_ops->end();
180 ++move_op) {
181 if (move_op->IsEliminated()) continue; 177 if (move_op->IsEliminated()) continue;
182 if (move_op->source()->Equals(to_spill->operand) && 178 if (move_op->source() == *to_spill->operand &&
183 move_op->destination()->Equals(op)) { 179 move_op->destination() == *op) {
184 found = true; 180 found = true;
185 break; 181 break;
186 } 182 }
187 } 183 }
188 if (found) continue; 184 if (found) continue;
189 } 185 }
190 move->AddMove(to_spill->operand, op, zone); 186 move->AddMove(*to_spill->operand, *op);
191 } 187 }
192 } 188 }
193 189
194 190
195 void LiveRange::SetSpillOperand(InstructionOperand* operand) { 191 void LiveRange::SetSpillOperand(InstructionOperand* operand) {
196 DCHECK(HasNoSpillType()); 192 DCHECK(HasNoSpillType());
197 DCHECK(!operand->IsUnallocated() && !operand->IsImmediate()); 193 DCHECK(!operand->IsUnallocated() && !operand->IsImmediate());
198 spill_type_ = SpillType::kSpillOperand; 194 spill_type_ = SpillType::kSpillOperand;
199 spill_operand_ = operand; 195 spill_operand_ = operand;
200 } 196 }
(...skipping 595 matching lines...) Expand 10 before | Expand all | Expand 10 after
796 auto range = LiveRangeFor(operand); 792 auto range = LiveRangeFor(operand);
797 if (range == nullptr) return; 793 if (range == nullptr) return;
798 if (operand->IsUnallocated()) { 794 if (operand->IsUnallocated()) {
799 UnallocatedOperand* unalloc_operand = UnallocatedOperand::cast(operand); 795 UnallocatedOperand* unalloc_operand = UnallocatedOperand::cast(operand);
800 range->AddUsePosition(position, unalloc_operand, hint, local_zone()); 796 range->AddUsePosition(position, unalloc_operand, hint, local_zone());
801 } 797 }
802 range->AddUseInterval(block_start, position, local_zone()); 798 range->AddUseInterval(block_start, position, local_zone());
803 } 799 }
804 800
805 801
806 void RegisterAllocator::AddGapMove(int index, Instruction::GapPosition position, 802 MoveOperands* RegisterAllocator::AddGapMove(int index,
807 InstructionOperand* from, 803 Instruction::GapPosition position,
808 InstructionOperand* to) { 804 const InstructionOperand& from,
805 const InstructionOperand& to) {
809 auto instr = code()->InstructionAt(index); 806 auto instr = code()->InstructionAt(index);
810 auto move = instr->GetOrCreateParallelMove(position, code_zone()); 807 auto moves = instr->GetOrCreateParallelMove(position, code_zone());
811 move->AddMove(from, to, code_zone()); 808 return moves->AddMove(from, to);
812 } 809 }
813 810
814 811
815 static bool AreUseIntervalsIntersecting(UseInterval* interval1, 812 static bool AreUseIntervalsIntersecting(UseInterval* interval1,
816 UseInterval* interval2) { 813 UseInterval* interval2) {
817 while (interval1 != nullptr && interval2 != nullptr) { 814 while (interval1 != nullptr && interval2 != nullptr) {
818 if (interval1->start().Value() < interval2->start().Value()) { 815 if (interval1->start().Value() < interval2->start().Value()) {
819 if (interval1->end().Value() > interval2->start().Value()) { 816 if (interval1->end().Value() > interval2->start().Value()) {
820 return true; 817 return true;
821 } 818 }
(...skipping 131 matching lines...) Expand 10 before | Expand all | Expand 10 after
953 950
954 void RegisterAllocator::CommitAssignment() { 951 void RegisterAllocator::CommitAssignment() {
955 for (auto range : live_ranges()) { 952 for (auto range : live_ranges()) {
956 if (range == nullptr || range->IsEmpty()) continue; 953 if (range == nullptr || range->IsEmpty()) continue;
957 InstructionOperand* spill_operand = nullptr; 954 InstructionOperand* spill_operand = nullptr;
958 if (!range->TopLevel()->HasNoSpillType()) { 955 if (!range->TopLevel()->HasNoSpillType()) {
959 spill_operand = range->TopLevel()->GetSpillOperand(); 956 spill_operand = range->TopLevel()->GetSpillOperand();
960 } 957 }
961 auto assigned = range->GetAssignedOperand(); 958 auto assigned = range->GetAssignedOperand();
962 range->ConvertUsesToOperand(assigned, spill_operand); 959 range->ConvertUsesToOperand(assigned, spill_operand);
960 if (range->is_phi()) AssignPhiInput(range, assigned);
963 if (!range->IsChild() && spill_operand != nullptr) { 961 if (!range->IsChild() && spill_operand != nullptr) {
964 range->CommitSpillsAtDefinition(code(), spill_operand, 962 range->CommitSpillsAtDefinition(code(), spill_operand,
965 range->has_slot_use()); 963 range->has_slot_use());
966 } 964 }
967 } 965 }
968 } 966 }
969 967
970 968
971 SpillRange* RegisterAllocator::AssignSpillRangeToLiveRange(LiveRange* range) { 969 SpillRange* RegisterAllocator::AssignSpillRangeToLiveRange(LiveRange* range) {
972 auto spill_range = new (local_zone()) SpillRange(range, local_zone()); 970 auto spill_range = new (local_zone()) SpillRange(range, local_zone());
973 spill_ranges().push_back(spill_range); 971 spill_ranges().push_back(spill_range);
974 return spill_range; 972 return spill_range;
975 } 973 }
976 974
977 975
978 bool RegisterAllocator::TryReuseSpillForPhi(LiveRange* range) { 976 bool RegisterAllocator::TryReuseSpillForPhi(LiveRange* range) {
979 if (range->IsChild() || !range->is_phi()) return false; 977 if (range->IsChild() || !range->is_phi()) return false;
980 DCHECK(!range->HasSpillOperand()); 978 DCHECK(!range->HasSpillOperand());
981 979
982 auto lookup = phi_map_.find(range->id()); 980 auto lookup = phi_map_.find(range->id());
983 DCHECK(lookup != phi_map_.end()); 981 DCHECK(lookup != phi_map_.end());
984 auto phi = lookup->second.phi; 982 auto phi = lookup->second->phi;
985 auto block = lookup->second.block; 983 auto block = lookup->second->block;
986 // Count the number of spilled operands. 984 // Count the number of spilled operands.
987 size_t spilled_count = 0; 985 size_t spilled_count = 0;
988 LiveRange* first_op = nullptr; 986 LiveRange* first_op = nullptr;
989 for (size_t i = 0; i < phi->operands().size(); i++) { 987 for (size_t i = 0; i < phi->operands().size(); i++) {
990 int op = phi->operands()[i]; 988 int op = phi->operands()[i];
991 LiveRange* op_range = LiveRangeFor(op); 989 LiveRange* op_range = LiveRangeFor(op);
992 if (op_range->GetSpillRange() == nullptr) continue; 990 if (op_range->GetSpillRange() == nullptr) continue;
993 auto pred = code()->InstructionBlockAt(block->predecessors()[i]); 991 auto pred = code()->InstructionBlockAt(block->predecessors()[i]);
994 auto pred_end = LifetimePosition::InstructionFromInstructionIndex( 992 auto pred_end = LifetimePosition::InstructionFromInstructionIndex(
995 pred->last_instruction_index()); 993 pred->last_instruction_index());
(...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after
1091 range->SetSpillStartIndex(end); 1089 range->SetSpillStartIndex(end);
1092 assigned = true; 1090 assigned = true;
1093 } 1091 }
1094 1092
1095 for (auto succ : block->successors()) { 1093 for (auto succ : block->successors()) {
1096 const InstructionBlock* successor = code()->InstructionBlockAt(succ); 1094 const InstructionBlock* successor = code()->InstructionBlockAt(succ);
1097 DCHECK(successor->PredecessorCount() == 1); 1095 DCHECK(successor->PredecessorCount() == 1);
1098 int gap_index = successor->first_instruction_index(); 1096 int gap_index = successor->first_instruction_index();
1099 // Create an unconstrained operand for the same virtual register 1097 // Create an unconstrained operand for the same virtual register
1100 // and insert a gap move from the fixed output to the operand. 1098 // and insert a gap move from the fixed output to the operand.
1101 UnallocatedOperand* output_copy = 1099 UnallocatedOperand output_copy(UnallocatedOperand::ANY, output_vreg);
1102 UnallocatedOperand(UnallocatedOperand::ANY, output_vreg) 1100 AddGapMove(gap_index, Instruction::START, *output, output_copy);
1103 .Copy(code_zone());
1104 AddGapMove(gap_index, Instruction::START, output, output_copy);
1105 } 1101 }
1106 } 1102 }
1107 1103
1108 if (!assigned) { 1104 if (!assigned) {
1109 for (auto succ : block->successors()) { 1105 for (auto succ : block->successors()) {
1110 const InstructionBlock* successor = code()->InstructionBlockAt(succ); 1106 const InstructionBlock* successor = code()->InstructionBlockAt(succ);
1111 DCHECK(successor->PredecessorCount() == 1); 1107 DCHECK(successor->PredecessorCount() == 1);
1112 int gap_index = successor->first_instruction_index(); 1108 int gap_index = successor->first_instruction_index();
1113 range->SpillAtDefinition(local_zone(), gap_index, output); 1109 range->SpillAtDefinition(local_zone(), gap_index, output);
1114 range->SetSpillStartIndex(gap_index); 1110 range->SetSpillStartIndex(gap_index);
(...skipping 17 matching lines...) Expand all
1132 int output_vreg = ConstantOperand::cast(output)->virtual_register(); 1128 int output_vreg = ConstantOperand::cast(output)->virtual_register();
1133 auto range = LiveRangeFor(output_vreg); 1129 auto range = LiveRangeFor(output_vreg);
1134 range->SetSpillStartIndex(instr_index + 1); 1130 range->SetSpillStartIndex(instr_index + 1);
1135 range->SetSpillOperand(output); 1131 range->SetSpillOperand(output);
1136 continue; 1132 continue;
1137 } 1133 }
1138 auto first_output = UnallocatedOperand::cast(output); 1134 auto first_output = UnallocatedOperand::cast(output);
1139 auto range = LiveRangeFor(first_output->virtual_register()); 1135 auto range = LiveRangeFor(first_output->virtual_register());
1140 bool assigned = false; 1136 bool assigned = false;
1141 if (first_output->HasFixedPolicy()) { 1137 if (first_output->HasFixedPolicy()) {
1142 auto output_copy = first_output->CopyUnconstrained(code_zone()); 1138 int output_vreg = first_output->virtual_register();
1143 bool is_tagged = HasTaggedValue(first_output->virtual_register()); 1139 UnallocatedOperand output_copy(UnallocatedOperand::ANY, output_vreg);
1140 bool is_tagged = HasTaggedValue(output_vreg);
1144 AllocateFixed(first_output, instr_index, is_tagged); 1141 AllocateFixed(first_output, instr_index, is_tagged);
1145 1142
1146 // This value is produced on the stack, we never need to spill it. 1143 // This value is produced on the stack, we never need to spill it.
1147 if (first_output->IsStackSlot()) { 1144 if (first_output->IsStackSlot()) {
1148 DCHECK(StackSlotOperand::cast(first_output)->index() < 1145 DCHECK(StackSlotOperand::cast(first_output)->index() <
1149 frame_->GetSpillSlotCount()); 1146 frame_->GetSpillSlotCount());
1150 range->SetSpillOperand(StackSlotOperand::cast(first_output)); 1147 range->SetSpillOperand(StackSlotOperand::cast(first_output));
1151 range->SetSpillStartIndex(instr_index + 1); 1148 range->SetSpillStartIndex(instr_index + 1);
1152 assigned = true; 1149 assigned = true;
1153 } 1150 }
1154 AddGapMove(instr_index + 1, Instruction::START, first_output, 1151 AddGapMove(instr_index + 1, Instruction::START, *first_output,
1155 output_copy); 1152 output_copy);
1156 } 1153 }
1157 // Make sure we add a gap move for spilling (if we have not done 1154 // Make sure we add a gap move for spilling (if we have not done
1158 // so already). 1155 // so already).
1159 if (!assigned) { 1156 if (!assigned) {
1160 range->SpillAtDefinition(local_zone(), instr_index + 1, first_output); 1157 range->SpillAtDefinition(local_zone(), instr_index + 1, first_output);
1161 range->SetSpillStartIndex(instr_index + 1); 1158 range->SetSpillStartIndex(instr_index + 1);
1162 } 1159 }
1163 } 1160 }
1164 } 1161 }
1165 1162
1166 1163
1167 void RegisterAllocator::MeetConstraintsBefore(int instr_index) { 1164 void RegisterAllocator::MeetConstraintsBefore(int instr_index) {
1168 auto second = InstructionAt(instr_index); 1165 auto second = InstructionAt(instr_index);
1169 // Handle fixed input operands of second instruction. 1166 // Handle fixed input operands of second instruction.
1170 for (size_t i = 0; i < second->InputCount(); i++) { 1167 for (size_t i = 0; i < second->InputCount(); i++) {
1171 auto input = second->InputAt(i); 1168 auto input = second->InputAt(i);
1172 if (input->IsImmediate()) continue; // Ignore immediates. 1169 if (input->IsImmediate()) continue; // Ignore immediates.
1173 auto cur_input = UnallocatedOperand::cast(input); 1170 auto cur_input = UnallocatedOperand::cast(input);
1174 if (cur_input->HasFixedPolicy()) { 1171 if (cur_input->HasFixedPolicy()) {
1175 auto input_copy = cur_input->CopyUnconstrained(code_zone()); 1172 int input_vreg = cur_input->virtual_register();
1176 bool is_tagged = HasTaggedValue(cur_input->virtual_register()); 1173 UnallocatedOperand input_copy(UnallocatedOperand::ANY, input_vreg);
1174 bool is_tagged = HasTaggedValue(input_vreg);
1177 AllocateFixed(cur_input, instr_index, is_tagged); 1175 AllocateFixed(cur_input, instr_index, is_tagged);
1178 AddGapMove(instr_index, Instruction::END, input_copy, cur_input); 1176 AddGapMove(instr_index, Instruction::END, input_copy, *cur_input);
1179 } 1177 }
1180 } 1178 }
1181 // Handle "output same as input" for second instruction. 1179 // Handle "output same as input" for second instruction.
1182 for (size_t i = 0; i < second->OutputCount(); i++) { 1180 for (size_t i = 0; i < second->OutputCount(); i++) {
1183 auto output = second->OutputAt(i); 1181 auto output = second->OutputAt(i);
1184 if (!output->IsUnallocated()) continue; 1182 if (!output->IsUnallocated()) continue;
1185 auto second_output = UnallocatedOperand::cast(output); 1183 auto second_output = UnallocatedOperand::cast(output);
1186 if (!second_output->HasSameAsInputPolicy()) continue; 1184 if (!second_output->HasSameAsInputPolicy()) continue;
1187 DCHECK(i == 0); // Only valid for first output. 1185 DCHECK(i == 0); // Only valid for first output.
1188 UnallocatedOperand* cur_input = 1186 UnallocatedOperand* cur_input =
1189 UnallocatedOperand::cast(second->InputAt(0)); 1187 UnallocatedOperand::cast(second->InputAt(0));
1190 int output_vreg = second_output->virtual_register(); 1188 int output_vreg = second_output->virtual_register();
1191 int input_vreg = cur_input->virtual_register(); 1189 int input_vreg = cur_input->virtual_register();
1192 auto input_copy = cur_input->CopyUnconstrained(code_zone()); 1190 UnallocatedOperand input_copy(UnallocatedOperand::ANY, input_vreg);
1193 cur_input->set_virtual_register(second_output->virtual_register()); 1191 cur_input->set_virtual_register(second_output->virtual_register());
1194 AddGapMove(instr_index, Instruction::END, input_copy, cur_input); 1192 AddGapMove(instr_index, Instruction::END, input_copy, *cur_input);
1195 if (HasTaggedValue(input_vreg) && !HasTaggedValue(output_vreg)) { 1193 if (HasTaggedValue(input_vreg) && !HasTaggedValue(output_vreg)) {
1196 if (second->HasReferenceMap()) { 1194 if (second->HasReferenceMap()) {
1197 second->reference_map()->RecordReference(*input_copy); 1195 second->reference_map()->RecordReference(input_copy);
1198 } 1196 }
1199 } else if (!HasTaggedValue(input_vreg) && HasTaggedValue(output_vreg)) { 1197 } else if (!HasTaggedValue(input_vreg) && HasTaggedValue(output_vreg)) {
1200 // The input is assumed to immediately have a tagged representation, 1198 // The input is assumed to immediately have a tagged representation,
1201 // before the pointer map can be used. I.e. the pointer map at the 1199 // before the pointer map can be used. I.e. the pointer map at the
1202 // instruction will include the output operand (whose value at the 1200 // instruction will include the output operand (whose value at the
1203 // beginning of the instruction is equal to the input operand). If 1201 // beginning of the instruction is equal to the input operand). If
1204 // this is not desired, then the pointer map at this instruction needs 1202 // this is not desired, then the pointer map at this instruction needs
1205 // to be adjusted manually. 1203 // to be adjusted manually.
1206 } 1204 }
1207 } 1205 }
(...skipping 116 matching lines...) Expand 10 before | Expand all | Expand 10 after
1324 curr_position = curr_position.PrevStart(); 1322 curr_position = curr_position.PrevStart();
1325 DCHECK(curr_position.IsGapPosition()); 1323 DCHECK(curr_position.IsGapPosition());
1326 for (auto position : kPositions) { 1324 for (auto position : kPositions) {
1327 auto move = instr->GetParallelMove(position); 1325 auto move = instr->GetParallelMove(position);
1328 if (move == nullptr) continue; 1326 if (move == nullptr) continue;
1329 if (position == Instruction::END) { 1327 if (position == Instruction::END) {
1330 curr_position = curr_position.End(); 1328 curr_position = curr_position.End();
1331 } else { 1329 } else {
1332 curr_position = curr_position.Start(); 1330 curr_position = curr_position.Start();
1333 } 1331 }
1334 auto move_ops = move->move_operands(); 1332 for (auto cur : *move) {
1335 for (auto cur = move_ops->begin(); cur != move_ops->end(); ++cur) { 1333 auto& from = cur->source();
1336 auto from = cur->source(); 1334 auto& to = cur->destination();
1337 auto to = cur->destination(); 1335 auto hint = &to;
1338 auto hint = to; 1336 if (to.IsUnallocated()) {
1339 if (to->IsUnallocated()) { 1337 int to_vreg = UnallocatedOperand::cast(to).virtual_register();
1340 int to_vreg = UnallocatedOperand::cast(to)->virtual_register();
1341 auto to_range = LiveRangeFor(to_vreg); 1338 auto to_range = LiveRangeFor(to_vreg);
1342 if (to_range->is_phi()) { 1339 if (to_range->is_phi()) {
1343 if (to_range->is_non_loop_phi()) { 1340 if (to_range->is_non_loop_phi()) {
1344 hint = to_range->current_hint_operand(); 1341 hint = to_range->current_hint_operand();
1345 } 1342 }
1346 } else { 1343 } else {
1347 if (live->Contains(to_vreg)) { 1344 if (live->Contains(to_vreg)) {
1348 Define(curr_position, to, from); 1345 Define(curr_position, &to, &from);
1349 live->Remove(to_vreg); 1346 live->Remove(to_vreg);
1350 } else { 1347 } else {
1351 cur->Eliminate(); 1348 cur->Eliminate();
1352 continue; 1349 continue;
1353 } 1350 }
1354 } 1351 }
1355 } else { 1352 } else {
1356 Define(curr_position, to, from); 1353 Define(curr_position, &to, &from);
1357 } 1354 }
1358 Use(block_start_position, curr_position, from, hint); 1355 Use(block_start_position, curr_position, &from, hint);
1359 if (from->IsUnallocated()) { 1356 if (from.IsUnallocated()) {
1360 live->Add(UnallocatedOperand::cast(from)->virtual_register()); 1357 live->Add(UnallocatedOperand::cast(from).virtual_register());
1361 } 1358 }
1362 } 1359 }
1363 } 1360 }
1364 } 1361 }
1365 } 1362 }
1366 1363
1367 1364
1368 void RegisterAllocator::ResolvePhis(const InstructionBlock* block) { 1365 void RegisterAllocator::ResolvePhis(const InstructionBlock* block) {
1369 for (auto phi : block->phis()) { 1366 for (auto phi : block->phis()) {
1370 int phi_vreg = phi->virtual_register(); 1367 int phi_vreg = phi->virtual_register();
1371 auto res = 1368 auto map_value = new (local_zone()) PhiMapValue(phi, block, local_zone());
1372 phi_map_.insert(std::make_pair(phi_vreg, PhiMapValue(phi, block))); 1369 auto res = phi_map_.insert(std::make_pair(phi_vreg, map_value));
1373 DCHECK(res.second); 1370 DCHECK(res.second);
1374 USE(res); 1371 USE(res);
1375 auto& output = phi->output(); 1372 auto& output = phi->output();
1376 for (size_t i = 0; i < phi->operands().size(); ++i) { 1373 for (size_t i = 0; i < phi->operands().size(); ++i) {
1377 InstructionBlock* cur_block = 1374 InstructionBlock* cur_block =
1378 code()->InstructionBlockAt(block->predecessors()[i]); 1375 code()->InstructionBlockAt(block->predecessors()[i]);
1379 AddGapMove(cur_block->last_instruction_index(), Instruction::END, 1376 UnallocatedOperand input(UnallocatedOperand::ANY, phi->operands()[i]);
1380 &phi->inputs()[i], &output); 1377 auto move = AddGapMove(cur_block->last_instruction_index(),
1378 Instruction::END, input, output);
1379 map_value->incoming_moves.push_back(move);
1381 DCHECK(!InstructionAt(cur_block->last_instruction_index()) 1380 DCHECK(!InstructionAt(cur_block->last_instruction_index())
1382 ->HasReferenceMap()); 1381 ->HasReferenceMap());
1383 } 1382 }
1384 auto live_range = LiveRangeFor(phi_vreg); 1383 auto live_range = LiveRangeFor(phi_vreg);
1385 int gap_index = block->first_instruction_index(); 1384 int gap_index = block->first_instruction_index();
1386 live_range->SpillAtDefinition(local_zone(), gap_index, &output); 1385 live_range->SpillAtDefinition(local_zone(), gap_index, &output);
1387 live_range->SetSpillStartIndex(gap_index); 1386 live_range->SetSpillStartIndex(gap_index);
1388 // We use the phi-ness of some nodes in some later heuristics. 1387 // We use the phi-ness of some nodes in some later heuristics.
1389 live_range->set_is_phi(true); 1388 live_range->set_is_phi(true);
1390 live_range->set_is_non_loop_phi(!block->IsLoopHeader()); 1389 live_range->set_is_non_loop_phi(!block->IsLoopHeader());
1391 } 1390 }
1392 } 1391 }
1393 1392
1394 1393
1394 void RegisterAllocator::AssignPhiInput(LiveRange* range,
1395 const InstructionOperand& assignment) {
1396 DCHECK(range->is_phi());
1397 auto it = phi_map_.find(range->id());
1398 DCHECK(it != phi_map_.end());
1399 for (auto move : it->second->incoming_moves) {
1400 move->set_destination(assignment);
1401 }
1402 }
1403
1404
1395 void RegisterAllocator::MeetRegisterConstraints() { 1405 void RegisterAllocator::MeetRegisterConstraints() {
1396 for (auto block : code()->instruction_blocks()) { 1406 for (auto block : code()->instruction_blocks()) {
1397 MeetRegisterConstraints(block); 1407 MeetRegisterConstraints(block);
1398 } 1408 }
1399 } 1409 }
1400 1410
1401 1411
1402 void RegisterAllocator::ResolvePhis() { 1412 void RegisterAllocator::ResolvePhis() {
1403 // Process the blocks in reverse order. 1413 // Process the blocks in reverse order.
1404 for (auto i = code()->instruction_blocks().rbegin(); 1414 for (auto i = code()->instruction_blocks().rbegin();
1405 i != code()->instruction_blocks().rend(); ++i) { 1415 i != code()->instruction_blocks().rend(); ++i) {
1406 ResolvePhis(*i); 1416 ResolvePhis(*i);
1407 } 1417 }
1408 } 1418 }
1409 1419
1410 1420
1411 const InstructionBlock* RegisterAllocator::GetInstructionBlock( 1421 const InstructionBlock* RegisterAllocator::GetInstructionBlock(
1412 LifetimePosition pos) { 1422 LifetimePosition pos) {
1413 return code()->GetInstructionBlock(pos.ToInstructionIndex()); 1423 return code()->GetInstructionBlock(pos.ToInstructionIndex());
1414 } 1424 }
1415 1425
1416 1426
1417 void RegisterAllocator::ConnectRanges() { 1427 void RegisterAllocator::ConnectRanges() {
1418 ZoneMap<std::pair<ParallelMove*, InstructionOperand*>, InstructionOperand*> 1428 ZoneMap<std::pair<ParallelMove*, InstructionOperand>, InstructionOperand>
1419 delayed_insertion_map(local_zone()); 1429 delayed_insertion_map(local_zone());
1420 for (auto first_range : live_ranges()) { 1430 for (auto first_range : live_ranges()) {
1421 if (first_range == nullptr || first_range->IsChild()) continue; 1431 if (first_range == nullptr || first_range->IsChild()) continue;
1422 for (auto second_range = first_range->next(); second_range != nullptr; 1432 for (auto second_range = first_range->next(); second_range != nullptr;
1423 first_range = second_range, second_range = second_range->next()) { 1433 first_range = second_range, second_range = second_range->next()) {
1424 auto pos = second_range->Start(); 1434 auto pos = second_range->Start();
1425 // Add gap move if the two live ranges touch and there is no block 1435 // Add gap move if the two live ranges touch and there is no block
1426 // boundary. 1436 // boundary.
1427 if (second_range->IsSpilled()) continue; 1437 if (second_range->IsSpilled()) continue;
1428 if (first_range->End().Value() != pos.Value()) continue; 1438 if (first_range->End().Value() != pos.Value()) continue;
1429 if (IsBlockBoundary(pos) && 1439 if (IsBlockBoundary(pos) &&
1430 !CanEagerlyResolveControlFlow(GetInstructionBlock(pos))) { 1440 !CanEagerlyResolveControlFlow(GetInstructionBlock(pos))) {
1431 continue; 1441 continue;
1432 } 1442 }
1433 auto prev = first_range->GetAssignedOperand(); 1443 auto prev_operand = first_range->GetAssignedOperand();
1434 auto cur = second_range->GetAssignedOperand(); 1444 auto cur_operand = second_range->GetAssignedOperand();
1435 if (prev == cur) continue; 1445 if (prev_operand == cur_operand) continue;
1436 bool delay_insertion = false; 1446 bool delay_insertion = false;
1437 Instruction::GapPosition gap_pos; 1447 Instruction::GapPosition gap_pos;
1438 int gap_index = pos.ToInstructionIndex(); 1448 int gap_index = pos.ToInstructionIndex();
1439 if (pos.IsGapPosition()) { 1449 if (pos.IsGapPosition()) {
1440 gap_pos = pos.IsStart() ? Instruction::START : Instruction::END; 1450 gap_pos = pos.IsStart() ? Instruction::START : Instruction::END;
1441 } else { 1451 } else {
1442 if (pos.IsStart()) { 1452 if (pos.IsStart()) {
1443 delay_insertion = true; 1453 delay_insertion = true;
1444 } else { 1454 } else {
1445 gap_index++; 1455 gap_index++;
1446 } 1456 }
1447 gap_pos = delay_insertion ? Instruction::END : Instruction::START; 1457 gap_pos = delay_insertion ? Instruction::END : Instruction::START;
1448 } 1458 }
1449 auto move = code()->InstructionAt(gap_index)->GetOrCreateParallelMove( 1459 auto move = code()->InstructionAt(gap_index)->GetOrCreateParallelMove(
1450 gap_pos, code_zone()); 1460 gap_pos, code_zone());
1451 auto prev_operand = InstructionOperand::New(code_zone(), prev);
1452 auto cur_operand = InstructionOperand::New(code_zone(), cur);
1453 if (!delay_insertion) { 1461 if (!delay_insertion) {
1454 move->AddMove(prev_operand, cur_operand, code_zone()); 1462 move->AddMove(prev_operand, cur_operand);
1455 } else { 1463 } else {
1456 delayed_insertion_map.insert( 1464 delayed_insertion_map.insert(
1457 std::make_pair(std::make_pair(move, prev_operand), cur_operand)); 1465 std::make_pair(std::make_pair(move, prev_operand), cur_operand));
1458 } 1466 }
1459 } 1467 }
1460 } 1468 }
1461 if (delayed_insertion_map.empty()) return; 1469 if (delayed_insertion_map.empty()) return;
1462 // Insert all the moves which should occur after the stored move. 1470 // Insert all the moves which should occur after the stored move.
1463 ZoneVector<MoveOperands> to_insert(local_zone()); 1471 ZoneVector<MoveOperands*> to_insert(local_zone());
1464 ZoneVector<MoveOperands*> to_eliminate(local_zone()); 1472 ZoneVector<MoveOperands*> to_eliminate(local_zone());
1465 to_insert.reserve(4); 1473 to_insert.reserve(4);
1466 to_eliminate.reserve(4); 1474 to_eliminate.reserve(4);
1467 auto move = delayed_insertion_map.begin()->first.first; 1475 auto moves = delayed_insertion_map.begin()->first.first;
1468 for (auto it = delayed_insertion_map.begin();; ++it) { 1476 for (auto it = delayed_insertion_map.begin();; ++it) {
1469 bool done = it == delayed_insertion_map.end(); 1477 bool done = it == delayed_insertion_map.end();
1470 if (done || it->first.first != move) { 1478 if (done || it->first.first != moves) {
1471 // Commit the MoveOperands for current ParallelMove. 1479 // Commit the MoveOperands for current ParallelMove.
1472 for (auto move_ops : to_eliminate) { 1480 for (auto move : to_eliminate) {
1473 move_ops->Eliminate(); 1481 move->Eliminate();
1474 } 1482 }
1475 for (auto move_ops : to_insert) { 1483 for (auto move : to_insert) {
1476 move->AddMove(move_ops.source(), move_ops.destination(), code_zone()); 1484 moves->push_back(move);
1477 } 1485 }
1478 if (done) break; 1486 if (done) break;
1479 // Reset state. 1487 // Reset state.
1480 to_eliminate.clear(); 1488 to_eliminate.clear();
1481 to_insert.clear(); 1489 to_insert.clear();
1482 move = it->first.first; 1490 moves = it->first.first;
1483 } 1491 }
1484 // Gather all MoveOperands for a single ParallelMove. 1492 // Gather all MoveOperands for a single ParallelMove.
1485 MoveOperands move_ops(it->first.second, it->second); 1493 auto move = new (code_zone()) MoveOperands(it->first.second, it->second);
1486 auto eliminate = move->PrepareInsertAfter(&move_ops); 1494 auto eliminate = moves->PrepareInsertAfter(move);
1487 to_insert.push_back(move_ops); 1495 to_insert.push_back(move);
1488 if (eliminate != nullptr) to_eliminate.push_back(eliminate); 1496 if (eliminate != nullptr) to_eliminate.push_back(eliminate);
1489 } 1497 }
1490 } 1498 }
1491 1499
1492 1500
1493 bool RegisterAllocator::CanEagerlyResolveControlFlow( 1501 bool RegisterAllocator::CanEagerlyResolveControlFlow(
1494 const InstructionBlock* block) const { 1502 const InstructionBlock* block) const {
1495 if (block->PredecessorCount() != 1) return false; 1503 if (block->PredecessorCount() != 1) return false;
1496 return block->predecessors()[0].IsNext(block->rpo_number()); 1504 return block->predecessors()[0].IsNext(block->rpo_number());
1497 } 1505 }
(...skipping 145 matching lines...) Expand 10 before | Expand all | Expand 10 after
1643 for (auto pred : block->predecessors()) { 1651 for (auto pred : block->predecessors()) {
1644 FindResult result; 1652 FindResult result;
1645 const auto* pred_block = code()->InstructionBlockAt(pred); 1653 const auto* pred_block = code()->InstructionBlockAt(pred);
1646 array->Find(block, pred_block, &result); 1654 array->Find(block, pred_block, &result);
1647 if (result.cur_cover_ == result.pred_cover_ || 1655 if (result.cur_cover_ == result.pred_cover_ ||
1648 result.cur_cover_->IsSpilled()) 1656 result.cur_cover_->IsSpilled())
1649 continue; 1657 continue;
1650 auto pred_op = result.pred_cover_->GetAssignedOperand(); 1658 auto pred_op = result.pred_cover_->GetAssignedOperand();
1651 auto cur_op = result.cur_cover_->GetAssignedOperand(); 1659 auto cur_op = result.cur_cover_->GetAssignedOperand();
1652 if (pred_op == cur_op) continue; 1660 if (pred_op == cur_op) continue;
1653 auto pred_ptr = InstructionOperand::New(code_zone(), pred_op); 1661 ResolveControlFlow(block, cur_op, pred_block, pred_op);
1654 auto cur_ptr = InstructionOperand::New(code_zone(), cur_op);
1655 ResolveControlFlow(block, cur_ptr, pred_block, pred_ptr);
1656 } 1662 }
1657 iterator.Advance(); 1663 iterator.Advance();
1658 } 1664 }
1659 } 1665 }
1660 } 1666 }
1661 1667
1662 1668
1663 void RegisterAllocator::ResolveControlFlow(const InstructionBlock* block, 1669 void RegisterAllocator::ResolveControlFlow(const InstructionBlock* block,
1664 InstructionOperand* cur_op, 1670 const InstructionOperand& cur_op,
1665 const InstructionBlock* pred, 1671 const InstructionBlock* pred,
1666 InstructionOperand* pred_op) { 1672 const InstructionOperand& pred_op) {
1667 DCHECK(!pred_op->Equals(cur_op)); 1673 DCHECK(pred_op != cur_op);
1668 int gap_index; 1674 int gap_index;
1669 Instruction::GapPosition position; 1675 Instruction::GapPosition position;
1670 if (block->PredecessorCount() == 1) { 1676 if (block->PredecessorCount() == 1) {
1671 gap_index = block->first_instruction_index(); 1677 gap_index = block->first_instruction_index();
1672 position = Instruction::START; 1678 position = Instruction::START;
1673 } else { 1679 } else {
1674 DCHECK(pred->SuccessorCount() == 1); 1680 DCHECK(pred->SuccessorCount() == 1);
1675 DCHECK(!InstructionAt(pred->last_instruction_index())->HasReferenceMap()); 1681 DCHECK(!InstructionAt(pred->last_instruction_index())->HasReferenceMap());
1676 gap_index = pred->last_instruction_index(); 1682 gap_index = pred->last_instruction_index();
1677 position = Instruction::END; 1683 position = Instruction::END;
(...skipping 15 matching lines...) Expand all
1693 // Process the instructions in reverse order, generating and killing 1699 // Process the instructions in reverse order, generating and killing
1694 // live values. 1700 // live values.
1695 ProcessInstructions(block, live); 1701 ProcessInstructions(block, live);
1696 // All phi output operands are killed by this block. 1702 // All phi output operands are killed by this block.
1697 for (auto phi : block->phis()) { 1703 for (auto phi : block->phis()) {
1698 // The live range interval already ends at the first instruction of the 1704 // The live range interval already ends at the first instruction of the
1699 // block. 1705 // block.
1700 int phi_vreg = phi->virtual_register(); 1706 int phi_vreg = phi->virtual_register();
1701 live->Remove(phi_vreg); 1707 live->Remove(phi_vreg);
1702 InstructionOperand* hint = nullptr; 1708 InstructionOperand* hint = nullptr;
1703 InstructionOperand* phi_operand = nullptr;
1704 auto instr = GetLastInstruction( 1709 auto instr = GetLastInstruction(
1705 code()->InstructionBlockAt(block->predecessors()[0])); 1710 code()->InstructionBlockAt(block->predecessors()[0]));
1706 auto move = instr->GetParallelMove(Instruction::END); 1711 for (auto move : *instr->GetParallelMove(Instruction::END)) {
1707 for (int j = 0; j < move->move_operands()->length(); ++j) { 1712 auto& to = move->destination();
1708 auto to = move->move_operands()->at(j).destination(); 1713 if (to.IsUnallocated() &&
1709 if (to->IsUnallocated() && 1714 UnallocatedOperand::cast(to).virtual_register() == phi_vreg) {
1710 UnallocatedOperand::cast(to)->virtual_register() == phi_vreg) { 1715 hint = &move->source();
1711 hint = move->move_operands()->at(j).source();
1712 phi_operand = to;
1713 break; 1716 break;
1714 } 1717 }
1715 } 1718 }
1716 DCHECK(hint != nullptr); 1719 DCHECK(hint != nullptr);
1717 auto block_start = LifetimePosition::GapFromInstructionIndex( 1720 auto block_start = LifetimePosition::GapFromInstructionIndex(
1718 block->first_instruction_index()); 1721 block->first_instruction_index());
1719 Define(block_start, phi_operand, hint); 1722 Define(block_start, &phi->output(), hint);
1720 } 1723 }
1721 1724
1722 // Now live is live_in for this block except not including values live 1725 // Now live is live_in for this block except not including values live
1723 // out on backward successor edges. 1726 // out on backward successor edges.
1724 live_in_sets_[block_id] = live; 1727 live_in_sets_[block_id] = live;
1725 1728
1726 if (block->IsLoopHeader()) { 1729 if (block->IsLoopHeader()) {
1727 // Add a live range stretching from the first loop instruction to the last 1730 // Add a live range stretching from the first loop instruction to the last
1728 // for each value live on entry to the header. 1731 // for each value live on entry to the header.
1729 BitVector::Iterator iterator(live); 1732 BitVector::Iterator iterator(live);
(...skipping 770 matching lines...) Expand 10 before | Expand all | Expand 10 after
2500 2503
2501 void RegisterAllocator::SetLiveRangeAssignedRegister(LiveRange* range, 2504 void RegisterAllocator::SetLiveRangeAssignedRegister(LiveRange* range,
2502 int reg) { 2505 int reg) {
2503 if (range->Kind() == DOUBLE_REGISTERS) { 2506 if (range->Kind() == DOUBLE_REGISTERS) {
2504 assigned_double_registers_->Add(reg); 2507 assigned_double_registers_->Add(reg);
2505 } else { 2508 } else {
2506 DCHECK(range->Kind() == GENERAL_REGISTERS); 2509 DCHECK(range->Kind() == GENERAL_REGISTERS);
2507 assigned_registers_->Add(reg); 2510 assigned_registers_->Add(reg);
2508 } 2511 }
2509 range->set_assigned_register(reg); 2512 range->set_assigned_register(reg);
2513 auto assignment = range->GetAssignedOperand();
2514 // TODO(dcarney): stop aliasing hint operands.
2515 range->ConvertUsesToOperand(assignment, nullptr);
2516 if (range->is_phi()) AssignPhiInput(range, assignment);
2510 } 2517 }
2511 2518
2512 } // namespace compiler 2519 } // namespace compiler
2513 } // namespace internal 2520 } // namespace internal
2514 } // namespace v8 2521 } // namespace v8
OLDNEW
« no previous file with comments | « src/compiler/register-allocator.h ('k') | src/compiler/register-allocator-verifier.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698