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

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

Issue 793323002: [turbofan] update SpillRange to use ZoneVector (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Created 6 years 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/compiler/linkage.h" 5 #include "src/compiler/linkage.h"
6 #include "src/compiler/register-allocator.h" 6 #include "src/compiler/register-allocator.h"
7 #include "src/string-stream.h" 7 #include "src/string-stream.h"
8 8
9 namespace v8 { 9 namespace v8 {
10 namespace internal { 10 namespace internal {
(...skipping 690 matching lines...) Expand 10 before | Expand all | Expand 10 after
701 DCHECK(result->IsFixed()); 701 DCHECK(result->IsFixed());
702 result->kind_ = DOUBLE_REGISTERS; 702 result->kind_ = DOUBLE_REGISTERS;
703 SetLiveRangeAssignedRegister(result, index); 703 SetLiveRangeAssignedRegister(result, index);
704 fixed_double_live_ranges()[index] = result; 704 fixed_double_live_ranges()[index] = result;
705 } 705 }
706 return result; 706 return result;
707 } 707 }
708 708
709 709
710 LiveRange* RegisterAllocator::LiveRangeFor(int index) { 710 LiveRange* RegisterAllocator::LiveRangeFor(int index) {
711 if (index >= static_cast<int>(live_ranges_.size())) { 711 if (index >= static_cast<int>(live_ranges().size())) {
712 live_ranges_.resize(index + 1, nullptr); 712 live_ranges().resize(index + 1, nullptr);
713 } 713 }
714 auto result = live_ranges()[index]; 714 auto result = live_ranges()[index];
715 if (result == nullptr) { 715 if (result == nullptr) {
716 result = new (local_zone()) LiveRange(index, code_zone()); 716 result = new (local_zone()) LiveRange(index, code_zone());
717 live_ranges()[index] = result; 717 live_ranges()[index] = result;
718 } 718 }
719 return result; 719 return result;
720 } 720 }
721 721
722 722
(...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after
810 if (interval2->end().Value() > interval1->start().Value()) { 810 if (interval2->end().Value() > interval1->start().Value()) {
811 return true; 811 return true;
812 } 812 }
813 interval2 = interval2->next(); 813 interval2 = interval2->next();
814 } 814 }
815 } 815 }
816 return false; 816 return false;
817 } 817 }
818 818
819 819
820 SpillRange::SpillRange(LiveRange* range, int id, Zone* zone) 820 SpillRange::SpillRange(LiveRange* range, Zone* zone) : live_ranges_(zone) {
821 : id_(id), live_ranges_(1, zone), end_position_(range->End()) {
822 auto src = range->first_interval(); 821 auto src = range->first_interval();
823 UseInterval* result = nullptr; 822 UseInterval* result = nullptr;
824 UseInterval* node = nullptr; 823 UseInterval* node = nullptr;
825 // Copy the nodes 824 // Copy the nodes
826 while (src != nullptr) { 825 while (src != nullptr) {
827 UseInterval* new_node = new (zone) UseInterval(src->start(), src->end()); 826 auto new_node = new (zone) UseInterval(src->start(), src->end());
828 if (result == nullptr) { 827 if (result == nullptr) {
829 result = new_node; 828 result = new_node;
830 } else { 829 } else {
831 node->set_next(new_node); 830 node->set_next(new_node);
832 } 831 }
833 node = new_node; 832 node = new_node;
834 src = src->next(); 833 src = src->next();
835 } 834 }
836 use_interval_ = result; 835 use_interval_ = result;
837 live_ranges_.Add(range, zone); 836 live_ranges().push_back(range);
837 end_position_ = node->end();
838 DCHECK(!range->HasSpillRange()); 838 DCHECK(!range->HasSpillRange());
839 range->SetSpillRange(this); 839 range->SetSpillRange(this);
840 } 840 }
841 841
842 842
843 bool SpillRange::IsIntersectingWith(SpillRange* other) { 843 bool SpillRange::IsIntersectingWith(SpillRange* other) const {
844 if (End().Value() <= other->use_interval_->start().Value() || 844 if (this->use_interval_ == nullptr || other->use_interval_ == nullptr ||
845 other->End().Value() <= use_interval_->start().Value()) { 845 this->End().Value() <= other->use_interval_->start().Value() ||
846 other->End().Value() <= this->use_interval_->start().Value()) {
846 return false; 847 return false;
847 } 848 }
848 return AreUseIntervalsIntersecting(use_interval_, other->use_interval_); 849 return AreUseIntervalsIntersecting(use_interval_, other->use_interval_);
849 } 850 }
850 851
851 852
852 bool SpillRange::TryMerge(SpillRange* other, Zone* zone) { 853 bool SpillRange::TryMerge(SpillRange* other) {
853 if (Kind() == other->Kind() && 854 if (Kind() != other->Kind() || IsIntersectingWith(other)) return false;
854 !AreUseIntervalsIntersecting(use_interval_, other->use_interval_)) {
855 if (End().Value() < other->End().Value()) {
856 end_position_ = other->End();
857 }
858 855
859 MergeDisjointIntervals(other->use_interval_, zone); 856 auto max = LifetimePosition::MaxPosition();
860 other->use_interval_ = nullptr; 857 if (End().Value() < other->End().Value() &&
858 other->End().Value() != max.Value()) {
859 end_position_ = other->End();
860 }
861 other->end_position_ = max;
861 862
862 for (int i = 0; i < other->live_ranges_.length(); i++) { 863 MergeDisjointIntervals(other->use_interval_);
863 DCHECK(other->live_ranges_.at(i)->GetSpillRange() == other); 864 other->use_interval_ = nullptr;
864 other->live_ranges_.at(i)->SetSpillRange(this);
865 }
866 865
867 live_ranges_.AddAll(other->live_ranges_, zone); 866 for (auto range : other->live_ranges()) {
868 other->live_ranges_.Clear(); 867 DCHECK(range->GetSpillRange() == other);
868 range->SetSpillRange(this);
869 }
869 870
870 return true; 871 live_ranges().insert(live_ranges().end(), other->live_ranges().begin(),
871 } 872 other->live_ranges().end());
872 return false; 873 other->live_ranges().clear();
874
875 return true;
873 } 876 }
874 877
875 878
876 void SpillRange::SetOperand(InstructionOperand* op) { 879 void SpillRange::SetOperand(InstructionOperand* op) {
877 for (int i = 0; i < live_ranges_.length(); i++) { 880 for (auto range : live_ranges()) {
878 DCHECK(live_ranges_.at(i)->GetSpillRange() == this); 881 DCHECK(range->GetSpillRange() == this);
879 live_ranges_.at(i)->CommitSpillOperand(op); 882 range->CommitSpillOperand(op);
880 } 883 }
881 } 884 }
882 885
883 886
884 void SpillRange::MergeDisjointIntervals(UseInterval* other, Zone* zone) { 887 void SpillRange::MergeDisjointIntervals(UseInterval* other) {
885 UseInterval* tail = nullptr; 888 UseInterval* tail = nullptr;
886 auto current = use_interval_; 889 auto current = use_interval_;
887 while (other != nullptr) { 890 while (other != nullptr) {
888 // Make sure the 'current' list starts first 891 // Make sure the 'current' list starts first
889 if (current == nullptr || 892 if (current == nullptr ||
890 current->start().Value() > other->start().Value()) { 893 current->start().Value() > other->start().Value()) {
891 std::swap(current, other); 894 std::swap(current, other);
892 } 895 }
893
894 // Check disjointness 896 // Check disjointness
895 DCHECK(other == nullptr || 897 DCHECK(other == nullptr ||
896 current->end().Value() <= other->start().Value()); 898 current->end().Value() <= other->start().Value());
897
898 // Append the 'current' node to the result accumulator and move forward 899 // Append the 'current' node to the result accumulator and move forward
899 if (tail == nullptr) { 900 if (tail == nullptr) {
900 use_interval_ = current; 901 use_interval_ = current;
901 } else { 902 } else {
902 tail->set_next(current); 903 tail->set_next(current);
903 } 904 }
904 tail = current; 905 tail = current;
905 current = current->next(); 906 current = current->next();
906 } 907 }
907 // Other list is empty => we are done 908 // Other list is empty => we are done
908 } 909 }
909 910
910 911
911 void RegisterAllocator::ReuseSpillSlots() { 912 void RegisterAllocator::ReuseSpillSlots() {
912 DCHECK(FLAG_turbo_reuse_spill_slots); 913 DCHECK(FLAG_turbo_reuse_spill_slots);
913 914
914 // Merge disjoint spill ranges 915 // Merge disjoint spill ranges
915 for (size_t i = 0; i < spill_ranges().size(); i++) { 916 for (size_t i = 0; i < spill_ranges().size(); i++) {
916 auto range = spill_ranges()[i]; 917 auto range = spill_ranges()[i];
917 if (range->IsEmpty()) continue; 918 if (range->IsEmpty()) continue;
918 for (size_t j = i + 1; j < spill_ranges().size(); j++) { 919 for (size_t j = i + 1; j < spill_ranges().size(); j++) {
919 auto other = spill_ranges()[j]; 920 auto other = spill_ranges()[j];
920 if (!other->IsEmpty()) { 921 if (!other->IsEmpty()) {
921 range->TryMerge(other, local_zone()); 922 range->TryMerge(other);
922 } 923 }
923 } 924 }
924 } 925 }
925 926
926 // Allocate slots for the merged spill ranges. 927 // Allocate slots for the merged spill ranges.
927 for (auto range : spill_ranges()) { 928 for (auto range : spill_ranges()) {
928 if (range->IsEmpty()) continue; 929 if (range->IsEmpty()) continue;
929 // Allocate a new operand referring to the spill slot. 930 // Allocate a new operand referring to the spill slot.
930 auto kind = range->Kind(); 931 auto kind = range->Kind();
931 int index = frame()->AllocateSpillSlot(kind == DOUBLE_REGISTERS); 932 int index = frame()->AllocateSpillSlot(kind == DOUBLE_REGISTERS);
(...skipping 13 matching lines...) Expand all
945 range->ConvertUsesToOperand(assigned); 946 range->ConvertUsesToOperand(assigned);
946 if (range->IsSpilled()) { 947 if (range->IsSpilled()) {
947 range->CommitSpillsAtDefinition(code(), assigned); 948 range->CommitSpillsAtDefinition(code(), assigned);
948 } 949 }
949 } 950 }
950 } 951 }
951 952
952 953
953 SpillRange* RegisterAllocator::AssignSpillRangeToLiveRange(LiveRange* range) { 954 SpillRange* RegisterAllocator::AssignSpillRangeToLiveRange(LiveRange* range) {
954 DCHECK(FLAG_turbo_reuse_spill_slots); 955 DCHECK(FLAG_turbo_reuse_spill_slots);
955 int spill_id = static_cast<int>(spill_ranges().size()); 956 auto spill_range = new (local_zone()) SpillRange(range, local_zone());
956 auto spill_range =
957 new (local_zone()) SpillRange(range, spill_id, local_zone());
958 spill_ranges().push_back(spill_range); 957 spill_ranges().push_back(spill_range);
959 return spill_range; 958 return spill_range;
960 } 959 }
961 960
962 961
963 bool RegisterAllocator::TryReuseSpillForPhi(LiveRange* range) { 962 bool RegisterAllocator::TryReuseSpillForPhi(LiveRange* range) {
964 DCHECK(FLAG_turbo_reuse_spill_slots); 963 DCHECK(FLAG_turbo_reuse_spill_slots);
965 DCHECK(range->HasNoSpillType()); 964 DCHECK(range->HasNoSpillType());
966 if (range->IsChild() || !range->is_phi()) return false; 965 if (range->IsChild() || !range->is_phi()) return false;
967 966
(...skipping 29 matching lines...) Expand all
997 996
998 // Try to merge the spilled operands and count the number of merged spilled 997 // Try to merge the spilled operands and count the number of merged spilled
999 // operands. 998 // operands.
1000 DCHECK(first_op != nullptr); 999 DCHECK(first_op != nullptr);
1001 auto first_op_spill = first_op->GetSpillRange(); 1000 auto first_op_spill = first_op->GetSpillRange();
1002 size_t num_merged = 1; 1001 size_t num_merged = 1;
1003 for (size_t i = 1; i < phi->operands().size(); i++) { 1002 for (size_t i = 1; i < phi->operands().size(); i++) {
1004 int op = phi->operands()[i]; 1003 int op = phi->operands()[i];
1005 auto op_range = LiveRangeFor(op); 1004 auto op_range = LiveRangeFor(op);
1006 auto op_spill = op_range->GetSpillRange(); 1005 auto op_spill = op_range->GetSpillRange();
1007 if (op_spill != nullptr) { 1006 if (op_spill != nullptr &&
1008 if (op_spill->id() == first_op_spill->id() || 1007 (op_spill == first_op_spill || first_op_spill->TryMerge(op_spill))) {
1009 first_op_spill->TryMerge(op_spill, local_zone())) { 1008 num_merged++;
1010 num_merged++;
1011 }
1012 } 1009 }
1013 } 1010 }
1014 1011
1015 // Only continue if enough operands could be merged to the 1012 // Only continue if enough operands could be merged to the
1016 // same spill slot. 1013 // same spill slot.
1017 if (num_merged * 2 <= phi->operands().size() || 1014 if (num_merged * 2 <= phi->operands().size() ||
1018 AreUseIntervalsIntersecting(first_op_spill->interval(), 1015 AreUseIntervalsIntersecting(first_op_spill->interval(),
1019 range->first_interval())) { 1016 range->first_interval())) {
1020 return false; 1017 return false;
1021 } 1018 }
1022 1019
1023 // If the range does not need register soon, spill it to the merged 1020 // If the range does not need register soon, spill it to the merged
1024 // spill range. 1021 // spill range.
1025 auto next_pos = range->Start(); 1022 auto next_pos = range->Start();
1026 if (code()->IsGapAt(next_pos.InstructionIndex())) { 1023 if (code()->IsGapAt(next_pos.InstructionIndex())) {
1027 next_pos = next_pos.NextInstruction(); 1024 next_pos = next_pos.NextInstruction();
1028 } 1025 }
1029 auto pos = range->NextUsePositionRegisterIsBeneficial(next_pos); 1026 auto pos = range->NextUsePositionRegisterIsBeneficial(next_pos);
1030 if (pos == nullptr) { 1027 if (pos == nullptr) {
1031 auto spill_range = AssignSpillRangeToLiveRange(range->TopLevel()); 1028 auto spill_range = AssignSpillRangeToLiveRange(range->TopLevel());
1032 CHECK(first_op_spill->TryMerge(spill_range, local_zone())); 1029 CHECK(first_op_spill->TryMerge(spill_range));
1033 Spill(range); 1030 Spill(range);
1034 return true; 1031 return true;
1035 } else if (pos->pos().Value() > range->Start().NextInstruction().Value()) { 1032 } else if (pos->pos().Value() > range->Start().NextInstruction().Value()) {
1036 auto spill_range = AssignSpillRangeToLiveRange(range->TopLevel()); 1033 auto spill_range = AssignSpillRangeToLiveRange(range->TopLevel());
1037 CHECK(first_op_spill->TryMerge(spill_range, local_zone())); 1034 CHECK(first_op_spill->TryMerge(spill_range));
1038 SpillBetween(range, range->Start(), pos->pos()); 1035 SpillBetween(range, range->Start(), pos->pos());
1039 if (!AllocationOk()) return false; 1036 if (!AllocationOk()) return false;
1040 DCHECK(UnhandledIsSorted()); 1037 DCHECK(UnhandledIsSorted());
1041 return true; 1038 return true;
1042 } 1039 }
1043 return false; 1040 return false;
1044 } 1041 }
1045 1042
1046 1043
1047 void RegisterAllocator::MeetRegisterConstraints(const InstructionBlock* block) { 1044 void RegisterAllocator::MeetRegisterConstraints(const InstructionBlock* block) {
(...skipping 1498 matching lines...) Expand 10 before | Expand all | Expand 10 after
2546 } else { 2543 } else {
2547 DCHECK(range->Kind() == GENERAL_REGISTERS); 2544 DCHECK(range->Kind() == GENERAL_REGISTERS);
2548 assigned_registers_->Add(reg); 2545 assigned_registers_->Add(reg);
2549 } 2546 }
2550 range->set_assigned_register(reg); 2547 range->set_assigned_register(reg);
2551 } 2548 }
2552 2549
2553 } // namespace compiler 2550 } // namespace compiler
2554 } // namespace internal 2551 } // namespace internal
2555 } // namespace v8 2552 } // 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