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/base/adapters.h" | 5 #include "src/base/adapters.h" |
6 #include "src/compiler/linkage.h" | 6 #include "src/compiler/linkage.h" |
7 #include "src/compiler/register-allocator.h" | 7 #include "src/compiler/register-allocator.h" |
8 #include "src/string-stream.h" | 8 #include "src/string-stream.h" |
9 | 9 |
10 namespace v8 { | 10 namespace v8 { |
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
62 } | 62 } |
63 | 63 |
64 | 64 |
65 bool IsBlockBoundary(const InstructionSequence* code, LifetimePosition pos) { | 65 bool IsBlockBoundary(const InstructionSequence* code, LifetimePosition pos) { |
66 return pos.IsFullStart() && | 66 return pos.IsFullStart() && |
67 code->GetInstructionBlock(pos.ToInstructionIndex())->code_start() == | 67 code->GetInstructionBlock(pos.ToInstructionIndex())->code_start() == |
68 pos.ToInstructionIndex(); | 68 pos.ToInstructionIndex(); |
69 } | 69 } |
70 | 70 |
71 | 71 |
| 72 Instruction* GetLastInstruction(InstructionSequence* code, |
| 73 const InstructionBlock* block) { |
| 74 return code->InstructionAt(block->last_instruction_index()); |
| 75 } |
| 76 |
72 } // namespace | 77 } // namespace |
73 | 78 |
74 | 79 |
75 UsePosition::UsePosition(LifetimePosition pos, InstructionOperand* operand, | 80 UsePosition::UsePosition(LifetimePosition pos, InstructionOperand* operand, |
76 InstructionOperand* hint) | 81 InstructionOperand* hint) |
77 : operand_(operand), hint_(hint), pos_(pos), next_(nullptr), flags_(0) { | 82 : operand_(operand), hint_(hint), pos_(pos), next_(nullptr), flags_(0) { |
78 bool register_beneficial = true; | 83 bool register_beneficial = true; |
79 UsePositionType type = UsePositionType::kAny; | 84 UsePositionType type = UsePositionType::kAny; |
80 if (operand_ != nullptr && operand_->IsUnallocated()) { | 85 if (operand_ != nullptr && operand_->IsUnallocated()) { |
81 const UnallocatedOperand* unalloc = UnallocatedOperand::cast(operand_); | 86 const UnallocatedOperand* unalloc = UnallocatedOperand::cast(operand_); |
(...skipping 744 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
826 assigned_registers_->Add(reg); | 831 assigned_registers_->Add(reg); |
827 } | 832 } |
828 range->set_assigned_register(reg); | 833 range->set_assigned_register(reg); |
829 auto assignment = range->GetAssignedOperand(); | 834 auto assignment = range->GetAssignedOperand(); |
830 // TODO(dcarney): stop aliasing hint operands. | 835 // TODO(dcarney): stop aliasing hint operands. |
831 range->ConvertUsesToOperand(assignment, nullptr); | 836 range->ConvertUsesToOperand(assignment, nullptr); |
832 if (range->is_phi()) AssignPhiInput(range, assignment); | 837 if (range->is_phi()) AssignPhiInput(range, assignment); |
833 } | 838 } |
834 | 839 |
835 | 840 |
836 LiveRangeBuilder::LiveRangeBuilder(RegisterAllocationData* data) | 841 ConstraintBuilder::ConstraintBuilder(RegisterAllocationData* data) |
837 : data_(data) {} | 842 : data_(data) {} |
838 | 843 |
839 | 844 |
840 BitVector* LiveRangeBuilder::ComputeLiveOut(const InstructionBlock* block) { | 845 InstructionOperand* ConstraintBuilder::AllocateFixed( |
841 // Compute live out for the given block, except not including backward | 846 UnallocatedOperand* operand, int pos, bool is_tagged) { |
842 // successor edges. | |
843 auto live_out = new (allocation_zone()) | |
844 BitVector(code()->VirtualRegisterCount(), allocation_zone()); | |
845 | |
846 // Process all successor blocks. | |
847 for (auto succ : block->successors()) { | |
848 // Add values live on entry to the successor. Note the successor's | |
849 // live_in will not be computed yet for backwards edges. | |
850 auto live_in = live_in_sets()[succ.ToSize()]; | |
851 if (live_in != nullptr) live_out->Union(*live_in); | |
852 | |
853 // All phi input operands corresponding to this successor edge are live | |
854 // out from this block. | |
855 auto successor = code()->InstructionBlockAt(succ); | |
856 size_t index = successor->PredecessorIndexOf(block->rpo_number()); | |
857 DCHECK(index < successor->PredecessorCount()); | |
858 for (auto phi : successor->phis()) { | |
859 live_out->Add(phi->operands()[index]); | |
860 } | |
861 } | |
862 return live_out; | |
863 } | |
864 | |
865 | |
866 void LiveRangeBuilder::AddInitialIntervals(const InstructionBlock* block, | |
867 BitVector* live_out) { | |
868 // Add an interval that includes the entire block to the live range for | |
869 // each live_out value. | |
870 auto start = LifetimePosition::GapFromInstructionIndex( | |
871 block->first_instruction_index()); | |
872 auto end = LifetimePosition::InstructionFromInstructionIndex( | |
873 block->last_instruction_index()).NextStart(); | |
874 BitVector::Iterator iterator(live_out); | |
875 while (!iterator.Done()) { | |
876 int operand_index = iterator.Current(); | |
877 auto range = LiveRangeFor(operand_index); | |
878 range->AddUseInterval(start, end, allocation_zone()); | |
879 iterator.Advance(); | |
880 } | |
881 } | |
882 | |
883 | |
884 Instruction* LiveRangeBuilder::GetLastInstruction( | |
885 const InstructionBlock* block) { | |
886 return code()->InstructionAt(block->last_instruction_index()); | |
887 } | |
888 | |
889 | |
890 int LiveRangeBuilder::FixedDoubleLiveRangeID(int index) { | |
891 return -index - 1 - config()->num_general_registers(); | |
892 } | |
893 | |
894 | |
895 InstructionOperand* LiveRangeBuilder::AllocateFixed(UnallocatedOperand* operand, | |
896 int pos, bool is_tagged) { | |
897 TRACE("Allocating fixed reg for op %d\n", operand->virtual_register()); | 847 TRACE("Allocating fixed reg for op %d\n", operand->virtual_register()); |
898 DCHECK(operand->HasFixedPolicy()); | 848 DCHECK(operand->HasFixedPolicy()); |
899 InstructionOperand allocated; | 849 InstructionOperand allocated; |
900 if (operand->HasFixedSlotPolicy()) { | 850 if (operand->HasFixedSlotPolicy()) { |
901 allocated = AllocatedOperand(AllocatedOperand::STACK_SLOT, | 851 allocated = AllocatedOperand(AllocatedOperand::STACK_SLOT, |
902 operand->fixed_slot_index()); | 852 operand->fixed_slot_index()); |
903 } else if (operand->HasFixedRegisterPolicy()) { | 853 } else if (operand->HasFixedRegisterPolicy()) { |
904 allocated = AllocatedOperand(AllocatedOperand::REGISTER, | 854 allocated = AllocatedOperand(AllocatedOperand::REGISTER, |
905 operand->fixed_register_index()); | 855 operand->fixed_register_index()); |
906 } else if (operand->HasFixedDoubleRegisterPolicy()) { | 856 } else if (operand->HasFixedDoubleRegisterPolicy()) { |
907 allocated = AllocatedOperand(AllocatedOperand::DOUBLE_REGISTER, | 857 allocated = AllocatedOperand(AllocatedOperand::DOUBLE_REGISTER, |
908 operand->fixed_register_index()); | 858 operand->fixed_register_index()); |
909 } else { | 859 } else { |
910 UNREACHABLE(); | 860 UNREACHABLE(); |
911 } | 861 } |
912 InstructionOperand::ReplaceWith(operand, &allocated); | 862 InstructionOperand::ReplaceWith(operand, &allocated); |
913 if (is_tagged) { | 863 if (is_tagged) { |
914 TRACE("Fixed reg is tagged at %d\n", pos); | 864 TRACE("Fixed reg is tagged at %d\n", pos); |
915 auto instr = InstructionAt(pos); | 865 auto instr = InstructionAt(pos); |
916 if (instr->HasReferenceMap()) { | 866 if (instr->HasReferenceMap()) { |
917 instr->reference_map()->RecordReference(*operand); | 867 instr->reference_map()->RecordReference(*operand); |
918 } | 868 } |
919 } | 869 } |
920 return operand; | 870 return operand; |
921 } | 871 } |
922 | 872 |
923 | 873 |
924 LiveRange* LiveRangeBuilder::FixedLiveRangeFor(int index) { | 874 void ConstraintBuilder::MeetRegisterConstraints() { |
925 DCHECK(index < config()->num_general_registers()); | 875 for (auto block : code()->instruction_blocks()) { |
926 auto result = fixed_live_ranges()[index]; | 876 MeetRegisterConstraints(block); |
927 if (result == nullptr) { | |
928 result = data()->NewLiveRange(FixedLiveRangeID(index)); | |
929 DCHECK(result->IsFixed()); | |
930 result->set_kind(GENERAL_REGISTERS); | |
931 data()->SetLiveRangeAssignedRegister(result, index); | |
932 fixed_live_ranges()[index] = result; | |
933 } | |
934 return result; | |
935 } | |
936 | |
937 | |
938 LiveRange* LiveRangeBuilder::FixedDoubleLiveRangeFor(int index) { | |
939 DCHECK(index < config()->num_aliased_double_registers()); | |
940 auto result = fixed_double_live_ranges()[index]; | |
941 if (result == nullptr) { | |
942 result = data()->NewLiveRange(FixedDoubleLiveRangeID(index)); | |
943 DCHECK(result->IsFixed()); | |
944 result->set_kind(DOUBLE_REGISTERS); | |
945 data()->SetLiveRangeAssignedRegister(result, index); | |
946 fixed_double_live_ranges()[index] = result; | |
947 } | |
948 return result; | |
949 } | |
950 | |
951 | |
952 LiveRange* LiveRangeBuilder::LiveRangeFor(InstructionOperand* operand) { | |
953 if (operand->IsUnallocated()) { | |
954 return LiveRangeFor(UnallocatedOperand::cast(operand)->virtual_register()); | |
955 } else if (operand->IsConstant()) { | |
956 return LiveRangeFor(ConstantOperand::cast(operand)->virtual_register()); | |
957 } else if (operand->IsRegister()) { | |
958 return FixedLiveRangeFor(RegisterOperand::cast(operand)->index()); | |
959 } else if (operand->IsDoubleRegister()) { | |
960 return FixedDoubleLiveRangeFor( | |
961 DoubleRegisterOperand::cast(operand)->index()); | |
962 } else { | |
963 return nullptr; | |
964 } | 877 } |
965 } | 878 } |
966 | 879 |
967 | 880 |
968 void LiveRangeBuilder::Define(LifetimePosition position, | 881 void ConstraintBuilder::MeetRegisterConstraints(const InstructionBlock* block) { |
969 InstructionOperand* operand, | |
970 InstructionOperand* hint) { | |
971 auto range = LiveRangeFor(operand); | |
972 if (range == nullptr) return; | |
973 | |
974 if (range->IsEmpty() || range->Start().Value() > position.Value()) { | |
975 // Can happen if there is a definition without use. | |
976 range->AddUseInterval(position, position.NextStart(), allocation_zone()); | |
977 range->AddUsePosition(position.NextStart(), nullptr, nullptr, | |
978 allocation_zone()); | |
979 } else { | |
980 range->ShortenTo(position); | |
981 } | |
982 | |
983 if (operand->IsUnallocated()) { | |
984 auto unalloc_operand = UnallocatedOperand::cast(operand); | |
985 range->AddUsePosition(position, unalloc_operand, hint, allocation_zone()); | |
986 } | |
987 } | |
988 | |
989 | |
990 void LiveRangeBuilder::Use(LifetimePosition block_start, | |
991 LifetimePosition position, | |
992 InstructionOperand* operand, | |
993 InstructionOperand* hint) { | |
994 auto range = LiveRangeFor(operand); | |
995 if (range == nullptr) return; | |
996 if (operand->IsUnallocated()) { | |
997 UnallocatedOperand* unalloc_operand = UnallocatedOperand::cast(operand); | |
998 range->AddUsePosition(position, unalloc_operand, hint, allocation_zone()); | |
999 } | |
1000 range->AddUseInterval(block_start, position, allocation_zone()); | |
1001 } | |
1002 | |
1003 | |
1004 void LiveRangeBuilder::MeetRegisterConstraints(const InstructionBlock* block) { | |
1005 int start = block->first_instruction_index(); | 882 int start = block->first_instruction_index(); |
1006 int end = block->last_instruction_index(); | 883 int end = block->last_instruction_index(); |
1007 DCHECK_NE(-1, start); | 884 DCHECK_NE(-1, start); |
1008 for (int i = start; i <= end; ++i) { | 885 for (int i = start; i <= end; ++i) { |
1009 MeetConstraintsBefore(i); | 886 MeetConstraintsBefore(i); |
1010 if (i != end) MeetConstraintsAfter(i); | 887 if (i != end) MeetConstraintsAfter(i); |
1011 } | 888 } |
1012 // Meet register constraints for the instruction in the end. | 889 // Meet register constraints for the instruction in the end. |
1013 MeetRegisterConstraintsForLastInstructionInBlock(block); | 890 MeetRegisterConstraintsForLastInstructionInBlock(block); |
1014 } | 891 } |
1015 | 892 |
1016 | 893 |
1017 void LiveRangeBuilder::MeetRegisterConstraintsForLastInstructionInBlock( | 894 void ConstraintBuilder::MeetRegisterConstraintsForLastInstructionInBlock( |
1018 const InstructionBlock* block) { | 895 const InstructionBlock* block) { |
1019 int end = block->last_instruction_index(); | 896 int end = block->last_instruction_index(); |
1020 auto last_instruction = InstructionAt(end); | 897 auto last_instruction = InstructionAt(end); |
1021 for (size_t i = 0; i < last_instruction->OutputCount(); i++) { | 898 for (size_t i = 0; i < last_instruction->OutputCount(); i++) { |
1022 auto output_operand = last_instruction->OutputAt(i); | 899 auto output_operand = last_instruction->OutputAt(i); |
1023 DCHECK(!output_operand->IsConstant()); | 900 DCHECK(!output_operand->IsConstant()); |
1024 auto output = UnallocatedOperand::cast(output_operand); | 901 auto output = UnallocatedOperand::cast(output_operand); |
1025 int output_vreg = output->virtual_register(); | 902 int output_vreg = output->virtual_register(); |
1026 auto range = LiveRangeFor(output_vreg); | 903 auto range = LiveRangeFor(output_vreg); |
1027 bool assigned = false; | 904 bool assigned = false; |
(...skipping 25 matching lines...) Expand all Loading... |
1053 DCHECK(successor->PredecessorCount() == 1); | 930 DCHECK(successor->PredecessorCount() == 1); |
1054 int gap_index = successor->first_instruction_index(); | 931 int gap_index = successor->first_instruction_index(); |
1055 range->SpillAtDefinition(allocation_zone(), gap_index, output); | 932 range->SpillAtDefinition(allocation_zone(), gap_index, output); |
1056 range->SetSpillStartIndex(gap_index); | 933 range->SetSpillStartIndex(gap_index); |
1057 } | 934 } |
1058 } | 935 } |
1059 } | 936 } |
1060 } | 937 } |
1061 | 938 |
1062 | 939 |
1063 void LiveRangeBuilder::MeetConstraintsAfter(int instr_index) { | 940 void ConstraintBuilder::MeetConstraintsAfter(int instr_index) { |
1064 auto first = InstructionAt(instr_index); | 941 auto first = InstructionAt(instr_index); |
1065 // Handle fixed temporaries. | 942 // Handle fixed temporaries. |
1066 for (size_t i = 0; i < first->TempCount(); i++) { | 943 for (size_t i = 0; i < first->TempCount(); i++) { |
1067 auto temp = UnallocatedOperand::cast(first->TempAt(i)); | 944 auto temp = UnallocatedOperand::cast(first->TempAt(i)); |
1068 if (temp->HasFixedPolicy()) AllocateFixed(temp, instr_index, false); | 945 if (temp->HasFixedPolicy()) AllocateFixed(temp, instr_index, false); |
1069 } | 946 } |
1070 // Handle constant/fixed output operands. | 947 // Handle constant/fixed output operands. |
1071 for (size_t i = 0; i < first->OutputCount(); i++) { | 948 for (size_t i = 0; i < first->OutputCount(); i++) { |
1072 InstructionOperand* output = first->OutputAt(i); | 949 InstructionOperand* output = first->OutputAt(i); |
1073 if (output->IsConstant()) { | 950 if (output->IsConstant()) { |
(...skipping 27 matching lines...) Expand all Loading... |
1101 // so already). | 978 // so already). |
1102 if (!assigned) { | 979 if (!assigned) { |
1103 range->SpillAtDefinition(allocation_zone(), instr_index + 1, | 980 range->SpillAtDefinition(allocation_zone(), instr_index + 1, |
1104 first_output); | 981 first_output); |
1105 range->SetSpillStartIndex(instr_index + 1); | 982 range->SetSpillStartIndex(instr_index + 1); |
1106 } | 983 } |
1107 } | 984 } |
1108 } | 985 } |
1109 | 986 |
1110 | 987 |
1111 void LiveRangeBuilder::MeetConstraintsBefore(int instr_index) { | 988 void ConstraintBuilder::MeetConstraintsBefore(int instr_index) { |
1112 auto second = InstructionAt(instr_index); | 989 auto second = InstructionAt(instr_index); |
1113 // Handle fixed input operands of second instruction. | 990 // Handle fixed input operands of second instruction. |
1114 for (size_t i = 0; i < second->InputCount(); i++) { | 991 for (size_t i = 0; i < second->InputCount(); i++) { |
1115 auto input = second->InputAt(i); | 992 auto input = second->InputAt(i); |
1116 if (input->IsImmediate()) continue; // Ignore immediates. | 993 if (input->IsImmediate()) continue; // Ignore immediates. |
1117 auto cur_input = UnallocatedOperand::cast(input); | 994 auto cur_input = UnallocatedOperand::cast(input); |
1118 if (cur_input->HasFixedPolicy()) { | 995 if (cur_input->HasFixedPolicy()) { |
1119 int input_vreg = cur_input->virtual_register(); | 996 int input_vreg = cur_input->virtual_register(); |
1120 UnallocatedOperand input_copy(UnallocatedOperand::ANY, input_vreg); | 997 UnallocatedOperand input_copy(UnallocatedOperand::ANY, input_vreg); |
1121 bool is_tagged = IsReference(input_vreg); | 998 bool is_tagged = IsReference(input_vreg); |
(...skipping 24 matching lines...) Expand all Loading... |
1146 // before the pointer map can be used. I.e. the pointer map at the | 1023 // before the pointer map can be used. I.e. the pointer map at the |
1147 // instruction will include the output operand (whose value at the | 1024 // instruction will include the output operand (whose value at the |
1148 // beginning of the instruction is equal to the input operand). If | 1025 // beginning of the instruction is equal to the input operand). If |
1149 // this is not desired, then the pointer map at this instruction needs | 1026 // this is not desired, then the pointer map at this instruction needs |
1150 // to be adjusted manually. | 1027 // to be adjusted manually. |
1151 } | 1028 } |
1152 } | 1029 } |
1153 } | 1030 } |
1154 | 1031 |
1155 | 1032 |
| 1033 void ConstraintBuilder::ResolvePhis() { |
| 1034 // Process the blocks in reverse order. |
| 1035 for (InstructionBlock* block : base::Reversed(code()->instruction_blocks())) { |
| 1036 ResolvePhis(block); |
| 1037 } |
| 1038 } |
| 1039 |
| 1040 |
| 1041 void ConstraintBuilder::ResolvePhis(const InstructionBlock* block) { |
| 1042 for (auto phi : block->phis()) { |
| 1043 int phi_vreg = phi->virtual_register(); |
| 1044 auto map_value = new (allocation_zone()) |
| 1045 RegisterAllocationData::PhiMapValue(phi, block, allocation_zone()); |
| 1046 auto res = data()->phi_map().insert(std::make_pair(phi_vreg, map_value)); |
| 1047 DCHECK(res.second); |
| 1048 USE(res); |
| 1049 auto& output = phi->output(); |
| 1050 for (size_t i = 0; i < phi->operands().size(); ++i) { |
| 1051 InstructionBlock* cur_block = |
| 1052 code()->InstructionBlockAt(block->predecessors()[i]); |
| 1053 UnallocatedOperand input(UnallocatedOperand::ANY, phi->operands()[i]); |
| 1054 auto move = data()->AddGapMove(cur_block->last_instruction_index(), |
| 1055 Instruction::END, input, output); |
| 1056 map_value->incoming_moves.push_back(move); |
| 1057 DCHECK(!InstructionAt(cur_block->last_instruction_index()) |
| 1058 ->HasReferenceMap()); |
| 1059 } |
| 1060 auto live_range = LiveRangeFor(phi_vreg); |
| 1061 int gap_index = block->first_instruction_index(); |
| 1062 live_range->SpillAtDefinition(allocation_zone(), gap_index, &output); |
| 1063 live_range->SetSpillStartIndex(gap_index); |
| 1064 // We use the phi-ness of some nodes in some later heuristics. |
| 1065 live_range->set_is_phi(true); |
| 1066 live_range->set_is_non_loop_phi(!block->IsLoopHeader()); |
| 1067 } |
| 1068 } |
| 1069 |
| 1070 |
| 1071 LiveRangeBuilder::LiveRangeBuilder(RegisterAllocationData* data) |
| 1072 : data_(data) {} |
| 1073 |
| 1074 |
| 1075 BitVector* LiveRangeBuilder::ComputeLiveOut(const InstructionBlock* block) { |
| 1076 // Compute live out for the given block, except not including backward |
| 1077 // successor edges. |
| 1078 auto live_out = new (allocation_zone()) |
| 1079 BitVector(code()->VirtualRegisterCount(), allocation_zone()); |
| 1080 |
| 1081 // Process all successor blocks. |
| 1082 for (auto succ : block->successors()) { |
| 1083 // Add values live on entry to the successor. Note the successor's |
| 1084 // live_in will not be computed yet for backwards edges. |
| 1085 auto live_in = live_in_sets()[succ.ToSize()]; |
| 1086 if (live_in != nullptr) live_out->Union(*live_in); |
| 1087 |
| 1088 // All phi input operands corresponding to this successor edge are live |
| 1089 // out from this block. |
| 1090 auto successor = code()->InstructionBlockAt(succ); |
| 1091 size_t index = successor->PredecessorIndexOf(block->rpo_number()); |
| 1092 DCHECK(index < successor->PredecessorCount()); |
| 1093 for (auto phi : successor->phis()) { |
| 1094 live_out->Add(phi->operands()[index]); |
| 1095 } |
| 1096 } |
| 1097 return live_out; |
| 1098 } |
| 1099 |
| 1100 |
| 1101 void LiveRangeBuilder::AddInitialIntervals(const InstructionBlock* block, |
| 1102 BitVector* live_out) { |
| 1103 // Add an interval that includes the entire block to the live range for |
| 1104 // each live_out value. |
| 1105 auto start = LifetimePosition::GapFromInstructionIndex( |
| 1106 block->first_instruction_index()); |
| 1107 auto end = LifetimePosition::InstructionFromInstructionIndex( |
| 1108 block->last_instruction_index()).NextStart(); |
| 1109 BitVector::Iterator iterator(live_out); |
| 1110 while (!iterator.Done()) { |
| 1111 int operand_index = iterator.Current(); |
| 1112 auto range = LiveRangeFor(operand_index); |
| 1113 range->AddUseInterval(start, end, allocation_zone()); |
| 1114 iterator.Advance(); |
| 1115 } |
| 1116 } |
| 1117 |
| 1118 |
| 1119 int LiveRangeBuilder::FixedDoubleLiveRangeID(int index) { |
| 1120 return -index - 1 - config()->num_general_registers(); |
| 1121 } |
| 1122 |
| 1123 |
| 1124 LiveRange* LiveRangeBuilder::FixedLiveRangeFor(int index) { |
| 1125 DCHECK(index < config()->num_general_registers()); |
| 1126 auto result = data()->fixed_live_ranges()[index]; |
| 1127 if (result == nullptr) { |
| 1128 result = data()->NewLiveRange(FixedLiveRangeID(index)); |
| 1129 DCHECK(result->IsFixed()); |
| 1130 result->set_kind(GENERAL_REGISTERS); |
| 1131 data()->SetLiveRangeAssignedRegister(result, index); |
| 1132 data()->fixed_live_ranges()[index] = result; |
| 1133 } |
| 1134 return result; |
| 1135 } |
| 1136 |
| 1137 |
| 1138 LiveRange* LiveRangeBuilder::FixedDoubleLiveRangeFor(int index) { |
| 1139 DCHECK(index < config()->num_aliased_double_registers()); |
| 1140 auto result = data()->fixed_double_live_ranges()[index]; |
| 1141 if (result == nullptr) { |
| 1142 result = data()->NewLiveRange(FixedDoubleLiveRangeID(index)); |
| 1143 DCHECK(result->IsFixed()); |
| 1144 result->set_kind(DOUBLE_REGISTERS); |
| 1145 data()->SetLiveRangeAssignedRegister(result, index); |
| 1146 data()->fixed_double_live_ranges()[index] = result; |
| 1147 } |
| 1148 return result; |
| 1149 } |
| 1150 |
| 1151 |
| 1152 LiveRange* LiveRangeBuilder::LiveRangeFor(InstructionOperand* operand) { |
| 1153 if (operand->IsUnallocated()) { |
| 1154 return LiveRangeFor(UnallocatedOperand::cast(operand)->virtual_register()); |
| 1155 } else if (operand->IsConstant()) { |
| 1156 return LiveRangeFor(ConstantOperand::cast(operand)->virtual_register()); |
| 1157 } else if (operand->IsRegister()) { |
| 1158 return FixedLiveRangeFor(RegisterOperand::cast(operand)->index()); |
| 1159 } else if (operand->IsDoubleRegister()) { |
| 1160 return FixedDoubleLiveRangeFor( |
| 1161 DoubleRegisterOperand::cast(operand)->index()); |
| 1162 } else { |
| 1163 return nullptr; |
| 1164 } |
| 1165 } |
| 1166 |
| 1167 |
| 1168 void LiveRangeBuilder::Define(LifetimePosition position, |
| 1169 InstructionOperand* operand, |
| 1170 InstructionOperand* hint) { |
| 1171 auto range = LiveRangeFor(operand); |
| 1172 if (range == nullptr) return; |
| 1173 |
| 1174 if (range->IsEmpty() || range->Start().Value() > position.Value()) { |
| 1175 // Can happen if there is a definition without use. |
| 1176 range->AddUseInterval(position, position.NextStart(), allocation_zone()); |
| 1177 range->AddUsePosition(position.NextStart(), nullptr, nullptr, |
| 1178 allocation_zone()); |
| 1179 } else { |
| 1180 range->ShortenTo(position); |
| 1181 } |
| 1182 |
| 1183 if (operand->IsUnallocated()) { |
| 1184 auto unalloc_operand = UnallocatedOperand::cast(operand); |
| 1185 range->AddUsePosition(position, unalloc_operand, hint, allocation_zone()); |
| 1186 } |
| 1187 } |
| 1188 |
| 1189 |
| 1190 void LiveRangeBuilder::Use(LifetimePosition block_start, |
| 1191 LifetimePosition position, |
| 1192 InstructionOperand* operand, |
| 1193 InstructionOperand* hint) { |
| 1194 auto range = LiveRangeFor(operand); |
| 1195 if (range == nullptr) return; |
| 1196 if (operand->IsUnallocated()) { |
| 1197 UnallocatedOperand* unalloc_operand = UnallocatedOperand::cast(operand); |
| 1198 range->AddUsePosition(position, unalloc_operand, hint, allocation_zone()); |
| 1199 } |
| 1200 range->AddUseInterval(block_start, position, allocation_zone()); |
| 1201 } |
| 1202 |
| 1203 |
1156 bool LiveRangeBuilder::IsOutputRegisterOf(Instruction* instr, int index) { | 1204 bool LiveRangeBuilder::IsOutputRegisterOf(Instruction* instr, int index) { |
1157 for (size_t i = 0; i < instr->OutputCount(); i++) { | 1205 for (size_t i = 0; i < instr->OutputCount(); i++) { |
1158 auto output = instr->OutputAt(i); | 1206 auto output = instr->OutputAt(i); |
1159 if (output->IsRegister() && RegisterOperand::cast(output)->index() == index) | 1207 if (output->IsRegister() && RegisterOperand::cast(output)->index() == index) |
1160 return true; | 1208 return true; |
1161 } | 1209 } |
1162 return false; | 1210 return false; |
1163 } | 1211 } |
1164 | 1212 |
1165 | 1213 |
(...skipping 11 matching lines...) Expand all Loading... |
1177 void LiveRangeBuilder::ProcessInstructions(const InstructionBlock* block, | 1225 void LiveRangeBuilder::ProcessInstructions(const InstructionBlock* block, |
1178 BitVector* live) { | 1226 BitVector* live) { |
1179 int block_start = block->first_instruction_index(); | 1227 int block_start = block->first_instruction_index(); |
1180 auto block_start_position = | 1228 auto block_start_position = |
1181 LifetimePosition::GapFromInstructionIndex(block_start); | 1229 LifetimePosition::GapFromInstructionIndex(block_start); |
1182 | 1230 |
1183 for (int index = block->last_instruction_index(); index >= block_start; | 1231 for (int index = block->last_instruction_index(); index >= block_start; |
1184 index--) { | 1232 index--) { |
1185 auto curr_position = | 1233 auto curr_position = |
1186 LifetimePosition::InstructionFromInstructionIndex(index); | 1234 LifetimePosition::InstructionFromInstructionIndex(index); |
1187 auto instr = InstructionAt(index); | 1235 auto instr = code()->InstructionAt(index); |
1188 DCHECK(instr != nullptr); | 1236 DCHECK(instr != nullptr); |
1189 DCHECK(curr_position.IsInstructionPosition()); | 1237 DCHECK(curr_position.IsInstructionPosition()); |
1190 // Process output, inputs, and temps of this instruction. | 1238 // Process output, inputs, and temps of this instruction. |
1191 for (size_t i = 0; i < instr->OutputCount(); i++) { | 1239 for (size_t i = 0; i < instr->OutputCount(); i++) { |
1192 auto output = instr->OutputAt(i); | 1240 auto output = instr->OutputAt(i); |
1193 if (output->IsUnallocated()) { | 1241 if (output->IsUnallocated()) { |
1194 // Unsupported. | 1242 // Unsupported. |
1195 DCHECK(!UnallocatedOperand::cast(output)->HasSlotPolicy()); | 1243 DCHECK(!UnallocatedOperand::cast(output)->HasSlotPolicy()); |
1196 int out_vreg = UnallocatedOperand::cast(output)->virtual_register(); | 1244 int out_vreg = UnallocatedOperand::cast(output)->virtual_register(); |
1197 live->Remove(out_vreg); | 1245 live->Remove(out_vreg); |
(...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1301 Use(block_start_position, curr_position, &from, hint); | 1349 Use(block_start_position, curr_position, &from, hint); |
1302 if (from.IsUnallocated()) { | 1350 if (from.IsUnallocated()) { |
1303 live->Add(UnallocatedOperand::cast(from).virtual_register()); | 1351 live->Add(UnallocatedOperand::cast(from).virtual_register()); |
1304 } | 1352 } |
1305 } | 1353 } |
1306 } | 1354 } |
1307 } | 1355 } |
1308 } | 1356 } |
1309 | 1357 |
1310 | 1358 |
1311 void LiveRangeBuilder::ResolvePhis(const InstructionBlock* block) { | |
1312 for (auto phi : block->phis()) { | |
1313 int phi_vreg = phi->virtual_register(); | |
1314 auto map_value = new (allocation_zone()) | |
1315 RegisterAllocationData::PhiMapValue(phi, block, allocation_zone()); | |
1316 auto res = phi_map().insert(std::make_pair(phi_vreg, map_value)); | |
1317 DCHECK(res.second); | |
1318 USE(res); | |
1319 auto& output = phi->output(); | |
1320 for (size_t i = 0; i < phi->operands().size(); ++i) { | |
1321 InstructionBlock* cur_block = | |
1322 code()->InstructionBlockAt(block->predecessors()[i]); | |
1323 UnallocatedOperand input(UnallocatedOperand::ANY, phi->operands()[i]); | |
1324 auto move = data()->AddGapMove(cur_block->last_instruction_index(), | |
1325 Instruction::END, input, output); | |
1326 map_value->incoming_moves.push_back(move); | |
1327 DCHECK(!InstructionAt(cur_block->last_instruction_index()) | |
1328 ->HasReferenceMap()); | |
1329 } | |
1330 auto live_range = LiveRangeFor(phi_vreg); | |
1331 int gap_index = block->first_instruction_index(); | |
1332 live_range->SpillAtDefinition(allocation_zone(), gap_index, &output); | |
1333 live_range->SetSpillStartIndex(gap_index); | |
1334 // We use the phi-ness of some nodes in some later heuristics. | |
1335 live_range->set_is_phi(true); | |
1336 live_range->set_is_non_loop_phi(!block->IsLoopHeader()); | |
1337 } | |
1338 } | |
1339 | |
1340 | |
1341 void LiveRangeBuilder::MeetRegisterConstraints() { | |
1342 for (auto block : code()->instruction_blocks()) { | |
1343 MeetRegisterConstraints(block); | |
1344 } | |
1345 } | |
1346 | |
1347 | |
1348 void LiveRangeBuilder::ResolvePhis() { | |
1349 // Process the blocks in reverse order. | |
1350 for (InstructionBlock* block : base::Reversed(code()->instruction_blocks())) { | |
1351 ResolvePhis(block); | |
1352 } | |
1353 } | |
1354 | |
1355 | |
1356 void LiveRangeBuilder::BuildLiveRanges() { | 1359 void LiveRangeBuilder::BuildLiveRanges() { |
1357 // Process the blocks in reverse order. | 1360 // Process the blocks in reverse order. |
1358 for (int block_id = code()->InstructionBlockCount() - 1; block_id >= 0; | 1361 for (int block_id = code()->InstructionBlockCount() - 1; block_id >= 0; |
1359 --block_id) { | 1362 --block_id) { |
1360 auto block = code()->InstructionBlockAt(RpoNumber::FromInt(block_id)); | 1363 auto block = code()->InstructionBlockAt(RpoNumber::FromInt(block_id)); |
1361 auto live = ComputeLiveOut(block); | 1364 auto live = ComputeLiveOut(block); |
1362 // Initially consider all live_out values live for the entire block. We | 1365 // Initially consider all live_out values live for the entire block. We |
1363 // will shorten these intervals if necessary. | 1366 // will shorten these intervals if necessary. |
1364 AddInitialIntervals(block, live); | 1367 AddInitialIntervals(block, live); |
1365 | 1368 |
1366 // Process the instructions in reverse order, generating and killing | 1369 // Process the instructions in reverse order, generating and killing |
1367 // live values. | 1370 // live values. |
1368 ProcessInstructions(block, live); | 1371 ProcessInstructions(block, live); |
1369 // All phi output operands are killed by this block. | 1372 // All phi output operands are killed by this block. |
1370 for (auto phi : block->phis()) { | 1373 for (auto phi : block->phis()) { |
1371 // The live range interval already ends at the first instruction of the | 1374 // The live range interval already ends at the first instruction of the |
1372 // block. | 1375 // block. |
1373 int phi_vreg = phi->virtual_register(); | 1376 int phi_vreg = phi->virtual_register(); |
1374 live->Remove(phi_vreg); | 1377 live->Remove(phi_vreg); |
1375 InstructionOperand* hint = nullptr; | 1378 InstructionOperand* hint = nullptr; |
1376 auto instr = GetLastInstruction( | 1379 auto instr = GetLastInstruction( |
1377 code()->InstructionBlockAt(block->predecessors()[0])); | 1380 code(), code()->InstructionBlockAt(block->predecessors()[0])); |
1378 for (auto move : *instr->GetParallelMove(Instruction::END)) { | 1381 for (auto move : *instr->GetParallelMove(Instruction::END)) { |
1379 auto& to = move->destination(); | 1382 auto& to = move->destination(); |
1380 if (to.IsUnallocated() && | 1383 if (to.IsUnallocated() && |
1381 UnallocatedOperand::cast(to).virtual_register() == phi_vreg) { | 1384 UnallocatedOperand::cast(to).virtual_register() == phi_vreg) { |
1382 hint = &move->source(); | 1385 hint = &move->source(); |
1383 break; | 1386 break; |
1384 } | 1387 } |
1385 } | 1388 } |
1386 DCHECK(hint != nullptr); | 1389 DCHECK(hint != nullptr); |
1387 auto block_start = LifetimePosition::GapFromInstructionIndex( | 1390 auto block_start = LifetimePosition::GapFromInstructionIndex( |
(...skipping 20 matching lines...) Expand all Loading... |
1408 iterator.Advance(); | 1411 iterator.Advance(); |
1409 } | 1412 } |
1410 // Insert all values into the live in sets of all blocks in the loop. | 1413 // Insert all values into the live in sets of all blocks in the loop. |
1411 for (int i = block->rpo_number().ToInt() + 1; | 1414 for (int i = block->rpo_number().ToInt() + 1; |
1412 i < block->loop_end().ToInt(); ++i) { | 1415 i < block->loop_end().ToInt(); ++i) { |
1413 live_in_sets()[i]->Union(*live); | 1416 live_in_sets()[i]->Union(*live); |
1414 } | 1417 } |
1415 } | 1418 } |
1416 } | 1419 } |
1417 | 1420 |
1418 for (auto range : live_ranges()) { | 1421 for (auto range : data()->live_ranges()) { |
1419 if (range == nullptr) continue; | 1422 if (range == nullptr) continue; |
1420 range->set_kind(RequiredRegisterKind(range->id())); | 1423 range->set_kind(RequiredRegisterKind(range->id())); |
1421 // Give slots to all ranges with a non fixed slot use. | 1424 // Give slots to all ranges with a non fixed slot use. |
1422 if (range->has_slot_use() && range->HasNoSpillType()) { | 1425 if (range->has_slot_use() && range->HasNoSpillType()) { |
1423 data()->AssignSpillRangeToLiveRange(range); | 1426 data()->AssignSpillRangeToLiveRange(range); |
1424 } | 1427 } |
1425 // TODO(bmeurer): This is a horrible hack to make sure that for constant | 1428 // TODO(bmeurer): This is a horrible hack to make sure that for constant |
1426 // live ranges, every use requires the constant to be in a register. | 1429 // live ranges, every use requires the constant to be in a register. |
1427 // Without this hack, all uses with "any" policy would get the constant | 1430 // Without this hack, all uses with "any" policy would get the constant |
1428 // operand assigned. | 1431 // operand assigned. |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1467 unhandled_live_ranges_(local_zone), | 1470 unhandled_live_ranges_(local_zone), |
1468 active_live_ranges_(local_zone), | 1471 active_live_ranges_(local_zone), |
1469 inactive_live_ranges_(local_zone) { | 1472 inactive_live_ranges_(local_zone) { |
1470 unhandled_live_ranges().reserve( | 1473 unhandled_live_ranges().reserve( |
1471 static_cast<size_t>(code()->VirtualRegisterCount() * 2)); | 1474 static_cast<size_t>(code()->VirtualRegisterCount() * 2)); |
1472 active_live_ranges().reserve(8); | 1475 active_live_ranges().reserve(8); |
1473 inactive_live_ranges().reserve(8); | 1476 inactive_live_ranges().reserve(8); |
1474 // TryAllocateFreeReg and AllocateBlockedReg assume this | 1477 // TryAllocateFreeReg and AllocateBlockedReg assume this |
1475 // when allocating local arrays. | 1478 // when allocating local arrays. |
1476 DCHECK(RegisterConfiguration::kMaxDoubleRegisters >= | 1479 DCHECK(RegisterConfiguration::kMaxDoubleRegisters >= |
1477 config()->num_general_registers()); | 1480 this->data()->config()->num_general_registers()); |
1478 } | 1481 } |
1479 | 1482 |
1480 | 1483 |
1481 void LinearScanAllocator::AllocateRegisters() { | 1484 void LinearScanAllocator::AllocateRegisters() { |
1482 DCHECK(unhandled_live_ranges().empty()); | 1485 DCHECK(unhandled_live_ranges().empty()); |
| 1486 DCHECK(active_live_ranges().empty()); |
| 1487 DCHECK(inactive_live_ranges().empty()); |
1483 | 1488 |
1484 for (auto range : live_ranges()) { | 1489 for (auto range : data()->live_ranges()) { |
1485 if (range == nullptr) continue; | 1490 if (range == nullptr) continue; |
1486 if (range->Kind() == mode_) { | 1491 if (range->Kind() == mode_) { |
1487 AddToUnhandledUnsorted(range); | 1492 AddToUnhandledUnsorted(range); |
1488 } | 1493 } |
1489 } | 1494 } |
1490 SortUnhandled(); | 1495 SortUnhandled(); |
1491 DCHECK(UnhandledIsSorted()); | 1496 DCHECK(UnhandledIsSorted()); |
1492 | 1497 |
1493 DCHECK(active_live_ranges().empty()); | |
1494 DCHECK(inactive_live_ranges().empty()); | |
1495 | |
1496 auto& fixed_ranges = GetFixedRegisters(data(), mode_); | 1498 auto& fixed_ranges = GetFixedRegisters(data(), mode_); |
1497 for (auto current : fixed_ranges) { | 1499 for (auto current : fixed_ranges) { |
1498 if (current != nullptr) { | 1500 if (current != nullptr) { |
1499 DCHECK_EQ(mode_, current->Kind()); | 1501 DCHECK_EQ(mode_, current->Kind()); |
1500 AddToInactive(current); | 1502 AddToInactive(current); |
1501 } | 1503 } |
1502 } | 1504 } |
1503 | 1505 |
1504 while (!unhandled_live_ranges().empty()) { | 1506 while (!unhandled_live_ranges().empty()) { |
1505 DCHECK(UnhandledIsSorted()); | 1507 DCHECK(UnhandledIsSorted()); |
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1558 } | 1560 } |
1559 | 1561 |
1560 DCHECK(!current->HasRegisterAssigned() && !current->IsSpilled()); | 1562 DCHECK(!current->HasRegisterAssigned() && !current->IsSpilled()); |
1561 | 1563 |
1562 bool result = TryAllocateFreeReg(current); | 1564 bool result = TryAllocateFreeReg(current); |
1563 if (!result) AllocateBlockedReg(current); | 1565 if (!result) AllocateBlockedReg(current); |
1564 if (current->HasRegisterAssigned()) { | 1566 if (current->HasRegisterAssigned()) { |
1565 AddToActive(current); | 1567 AddToActive(current); |
1566 } | 1568 } |
1567 } | 1569 } |
1568 | |
1569 active_live_ranges().clear(); | |
1570 inactive_live_ranges().clear(); | |
1571 } | 1570 } |
1572 | 1571 |
1573 | 1572 |
1574 const char* LinearScanAllocator::RegisterName(int allocation_index) const { | 1573 const char* LinearScanAllocator::RegisterName(int allocation_index) const { |
1575 if (mode_ == GENERAL_REGISTERS) { | 1574 if (mode_ == GENERAL_REGISTERS) { |
1576 return config()->general_register_name(allocation_index); | 1575 return data()->config()->general_register_name(allocation_index); |
1577 } else { | 1576 } else { |
1578 return config()->double_register_name(allocation_index); | 1577 return data()->config()->double_register_name(allocation_index); |
1579 } | 1578 } |
1580 } | 1579 } |
1581 | 1580 |
1582 | 1581 |
1583 void LinearScanAllocator::AddToActive(LiveRange* range) { | 1582 void LinearScanAllocator::AddToActive(LiveRange* range) { |
1584 TRACE("Add live range %d to active\n", range->id()); | 1583 TRACE("Add live range %d to active\n", range->id()); |
1585 active_live_ranges().push_back(range); | 1584 active_live_ranges().push_back(range); |
1586 } | 1585 } |
1587 | 1586 |
1588 | 1587 |
(...skipping 314 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1903 } | 1902 } |
1904 } | 1903 } |
1905 } | 1904 } |
1906 } | 1905 } |
1907 | 1906 |
1908 | 1907 |
1909 bool LinearScanAllocator::TryReuseSpillForPhi(LiveRange* range) { | 1908 bool LinearScanAllocator::TryReuseSpillForPhi(LiveRange* range) { |
1910 if (range->IsChild() || !range->is_phi()) return false; | 1909 if (range->IsChild() || !range->is_phi()) return false; |
1911 DCHECK(!range->HasSpillOperand()); | 1910 DCHECK(!range->HasSpillOperand()); |
1912 | 1911 |
1913 auto lookup = phi_map().find(range->id()); | 1912 auto lookup = data()->phi_map().find(range->id()); |
1914 DCHECK(lookup != phi_map().end()); | 1913 DCHECK(lookup != data()->phi_map().end()); |
1915 auto phi = lookup->second->phi; | 1914 auto phi = lookup->second->phi; |
1916 auto block = lookup->second->block; | 1915 auto block = lookup->second->block; |
1917 // Count the number of spilled operands. | 1916 // Count the number of spilled operands. |
1918 size_t spilled_count = 0; | 1917 size_t spilled_count = 0; |
1919 LiveRange* first_op = nullptr; | 1918 LiveRange* first_op = nullptr; |
1920 for (size_t i = 0; i < phi->operands().size(); i++) { | 1919 for (size_t i = 0; i < phi->operands().size(); i++) { |
1921 int op = phi->operands()[i]; | 1920 int op = phi->operands()[i]; |
1922 LiveRange* op_range = LiveRangeFor(op); | 1921 LiveRange* op_range = LiveRangeFor(op); |
1923 if (!op_range->HasSpillRange()) continue; | 1922 if (!op_range->HasSpillRange()) continue; |
1924 auto pred = code()->InstructionBlockAt(block->predecessors()[i]); | 1923 auto pred = code()->InstructionBlockAt(block->predecessors()[i]); |
(...skipping 258 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2183 // Iterate over all safe point positions and record a pointer | 2182 // Iterate over all safe point positions and record a pointer |
2184 // for all spilled live ranges at this point. | 2183 // for all spilled live ranges at this point. |
2185 int last_range_start = 0; | 2184 int last_range_start = 0; |
2186 auto reference_maps = data()->code()->reference_maps(); | 2185 auto reference_maps = data()->code()->reference_maps(); |
2187 ReferenceMapDeque::const_iterator first_it = reference_maps->begin(); | 2186 ReferenceMapDeque::const_iterator first_it = reference_maps->begin(); |
2188 for (LiveRange* range : data()->live_ranges()) { | 2187 for (LiveRange* range : data()->live_ranges()) { |
2189 if (range == nullptr) continue; | 2188 if (range == nullptr) continue; |
2190 // Iterate over the first parts of multi-part live ranges. | 2189 // Iterate over the first parts of multi-part live ranges. |
2191 if (range->IsChild()) continue; | 2190 if (range->IsChild()) continue; |
2192 // Skip non-reference values. | 2191 // Skip non-reference values. |
2193 if (!IsReference(range->id())) continue; | 2192 if (!data()->IsReference(range->id())) continue; |
2194 // Skip empty live ranges. | 2193 // Skip empty live ranges. |
2195 if (range->IsEmpty()) continue; | 2194 if (range->IsEmpty()) continue; |
2196 | 2195 |
2197 // Find the extent of the range and its children. | 2196 // Find the extent of the range and its children. |
2198 int start = range->Start().ToInstructionIndex(); | 2197 int start = range->Start().ToInstructionIndex(); |
2199 int end = 0; | 2198 int end = 0; |
2200 for (auto cur = range; cur != nullptr; cur = cur->next()) { | 2199 for (auto cur = range; cur != nullptr; cur = cur->next()) { |
2201 auto this_end = cur->End(); | 2200 auto this_end = cur->End(); |
2202 if (this_end.ToInstructionIndex() > end) | 2201 if (this_end.ToInstructionIndex() > end) |
2203 end = this_end.ToInstructionIndex(); | 2202 end = this_end.ToInstructionIndex(); |
(...skipping 233 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2437 const InstructionBlock* pred, | 2436 const InstructionBlock* pred, |
2438 const InstructionOperand& pred_op) { | 2437 const InstructionOperand& pred_op) { |
2439 DCHECK(pred_op != cur_op); | 2438 DCHECK(pred_op != cur_op); |
2440 int gap_index; | 2439 int gap_index; |
2441 Instruction::GapPosition position; | 2440 Instruction::GapPosition position; |
2442 if (block->PredecessorCount() == 1) { | 2441 if (block->PredecessorCount() == 1) { |
2443 gap_index = block->first_instruction_index(); | 2442 gap_index = block->first_instruction_index(); |
2444 position = Instruction::START; | 2443 position = Instruction::START; |
2445 } else { | 2444 } else { |
2446 DCHECK(pred->SuccessorCount() == 1); | 2445 DCHECK(pred->SuccessorCount() == 1); |
2447 DCHECK(!data() | 2446 DCHECK(!code() |
2448 ->InstructionAt(pred->last_instruction_index()) | 2447 ->InstructionAt(pred->last_instruction_index()) |
2449 ->HasReferenceMap()); | 2448 ->HasReferenceMap()); |
2450 gap_index = pred->last_instruction_index(); | 2449 gap_index = pred->last_instruction_index(); |
2451 position = Instruction::END; | 2450 position = Instruction::END; |
2452 } | 2451 } |
2453 data()->AddGapMove(gap_index, position, pred_op, cur_op); | 2452 data()->AddGapMove(gap_index, position, pred_op, cur_op); |
2454 } | 2453 } |
2455 | 2454 |
2456 | 2455 |
2457 void LiveRangeConnector::ConnectRanges(Zone* local_zone) { | 2456 void LiveRangeConnector::ConnectRanges(Zone* local_zone) { |
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2523 auto move = new (code_zone()) MoveOperands(it->first.second, it->second); | 2522 auto move = new (code_zone()) MoveOperands(it->first.second, it->second); |
2524 auto eliminate = moves->PrepareInsertAfter(move); | 2523 auto eliminate = moves->PrepareInsertAfter(move); |
2525 to_insert.push_back(move); | 2524 to_insert.push_back(move); |
2526 if (eliminate != nullptr) to_eliminate.push_back(eliminate); | 2525 if (eliminate != nullptr) to_eliminate.push_back(eliminate); |
2527 } | 2526 } |
2528 } | 2527 } |
2529 | 2528 |
2530 } // namespace compiler | 2529 } // namespace compiler |
2531 } // namespace internal | 2530 } // namespace internal |
2532 } // namespace v8 | 2531 } // namespace v8 |
OLD | NEW |