Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2014 the V8 project authors. All rights reserved. | 1 // Copyright 2014 the V8 project authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #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/zone-containers.h" | 10 #include "src/zone-containers.h" |
| 10 | 11 |
| 12 | |
| 11 namespace v8 { | 13 namespace v8 { |
| 12 namespace internal { | 14 namespace internal { |
| 13 namespace compiler { | 15 namespace compiler { |
| 14 | 16 |
| 15 enum RegisterKind { | 17 enum RegisterKind { |
| 16 UNALLOCATED_REGISTERS, | 18 UNALLOCATED_REGISTERS, |
| 17 GENERAL_REGISTERS, | 19 GENERAL_REGISTERS, |
| 18 DOUBLE_REGISTERS | 20 DOUBLE_REGISTERS |
| 19 }; | 21 }; |
| 20 | 22 |
| (...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 93 return LifetimePosition(FullStart().value_ + kStep); | 95 return LifetimePosition(FullStart().value_ + kStep); |
| 94 } | 96 } |
| 95 | 97 |
| 96 // Returns the lifetime position for the beginning of the previous START. | 98 // Returns the lifetime position for the beginning of the previous START. |
| 97 LifetimePosition PrevStart() const { | 99 LifetimePosition PrevStart() const { |
| 98 DCHECK(IsValid()); | 100 DCHECK(IsValid()); |
| 99 DCHECK(value_ >= kHalfStep); | 101 DCHECK(value_ >= kHalfStep); |
| 100 return LifetimePosition(Start().value_ - kHalfStep); | 102 return LifetimePosition(Start().value_ - kHalfStep); |
| 101 } | 103 } |
| 102 | 104 |
| 105 LifetimePosition Next() const { | |
| 106 DCHECK(IsValid()); | |
| 107 return LifetimePosition(value_ + 1); | |
| 108 } | |
| 109 | |
| 110 LifetimePosition Prev() const { | |
| 111 DCHECK(IsValid()); | |
| 112 return LifetimePosition(value_ - 1); | |
| 113 } | |
| 114 | |
| 103 // Constructs the lifetime position which does not correspond to any | 115 // Constructs the lifetime position which does not correspond to any |
| 104 // instruction. | 116 // instruction. |
| 105 LifetimePosition() : value_(-1) {} | 117 LifetimePosition() : value_(-1) {} |
| 106 | 118 |
| 107 // Returns true if this lifetime positions corrensponds to some | 119 // Returns true if this lifetime positions corrensponds to some |
| 108 // instruction. | 120 // instruction. |
| 109 bool IsValid() const { return value_ != -1; } | 121 bool IsValid() const { return value_ != -1; } |
| 110 | 122 |
| 111 bool operator<(const LifetimePosition& that) const { | 123 bool operator<(const LifetimePosition& that) const { |
| 112 return this->value_ < that.value_; | 124 return this->value_ < that.value_; |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 146 | 158 |
| 147 // Code relies on kStep and kHalfStep being a power of two. | 159 // Code relies on kStep and kHalfStep being a power of two. |
| 148 STATIC_ASSERT(IS_POWER_OF_TWO(kHalfStep)); | 160 STATIC_ASSERT(IS_POWER_OF_TWO(kHalfStep)); |
| 149 | 161 |
| 150 explicit LifetimePosition(int value) : value_(value) {} | 162 explicit LifetimePosition(int value) : value_(value) {} |
| 151 | 163 |
| 152 int value_; | 164 int value_; |
| 153 }; | 165 }; |
| 154 | 166 |
| 155 | 167 |
| 168 std::ostream& operator<<(std::ostream& os, const LifetimePosition pos); | |
| 169 | |
| 170 | |
| 156 // Representation of the non-empty interval [start,end[. | 171 // Representation of the non-empty interval [start,end[. |
| 157 class UseInterval final : public ZoneObject { | 172 class UseInterval final : public ZoneObject { |
| 158 public: | 173 public: |
| 159 UseInterval(LifetimePosition start, LifetimePosition end) | 174 UseInterval(LifetimePosition start, LifetimePosition end) |
| 160 : start_(start), end_(end), next_(nullptr) { | 175 : start_(start), end_(end), next_(nullptr) { |
| 161 DCHECK(start < end); | 176 DCHECK(start < end); |
| 162 } | 177 } |
| 163 | 178 |
| 164 LifetimePosition start() const { return start_; } | 179 LifetimePosition start() const { return start_; } |
| 165 void set_start(LifetimePosition start) { start_ = start; } | 180 void set_start(LifetimePosition start) { start_ = start; } |
| (...skipping 292 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 458 // This is used as a cache, it doesn't affect correctness. | 473 // This is used as a cache, it doesn't affect correctness. |
| 459 mutable UseInterval* current_interval_; | 474 mutable UseInterval* current_interval_; |
| 460 // This is used as a cache, it doesn't affect correctness. | 475 // This is used as a cache, it doesn't affect correctness. |
| 461 mutable UsePosition* last_processed_use_; | 476 mutable UsePosition* last_processed_use_; |
| 462 // This is used as a cache, it's invalid outside of BuildLiveRanges. | 477 // This is used as a cache, it's invalid outside of BuildLiveRanges. |
| 463 mutable UsePosition* current_hint_position_; | 478 mutable UsePosition* current_hint_position_; |
| 464 | 479 |
| 465 DISALLOW_COPY_AND_ASSIGN(LiveRange); | 480 DISALLOW_COPY_AND_ASSIGN(LiveRange); |
| 466 }; | 481 }; |
| 467 | 482 |
| 483 struct PrintableLiveRange { | |
| 484 const RegisterConfiguration* register_configuration_; | |
| 485 const LiveRange* range_; | |
| 486 }; | |
| 487 | |
| 488 std::ostream& operator<<(std::ostream& os, | |
| 489 const PrintableLiveRange printable_range); | |
| 468 | 490 |
| 469 class SpillRange final : public ZoneObject { | 491 class SpillRange final : public ZoneObject { |
| 470 public: | 492 public: |
| 471 SpillRange(LiveRange* range, Zone* zone); | 493 SpillRange(LiveRange* range, Zone* zone); |
| 472 | 494 |
| 473 UseInterval* interval() const { return use_interval_; } | 495 UseInterval* interval() const { return use_interval_; } |
| 474 RegisterKind kind() const { return live_ranges_[0]->kind(); } | 496 RegisterKind kind() const { return live_ranges_[0]->kind(); } |
| 475 bool IsEmpty() const { return live_ranges_.empty(); } | 497 bool IsEmpty() const { return live_ranges_.empty(); } |
| 476 bool TryMerge(SpillRange* other); | 498 bool TryMerge(SpillRange* other); |
| 477 void SetOperand(AllocatedOperand* op); | 499 void SetOperand(AllocatedOperand* op); |
| (...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 565 | 587 |
| 566 // Creates a new live range. | 588 // Creates a new live range. |
| 567 LiveRange* NewLiveRange(int index); | 589 LiveRange* NewLiveRange(int index); |
| 568 | 590 |
| 569 void MarkAllocated(RegisterKind kind, int index); | 591 void MarkAllocated(RegisterKind kind, int index); |
| 570 | 592 |
| 571 PhiMapValue* InitializePhiMap(const InstructionBlock* block, | 593 PhiMapValue* InitializePhiMap(const InstructionBlock* block, |
| 572 PhiInstruction* phi); | 594 PhiInstruction* phi); |
| 573 PhiMapValue* GetPhiMapValueFor(int virtual_register); | 595 PhiMapValue* GetPhiMapValueFor(int virtual_register); |
| 574 | 596 |
| 597 PrintableInstruction ToPrintable(Instruction* ins) const { | |
| 598 return {config_, ins}; | |
| 599 } | |
| 600 | |
| 601 PrintableInstructionOperand ToPrintable(InstructionOperand op) const { | |
| 602 return {config_, op}; | |
| 603 } | |
| 604 | |
| 605 PrintableInstructionSequence ToPrintable(InstructionSequence* seq) const { | |
| 606 return {config_, seq}; | |
| 607 } | |
| 608 | |
| 609 PrintableLiveRange ToPrintable(LiveRange* range) const { | |
| 610 return {config_, range}; | |
| 611 } | |
| 612 | |
| 613 void Print(Instruction* ins); | |
| 614 void Print(InstructionOperand op); | |
| 615 void Print(InstructionSequence* seq); | |
| 616 void Print(LiveRange* range); | |
| 617 | |
| 618 std::ostream& dbgs() { return dbgs_; } | |
| 619 | |
| 575 private: | 620 private: |
| 576 Zone* const allocation_zone_; | 621 Zone* const allocation_zone_; |
| 577 Frame* const frame_; | 622 Frame* const frame_; |
| 578 InstructionSequence* const code_; | 623 InstructionSequence* const code_; |
| 579 const char* const debug_name_; | 624 const char* const debug_name_; |
| 580 const RegisterConfiguration* const config_; | 625 const RegisterConfiguration* const config_; |
| 581 PhiMap phi_map_; | 626 PhiMap phi_map_; |
| 582 ZoneVector<BitVector*> live_in_sets_; | 627 ZoneVector<BitVector*> live_in_sets_; |
| 583 ZoneVector<LiveRange*> live_ranges_; | 628 ZoneVector<LiveRange*> live_ranges_; |
| 584 ZoneVector<LiveRange*> fixed_live_ranges_; | 629 ZoneVector<LiveRange*> fixed_live_ranges_; |
| 585 ZoneVector<LiveRange*> fixed_double_live_ranges_; | 630 ZoneVector<LiveRange*> fixed_double_live_ranges_; |
| 586 ZoneVector<SpillRange*> spill_ranges_; | 631 ZoneVector<SpillRange*> spill_ranges_; |
| 587 BitVector* assigned_registers_; | 632 BitVector* assigned_registers_; |
| 588 BitVector* assigned_double_registers_; | 633 BitVector* assigned_double_registers_; |
| 634 OFStream dbgs_; | |
|
dcarney
2015/04/30 06:01:32
this is not done anywhere in v8 and seems anyway a
| |
| 589 | 635 |
| 590 DISALLOW_COPY_AND_ASSIGN(RegisterAllocationData); | 636 DISALLOW_COPY_AND_ASSIGN(RegisterAllocationData); |
| 591 }; | 637 }; |
| 592 | 638 |
| 593 | 639 |
| 594 class ConstraintBuilder final : public ZoneObject { | 640 class ConstraintBuilder final : public ZoneObject { |
| 595 public: | 641 public: |
| 596 explicit ConstraintBuilder(RegisterAllocationData* data); | 642 explicit ConstraintBuilder(RegisterAllocationData* data); |
| 597 | 643 |
| 598 // Phase 1 : insert moves to account for fixed register operands. | 644 // Phase 1 : insert moves to account for fixed register operands. |
| (...skipping 213 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 812 // http://blog.llvm.org/2011/09/greedy-register-allocation-in-llvm-30.html | 858 // http://blog.llvm.org/2011/09/greedy-register-allocation-in-llvm-30.html |
| 813 class GreedyAllocator final : public RegisterAllocator { | 859 class GreedyAllocator final : public RegisterAllocator { |
| 814 public: | 860 public: |
| 815 explicit GreedyAllocator(RegisterAllocationData* data, RegisterKind kind, | 861 explicit GreedyAllocator(RegisterAllocationData* data, RegisterKind kind, |
| 816 Zone* local_zone); | 862 Zone* local_zone); |
| 817 | 863 |
| 818 void AllocateRegisters(); | 864 void AllocateRegisters(); |
| 819 | 865 |
| 820 private: | 866 private: |
| 821 const RegisterConfiguration* config() const { return data()->config(); } | 867 const RegisterConfiguration* config() const { return data()->config(); } |
| 868 bool TryReuseSpillForPhi(LiveRange* range); | |
| 869 int GetHintedRegister(LiveRange* range); | |
| 822 | 870 |
| 823 typedef ZonePriorityQueue<std::pair<unsigned, LiveRange*>> PQueue; | 871 typedef ZonePriorityQueue<std::pair<unsigned, LiveRange*>> PQueue; |
| 824 | 872 |
| 825 unsigned GetLiveRangeSize(LiveRange* range); | 873 unsigned GetLiveRangeSize(LiveRange* range); |
| 826 void Enqueue(LiveRange* range); | 874 void Enqueue(LiveRange* range); |
| 827 | 875 |
| 828 void Evict(LiveRange* range); | 876 void Evict(LiveRange* range); |
| 829 float CalculateSpillWeight(LiveRange* range); | 877 float CalculateSpillWeight(LiveRange* range); |
| 830 float CalculateMaxSpillWeight(const ZoneSet<LiveRange*>& ranges); | 878 float CalculateMaxSpillWeight(const ZoneSet<LiveRange*>& ranges); |
| 831 | 879 |
| 832 | 880 |
| 833 bool TryAllocate(LiveRange* current, ZoneSet<LiveRange*>* conflicting); | 881 bool TryAllocate(LiveRange* current, ZoneSet<LiveRange*>* conflicting); |
| 834 bool TryAllocatePhysicalRegister(unsigned reg_id, LiveRange* range, | 882 bool TryAllocatePhysicalRegister(unsigned reg_id, LiveRange* range, |
| 835 ZoneSet<LiveRange*>* conflicting); | 883 ZoneSet<LiveRange*>* conflicting); |
| 836 bool HandleSpillOperands(LiveRange* range); | 884 bool HandleSpillOperands(LiveRange* range); |
| 837 bool AllocateBlockedRange(LiveRange*, const ZoneSet<LiveRange*>&); | 885 void AllocateBlockedRange(LiveRange* current, LifetimePosition pos, |
| 886 bool spill); | |
| 838 | 887 |
| 839 LiveRange* SpillBetweenUntil(LiveRange* range, LifetimePosition start, | 888 LiveRange* SpillBetweenUntil(LiveRange* range, LifetimePosition start, |
| 840 LifetimePosition until, LifetimePosition end); | 889 LifetimePosition until, LifetimePosition end); |
| 841 void AssignRangeToRegister(int reg_id, LiveRange* range); | 890 void AssignRangeToRegister(int reg_id, LiveRange* range); |
| 842 | 891 |
| 892 LifetimePosition FindProgressingSplitPosition(LiveRange* range, | |
| 893 bool* is_spill_pos); | |
| 894 | |
| 843 ZoneVector<CoallescedLiveRanges*> allocations_; | 895 ZoneVector<CoallescedLiveRanges*> allocations_; |
| 844 PQueue queue_; | 896 PQueue queue_; |
| 845 DISALLOW_COPY_AND_ASSIGN(GreedyAllocator); | 897 DISALLOW_COPY_AND_ASSIGN(GreedyAllocator); |
| 846 }; | 898 }; |
| 847 | 899 |
| 848 | 900 |
| 849 class OperandAssigner final : public ZoneObject { | 901 class OperandAssigner final : public ZoneObject { |
| 850 public: | 902 public: |
| 851 explicit OperandAssigner(RegisterAllocationData* data); | 903 explicit OperandAssigner(RegisterAllocationData* data); |
| 852 | 904 |
| (...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 902 void ResolveControlFlow(const InstructionBlock* block, | 954 void ResolveControlFlow(const InstructionBlock* block, |
| 903 const InstructionOperand& cur_op, | 955 const InstructionOperand& cur_op, |
| 904 const InstructionBlock* pred, | 956 const InstructionBlock* pred, |
| 905 const InstructionOperand& pred_op); | 957 const InstructionOperand& pred_op); |
| 906 | 958 |
| 907 RegisterAllocationData* const data_; | 959 RegisterAllocationData* const data_; |
| 908 | 960 |
| 909 DISALLOW_COPY_AND_ASSIGN(LiveRangeConnector); | 961 DISALLOW_COPY_AND_ASSIGN(LiveRangeConnector); |
| 910 }; | 962 }; |
| 911 | 963 |
| 964 | |
| 912 } // namespace compiler | 965 } // namespace compiler |
| 913 } // namespace internal | 966 } // namespace internal |
| 914 } // namespace v8 | 967 } // namespace v8 |
| 915 | 968 |
| 916 #endif // V8_REGISTER_ALLOCATOR_H_ | 969 #endif // V8_REGISTER_ALLOCATOR_H_ |
| OLD | NEW |