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

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

Issue 1391023007: [turbofan] Splinter into one range. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Created 5 years, 2 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') | test/unittests/compiler/live-range-unittest.cc » ('j') | 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 680 matching lines...) Expand 10 before | Expand all | Expand 10 after
691 TopLevelLiveRange::TopLevelLiveRange(int vreg, MachineType machine_type) 691 TopLevelLiveRange::TopLevelLiveRange(int vreg, MachineType machine_type)
692 : LiveRange(0, machine_type, this), 692 : LiveRange(0, machine_type, this),
693 vreg_(vreg), 693 vreg_(vreg),
694 last_child_id_(0), 694 last_child_id_(0),
695 splintered_from_(nullptr), 695 splintered_from_(nullptr),
696 spill_operand_(nullptr), 696 spill_operand_(nullptr),
697 spills_at_definition_(nullptr), 697 spills_at_definition_(nullptr),
698 spilled_in_deferred_blocks_(false), 698 spilled_in_deferred_blocks_(false),
699 spill_start_index_(kMaxInt), 699 spill_start_index_(kMaxInt),
700 last_child_(this), 700 last_child_(this),
701 last_insertion_point_(this) { 701 last_pos_(nullptr),
702 splinter_(nullptr) {
702 bits_ |= SpillTypeField::encode(SpillType::kNoSpillType); 703 bits_ |= SpillTypeField::encode(SpillType::kNoSpillType);
703 } 704 }
704 705
705 706
706 void TopLevelLiveRange::SpillAtDefinition(Zone* zone, int gap_index, 707 void TopLevelLiveRange::SpillAtDefinition(Zone* zone, int gap_index,
707 InstructionOperand* operand) { 708 InstructionOperand* operand) {
708 DCHECK(HasNoSpillType()); 709 DCHECK(HasNoSpillType());
709 spills_at_definition_ = new (zone) 710 spills_at_definition_ = new (zone)
710 SpillAtDefinitionList(gap_index, operand, spills_at_definition_); 711 SpillAtDefinitionList(gap_index, operand, spills_at_definition_);
711 } 712 }
(...skipping 126 matching lines...) Expand 10 before | Expand all | Expand 10 after
838 return StackSlotOperand(machine_type(), index); 839 return StackSlotOperand(machine_type(), index);
839 case DOUBLE_REGISTERS: 840 case DOUBLE_REGISTERS:
840 return DoubleStackSlotOperand(machine_type(), index); 841 return DoubleStackSlotOperand(machine_type(), index);
841 } 842 }
842 UNREACHABLE(); 843 UNREACHABLE();
843 return StackSlotOperand(kMachNone, 0); 844 return StackSlotOperand(kMachNone, 0);
844 } 845 }
845 846
846 847
847 void TopLevelLiveRange::Splinter(LifetimePosition start, LifetimePosition end, 848 void TopLevelLiveRange::Splinter(LifetimePosition start, LifetimePosition end,
848 TopLevelLiveRange* result, Zone* zone) { 849 Zone* zone) {
849 DCHECK(start != Start() || end != End()); 850 DCHECK(start != Start() || end != End());
850 DCHECK(start < end); 851 DCHECK(start < end);
851 852
852 result->set_spill_type(spill_type()); 853 TopLevelLiveRange splinter_temp(-1, machine_type());
853 854 UsePosition* last_in_splinter = nullptr;
854 if (start <= Start()) { 855 if (start <= Start()) {
855 // TODO(mtrofin): here, the TopLevel part is in the deferred range, so we 856 // TODO(mtrofin): here, the TopLevel part is in the deferred range, so we
856 // may want to continue processing the splinter. However, if the value is 857 // may want to continue processing the splinter. However, if the value is
857 // defined in a cold block, and then used in a hot block, it follows that 858 // defined in a cold block, and then used in a hot block, it follows that
858 // it should terminate on the RHS of a phi, defined on the hot path. We 859 // it should terminate on the RHS of a phi, defined on the hot path. We
859 // should check this, however, this may not be the place, because we don't 860 // should check this, however, this may not be the place, because we don't
860 // have access to the instruction sequence. 861 // have access to the instruction sequence.
861 DCHECK(end < End()); 862 DCHECK(end < End());
862 DetachAt(end, result, zone); 863 DetachAt(end, &splinter_temp, zone);
863 next_ = nullptr; 864 next_ = nullptr;
864 } else if (end >= End()) { 865 } else if (end >= End()) {
865 DCHECK(start > Start()); 866 DCHECK(start > Start());
866 DetachAt(start, result, zone); 867 DetachAt(start, &splinter_temp, zone);
867 next_ = nullptr; 868 next_ = nullptr;
868 } else { 869 } else {
869 DCHECK(start < End() && Start() < end); 870 DCHECK(start < End() && Start() < end);
870 871
871 const int kInvalidId = std::numeric_limits<int>::max(); 872 const int kInvalidId = std::numeric_limits<int>::max();
872 873
873 UsePosition* last = DetachAt(start, result, zone); 874 UsePosition* last = DetachAt(start, &splinter_temp, zone);
874 875
875 LiveRange end_part(kInvalidId, this->machine_type(), nullptr); 876 LiveRange end_part(kInvalidId, this->machine_type(), nullptr);
876 result->DetachAt(end, &end_part, zone); 877 last_in_splinter = splinter_temp.DetachAt(end, &end_part, zone);
877 878
878 next_ = end_part.next_; 879 next_ = end_part.next_;
879 last_interval_->set_next(end_part.first_interval_); 880 last_interval_->set_next(end_part.first_interval_);
880 // The next splinter will happen either at or after the current interval. 881 // The next splinter will happen either at or after the current interval.
881 // We can optimize DetachAt by setting current_interval_ accordingly, 882 // We can optimize DetachAt by setting current_interval_ accordingly,
882 // which will then be picked up by FirstSearchIntervalForPosition. 883 // which will then be picked up by FirstSearchIntervalForPosition.
883 current_interval_ = last_interval_; 884 current_interval_ = last_interval_;
884 last_interval_ = end_part.last_interval_; 885 last_interval_ = end_part.last_interval_;
885 886
886 if (first_pos_ == nullptr) { 887 if (first_pos_ == nullptr) {
887 first_pos_ = end_part.first_pos_; 888 first_pos_ = end_part.first_pos_;
888 } else { 889 } else {
889 splitting_pointer_ = last; 890 splitting_pointer_ = last;
890 if (last != nullptr) last->set_next(end_part.first_pos_); 891 if (last != nullptr) last->set_next(end_part.first_pos_);
891 } 892 }
892 } 893 }
893 result->next_ = nullptr;
894 result->top_level_ = result;
895 894
896 result->SetSplinteredFrom(this); 895 if (splinter()->IsEmpty()) {
897 // Ensure the result's relative ID is unique within the IDs used for this 896 splinter()->first_interval_ = splinter_temp.first_interval_;
898 // virtual register's children and splinters. 897 splinter()->last_interval_ = splinter_temp.last_interval_;
899 result->relative_id_ = GetNextChildId(); 898 } else {
899 splinter()->last_interval_->set_next(splinter_temp.first_interval_);
900 splinter()->last_interval_ = splinter_temp.last_interval_;
901 }
902 if (splinter()->first_pos() == nullptr) {
903 splinter()->first_pos_ = splinter_temp.first_pos_;
904 } else {
905 splinter()->last_pos_->set_next(splinter_temp.first_pos_);
906 }
907 if (last_in_splinter != nullptr) {
908 splinter()->last_pos_ = last_in_splinter;
909 } else {
910 if (splinter()->first_pos() != nullptr &&
911 splinter()->last_pos_ == nullptr) {
912 splinter()->last_pos_ = splinter()->first_pos();
913 for (UsePosition* pos = splinter()->first_pos(); pos != nullptr;
914 pos = pos->next()) {
915 splinter()->last_pos_ = pos;
916 }
917 }
918 }
919 #if DEBUG
920 Verify();
921 splinter()->Verify();
922 #endif
900 } 923 }
901 924
902 925
903 void TopLevelLiveRange::SetSplinteredFrom(TopLevelLiveRange* splinter_parent) { 926 void TopLevelLiveRange::SetSplinteredFrom(TopLevelLiveRange* splinter_parent) {
904 // The splinter parent is always the original "Top".
905 DCHECK(splinter_parent->Start() < Start());
906
907 splintered_from_ = splinter_parent; 927 splintered_from_ = splinter_parent;
908 if (!HasSpillOperand() && splinter_parent->spill_range_ != nullptr) { 928 if (!HasSpillOperand() && splinter_parent->spill_range_ != nullptr) {
909 SetSpillRange(splinter_parent->spill_range_); 929 SetSpillRange(splinter_parent->spill_range_);
910 } 930 }
911 } 931 }
912 932
913 933
914 void TopLevelLiveRange::UpdateSpillRangePostMerge(TopLevelLiveRange* merged) { 934 void TopLevelLiveRange::UpdateSpillRangePostMerge(TopLevelLiveRange* merged) {
915 DCHECK(merged->TopLevel() == this); 935 DCHECK(merged->TopLevel() == this);
916 936
917 if (HasNoSpillType() && merged->HasSpillRange()) { 937 if (HasNoSpillType() && merged->HasSpillRange()) {
918 set_spill_type(merged->spill_type()); 938 set_spill_type(merged->spill_type());
919 DCHECK(GetSpillRange()->live_ranges().size() > 0); 939 DCHECK(GetSpillRange()->live_ranges().size() > 0);
920 merged->spill_range_ = nullptr; 940 merged->spill_range_ = nullptr;
921 merged->bits_ = 941 merged->bits_ =
922 SpillTypeField::update(merged->bits_, SpillType::kNoSpillType); 942 SpillTypeField::update(merged->bits_, SpillType::kNoSpillType);
923 } 943 }
924 } 944 }
925 945
926 946
927 void TopLevelLiveRange::Merge(TopLevelLiveRange* other, Zone* zone) { 947 void TopLevelLiveRange::Merge(TopLevelLiveRange* other, Zone* zone) {
928 DCHECK(Start() < other->Start()); 948 DCHECK(Start() < other->Start());
929 DCHECK(other->splintered_from() == this); 949 DCHECK(other->splintered_from() == this);
930 950
931 LiveRange* last_other = other->last_child(); 951 LiveRange* first = this;
932 LiveRange* last_me = last_child(); 952 LiveRange* second = other;
953 DCHECK(first->Start() < second->Start());
954 while (first != nullptr && second != nullptr) {
955 DCHECK(first != second);
956 // Make sure the ranges are in order each time we iterate.
957 if (second->Start() < first->Start()) {
958 LiveRange* tmp = second;
959 second = first;
960 first = tmp;
961 continue;
962 }
933 963
934 // Simple case: we just append at the end. 964 if (first->End() <= second->Start()) {
935 if (last_me->End() <= other->Start()) return last_me->AppendAsChild(other); 965 if (first->next() == nullptr ||
966 first->next()->Start() > second->Start()) {
967 // First is in order before second.
968 LiveRange* temp = first->next();
969 first->next_ = second;
970 first = temp;
971 } else {
972 // First is in order before its successor (or second), so advance first.
973 first = first->next();
974 }
975 continue;
976 }
936 977
937 DCHECK(last_me->End() > last_other->End()); 978 DCHECK(first->Start() < second->Start());
979 // If first and second intersect, split first.
980 if (first->Start() < second->End() && second->Start() < first->End()) {
981 LiveRange* temp = first->SplitAt(second->Start(), zone);
Benedikt Meurer 2015/10/15 13:26:54 I ran into an endless loop here with stress varian
938 982
939 // In the more general case, we need to find the ranges between which to 983 temp->set_spilled(first->spilled());
940 // insert. 984 if (!temp->spilled())
941 if (other->Start() < last_insertion_point_->Start()) { 985 temp->set_assigned_register(first->assigned_register());
942 last_insertion_point_ = this; 986
987 first->next_ = second;
988 first = temp;
989 continue;
990 }
991 DCHECK(first->End() <= second->Start());
943 } 992 }
944 993
945 for (; last_insertion_point_->next() != nullptr && 994 TopLevel()->UpdateParentForAllChildren(TopLevel());
946 last_insertion_point_->next()->Start() <= other->Start(); 995 TopLevel()->UpdateSpillRangePostMerge(other);
947 last_insertion_point_ = last_insertion_point_->next()) {
948 }
949 996
950 // When we splintered the original range, we reconstituted the original range 997 #if DEBUG
951 // into one range without children, but with discontinuities. To merge the 998 Verify();
952 // splinter back in, we need to split the range - or a child obtained after 999 #endif
953 // register allocation splitting.
954 LiveRange* after = last_insertion_point_->next();
955 if (last_insertion_point_->End() > other->Start()) {
956 LiveRange* new_after = last_insertion_point_->SplitAt(other->Start(), zone);
957 new_after->set_spilled(last_insertion_point_->spilled());
958 if (!new_after->spilled())
959 new_after->set_assigned_register(
960 last_insertion_point_->assigned_register());
961 after = new_after;
962 }
963
964 last_other->next_ = after;
965 last_insertion_point_->next_ = other;
966 other->UpdateParentForAllChildren(TopLevel());
967 TopLevel()->UpdateSpillRangePostMerge(other);
968 } 1000 }
969 1001
970 1002
971 void TopLevelLiveRange::ShortenTo(LifetimePosition start) { 1003 void TopLevelLiveRange::ShortenTo(LifetimePosition start) {
972 TRACE("Shorten live range %d to [%d\n", vreg(), start.value()); 1004 TRACE("Shorten live range %d to [%d\n", vreg(), start.value());
973 DCHECK(first_interval_ != nullptr); 1005 DCHECK(first_interval_ != nullptr);
974 DCHECK(first_interval_->start() <= start); 1006 DCHECK(first_interval_->start() <= start);
975 DCHECK(start < first_interval_->end()); 1007 DCHECK(start < first_interval_->end());
976 first_interval_->set_start(start); 1008 first_interval_->set_start(start);
977 } 1009 }
(...skipping 2383 matching lines...) Expand 10 before | Expand all | Expand 10 after
3361 auto eliminate = moves->PrepareInsertAfter(move); 3393 auto eliminate = moves->PrepareInsertAfter(move);
3362 to_insert.push_back(move); 3394 to_insert.push_back(move);
3363 if (eliminate != nullptr) to_eliminate.push_back(eliminate); 3395 if (eliminate != nullptr) to_eliminate.push_back(eliminate);
3364 } 3396 }
3365 } 3397 }
3366 3398
3367 3399
3368 } // namespace compiler 3400 } // namespace compiler
3369 } // namespace internal 3401 } // namespace internal
3370 } // namespace v8 3402 } // namespace v8
OLDNEW
« no previous file with comments | « src/compiler/register-allocator.h ('k') | test/unittests/compiler/live-range-unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698