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

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

Issue 1099093002: [turbofan] Split ConstraintBuilder off of LiveRangeBuilder. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Created 5 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « src/compiler/register-allocator.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2014 the V8 project authors. All rights reserved. 1 // Copyright 2014 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "src/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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
OLDNEW
« no previous file with comments | « src/compiler/register-allocator.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698