| 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/register-allocator.h" | 5 #include "src/compiler/register-allocator.h" |
| 6 | 6 |
| 7 #include "src/compiler/generic-node-inl.h" | 7 #include "src/compiler/generic-node-inl.h" |
| 8 #include "src/compiler/linkage.h" | 8 #include "src/compiler/linkage.h" |
| 9 #include "src/hydrogen.h" | 9 #include "src/hydrogen.h" |
| 10 #include "src/string-stream.h" | 10 #include "src/string-stream.h" |
| (...skipping 541 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 552 } | 552 } |
| 553 } | 553 } |
| 554 return live_out; | 554 return live_out; |
| 555 } | 555 } |
| 556 | 556 |
| 557 | 557 |
| 558 void RegisterAllocator::AddInitialIntervals(BasicBlock* block, | 558 void RegisterAllocator::AddInitialIntervals(BasicBlock* block, |
| 559 BitVector* live_out) { | 559 BitVector* live_out) { |
| 560 // Add an interval that includes the entire block to the live range for | 560 // Add an interval that includes the entire block to the live range for |
| 561 // each live_out value. | 561 // each live_out value. |
| 562 LifetimePosition start = | 562 LifetimePosition start = LifetimePosition::FromInstructionIndex( |
| 563 LifetimePosition::FromInstructionIndex(block->first_instruction_index()); | 563 code()->first_instruction_index(block)); |
| 564 LifetimePosition end = LifetimePosition::FromInstructionIndex( | 564 LifetimePosition end = |
| 565 block->last_instruction_index()).NextInstruction(); | 565 LifetimePosition::FromInstructionIndex( |
| 566 code()->last_instruction_index(block)).NextInstruction(); |
| 566 BitVector::Iterator iterator(live_out); | 567 BitVector::Iterator iterator(live_out); |
| 567 while (!iterator.Done()) { | 568 while (!iterator.Done()) { |
| 568 int operand_index = iterator.Current(); | 569 int operand_index = iterator.Current(); |
| 569 LiveRange* range = LiveRangeFor(operand_index); | 570 LiveRange* range = LiveRangeFor(operand_index); |
| 570 range->AddUseInterval(start, end, zone()); | 571 range->AddUseInterval(start, end, zone()); |
| 571 iterator.Advance(); | 572 iterator.Advance(); |
| 572 } | 573 } |
| 573 } | 574 } |
| 574 | 575 |
| 575 | 576 |
| (...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 644 LiveRange* result = live_ranges_[index]; | 645 LiveRange* result = live_ranges_[index]; |
| 645 if (result == NULL) { | 646 if (result == NULL) { |
| 646 result = new (zone()) LiveRange(index, code_zone()); | 647 result = new (zone()) LiveRange(index, code_zone()); |
| 647 live_ranges_[index] = result; | 648 live_ranges_[index] = result; |
| 648 } | 649 } |
| 649 return result; | 650 return result; |
| 650 } | 651 } |
| 651 | 652 |
| 652 | 653 |
| 653 GapInstruction* RegisterAllocator::GetLastGap(BasicBlock* block) { | 654 GapInstruction* RegisterAllocator::GetLastGap(BasicBlock* block) { |
| 654 int last_instruction = block->last_instruction_index(); | 655 int last_instruction = code()->last_instruction_index(block); |
| 655 return code()->GapAt(last_instruction - 1); | 656 return code()->GapAt(last_instruction - 1); |
| 656 } | 657 } |
| 657 | 658 |
| 658 | 659 |
| 659 LiveRange* RegisterAllocator::LiveRangeFor(InstructionOperand* operand) { | 660 LiveRange* RegisterAllocator::LiveRangeFor(InstructionOperand* operand) { |
| 660 if (operand->IsUnallocated()) { | 661 if (operand->IsUnallocated()) { |
| 661 return LiveRangeFor(UnallocatedOperand::cast(operand)->virtual_register()); | 662 return LiveRangeFor(UnallocatedOperand::cast(operand)->virtual_register()); |
| 662 } else if (operand->IsRegister()) { | 663 } else if (operand->IsRegister()) { |
| 663 return FixedLiveRangeFor(operand->index()); | 664 return FixedLiveRangeFor(operand->index()); |
| 664 } else if (operand->IsDoubleRegister()) { | 665 } else if (operand->IsDoubleRegister()) { |
| (...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 722 return; | 723 return; |
| 723 } | 724 } |
| 724 } | 725 } |
| 725 } | 726 } |
| 726 } | 727 } |
| 727 move->AddMove(from, to, code_zone()); | 728 move->AddMove(from, to, code_zone()); |
| 728 } | 729 } |
| 729 | 730 |
| 730 | 731 |
| 731 void RegisterAllocator::MeetRegisterConstraints(BasicBlock* block) { | 732 void RegisterAllocator::MeetRegisterConstraints(BasicBlock* block) { |
| 732 int start = block->first_instruction_index(); | 733 int start = code()->first_instruction_index(block); |
| 733 int end = block->last_instruction_index(); | 734 int end = code()->last_instruction_index(block); |
| 734 DCHECK_NE(-1, start); | 735 DCHECK_NE(-1, start); |
| 735 for (int i = start; i <= end; ++i) { | 736 for (int i = start; i <= end; ++i) { |
| 736 if (code()->IsGapAt(i)) { | 737 if (code()->IsGapAt(i)) { |
| 737 Instruction* instr = NULL; | 738 Instruction* instr = NULL; |
| 738 Instruction* prev_instr = NULL; | 739 Instruction* prev_instr = NULL; |
| 739 if (i < end) instr = InstructionAt(i + 1); | 740 if (i < end) instr = InstructionAt(i + 1); |
| 740 if (i > start) prev_instr = InstructionAt(i - 1); | 741 if (i > start) prev_instr = InstructionAt(i - 1); |
| 741 MeetConstraintsBetween(prev_instr, instr, i); | 742 MeetConstraintsBetween(prev_instr, instr, i); |
| 742 if (!AllocationOk()) return; | 743 if (!AllocationOk()) return; |
| 743 } | 744 } |
| 744 } | 745 } |
| 745 | 746 |
| 746 // Meet register constraints for the instruction in the end. | 747 // Meet register constraints for the instruction in the end. |
| 747 if (!code()->IsGapAt(end)) { | 748 if (!code()->IsGapAt(end)) { |
| 748 MeetRegisterConstraintsForLastInstructionInBlock(block); | 749 MeetRegisterConstraintsForLastInstructionInBlock(block); |
| 749 } | 750 } |
| 750 } | 751 } |
| 751 | 752 |
| 752 | 753 |
| 753 void RegisterAllocator::MeetRegisterConstraintsForLastInstructionInBlock( | 754 void RegisterAllocator::MeetRegisterConstraintsForLastInstructionInBlock( |
| 754 BasicBlock* block) { | 755 BasicBlock* block) { |
| 755 int end = block->last_instruction_index(); | 756 int end = code()->last_instruction_index(block); |
| 756 Instruction* last_instruction = InstructionAt(end); | 757 Instruction* last_instruction = InstructionAt(end); |
| 757 for (size_t i = 0; i < last_instruction->OutputCount(); i++) { | 758 for (size_t i = 0; i < last_instruction->OutputCount(); i++) { |
| 758 InstructionOperand* output_operand = last_instruction->OutputAt(i); | 759 InstructionOperand* output_operand = last_instruction->OutputAt(i); |
| 759 DCHECK(!output_operand->IsConstant()); | 760 DCHECK(!output_operand->IsConstant()); |
| 760 UnallocatedOperand* output = UnallocatedOperand::cast(output_operand); | 761 UnallocatedOperand* output = UnallocatedOperand::cast(output_operand); |
| 761 int output_vreg = output->virtual_register(); | 762 int output_vreg = output->virtual_register(); |
| 762 LiveRange* range = LiveRangeFor(output_vreg); | 763 LiveRange* range = LiveRangeFor(output_vreg); |
| 763 bool assigned = false; | 764 bool assigned = false; |
| 764 if (output->HasFixedPolicy()) { | 765 if (output->HasFixedPolicy()) { |
| 765 AllocateFixed(output, -1, false); | 766 AllocateFixed(output, -1, false); |
| 766 // This value is produced on the stack, we never need to spill it. | 767 // This value is produced on the stack, we never need to spill it. |
| 767 if (output->IsStackSlot()) { | 768 if (output->IsStackSlot()) { |
| 768 range->SetSpillOperand(output); | 769 range->SetSpillOperand(output); |
| 769 range->SetSpillStartIndex(end); | 770 range->SetSpillStartIndex(end); |
| 770 assigned = true; | 771 assigned = true; |
| 771 } | 772 } |
| 772 | 773 |
| 773 for (BasicBlock::Successors::iterator succ = block->successors_begin(); | 774 for (BasicBlock::Successors::iterator succ = block->successors_begin(); |
| 774 succ != block->successors_end(); ++succ) { | 775 succ != block->successors_end(); ++succ) { |
| 775 DCHECK((*succ)->PredecessorCount() == 1); | 776 DCHECK((*succ)->PredecessorCount() == 1); |
| 776 int gap_index = (*succ)->first_instruction_index() + 1; | 777 int gap_index = code()->first_instruction_index(*succ) + 1; |
| 777 DCHECK(code()->IsGapAt(gap_index)); | 778 DCHECK(code()->IsGapAt(gap_index)); |
| 778 | 779 |
| 779 // Create an unconstrained operand for the same virtual register | 780 // Create an unconstrained operand for the same virtual register |
| 780 // and insert a gap move from the fixed output to the operand. | 781 // and insert a gap move from the fixed output to the operand. |
| 781 UnallocatedOperand* output_copy = | 782 UnallocatedOperand* output_copy = |
| 782 new (code_zone()) UnallocatedOperand(UnallocatedOperand::ANY); | 783 new (code_zone()) UnallocatedOperand(UnallocatedOperand::ANY); |
| 783 output_copy->set_virtual_register(output_vreg); | 784 output_copy->set_virtual_register(output_vreg); |
| 784 | 785 |
| 785 code()->AddGapMove(gap_index, output, output_copy); | 786 code()->AddGapMove(gap_index, output, output_copy); |
| 786 } | 787 } |
| 787 } | 788 } |
| 788 | 789 |
| 789 if (!assigned) { | 790 if (!assigned) { |
| 790 for (BasicBlock::Successors::iterator succ = block->successors_begin(); | 791 for (BasicBlock::Successors::iterator succ = block->successors_begin(); |
| 791 succ != block->successors_end(); ++succ) { | 792 succ != block->successors_end(); ++succ) { |
| 792 DCHECK((*succ)->PredecessorCount() == 1); | 793 DCHECK((*succ)->PredecessorCount() == 1); |
| 793 int gap_index = (*succ)->first_instruction_index() + 1; | 794 int gap_index = code()->first_instruction_index(*succ) + 1; |
| 794 range->SetSpillStartIndex(gap_index); | 795 range->SetSpillStartIndex(gap_index); |
| 795 | 796 |
| 796 // This move to spill operand is not a real use. Liveness analysis | 797 // This move to spill operand is not a real use. Liveness analysis |
| 797 // and splitting of live ranges do not account for it. | 798 // and splitting of live ranges do not account for it. |
| 798 // Thus it should be inserted to a lifetime position corresponding to | 799 // Thus it should be inserted to a lifetime position corresponding to |
| 799 // the instruction end. | 800 // the instruction end. |
| 800 GapInstruction* gap = code()->GapAt(gap_index); | 801 GapInstruction* gap = code()->GapAt(gap_index); |
| 801 ParallelMove* move = | 802 ParallelMove* move = |
| 802 gap->GetOrCreateParallelMove(GapInstruction::BEFORE, code_zone()); | 803 gap->GetOrCreateParallelMove(GapInstruction::BEFORE, code_zone()); |
| 803 move->AddMove(output, range->GetSpillOperand(), code_zone()); | 804 move->AddMove(output, range->GetSpillOperand(), code_zone()); |
| (...skipping 126 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 930 for (size_t i = 0; i < instr->OutputCount(); i++) { | 931 for (size_t i = 0; i < instr->OutputCount(); i++) { |
| 931 InstructionOperand* output = instr->OutputAt(i); | 932 InstructionOperand* output = instr->OutputAt(i); |
| 932 if (output->IsDoubleRegister() && output->index() == index) return true; | 933 if (output->IsDoubleRegister() && output->index() == index) return true; |
| 933 } | 934 } |
| 934 return false; | 935 return false; |
| 935 } | 936 } |
| 936 | 937 |
| 937 | 938 |
| 938 void RegisterAllocator::ProcessInstructions(BasicBlock* block, | 939 void RegisterAllocator::ProcessInstructions(BasicBlock* block, |
| 939 BitVector* live) { | 940 BitVector* live) { |
| 940 int block_start = block->first_instruction_index(); | 941 int block_start = code()->first_instruction_index(block); |
| 941 | 942 |
| 942 LifetimePosition block_start_position = | 943 LifetimePosition block_start_position = |
| 943 LifetimePosition::FromInstructionIndex(block_start); | 944 LifetimePosition::FromInstructionIndex(block_start); |
| 944 | 945 |
| 945 for (int index = block->last_instruction_index(); index >= block_start; | 946 for (int index = code()->last_instruction_index(block); index >= block_start; |
| 946 index--) { | 947 index--) { |
| 947 LifetimePosition curr_position = | 948 LifetimePosition curr_position = |
| 948 LifetimePosition::FromInstructionIndex(index); | 949 LifetimePosition::FromInstructionIndex(index); |
| 949 | 950 |
| 950 Instruction* instr = InstructionAt(index); | 951 Instruction* instr = InstructionAt(index); |
| 951 DCHECK(instr != NULL); | 952 DCHECK(instr != NULL); |
| 952 if (instr->IsGapMoves()) { | 953 if (instr->IsGapMoves()) { |
| 953 // Process the moves of the gap instruction, making their sources live. | 954 // Process the moves of the gap instruction, making their sources live. |
| 954 GapInstruction* gap = code()->GapAt(index); | 955 GapInstruction* gap = code()->GapAt(index); |
| 955 | 956 |
| (...skipping 118 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1074 ++iter, ++j) { | 1075 ++iter, ++j) { |
| 1075 Node* op = *iter; | 1076 Node* op = *iter; |
| 1076 // TODO(mstarzinger): Use a ValueInputIterator instead. | 1077 // TODO(mstarzinger): Use a ValueInputIterator instead. |
| 1077 if (j >= block->PredecessorCount()) continue; | 1078 if (j >= block->PredecessorCount()) continue; |
| 1078 UnallocatedOperand* operand = | 1079 UnallocatedOperand* operand = |
| 1079 new (code_zone()) UnallocatedOperand(UnallocatedOperand::ANY); | 1080 new (code_zone()) UnallocatedOperand(UnallocatedOperand::ANY); |
| 1080 operand->set_virtual_register(code()->GetVirtualRegister(op)); | 1081 operand->set_virtual_register(code()->GetVirtualRegister(op)); |
| 1081 BasicBlock* cur_block = block->PredecessorAt(j); | 1082 BasicBlock* cur_block = block->PredecessorAt(j); |
| 1082 // The gap move must be added without any special processing as in | 1083 // The gap move must be added without any special processing as in |
| 1083 // the AddConstraintsGapMove. | 1084 // the AddConstraintsGapMove. |
| 1084 code()->AddGapMove(cur_block->last_instruction_index() - 1, operand, | 1085 code()->AddGapMove(code()->last_instruction_index(cur_block) - 1, operand, |
| 1085 phi_operand); | 1086 phi_operand); |
| 1086 | 1087 |
| 1087 Instruction* branch = InstructionAt(cur_block->last_instruction_index()); | 1088 Instruction* branch = |
| 1089 InstructionAt(code()->last_instruction_index(cur_block)); |
| 1088 DCHECK(!branch->HasPointerMap()); | 1090 DCHECK(!branch->HasPointerMap()); |
| 1089 USE(branch); | 1091 USE(branch); |
| 1090 } | 1092 } |
| 1091 | 1093 |
| 1092 LiveRange* live_range = LiveRangeFor(phi_vreg); | 1094 LiveRange* live_range = LiveRangeFor(phi_vreg); |
| 1093 BlockStartInstruction* block_start = code()->GetBlockStart(block); | 1095 BlockStartInstruction* block_start = |
| 1096 code()->GetBlockStart(block->GetRpoNumber()); |
| 1094 block_start->GetOrCreateParallelMove(GapInstruction::START, code_zone()) | 1097 block_start->GetOrCreateParallelMove(GapInstruction::START, code_zone()) |
| 1095 ->AddMove(phi_operand, live_range->GetSpillOperand(), code_zone()); | 1098 ->AddMove(phi_operand, live_range->GetSpillOperand(), code_zone()); |
| 1096 live_range->SetSpillStartIndex(block->first_instruction_index()); | 1099 live_range->SetSpillStartIndex(code()->first_instruction_index(block)); |
| 1097 | 1100 |
| 1098 // We use the phi-ness of some nodes in some later heuristics. | 1101 // We use the phi-ness of some nodes in some later heuristics. |
| 1099 live_range->set_is_phi(true); | 1102 live_range->set_is_phi(true); |
| 1100 if (!block->IsLoopHeader()) { | 1103 if (!block->IsLoopHeader()) { |
| 1101 live_range->set_is_non_loop_phi(true); | 1104 live_range->set_is_non_loop_phi(true); |
| 1102 } | 1105 } |
| 1103 } | 1106 } |
| 1104 } | 1107 } |
| 1105 | 1108 |
| 1106 | 1109 |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1140 | 1143 |
| 1141 // Process the blocks in reverse order. | 1144 // Process the blocks in reverse order. |
| 1142 for (int i = code()->BasicBlockCount() - 1; i >= 0; --i) { | 1145 for (int i = code()->BasicBlockCount() - 1; i >= 0; --i) { |
| 1143 ResolvePhis(code()->BlockAt(i)); | 1146 ResolvePhis(code()->BlockAt(i)); |
| 1144 } | 1147 } |
| 1145 } | 1148 } |
| 1146 | 1149 |
| 1147 | 1150 |
| 1148 void RegisterAllocator::ResolveControlFlow(LiveRange* range, BasicBlock* block, | 1151 void RegisterAllocator::ResolveControlFlow(LiveRange* range, BasicBlock* block, |
| 1149 BasicBlock* pred) { | 1152 BasicBlock* pred) { |
| 1150 LifetimePosition pred_end = | 1153 LifetimePosition pred_end = LifetimePosition::FromInstructionIndex( |
| 1151 LifetimePosition::FromInstructionIndex(pred->last_instruction_index()); | 1154 code()->last_instruction_index(pred)); |
| 1152 LifetimePosition cur_start = | 1155 LifetimePosition cur_start = LifetimePosition::FromInstructionIndex( |
| 1153 LifetimePosition::FromInstructionIndex(block->first_instruction_index()); | 1156 code()->first_instruction_index(block)); |
| 1154 LiveRange* pred_cover = NULL; | 1157 LiveRange* pred_cover = NULL; |
| 1155 LiveRange* cur_cover = NULL; | 1158 LiveRange* cur_cover = NULL; |
| 1156 LiveRange* cur_range = range; | 1159 LiveRange* cur_range = range; |
| 1157 while (cur_range != NULL && (cur_cover == NULL || pred_cover == NULL)) { | 1160 while (cur_range != NULL && (cur_cover == NULL || pred_cover == NULL)) { |
| 1158 if (cur_range->CanCover(cur_start)) { | 1161 if (cur_range->CanCover(cur_start)) { |
| 1159 DCHECK(cur_cover == NULL); | 1162 DCHECK(cur_cover == NULL); |
| 1160 cur_cover = cur_range; | 1163 cur_cover = cur_range; |
| 1161 } | 1164 } |
| 1162 if (cur_range->CanCover(pred_end)) { | 1165 if (cur_range->CanCover(pred_end)) { |
| 1163 DCHECK(pred_cover == NULL); | 1166 DCHECK(pred_cover == NULL); |
| 1164 pred_cover = cur_range; | 1167 pred_cover = cur_range; |
| 1165 } | 1168 } |
| 1166 cur_range = cur_range->next(); | 1169 cur_range = cur_range->next(); |
| 1167 } | 1170 } |
| 1168 | 1171 |
| 1169 if (cur_cover->IsSpilled()) return; | 1172 if (cur_cover->IsSpilled()) return; |
| 1170 DCHECK(pred_cover != NULL && cur_cover != NULL); | 1173 DCHECK(pred_cover != NULL && cur_cover != NULL); |
| 1171 if (pred_cover != cur_cover) { | 1174 if (pred_cover != cur_cover) { |
| 1172 InstructionOperand* pred_op = | 1175 InstructionOperand* pred_op = |
| 1173 pred_cover->CreateAssignedOperand(code_zone()); | 1176 pred_cover->CreateAssignedOperand(code_zone()); |
| 1174 InstructionOperand* cur_op = cur_cover->CreateAssignedOperand(code_zone()); | 1177 InstructionOperand* cur_op = cur_cover->CreateAssignedOperand(code_zone()); |
| 1175 if (!pred_op->Equals(cur_op)) { | 1178 if (!pred_op->Equals(cur_op)) { |
| 1176 GapInstruction* gap = NULL; | 1179 GapInstruction* gap = NULL; |
| 1177 if (block->PredecessorCount() == 1) { | 1180 if (block->PredecessorCount() == 1) { |
| 1178 gap = code()->GapAt(block->first_instruction_index()); | 1181 gap = code()->GapAt(code()->first_instruction_index(block)); |
| 1179 } else { | 1182 } else { |
| 1180 DCHECK(pred->SuccessorCount() == 1); | 1183 DCHECK(pred->SuccessorCount() == 1); |
| 1181 gap = GetLastGap(pred); | 1184 gap = GetLastGap(pred); |
| 1182 | 1185 |
| 1183 Instruction* branch = InstructionAt(pred->last_instruction_index()); | 1186 Instruction* branch = |
| 1187 InstructionAt(code()->last_instruction_index(pred)); |
| 1184 DCHECK(!branch->HasPointerMap()); | 1188 DCHECK(!branch->HasPointerMap()); |
| 1185 USE(branch); | 1189 USE(branch); |
| 1186 } | 1190 } |
| 1187 gap->GetOrCreateParallelMove(GapInstruction::START, code_zone()) | 1191 gap->GetOrCreateParallelMove(GapInstruction::START, code_zone()) |
| 1188 ->AddMove(pred_op, cur_op, code_zone()); | 1192 ->AddMove(pred_op, cur_op, code_zone()); |
| 1189 } | 1193 } |
| 1190 } | 1194 } |
| 1191 } | 1195 } |
| 1192 | 1196 |
| 1193 | 1197 |
| (...skipping 119 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1313 if (to->IsUnallocated() && | 1317 if (to->IsUnallocated() && |
| 1314 UnallocatedOperand::cast(to)->virtual_register() == phi_vreg) { | 1318 UnallocatedOperand::cast(to)->virtual_register() == phi_vreg) { |
| 1315 hint = move->move_operands()->at(j).source(); | 1319 hint = move->move_operands()->at(j).source(); |
| 1316 phi_operand = to; | 1320 phi_operand = to; |
| 1317 break; | 1321 break; |
| 1318 } | 1322 } |
| 1319 } | 1323 } |
| 1320 DCHECK(hint != NULL); | 1324 DCHECK(hint != NULL); |
| 1321 | 1325 |
| 1322 LifetimePosition block_start = LifetimePosition::FromInstructionIndex( | 1326 LifetimePosition block_start = LifetimePosition::FromInstructionIndex( |
| 1323 block->first_instruction_index()); | 1327 code()->first_instruction_index(block)); |
| 1324 Define(block_start, phi_operand, hint); | 1328 Define(block_start, phi_operand, hint); |
| 1325 } | 1329 } |
| 1326 | 1330 |
| 1327 // Now live is live_in for this block except not including values live | 1331 // Now live is live_in for this block except not including values live |
| 1328 // out on backward successor edges. | 1332 // out on backward successor edges. |
| 1329 live_in_sets_[block_id] = live; | 1333 live_in_sets_[block_id] = live; |
| 1330 | 1334 |
| 1331 if (block->IsLoopHeader()) { | 1335 if (block->IsLoopHeader()) { |
| 1332 // Add a live range stretching from the first loop instruction to the last | 1336 // Add a live range stretching from the first loop instruction to the last |
| 1333 // for each value live on entry to the header. | 1337 // for each value live on entry to the header. |
| 1334 BitVector::Iterator iterator(live); | 1338 BitVector::Iterator iterator(live); |
| 1335 LifetimePosition start = LifetimePosition::FromInstructionIndex( | 1339 LifetimePosition start = LifetimePosition::FromInstructionIndex( |
| 1336 block->first_instruction_index()); | 1340 code()->first_instruction_index(block)); |
| 1337 int end_index = | 1341 int end_index = |
| 1338 code()->BlockAt(block->loop_end())->last_instruction_index(); | 1342 code()->last_instruction_index(code()->BlockAt(block->loop_end())); |
| 1339 LifetimePosition end = | 1343 LifetimePosition end = |
| 1340 LifetimePosition::FromInstructionIndex(end_index).NextInstruction(); | 1344 LifetimePosition::FromInstructionIndex(end_index).NextInstruction(); |
| 1341 while (!iterator.Done()) { | 1345 while (!iterator.Done()) { |
| 1342 int operand_index = iterator.Current(); | 1346 int operand_index = iterator.Current(); |
| 1343 LiveRange* range = LiveRangeFor(operand_index); | 1347 LiveRange* range = LiveRangeFor(operand_index); |
| 1344 range->EnsureInterval(start, end, zone()); | 1348 range->EnsureInterval(start, end, zone()); |
| 1345 iterator.Advance(); | 1349 iterator.Advance(); |
| 1346 } | 1350 } |
| 1347 | 1351 |
| 1348 // Insert all values into the live in sets of all blocks in the loop. | 1352 // Insert all values into the live in sets of all blocks in the loop. |
| (...skipping 611 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1960 | 1964 |
| 1961 if (loop_header == NULL) return pos; | 1965 if (loop_header == NULL) return pos; |
| 1962 | 1966 |
| 1963 UsePosition* prev_use = range->PreviousUsePositionRegisterIsBeneficial(pos); | 1967 UsePosition* prev_use = range->PreviousUsePositionRegisterIsBeneficial(pos); |
| 1964 | 1968 |
| 1965 while (loop_header != NULL) { | 1969 while (loop_header != NULL) { |
| 1966 // We are going to spill live range inside the loop. | 1970 // We are going to spill live range inside the loop. |
| 1967 // If possible try to move spilling position backwards to loop header. | 1971 // If possible try to move spilling position backwards to loop header. |
| 1968 // This will reduce number of memory moves on the back edge. | 1972 // This will reduce number of memory moves on the back edge. |
| 1969 LifetimePosition loop_start = LifetimePosition::FromInstructionIndex( | 1973 LifetimePosition loop_start = LifetimePosition::FromInstructionIndex( |
| 1970 loop_header->first_instruction_index()); | 1974 code()->first_instruction_index(loop_header)); |
| 1971 | 1975 |
| 1972 if (range->Covers(loop_start)) { | 1976 if (range->Covers(loop_start)) { |
| 1973 if (prev_use == NULL || prev_use->pos().Value() < loop_start.Value()) { | 1977 if (prev_use == NULL || prev_use->pos().Value() < loop_start.Value()) { |
| 1974 // No register beneficial use inside the loop before the pos. | 1978 // No register beneficial use inside the loop before the pos. |
| 1975 pos = loop_start; | 1979 pos = loop_start; |
| 1976 } | 1980 } |
| 1977 } | 1981 } |
| 1978 | 1982 |
| 1979 // Try hoisting out to an outer loop. | 1983 // Try hoisting out to an outer loop. |
| 1980 loop_header = code()->GetContainingLoop(loop_header); | 1984 loop_header = code()->GetContainingLoop(loop_header); |
| (...skipping 117 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2098 code()->GetContainingLoop(block)->rpo_number() > | 2102 code()->GetContainingLoop(block)->rpo_number() > |
| 2099 start_block->rpo_number()) { | 2103 start_block->rpo_number()) { |
| 2100 block = code()->GetContainingLoop(block); | 2104 block = code()->GetContainingLoop(block); |
| 2101 } | 2105 } |
| 2102 | 2106 |
| 2103 // We did not find any suitable outer loop. Split at the latest possible | 2107 // We did not find any suitable outer loop. Split at the latest possible |
| 2104 // position unless end_block is a loop header itself. | 2108 // position unless end_block is a loop header itself. |
| 2105 if (block == end_block && !end_block->IsLoopHeader()) return end; | 2109 if (block == end_block && !end_block->IsLoopHeader()) return end; |
| 2106 | 2110 |
| 2107 return LifetimePosition::FromInstructionIndex( | 2111 return LifetimePosition::FromInstructionIndex( |
| 2108 block->first_instruction_index()); | 2112 code()->first_instruction_index(block)); |
| 2109 } | 2113 } |
| 2110 | 2114 |
| 2111 | 2115 |
| 2112 void RegisterAllocator::SpillAfter(LiveRange* range, LifetimePosition pos) { | 2116 void RegisterAllocator::SpillAfter(LiveRange* range, LifetimePosition pos) { |
| 2113 LiveRange* second_part = SplitRangeAt(range, pos); | 2117 LiveRange* second_part = SplitRangeAt(range, pos); |
| 2114 if (!AllocationOk()) return; | 2118 if (!AllocationOk()) return; |
| 2115 Spill(second_part); | 2119 Spill(second_part); |
| 2116 } | 2120 } |
| 2117 | 2121 |
| 2118 | 2122 |
| (...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2221 allocator_zone_start_allocation_size_; | 2225 allocator_zone_start_allocation_size_; |
| 2222 isolate()->GetTStatistics()->SaveTiming(name(), base::TimeDelta(), size); | 2226 isolate()->GetTStatistics()->SaveTiming(name(), base::TimeDelta(), size); |
| 2223 } | 2227 } |
| 2224 #ifdef DEBUG | 2228 #ifdef DEBUG |
| 2225 if (allocator_ != NULL) allocator_->Verify(); | 2229 if (allocator_ != NULL) allocator_->Verify(); |
| 2226 #endif | 2230 #endif |
| 2227 } | 2231 } |
| 2228 } | 2232 } |
| 2229 } | 2233 } |
| 2230 } // namespace v8::internal::compiler | 2234 } // namespace v8::internal::compiler |
| OLD | NEW |