| OLD | NEW |
| 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 759 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 770 auto range = LiveRangeFor(operand); | 770 auto range = LiveRangeFor(operand); |
| 771 if (range == nullptr) return; | 771 if (range == nullptr) return; |
| 772 if (operand->IsUnallocated()) { | 772 if (operand->IsUnallocated()) { |
| 773 UnallocatedOperand* unalloc_operand = UnallocatedOperand::cast(operand); | 773 UnallocatedOperand* unalloc_operand = UnallocatedOperand::cast(operand); |
| 774 range->AddUsePosition(position, unalloc_operand, hint, local_zone()); | 774 range->AddUsePosition(position, unalloc_operand, hint, local_zone()); |
| 775 } | 775 } |
| 776 range->AddUseInterval(block_start, position, local_zone()); | 776 range->AddUseInterval(block_start, position, local_zone()); |
| 777 } | 777 } |
| 778 | 778 |
| 779 | 779 |
| 780 void RegisterAllocator::AddConstraintsGapMove(int index, | 780 void RegisterAllocator::AddGapMove(int index, |
| 781 InstructionOperand* from, | 781 GapInstruction::InnerPosition position, |
| 782 InstructionOperand* to) { | 782 InstructionOperand* from, |
| 783 InstructionOperand* to) { |
| 783 auto gap = code()->GapAt(index); | 784 auto gap = code()->GapAt(index); |
| 784 auto move = gap->GetOrCreateParallelMove(GapInstruction::START, code_zone()); | 785 auto move = gap->GetOrCreateParallelMove(position, code_zone()); |
| 785 if (from->IsUnallocated()) { | |
| 786 const ZoneList<MoveOperands>* move_operands = move->move_operands(); | |
| 787 for (int i = 0; i < move_operands->length(); ++i) { | |
| 788 auto cur = move_operands->at(i); | |
| 789 auto cur_to = cur.destination(); | |
| 790 if (cur_to->IsUnallocated()) { | |
| 791 if (UnallocatedOperand::cast(cur_to)->virtual_register() == | |
| 792 UnallocatedOperand::cast(from)->virtual_register()) { | |
| 793 move->AddMove(cur.source(), to, code_zone()); | |
| 794 return; | |
| 795 } | |
| 796 } | |
| 797 } | |
| 798 } | |
| 799 move->AddMove(from, to, code_zone()); | 786 move->AddMove(from, to, code_zone()); |
| 800 } | 787 } |
| 801 | 788 |
| 802 | 789 |
| 803 static bool AreUseIntervalsIntersecting(UseInterval* interval1, | 790 static bool AreUseIntervalsIntersecting(UseInterval* interval1, |
| 804 UseInterval* interval2) { | 791 UseInterval* interval2) { |
| 805 while (interval1 != nullptr && interval2 != nullptr) { | 792 while (interval1 != nullptr && interval2 != nullptr) { |
| 806 if (interval1->start().Value() < interval2->start().Value()) { | 793 if (interval1->start().Value() < interval2->start().Value()) { |
| 807 if (interval1->end().Value() > interval2->start().Value()) { | 794 if (interval1->end().Value() > interval2->start().Value()) { |
| 808 return true; | 795 return true; |
| (...skipping 284 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1093 DCHECK(successor->PredecessorCount() == 1); | 1080 DCHECK(successor->PredecessorCount() == 1); |
| 1094 int gap_index = successor->first_instruction_index() + 1; | 1081 int gap_index = successor->first_instruction_index() + 1; |
| 1095 DCHECK(code()->IsGapAt(gap_index)); | 1082 DCHECK(code()->IsGapAt(gap_index)); |
| 1096 | 1083 |
| 1097 // Create an unconstrained operand for the same virtual register | 1084 // Create an unconstrained operand for the same virtual register |
| 1098 // and insert a gap move from the fixed output to the operand. | 1085 // and insert a gap move from the fixed output to the operand. |
| 1099 UnallocatedOperand* output_copy = | 1086 UnallocatedOperand* output_copy = |
| 1100 new (code_zone()) UnallocatedOperand(UnallocatedOperand::ANY); | 1087 new (code_zone()) UnallocatedOperand(UnallocatedOperand::ANY); |
| 1101 output_copy->set_virtual_register(output_vreg); | 1088 output_copy->set_virtual_register(output_vreg); |
| 1102 | 1089 |
| 1103 code()->AddGapMove(gap_index, output, output_copy); | 1090 AddGapMove(gap_index, GapInstruction::START, output, output_copy); |
| 1104 } | 1091 } |
| 1105 } | 1092 } |
| 1106 | 1093 |
| 1107 if (!assigned) { | 1094 if (!assigned) { |
| 1108 for (auto succ : block->successors()) { | 1095 for (auto succ : block->successors()) { |
| 1109 const InstructionBlock* successor = code()->InstructionBlockAt(succ); | 1096 const InstructionBlock* successor = code()->InstructionBlockAt(succ); |
| 1110 DCHECK(successor->PredecessorCount() == 1); | 1097 DCHECK(successor->PredecessorCount() == 1); |
| 1111 int gap_index = successor->first_instruction_index() + 1; | 1098 int gap_index = successor->first_instruction_index() + 1; |
| 1112 range->SpillAtDefinition(local_zone(), gap_index, output); | 1099 range->SpillAtDefinition(local_zone(), gap_index, output); |
| 1113 range->SetSpillStartIndex(gap_index); | 1100 range->SetSpillStartIndex(gap_index); |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1146 bool is_tagged = HasTaggedValue(first_output->virtual_register()); | 1133 bool is_tagged = HasTaggedValue(first_output->virtual_register()); |
| 1147 AllocateFixed(first_output, gap_index, is_tagged); | 1134 AllocateFixed(first_output, gap_index, is_tagged); |
| 1148 | 1135 |
| 1149 // This value is produced on the stack, we never need to spill it. | 1136 // This value is produced on the stack, we never need to spill it. |
| 1150 if (first_output->IsStackSlot()) { | 1137 if (first_output->IsStackSlot()) { |
| 1151 DCHECK(first_output->index() < 0); | 1138 DCHECK(first_output->index() < 0); |
| 1152 range->SetSpillOperand(first_output); | 1139 range->SetSpillOperand(first_output); |
| 1153 range->SetSpillStartIndex(gap_index - 1); | 1140 range->SetSpillStartIndex(gap_index - 1); |
| 1154 assigned = true; | 1141 assigned = true; |
| 1155 } | 1142 } |
| 1156 code()->AddGapMove(gap_index, first_output, output_copy); | 1143 AddGapMove(gap_index, GapInstruction::START, first_output, |
| 1144 output_copy); |
| 1157 } | 1145 } |
| 1158 | 1146 |
| 1159 // Make sure we add a gap move for spilling (if we have not done | 1147 // Make sure we add a gap move for spilling (if we have not done |
| 1160 // so already). | 1148 // so already). |
| 1161 if (!assigned) { | 1149 if (!assigned) { |
| 1162 range->SpillAtDefinition(local_zone(), gap_index, first_output); | 1150 range->SpillAtDefinition(local_zone(), gap_index, first_output); |
| 1163 range->SetSpillStartIndex(gap_index); | 1151 range->SetSpillStartIndex(gap_index); |
| 1164 } | 1152 } |
| 1165 } | 1153 } |
| 1166 } | 1154 } |
| 1167 } | 1155 } |
| 1168 | 1156 |
| 1169 if (second != nullptr) { | 1157 if (second != nullptr) { |
| 1170 // Handle fixed input operands of second instruction. | 1158 // Handle fixed input operands of second instruction. |
| 1171 for (size_t i = 0; i < second->InputCount(); i++) { | 1159 for (size_t i = 0; i < second->InputCount(); i++) { |
| 1172 auto input = second->InputAt(i); | 1160 auto input = second->InputAt(i); |
| 1173 if (input->IsImmediate()) continue; // Ignore immediates. | 1161 if (input->IsImmediate()) continue; // Ignore immediates. |
| 1174 auto cur_input = UnallocatedOperand::cast(input); | 1162 auto cur_input = UnallocatedOperand::cast(input); |
| 1175 if (cur_input->HasFixedPolicy()) { | 1163 if (cur_input->HasFixedPolicy()) { |
| 1176 auto input_copy = cur_input->CopyUnconstrained(code_zone()); | 1164 auto input_copy = cur_input->CopyUnconstrained(code_zone()); |
| 1177 bool is_tagged = HasTaggedValue(cur_input->virtual_register()); | 1165 bool is_tagged = HasTaggedValue(cur_input->virtual_register()); |
| 1178 AllocateFixed(cur_input, gap_index + 1, is_tagged); | 1166 AllocateFixed(cur_input, gap_index + 1, is_tagged); |
| 1179 AddConstraintsGapMove(gap_index, input_copy, cur_input); | 1167 AddGapMove(gap_index, GapInstruction::END, input_copy, cur_input); |
| 1180 } | 1168 } |
| 1181 } | 1169 } |
| 1182 | 1170 |
| 1183 // Handle "output same as input" for second instruction. | 1171 // Handle "output same as input" for second instruction. |
| 1184 for (size_t i = 0; i < second->OutputCount(); i++) { | 1172 for (size_t i = 0; i < second->OutputCount(); i++) { |
| 1185 auto output = second->OutputAt(i); | 1173 auto output = second->OutputAt(i); |
| 1186 if (!output->IsUnallocated()) continue; | 1174 if (!output->IsUnallocated()) continue; |
| 1187 auto second_output = UnallocatedOperand::cast(output); | 1175 auto second_output = UnallocatedOperand::cast(output); |
| 1188 if (second_output->HasSameAsInputPolicy()) { | 1176 if (second_output->HasSameAsInputPolicy()) { |
| 1189 DCHECK(i == 0); // Only valid for first output. | 1177 DCHECK(i == 0); // Only valid for first output. |
| 1190 UnallocatedOperand* cur_input = | 1178 UnallocatedOperand* cur_input = |
| 1191 UnallocatedOperand::cast(second->InputAt(0)); | 1179 UnallocatedOperand::cast(second->InputAt(0)); |
| 1192 int output_vreg = second_output->virtual_register(); | 1180 int output_vreg = second_output->virtual_register(); |
| 1193 int input_vreg = cur_input->virtual_register(); | 1181 int input_vreg = cur_input->virtual_register(); |
| 1194 | 1182 |
| 1195 auto input_copy = cur_input->CopyUnconstrained(code_zone()); | 1183 auto input_copy = cur_input->CopyUnconstrained(code_zone()); |
| 1196 cur_input->set_virtual_register(second_output->virtual_register()); | 1184 cur_input->set_virtual_register(second_output->virtual_register()); |
| 1197 AddConstraintsGapMove(gap_index, input_copy, cur_input); | 1185 AddGapMove(gap_index, GapInstruction::END, input_copy, cur_input); |
| 1198 | 1186 |
| 1199 if (HasTaggedValue(input_vreg) && !HasTaggedValue(output_vreg)) { | 1187 if (HasTaggedValue(input_vreg) && !HasTaggedValue(output_vreg)) { |
| 1200 int index = gap_index + 1; | 1188 int index = gap_index + 1; |
| 1201 Instruction* instr = InstructionAt(index); | 1189 Instruction* instr = InstructionAt(index); |
| 1202 if (instr->HasPointerMap()) { | 1190 if (instr->HasPointerMap()) { |
| 1203 instr->pointer_map()->RecordPointer(input_copy, code_zone()); | 1191 instr->pointer_map()->RecordPointer(input_copy, code_zone()); |
| 1204 } | 1192 } |
| 1205 } else if (!HasTaggedValue(input_vreg) && HasTaggedValue(output_vreg)) { | 1193 } else if (!HasTaggedValue(input_vreg) && HasTaggedValue(output_vreg)) { |
| 1206 // The input is assumed to immediately have a tagged representation, | 1194 // The input is assumed to immediately have a tagged representation, |
| 1207 // before the pointer map can be used. I.e. the pointer map at the | 1195 // before the pointer map can be used. I.e. the pointer map at the |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1242 LifetimePosition::FromInstructionIndex(block_start); | 1230 LifetimePosition::FromInstructionIndex(block_start); |
| 1243 | 1231 |
| 1244 for (int index = block->last_instruction_index(); index >= block_start; | 1232 for (int index = block->last_instruction_index(); index >= block_start; |
| 1245 index--) { | 1233 index--) { |
| 1246 auto curr_position = LifetimePosition::FromInstructionIndex(index); | 1234 auto curr_position = LifetimePosition::FromInstructionIndex(index); |
| 1247 auto instr = InstructionAt(index); | 1235 auto instr = InstructionAt(index); |
| 1248 DCHECK(instr != nullptr); | 1236 DCHECK(instr != nullptr); |
| 1249 if (instr->IsGapMoves()) { | 1237 if (instr->IsGapMoves()) { |
| 1250 // Process the moves of the gap instruction, making their sources live. | 1238 // Process the moves of the gap instruction, making their sources live. |
| 1251 auto gap = code()->GapAt(index); | 1239 auto gap = code()->GapAt(index); |
| 1252 | 1240 const GapInstruction::InnerPosition kPositions[] = { |
| 1253 // TODO(titzer): no need to create the parallel move if it doesn't exist. | 1241 GapInstruction::END, GapInstruction::START}; |
| 1254 auto move = | 1242 for (auto position : kPositions) { |
| 1255 gap->GetOrCreateParallelMove(GapInstruction::START, code_zone()); | 1243 auto move = gap->GetParallelMove(position); |
| 1256 const ZoneList<MoveOperands>* move_operands = move->move_operands(); | 1244 if (move == nullptr) continue; |
| 1257 for (int i = 0; i < move_operands->length(); ++i) { | 1245 if (position == GapInstruction::END) { |
| 1258 auto cur = &move_operands->at(i); | 1246 curr_position = curr_position.InstructionEnd(); |
| 1259 auto from = cur->source(); | 1247 } else { |
| 1260 auto to = cur->destination(); | 1248 curr_position = curr_position.InstructionStart(); |
| 1261 auto hint = to; | 1249 } |
| 1262 if (to->IsUnallocated()) { | 1250 auto move_ops = move->move_operands(); |
| 1263 int to_vreg = UnallocatedOperand::cast(to)->virtual_register(); | 1251 for (auto cur = move_ops->begin(); cur != move_ops->end(); ++cur) { |
| 1264 auto to_range = LiveRangeFor(to_vreg); | 1252 auto from = cur->source(); |
| 1265 if (to_range->is_phi()) { | 1253 auto to = cur->destination(); |
| 1266 DCHECK(!FLAG_turbo_delay_ssa_decon); | 1254 auto hint = to; |
| 1267 if (to_range->is_non_loop_phi()) { | 1255 if (to->IsUnallocated()) { |
| 1268 hint = to_range->current_hint_operand(); | 1256 int to_vreg = UnallocatedOperand::cast(to)->virtual_register(); |
| 1257 auto to_range = LiveRangeFor(to_vreg); |
| 1258 if (to_range->is_phi()) { |
| 1259 DCHECK(!FLAG_turbo_delay_ssa_decon); |
| 1260 if (to_range->is_non_loop_phi()) { |
| 1261 hint = to_range->current_hint_operand(); |
| 1262 } |
| 1263 } else { |
| 1264 if (live->Contains(to_vreg)) { |
| 1265 Define(curr_position, to, from); |
| 1266 live->Remove(to_vreg); |
| 1267 } else { |
| 1268 cur->Eliminate(); |
| 1269 continue; |
| 1270 } |
| 1269 } | 1271 } |
| 1270 } else { | 1272 } else { |
| 1271 if (live->Contains(to_vreg)) { | 1273 Define(curr_position, to, from); |
| 1272 Define(curr_position, to, from); | |
| 1273 live->Remove(to_vreg); | |
| 1274 } else { | |
| 1275 cur->Eliminate(); | |
| 1276 continue; | |
| 1277 } | |
| 1278 } | 1274 } |
| 1279 } else { | 1275 Use(block_start_position, curr_position, from, hint); |
| 1280 Define(curr_position, to, from); | 1276 if (from->IsUnallocated()) { |
| 1281 } | 1277 live->Add(UnallocatedOperand::cast(from)->virtual_register()); |
| 1282 Use(block_start_position, curr_position, from, hint); | 1278 } |
| 1283 if (from->IsUnallocated()) { | |
| 1284 live->Add(UnallocatedOperand::cast(from)->virtual_register()); | |
| 1285 } | 1279 } |
| 1286 } | 1280 } |
| 1287 } else { | 1281 } else { |
| 1288 // Process output, inputs, and temps of this non-gap instruction. | 1282 // Process output, inputs, and temps of this non-gap instruction. |
| 1289 for (size_t i = 0; i < instr->OutputCount(); i++) { | 1283 for (size_t i = 0; i < instr->OutputCount(); i++) { |
| 1290 auto output = instr->OutputAt(i); | 1284 auto output = instr->OutputAt(i); |
| 1291 if (output->IsUnallocated()) { | 1285 if (output->IsUnallocated()) { |
| 1292 int out_vreg = UnallocatedOperand::cast(output)->virtual_register(); | 1286 int out_vreg = UnallocatedOperand::cast(output)->virtual_register(); |
| 1293 live->Remove(out_vreg); | 1287 live->Remove(out_vreg); |
| 1294 } else if (output->IsConstant()) { | 1288 } else if (output->IsConstant()) { |
| (...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1362 std::make_pair(phi->virtual_register(), PhiMapValue(phi, block))); | 1356 std::make_pair(phi->virtual_register(), PhiMapValue(phi, block))); |
| 1363 DCHECK(res.second); | 1357 DCHECK(res.second); |
| 1364 USE(res); | 1358 USE(res); |
| 1365 } | 1359 } |
| 1366 auto output = phi->output(); | 1360 auto output = phi->output(); |
| 1367 int phi_vreg = phi->virtual_register(); | 1361 int phi_vreg = phi->virtual_register(); |
| 1368 if (!FLAG_turbo_delay_ssa_decon) { | 1362 if (!FLAG_turbo_delay_ssa_decon) { |
| 1369 for (size_t i = 0; i < phi->operands().size(); ++i) { | 1363 for (size_t i = 0; i < phi->operands().size(); ++i) { |
| 1370 InstructionBlock* cur_block = | 1364 InstructionBlock* cur_block = |
| 1371 code()->InstructionBlockAt(block->predecessors()[i]); | 1365 code()->InstructionBlockAt(block->predecessors()[i]); |
| 1372 // The gap move must be added without any special processing as in | 1366 AddGapMove(cur_block->last_instruction_index() - 1, GapInstruction::END, |
| 1373 // the AddConstraintsGapMove. | 1367 phi->inputs()[i], output); |
| 1374 code()->AddGapMove(cur_block->last_instruction_index() - 1, | |
| 1375 phi->inputs()[i], output); | |
| 1376 DCHECK(!InstructionAt(cur_block->last_instruction_index()) | 1368 DCHECK(!InstructionAt(cur_block->last_instruction_index()) |
| 1377 ->HasPointerMap()); | 1369 ->HasPointerMap()); |
| 1378 } | 1370 } |
| 1379 } | 1371 } |
| 1380 auto live_range = LiveRangeFor(phi_vreg); | 1372 auto live_range = LiveRangeFor(phi_vreg); |
| 1381 int gap_index = block->first_instruction_index(); | 1373 int gap_index = block->first_instruction_index(); |
| 1382 live_range->SpillAtDefinition(local_zone(), gap_index, output); | 1374 live_range->SpillAtDefinition(local_zone(), gap_index, output); |
| 1383 live_range->SetSpillStartIndex(gap_index); | 1375 live_range->SetSpillStartIndex(gap_index); |
| 1384 // We use the phi-ness of some nodes in some later heuristics. | 1376 // We use the phi-ness of some nodes in some later heuristics. |
| 1385 live_range->set_is_phi(true); | 1377 live_range->set_is_phi(true); |
| (...skipping 255 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1641 } | 1633 } |
| 1642 } | 1634 } |
| 1643 } | 1635 } |
| 1644 | 1636 |
| 1645 | 1637 |
| 1646 void RegisterAllocator::ResolveControlFlow(const InstructionBlock* block, | 1638 void RegisterAllocator::ResolveControlFlow(const InstructionBlock* block, |
| 1647 InstructionOperand* cur_op, | 1639 InstructionOperand* cur_op, |
| 1648 const InstructionBlock* pred, | 1640 const InstructionBlock* pred, |
| 1649 InstructionOperand* pred_op) { | 1641 InstructionOperand* pred_op) { |
| 1650 if (pred_op->Equals(cur_op)) return; | 1642 if (pred_op->Equals(cur_op)) return; |
| 1651 GapInstruction* gap = nullptr; | 1643 int gap_index; |
| 1644 GapInstruction::InnerPosition position; |
| 1652 if (block->PredecessorCount() == 1) { | 1645 if (block->PredecessorCount() == 1) { |
| 1653 gap = code()->GapAt(block->first_instruction_index()); | 1646 gap_index = block->first_instruction_index(); |
| 1647 position = GapInstruction::START; |
| 1654 } else { | 1648 } else { |
| 1655 DCHECK(pred->SuccessorCount() == 1); | 1649 DCHECK(pred->SuccessorCount() == 1); |
| 1656 gap = GetLastGap(pred); | 1650 DCHECK(!InstructionAt(pred->last_instruction_index())->HasPointerMap()); |
| 1657 auto branch = InstructionAt(pred->last_instruction_index()); | 1651 gap_index = pred->last_instruction_index() - 1; |
| 1658 DCHECK(!branch->HasPointerMap()); | 1652 position = GapInstruction::END; |
| 1659 USE(branch); | |
| 1660 } | 1653 } |
| 1661 gap->GetOrCreateParallelMove(GapInstruction::START, code_zone()) | 1654 AddGapMove(gap_index, position, pred_op, cur_op); |
| 1662 ->AddMove(pred_op, cur_op, code_zone()); | |
| 1663 } | 1655 } |
| 1664 | 1656 |
| 1665 | 1657 |
| 1666 void RegisterAllocator::BuildLiveRanges() { | 1658 void RegisterAllocator::BuildLiveRanges() { |
| 1667 // Process the blocks in reverse order. | 1659 // Process the blocks in reverse order. |
| 1668 for (int block_id = code()->InstructionBlockCount() - 1; block_id >= 0; | 1660 for (int block_id = code()->InstructionBlockCount() - 1; block_id >= 0; |
| 1669 --block_id) { | 1661 --block_id) { |
| 1670 auto block = | 1662 auto block = |
| 1671 code()->InstructionBlockAt(BasicBlock::RpoNumber::FromInt(block_id)); | 1663 code()->InstructionBlockAt(BasicBlock::RpoNumber::FromInt(block_id)); |
| 1672 auto live = ComputeLiveOut(block); | 1664 auto live = ComputeLiveOut(block); |
| 1673 // Initially consider all live_out values live for the entire block. We | 1665 // Initially consider all live_out values live for the entire block. We |
| 1674 // will shorten these intervals if necessary. | 1666 // will shorten these intervals if necessary. |
| 1675 AddInitialIntervals(block, live); | 1667 AddInitialIntervals(block, live); |
| 1676 | 1668 |
| 1677 // Process the instructions in reverse order, generating and killing | 1669 // Process the instructions in reverse order, generating and killing |
| 1678 // live values. | 1670 // live values. |
| 1679 ProcessInstructions(block, live); | 1671 ProcessInstructions(block, live); |
| 1680 // All phi output operands are killed by this block. | 1672 // All phi output operands are killed by this block. |
| 1681 for (auto phi : block->phis()) { | 1673 for (auto phi : block->phis()) { |
| 1682 // The live range interval already ends at the first instruction of the | 1674 // The live range interval already ends at the first instruction of the |
| 1683 // block. | 1675 // block. |
| 1684 int phi_vreg = phi->virtual_register(); | 1676 int phi_vreg = phi->virtual_register(); |
| 1685 live->Remove(phi_vreg); | 1677 live->Remove(phi_vreg); |
| 1686 if (!FLAG_turbo_delay_ssa_decon) { | 1678 if (!FLAG_turbo_delay_ssa_decon) { |
| 1687 InstructionOperand* hint = nullptr; | 1679 InstructionOperand* hint = nullptr; |
| 1688 InstructionOperand* phi_operand = nullptr; | 1680 InstructionOperand* phi_operand = nullptr; |
| 1689 auto gap = | 1681 auto gap = |
| 1690 GetLastGap(code()->InstructionBlockAt(block->predecessors()[0])); | 1682 GetLastGap(code()->InstructionBlockAt(block->predecessors()[0])); |
| 1691 auto move = | 1683 auto move = |
| 1692 gap->GetOrCreateParallelMove(GapInstruction::START, code_zone()); | 1684 gap->GetOrCreateParallelMove(GapInstruction::END, code_zone()); |
| 1693 for (int j = 0; j < move->move_operands()->length(); ++j) { | 1685 for (int j = 0; j < move->move_operands()->length(); ++j) { |
| 1694 auto to = move->move_operands()->at(j).destination(); | 1686 auto to = move->move_operands()->at(j).destination(); |
| 1695 if (to->IsUnallocated() && | 1687 if (to->IsUnallocated() && |
| 1696 UnallocatedOperand::cast(to)->virtual_register() == phi_vreg) { | 1688 UnallocatedOperand::cast(to)->virtual_register() == phi_vreg) { |
| 1697 hint = move->move_operands()->at(j).source(); | 1689 hint = move->move_operands()->at(j).source(); |
| 1698 phi_operand = to; | 1690 phi_operand = to; |
| 1699 break; | 1691 break; |
| 1700 } | 1692 } |
| 1701 } | 1693 } |
| 1702 DCHECK(hint != nullptr); | 1694 DCHECK(hint != nullptr); |
| (...skipping 844 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2547 } else { | 2539 } else { |
| 2548 DCHECK(range->Kind() == GENERAL_REGISTERS); | 2540 DCHECK(range->Kind() == GENERAL_REGISTERS); |
| 2549 assigned_registers_->Add(reg); | 2541 assigned_registers_->Add(reg); |
| 2550 } | 2542 } |
| 2551 range->set_assigned_register(reg, code_zone()); | 2543 range->set_assigned_register(reg, code_zone()); |
| 2552 } | 2544 } |
| 2553 | 2545 |
| 2554 } // namespace compiler | 2546 } // namespace compiler |
| 2555 } // namespace internal | 2547 } // namespace internal |
| 2556 } // namespace v8 | 2548 } // namespace v8 |
| OLD | NEW |