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

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

Issue 1157663007: Greedy allocator: perf work (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Created 5 years, 6 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 | « no previous file | src/compiler/register-allocator.cc » ('j') | src/compiler/register-allocator.cc » ('J')
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 #ifndef V8_REGISTER_ALLOCATOR_H_ 5 #ifndef V8_REGISTER_ALLOCATOR_H_
6 #define V8_REGISTER_ALLOCATOR_H_ 6 #define V8_REGISTER_ALLOCATOR_H_
7 7
8 #include "src/compiler/instruction.h" 8 #include "src/compiler/instruction.h"
9 #include "src/ostreams.h" 9 #include "src/ostreams.h"
10 #include "src/zone-containers.h" 10 #include "src/zone-containers.h"
(...skipping 233 matching lines...) Expand 10 before | Expand all | Expand 10 after
244 UsePositionHintType hint_type() const { 244 UsePositionHintType hint_type() const {
245 return HintTypeField::decode(flags_); 245 return HintTypeField::decode(flags_);
246 } 246 }
247 bool HasHint() const; 247 bool HasHint() const;
248 bool HintRegister(int* register_index) const; 248 bool HintRegister(int* register_index) const;
249 void ResolveHint(UsePosition* use_pos); 249 void ResolveHint(UsePosition* use_pos);
250 bool IsResolved() const { 250 bool IsResolved() const {
251 return hint_type() != UsePositionHintType::kUnresolved; 251 return hint_type() != UsePositionHintType::kUnresolved;
252 } 252 }
253 static UsePositionHintType HintTypeForOperand(const InstructionOperand& op); 253 static UsePositionHintType HintTypeForOperand(const InstructionOperand& op);
254 void dump_hint(std::ostream& os, const RegisterConfiguration* config);
254 255
255 private: 256 private:
256 typedef BitField<UsePositionType, 0, 2> TypeField; 257 typedef BitField<UsePositionType, 0, 2> TypeField;
257 typedef BitField<UsePositionHintType, 2, 3> HintTypeField; 258 typedef BitField<UsePositionHintType, 2, 3> HintTypeField;
258 typedef BitField<bool, 5, 1> RegisterBeneficialField; 259 typedef BitField<bool, 5, 1> RegisterBeneficialField;
259 typedef BitField<int32_t, 6, 6> AssignedRegisterField; 260 typedef BitField<int32_t, 6, 6> AssignedRegisterField;
260 261
261 InstructionOperand* const operand_; 262 InstructionOperand* const operand_;
262 void* hint_; 263 void* hint_;
263 UsePosition* next_; 264 UsePosition* next_;
264 LifetimePosition const pos_; 265 LifetimePosition const pos_;
265 uint32_t flags_; 266 uint32_t flags_;
266 267
267 DISALLOW_COPY_AND_ASSIGN(UsePosition); 268 DISALLOW_COPY_AND_ASSIGN(UsePosition);
268 }; 269 };
269 270
270 271
271 class SpillRange; 272 class SpillRange;
273 class LiveRangeGroup;
272 274
273 275
274 // Representation of SSA values' live ranges as a collection of (continuous) 276 // Representation of SSA values' live ranges as a collection of (continuous)
275 // intervals over the instruction ordering. 277 // intervals over the instruction ordering.
276 class LiveRange final : public ZoneObject { 278 class LiveRange final : public ZoneObject {
277 public: 279 public:
278 explicit LiveRange(int id, MachineType machine_type); 280 explicit LiveRange(int id, MachineType machine_type);
279 281
280 UseInterval* first_interval() const { return first_interval_; } 282 UseInterval* first_interval() const { return first_interval_; }
281 UsePosition* first_pos() const { return first_pos_; } 283 UsePosition* first_pos() const { return first_pos_; }
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after
334 // range and which follows both start and last processed use position 336 // range and which follows both start and last processed use position
335 UsePosition* NextUsePositionRegisterIsBeneficial( 337 UsePosition* NextUsePositionRegisterIsBeneficial(
336 LifetimePosition start) const; 338 LifetimePosition start) const;
337 339
338 // Returns use position for which register is beneficial in this live 340 // Returns use position for which register is beneficial in this live
339 // range and which precedes start. 341 // range and which precedes start.
340 UsePosition* PreviousUsePositionRegisterIsBeneficial( 342 UsePosition* PreviousUsePositionRegisterIsBeneficial(
341 LifetimePosition start) const; 343 LifetimePosition start) const;
342 344
343 // Can this live range be spilled at this position. 345 // Can this live range be spilled at this position.
344 bool CanBeSpilled(LifetimePosition pos) const; 346 bool CanBeSpilled(LifetimePosition pos) const { return CanBeSplit(pos); }
347
348 // Can this live range be split at this position.
349 bool CanBeSplit(LifetimePosition pos) const;
345 350
346 // Split this live range at the given position which must follow the start of 351 // Split this live range at the given position which must follow the start of
347 // the range. 352 // the range.
348 // All uses following the given position will be moved from this 353 // All uses following the given position will be moved from this
349 // live range to the result live range. 354 // live range to the result live range.
350 void SplitAt(LifetimePosition position, LiveRange* result, Zone* zone); 355 void SplitAt(LifetimePosition position, LiveRange* result, Zone* zone);
351 356
352 // Returns nullptr when no register is hinted, otherwise sets register_index. 357 // Returns nullptr when no register is hinted, otherwise sets register_index.
353 UsePosition* FirstHintPosition(int* register_index) const; 358 UsePosition* FirstHintPosition(int* register_index) const;
354 UsePosition* FirstHintPosition() const { 359 UsePosition* FirstHintPosition() const {
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after
421 const InstructionOperand& spill_op); 426 const InstructionOperand& spill_op);
422 void SetUseHints(int register_index); 427 void SetUseHints(int register_index);
423 void UnsetUseHints() { SetUseHints(kUnassignedRegister); } 428 void UnsetUseHints() { SetUseHints(kUnassignedRegister); }
424 429
425 struct SpillAtDefinitionList; 430 struct SpillAtDefinitionList;
426 431
427 SpillAtDefinitionList* spills_at_definition() const { 432 SpillAtDefinitionList* spills_at_definition() const {
428 return spills_at_definition_; 433 return spills_at_definition_;
429 } 434 }
430 435
436 LiveRangeGroup* group() const { return group_; }
437 void SetGroup(LiveRangeGroup* grp) { group_ = grp; }
438
439 float GetWeight() const {
440 DCHECK(weight_ >= 0.0f);
441 return weight_;
442 }
443
444 unsigned GetSize() {
445 if (size_ < 0) RecalculateSize();
446 DCHECK(size_ > 0);
447 return static_cast<unsigned>(size_);
448 }
449
450 void InvalidateWeightAndSize() {
451 weight_ = kInvalidWeight;
452 size_ = kInvalidSize;
453 }
454 void RecalculateWeight(InstructionSequence* code);
455 LifetimePosition GetFirstSplittablePosition();
456
457 static const float kMaxWeight;
458
431 private: 459 private:
460 static const float kUseInLoopWeightMultiplier;
461 static const float kPreferredRegisterWeightMultiplier;
462 static const float kInvalidWeight;
463 static const int kInvalidSize = -1;
464
465 void RecalculateSize();
432 void set_spill_type(SpillType value) { 466 void set_spill_type(SpillType value) {
433 bits_ = SpillTypeField::update(bits_, value); 467 bits_ = SpillTypeField::update(bits_, value);
434 } 468 }
435 469
436 void set_spilled(bool value) { bits_ = SpilledField::update(bits_, value); } 470 void set_spilled(bool value) { bits_ = SpilledField::update(bits_, value); }
437 471
438 UseInterval* FirstSearchIntervalForPosition(LifetimePosition position) const; 472 UseInterval* FirstSearchIntervalForPosition(LifetimePosition position) const;
439 void AdvanceLastProcessedMarker(UseInterval* to_start_of, 473 void AdvanceLastProcessedMarker(UseInterval* to_start_of,
440 LifetimePosition but_not_past) const; 474 LifetimePosition but_not_past) const;
441 475
(...skipping 19 matching lines...) Expand all
461 SpillRange* spill_range_; 495 SpillRange* spill_range_;
462 }; 496 };
463 SpillAtDefinitionList* spills_at_definition_; 497 SpillAtDefinitionList* spills_at_definition_;
464 // This is used as a cache, it doesn't affect correctness. 498 // This is used as a cache, it doesn't affect correctness.
465 mutable UseInterval* current_interval_; 499 mutable UseInterval* current_interval_;
466 // This is used as a cache, it doesn't affect correctness. 500 // This is used as a cache, it doesn't affect correctness.
467 mutable UsePosition* last_processed_use_; 501 mutable UsePosition* last_processed_use_;
468 // This is used as a cache, it's invalid outside of BuildLiveRanges. 502 // This is used as a cache, it's invalid outside of BuildLiveRanges.
469 mutable UsePosition* current_hint_position_; 503 mutable UsePosition* current_hint_position_;
470 504
505 // Used only by the greedy allocator.
506 float weight_;
507 int size_;
508 LiveRangeGroup* group_;
471 DISALLOW_COPY_AND_ASSIGN(LiveRange); 509 DISALLOW_COPY_AND_ASSIGN(LiveRange);
472 }; 510 };
473 511
474 512
513 class LiveRangeGroup final : public ZoneObject {
514 public:
515 explicit LiveRangeGroup(Zone* zone) : ranges_(zone) {}
516 ZoneSet<LiveRange*>& ranges() { return ranges_; }
517 bool CanAdd(LiveRange* r);
518 void TryMerge(LiveRangeGroup* other);
519
520 private:
521 ZoneSet<LiveRange*> ranges_;
522
523 DISALLOW_COPY_AND_ASSIGN(LiveRangeGroup);
524 };
525
475 struct PrintableLiveRange { 526 struct PrintableLiveRange {
476 const RegisterConfiguration* register_configuration_; 527 const RegisterConfiguration* register_configuration_;
477 const LiveRange* range_; 528 const LiveRange* range_;
478 }; 529 };
479 530
480 531
481 std::ostream& operator<<(std::ostream& os, 532 std::ostream& operator<<(std::ostream& os,
482 const PrintableLiveRange& printable_range); 533 const PrintableLiveRange& printable_range);
483 534
484 535
485 class SpillRange final : public ZoneObject { 536 class SpillRange final : public ZoneObject {
486 public: 537 public:
487 static const int kUnassignedSlot = -1; 538 static const int kUnassignedSlot = -1;
488 SpillRange(LiveRange* range, Zone* zone); 539 SpillRange(LiveRange* range, Zone* zone);
489 540
490 UseInterval* interval() const { return use_interval_; } 541 UseInterval* interval() const { return use_interval_; }
491 // Currently, only 4 or 8 byte slots are supported. 542 // Currently, only 4 or 8 byte slots are supported.
492 int ByteWidth() const; 543 int ByteWidth() const;
493 bool IsEmpty() const { return live_ranges_.empty(); } 544 bool IsEmpty() const { return live_ranges_.empty(); }
494 bool TryMerge(SpillRange* other); 545 bool TryMerge(SpillRange* other);
495 546
496 void set_assigned_slot(int index) { 547 void set_assigned_slot(int index) {
497 DCHECK_EQ(kUnassignedSlot, assigned_slot_); 548 DCHECK_EQ(kUnassignedSlot, assigned_slot_);
498 assigned_slot_ = index; 549 assigned_slot_ = index;
499 } 550 }
551 bool IsSlotAssigned() const { return assigned_slot_ != kUnassignedSlot; }
500 int assigned_slot() { 552 int assigned_slot() {
501 DCHECK_NE(kUnassignedSlot, assigned_slot_); 553 DCHECK_NE(kUnassignedSlot, assigned_slot_);
502 return assigned_slot_; 554 return assigned_slot_;
503 } 555 }
504 556
505 private: 557 private:
506 LifetimePosition End() const { return end_position_; } 558 LifetimePosition End() const { return end_position_; }
507 ZoneVector<LiveRange*>& live_ranges() { return live_ranges_; } 559 ZoneVector<LiveRange*>& live_ranges() { return live_ranges_; }
508 bool IsIntersectingWith(SpillRange* other) const; 560 bool IsIntersectingWith(SpillRange* other) const;
509 // Merge intervals, making sure the use intervals are sorted 561 // Merge intervals, making sure the use intervals are sorted
510 void MergeDisjointIntervals(UseInterval* other); 562 void MergeDisjointIntervals(UseInterval* other);
511 563
512 ZoneVector<LiveRange*> live_ranges_; 564 ZoneVector<LiveRange*> live_ranges_;
513 UseInterval* use_interval_; 565 UseInterval* use_interval_;
514 LifetimePosition end_position_; 566 LifetimePosition end_position_;
515 int assigned_slot_; 567 int assigned_slot_;
516 568
517 DISALLOW_COPY_AND_ASSIGN(SpillRange); 569 DISALLOW_COPY_AND_ASSIGN(SpillRange);
518 }; 570 };
519 571
520 572
573 std::ostream& operator<<(std::ostream& os, SpillRange* range);
574
575
521 class RegisterAllocationData final : public ZoneObject { 576 class RegisterAllocationData final : public ZoneObject {
522 public: 577 public:
523 class PhiMapValue : public ZoneObject { 578 class PhiMapValue : public ZoneObject {
524 public: 579 public:
525 PhiMapValue(PhiInstruction* phi, const InstructionBlock* block, Zone* zone); 580 PhiMapValue(PhiInstruction* phi, const InstructionBlock* block, Zone* zone);
526 581
527 const PhiInstruction* phi() const { return phi_; } 582 const PhiInstruction* phi() const { return phi_; }
528 const InstructionBlock* block() const { return block_; } 583 const InstructionBlock* block() const { return block_; }
529 584
530 // For hinting. 585 // For hinting.
(...skipping 190 matching lines...) Expand 10 before | Expand all | Expand 10 after
721 InstructionOperand* operand) { 776 InstructionOperand* operand) {
722 Use(block_start, position, operand, nullptr, UsePositionHintType::kNone); 777 Use(block_start, position, operand, nullptr, UsePositionHintType::kNone);
723 } 778 }
724 779
725 RegisterAllocationData* const data_; 780 RegisterAllocationData* const data_;
726 ZoneMap<InstructionOperand*, UsePosition*> phi_hints_; 781 ZoneMap<InstructionOperand*, UsePosition*> phi_hints_;
727 782
728 DISALLOW_COPY_AND_ASSIGN(LiveRangeBuilder); 783 DISALLOW_COPY_AND_ASSIGN(LiveRangeBuilder);
729 }; 784 };
730 785
786 struct AllocatorStats {
787 unsigned spills;
788 unsigned wins;
789 unsigned losses_no_eviction;
790 unsigned losses_after_eviction;
791 unsigned good_split_attempts;
792 unsigned good_split_successes;
793 unsigned good_split_smart_above;
794 unsigned good_split_smart_below;
795 unsigned good_split_above;
796 unsigned good_split_below;
797 unsigned groups_attempted;
798 unsigned groups_succeeded;
799 unsigned groups_allocated;
800 void reset() { *this = {0}; }
801 };
802
803
804 std::ostream& operator<<(std::ostream& os, const AllocatorStats& stats);
805
731 806
732 class RegisterAllocator : public ZoneObject { 807 class RegisterAllocator : public ZoneObject {
733 public: 808 public:
734 explicit RegisterAllocator(RegisterAllocationData* data, RegisterKind kind); 809 explicit RegisterAllocator(RegisterAllocationData* data, RegisterKind kind);
735 810
736 protected: 811 protected:
812 AllocatorStats stats_;
737 RegisterAllocationData* data() const { return data_; } 813 RegisterAllocationData* data() const { return data_; }
738 InstructionSequence* code() const { return data()->code(); } 814 InstructionSequence* code() const { return data()->code(); }
739 RegisterKind mode() const { return mode_; } 815 RegisterKind mode() const { return mode_; }
740 int num_registers() const { return num_registers_; } 816 int num_registers() const { return num_registers_; }
741 817
742 Zone* allocation_zone() const { return data()->allocation_zone(); } 818 Zone* allocation_zone() const { return data()->allocation_zone(); }
743 819
744 LiveRange* LiveRangeFor(int index) { return data()->LiveRangeFor(index); } 820 LiveRange* LiveRangeFor(int index) { return data()->LiveRangeFor(index); }
745 821
746 // Split the given range at the given position. 822 // Split the given range at the given position.
(...skipping 13 matching lines...) Expand all
760 // loop covered by this interval or the latest possible position. 836 // loop covered by this interval or the latest possible position.
761 LifetimePosition FindOptimalSplitPos(LifetimePosition start, 837 LifetimePosition FindOptimalSplitPos(LifetimePosition start,
762 LifetimePosition end); 838 LifetimePosition end);
763 839
764 void Spill(LiveRange* range); 840 void Spill(LiveRange* range);
765 841
766 // If we are trying to spill a range inside the loop try to 842 // If we are trying to spill a range inside the loop try to
767 // hoist spill position out to the point just before the loop. 843 // hoist spill position out to the point just before the loop.
768 LifetimePosition FindOptimalSpillingPos(LiveRange* range, 844 LifetimePosition FindOptimalSpillingPos(LiveRange* range,
769 LifetimePosition pos); 845 LifetimePosition pos);
846 const char* RegisterName(int allocation_index) const;
770 847
771 private: 848 private:
772 RegisterAllocationData* const data_; 849 RegisterAllocationData* const data_;
773 const RegisterKind mode_; 850 const RegisterKind mode_;
774 const int num_registers_; 851 const int num_registers_;
775 852
776 DISALLOW_COPY_AND_ASSIGN(RegisterAllocator); 853 DISALLOW_COPY_AND_ASSIGN(RegisterAllocator);
777 }; 854 };
778 855
779 856
780 class LinearScanAllocator final : public RegisterAllocator { 857 class LinearScanAllocator final : public RegisterAllocator {
781 public: 858 public:
782 LinearScanAllocator(RegisterAllocationData* data, RegisterKind kind, 859 LinearScanAllocator(RegisterAllocationData* data, RegisterKind kind,
783 Zone* local_zone); 860 Zone* local_zone);
784 861
785 // Phase 4: compute register assignments. 862 // Phase 4: compute register assignments.
786 void AllocateRegisters(); 863 void AllocateRegisters();
787 864
788 private: 865 private:
789 const char* RegisterName(int allocation_index) const;
790
791 ZoneVector<LiveRange*>& unhandled_live_ranges() { 866 ZoneVector<LiveRange*>& unhandled_live_ranges() {
792 return unhandled_live_ranges_; 867 return unhandled_live_ranges_;
793 } 868 }
794 ZoneVector<LiveRange*>& active_live_ranges() { return active_live_ranges_; } 869 ZoneVector<LiveRange*>& active_live_ranges() { return active_live_ranges_; }
795 ZoneVector<LiveRange*>& inactive_live_ranges() { 870 ZoneVector<LiveRange*>& inactive_live_ranges() {
796 return inactive_live_ranges_; 871 return inactive_live_ranges_;
797 } 872 }
798 873
799 void SetLiveRangeAssignedRegister(LiveRange* range, int reg); 874 void SetLiveRangeAssignedRegister(LiveRange* range, int reg);
800 875
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
833 ZoneVector<LiveRange*> active_live_ranges_; 908 ZoneVector<LiveRange*> active_live_ranges_;
834 ZoneVector<LiveRange*> inactive_live_ranges_; 909 ZoneVector<LiveRange*> inactive_live_ranges_;
835 910
836 #ifdef DEBUG 911 #ifdef DEBUG
837 LifetimePosition allocation_finger_; 912 LifetimePosition allocation_finger_;
838 #endif 913 #endif
839 914
840 DISALLOW_COPY_AND_ASSIGN(LinearScanAllocator); 915 DISALLOW_COPY_AND_ASSIGN(LinearScanAllocator);
841 }; 916 };
842 917
918
919 // Storage detail for CoalescedLiveRanges.
920 struct AllocatedInterval {
921 LifetimePosition start;
922 LifetimePosition end;
923 LiveRange* range;
924 struct Comparer : public std::binary_function<AllocatedInterval,
925 AllocatedInterval, bool> {
926 bool operator()(const AllocatedInterval& x,
927 const AllocatedInterval& y) const {
928 return x.start < y.start;
929 }
930 };
931 };
932
933
843 class CoalescedLiveRanges; 934 class CoalescedLiveRanges;
844 935
845 936
937 // Iterator over allocated live ranges (CoalescedLiveRanges) that conflict with
938 // a given one. See CoalescedLiveRanges::first_conflict.
939 // Note that iterating may produce non-consecutively repeating live ranges.
940 struct conflict_iterator {
941 conflict_iterator() : storage_(nullptr) {}
Jarin 2015/06/12 04:09:12 Initialize all fields here.
942 const LiveRange* operator->() const { return pos_->range; }
943
944 LiveRange* operator*() const { return pos_->range; }
945
946 conflict_iterator& operator++();
947 bool IsEnd() const {
948 DCHECK(storage_ != nullptr);
949 return pos_ == storage_->end();
950 }
951
952 private:
953 friend class CoalescedLiveRanges;
954 friend bool operator==(const conflict_iterator& first,
955 const conflict_iterator& second);
956
957 typedef ZoneSet<AllocatedInterval, AllocatedInterval::Comparer> IntervalStore;
958 typedef IntervalStore::const_iterator interval_iterator;
959
960 void Invalidate() {
961 DCHECK(storage_ != nullptr);
962 pos_ = storage_->end();
963 query_ = nullptr;
964 }
965
966 static bool Intersects(LifetimePosition a_start, LifetimePosition a_end,
967 LifetimePosition b_start, LifetimePosition b_end) {
968 if (a_start == b_start) return true;
969 if (a_start < b_start) return a_end > b_start;
Jarin 2015/06/12 04:09:12 Out of curiosity, cannot you just leave out the "i
Sven Panne 2015/06/12 07:36:37 Hmmm, this looks still too complicated, normally j
970 return Intersects(b_start, b_end, a_start, a_end);
971 }
972
973 bool QueryIntersectsAllocatedInterval() {
974 DCHECK(query_ != nullptr);
975 return Intersects(query_->start(), query_->end(), pos_->start, pos_->end);
976 }
977
978 bool NextQueryIntersectsAllocatedInterval() {
979 DCHECK(query_->next() != nullptr);
980 return Intersects(query_->next()->start(), query_->next()->end(),
981 pos_->start, pos_->end);
982 }
983
984 conflict_iterator(UseInterval* query, IntervalStore* storage)
985 : query_(query), storage_(storage) {
986 InitializeForNewQuery();
987 }
988
989 explicit conflict_iterator(IntervalStore* storage) : storage_(storage) {
990 Invalidate();
991 }
992
993 static conflict_iterator EndIteratorForStorage(IntervalStore* storage) {
994 conflict_iterator ret(storage);
995 return ret;
996 }
997
998 void InitializeForNewQuery();
999 void SkipMatchedQueries();
1000
1001 AllocatedInterval AsAllocatedInterval(LifetimePosition pos) {
1002 return {pos, LifetimePosition::Invalid(), nullptr};
1003 }
1004
1005 UseInterval* query_;
1006 IntervalStore* storage_;
1007 interval_iterator pos_;
1008 };
1009
1010 bool operator==(const conflict_iterator& first,
1011 const conflict_iterator& second);
1012 bool operator!=(const conflict_iterator& first,
1013 const conflict_iterator& second);
1014
1015
846 // A variant of the LLVM Greedy Register Allocator. See 1016 // A variant of the LLVM Greedy Register Allocator. See
847 // http://blog.llvm.org/2011/09/greedy-register-allocation-in-llvm-30.html 1017 // http://blog.llvm.org/2011/09/greedy-register-allocation-in-llvm-30.html
848 class GreedyAllocator final : public RegisterAllocator { 1018 class GreedyAllocator final : public RegisterAllocator {
849 public: 1019 public:
850 explicit GreedyAllocator(RegisterAllocationData* data, RegisterKind kind, 1020 explicit GreedyAllocator(RegisterAllocationData* data, RegisterKind kind,
851 Zone* local_zone); 1021 Zone* local_zone);
852 1022
853 void AllocateRegisters(); 1023 void AllocateRegisters();
854 1024
855 private: 1025 private:
856 LifetimePosition GetSplittablePos(LifetimePosition pos); 1026 void AllocateRange(LiveRange* current);
1027 void AllocateGroup(LiveRangeGroup* grp);
1028 bool TryAllocateGroup(LiveRangeGroup* grp);
1029 bool TryAllocateGroupAtRegister(unsigned reg, LiveRangeGroup* grp);
1030
1031 struct PQueueElem {
Jarin 2015/06/12 04:09:12 PQueueElem -> QueueElement (or PriorityQueueElemen
1032 bool IsGroup() { return is_grp_; }
1033 explicit PQueueElem(LiveRange* range) : is_grp_(false) {
1034 storage_.range_ = range;
1035 }
1036
1037 explicit PQueueElem(LiveRangeGroup* grp) : is_grp_(true) {
1038 storage_.grp_ = grp;
1039 }
1040
1041
1042 LiveRange* get_range() {
1043 if (is_grp_) return nullptr;
Jarin 2015/06/12 04:09:12 The callers should (and do) always consult IsGroup
1044 return storage_.range_;
1045 }
1046
1047
1048 LiveRangeGroup* get_group() {
1049 if (is_grp_) return storage_.grp_;
Jarin 2015/06/12 04:09:12 Similarly, "DCHECK(IsGroup()); return storage_.grp
1050 return nullptr;
1051 }
1052
1053 private:
1054 bool is_grp_;
1055 union {
1056 LiveRange* range_;
1057 LiveRangeGroup* grp_;
1058 } storage_;
1059 };
1060
1061 void GroupAndEnqueue();
Jarin 2015/06/12 04:09:12 GroupAndEnqueue -> EnqueuePhiGroups?
857 const RegisterConfiguration* config() const { return data()->config(); } 1062 const RegisterConfiguration* config() const { return data()->config(); }
858 Zone* local_zone() const { return local_zone_; } 1063 Zone* local_zone() const { return local_zone_; }
859 bool TryReuseSpillForPhi(LiveRange* range);
860 int GetHintedRegister(LiveRange* range);
861 1064
862 typedef ZonePriorityQueue<std::pair<unsigned, LiveRange*>> PQueue; 1065 struct PQueueElemComparer
1066 : public std::binary_function<std::pair<unsigned, PQueueElem>,
1067 std::pair<unsigned, PQueueElem>, bool> {
1068 bool operator()(const std::pair<unsigned, PQueueElem>& x,
1069 const std::pair<unsigned, PQueueElem>& y) const {
1070 return x.first < y.first;
1071 }
1072 };
863 1073
864 unsigned GetLiveRangeSize(LiveRange* range); 1074 typedef ZonePriorityQueue<std::pair<unsigned, PQueueElem>, PQueueElemComparer>
1075 PQueue;
Jarin 2015/06/12 04:09:12 PQueue -> PriorityQueue
1076
865 void Enqueue(LiveRange* range); 1077 void Enqueue(LiveRange* range);
1078 void Enqueue(LiveRangeGroup* group);
866 1079
867 void Evict(LiveRange* range); 1080 void Evict(LiveRange* range);
868 float CalculateSpillWeight(LiveRange* range); 1081 void EvictAll(int reg, const conflict_iterator& first_conflict);
869 float CalculateMaxSpillWeight(const ZoneSet<LiveRange*>& ranges);
870 1082
1083 // Find the register with the minimum spill weight. If that is still higher
1084 // or equal to competing, return -1.
1085 int FindRegisterToEvictForRange(
1086 conflict_iterator
1087 all_conflicts[RegisterConfiguration::kMaxDoubleRegisters],
1088 float competing);
871 1089
872 bool TryAllocate(LiveRange* current, ZoneSet<LiveRange*>* conflicting); 1090 // Same as above, for all the registers in a group.
873 bool TryAllocatePhysicalRegister(unsigned reg_id, LiveRange* range, 1091 int FindRegisterToEvictForGroup(LiveRangeGroup* grp, float competing);
874 ZoneSet<LiveRange*>* conflicting); 1092
875 bool HandleSpillOperands(LiveRange* range); 1093 template <typename TIter>
876 void AllocateBlockedRange(LiveRange* current, LifetimePosition pos, 1094 float CalculateMaxSpillWeight(const TIter& begin, const TIter& end);
Jarin 2015/06/12 04:09:12 Static?
877 bool spill); 1095
1096 bool HandleSpillOperands(LiveRange* range, LiveRange** remaining);
1097 void HandleBlockedRange(LiveRange* current);
1098 bool TrySplitBeforeLoops(LiveRange* current);
1099 bool TrySplitAfterLoops(LiveRange* current);
1100 bool TrySplitAroundCalls(LiveRange* range);
878 1101
879 LiveRange* SpillBetweenUntil(LiveRange* range, LifetimePosition start, 1102 LiveRange* SpillBetweenUntil(LiveRange* range, LifetimePosition start,
880 LifetimePosition until, LifetimePosition end); 1103 LifetimePosition until, LifetimePosition end);
881 void AssignRangeToRegister(int reg_id, LiveRange* range); 1104 void AssignRangeToRegister(int reg_id, LiveRange* range);
882 1105
883 LifetimePosition FindProgressingSplitPosition(LiveRange* range,
884 bool* is_spill_pos);
885
886 Zone* local_zone_; 1106 Zone* local_zone_;
887 ZoneVector<CoalescedLiveRanges*> allocations_; 1107 ZoneVector<CoalescedLiveRanges*> allocations_;
888 PQueue queue_; 1108 PQueue queue_;
889 DISALLOW_COPY_AND_ASSIGN(GreedyAllocator); 1109 DISALLOW_COPY_AND_ASSIGN(GreedyAllocator);
890 }; 1110 };
891 1111
892 1112
893 class SpillSlotLocator final : public ZoneObject { 1113 class SpillSlotLocator final : public ZoneObject {
894 public: 1114 public:
895 explicit SpillSlotLocator(RegisterAllocationData* data); 1115 explicit SpillSlotLocator(RegisterAllocationData* data);
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after
966 RegisterAllocationData* const data_; 1186 RegisterAllocationData* const data_;
967 1187
968 DISALLOW_COPY_AND_ASSIGN(LiveRangeConnector); 1188 DISALLOW_COPY_AND_ASSIGN(LiveRangeConnector);
969 }; 1189 };
970 1190
971 } // namespace compiler 1191 } // namespace compiler
972 } // namespace internal 1192 } // namespace internal
973 } // namespace v8 1193 } // namespace v8
974 1194
975 #endif // V8_REGISTER_ALLOCATOR_H_ 1195 #endif // V8_REGISTER_ALLOCATOR_H_
OLDNEW
« no previous file with comments | « no previous file | src/compiler/register-allocator.cc » ('j') | src/compiler/register-allocator.cc » ('J')

Powered by Google App Engine
This is Rietveld 408576698