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/zone-containers.h" | 9 #include "src/zone-containers.h" |
10 | 10 |
(...skipping 567 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
578 InstructionOperand* operand, InstructionOperand* hint); | 578 InstructionOperand* operand, InstructionOperand* hint); |
579 | 579 |
580 RegisterAllocationData* const data_; | 580 RegisterAllocationData* const data_; |
581 | 581 |
582 DISALLOW_COPY_AND_ASSIGN(LiveRangeBuilder); | 582 DISALLOW_COPY_AND_ASSIGN(LiveRangeBuilder); |
583 }; | 583 }; |
584 | 584 |
585 | 585 |
586 class RegisterAllocator : public ZoneObject { | 586 class RegisterAllocator : public ZoneObject { |
587 public: | 587 public: |
588 explicit RegisterAllocator(RegisterAllocationData* data, RegisterKind kind); | 588 explicit RegisterAllocator(RegisterAllocationData* data); |
589 | 589 |
590 protected: | 590 protected: |
591 RegisterAllocationData* data() const { return data_; } | 591 RegisterAllocationData* data() const { return data_; } |
592 InstructionSequence* code() const { return data()->code(); } | 592 InstructionSequence* code() const { return data()->code(); } |
593 RegisterKind mode() const { return mode_; } | |
594 int num_registers() const { return num_registers_; } | |
595 | |
596 Zone* allocation_zone() const { return data()->allocation_zone(); } | 593 Zone* allocation_zone() const { return data()->allocation_zone(); } |
597 | 594 |
598 LiveRange* LiveRangeFor(int index) { return data()->LiveRangeFor(index); } | 595 LiveRange* LiveRangeFor(int index) { return data()->LiveRangeFor(index); } |
599 | 596 |
600 // Split the given range at the given position. | 597 // Split the given range at the given position. |
601 // If range starts at or after the given position then the | 598 // If range starts at or after the given position then the |
602 // original range is returned. | 599 // original range is returned. |
603 // Otherwise returns the live range that starts at pos and contains | 600 // Otherwise returns the live range that starts at pos and contains |
604 // all uses from the original range that follow pos. Uses at pos will | 601 // all uses from the original range that follow pos. Uses at pos will |
605 // still be owned by the original range after splitting. | 602 // still be owned by the original range after splitting. |
(...skipping 11 matching lines...) Expand all Loading... |
617 | 614 |
618 void Spill(LiveRange* range); | 615 void Spill(LiveRange* range); |
619 | 616 |
620 // If we are trying to spill a range inside the loop try to | 617 // If we are trying to spill a range inside the loop try to |
621 // hoist spill position out to the point just before the loop. | 618 // hoist spill position out to the point just before the loop. |
622 LifetimePosition FindOptimalSpillingPos(LiveRange* range, | 619 LifetimePosition FindOptimalSpillingPos(LiveRange* range, |
623 LifetimePosition pos); | 620 LifetimePosition pos); |
624 | 621 |
625 private: | 622 private: |
626 RegisterAllocationData* const data_; | 623 RegisterAllocationData* const data_; |
627 const RegisterKind mode_; | |
628 const int num_registers_; | |
629 | 624 |
630 DISALLOW_COPY_AND_ASSIGN(RegisterAllocator); | 625 DISALLOW_COPY_AND_ASSIGN(RegisterAllocator); |
631 }; | 626 }; |
632 | 627 |
633 | 628 |
634 class LinearScanAllocator final : public RegisterAllocator { | 629 class LinearScanAllocator final : public RegisterAllocator { |
635 public: | 630 public: |
636 LinearScanAllocator(RegisterAllocationData* data, RegisterKind kind, | 631 LinearScanAllocator(RegisterAllocationData* data, RegisterKind kind, |
637 Zone* local_zone); | 632 Zone* local_zone); |
638 | 633 |
639 // Phase 4: compute register assignments. | 634 // Phase 4: compute register assignments. |
640 void AllocateRegisters(); | 635 void AllocateRegisters(); |
641 | 636 |
642 private: | 637 private: |
| 638 int num_registers() const { return num_registers_; } |
643 const char* RegisterName(int allocation_index) const; | 639 const char* RegisterName(int allocation_index) const; |
644 | 640 |
645 ZoneVector<LiveRange*>& unhandled_live_ranges() { | 641 ZoneVector<LiveRange*>& unhandled_live_ranges() { |
646 return unhandled_live_ranges_; | 642 return unhandled_live_ranges_; |
647 } | 643 } |
648 ZoneVector<LiveRange*>& active_live_ranges() { return active_live_ranges_; } | 644 ZoneVector<LiveRange*>& active_live_ranges() { return active_live_ranges_; } |
649 ZoneVector<LiveRange*>& inactive_live_ranges() { | 645 ZoneVector<LiveRange*>& inactive_live_ranges() { |
650 return inactive_live_ranges_; | 646 return inactive_live_ranges_; |
651 } | 647 } |
652 | 648 |
(...skipping 21 matching lines...) Expand all Loading... |
674 void SpillBetween(LiveRange* range, LifetimePosition start, | 670 void SpillBetween(LiveRange* range, LifetimePosition start, |
675 LifetimePosition end); | 671 LifetimePosition end); |
676 | 672 |
677 // Spill the given life range after position [start] and up to position [end]. | 673 // Spill the given life range after position [start] and up to position [end]. |
678 // Range is guaranteed to be spilled at least until position [until]. | 674 // Range is guaranteed to be spilled at least until position [until]. |
679 void SpillBetweenUntil(LiveRange* range, LifetimePosition start, | 675 void SpillBetweenUntil(LiveRange* range, LifetimePosition start, |
680 LifetimePosition until, LifetimePosition end); | 676 LifetimePosition until, LifetimePosition end); |
681 | 677 |
682 void SplitAndSpillIntersecting(LiveRange* range); | 678 void SplitAndSpillIntersecting(LiveRange* range); |
683 | 679 |
| 680 const RegisterKind mode_; |
| 681 const int num_registers_; |
| 682 |
684 ZoneVector<LiveRange*> unhandled_live_ranges_; | 683 ZoneVector<LiveRange*> unhandled_live_ranges_; |
685 ZoneVector<LiveRange*> active_live_ranges_; | 684 ZoneVector<LiveRange*> active_live_ranges_; |
686 ZoneVector<LiveRange*> inactive_live_ranges_; | 685 ZoneVector<LiveRange*> inactive_live_ranges_; |
687 | 686 |
688 #ifdef DEBUG | 687 #ifdef DEBUG |
689 LifetimePosition allocation_finger_; | 688 LifetimePosition allocation_finger_; |
690 #endif | 689 #endif |
691 | 690 |
692 DISALLOW_COPY_AND_ASSIGN(LinearScanAllocator); | 691 DISALLOW_COPY_AND_ASSIGN(LinearScanAllocator); |
693 }; | 692 }; |
694 | 693 |
695 class CoallescedLiveRanges; | |
696 | 694 |
697 | |
698 // A variant of the LLVM Greedy Register Allocator. See | |
699 // http://blog.llvm.org/2011/09/greedy-register-allocation-in-llvm-30.html | |
700 class GreedyAllocator final : public RegisterAllocator { | |
701 public: | |
702 explicit GreedyAllocator(RegisterAllocationData* data, RegisterKind kind, | |
703 Zone* local_zone); | |
704 | |
705 void AllocateRegisters(); | |
706 | |
707 private: | |
708 const RegisterConfiguration* config() const { return data()->config(); } | |
709 | |
710 typedef ZonePriorityQueue<std::pair<unsigned, LiveRange*>> PQueue; | |
711 | |
712 unsigned GetLiveRangeSize(LiveRange* range); | |
713 void Enqueue(LiveRange* range); | |
714 | |
715 void Evict(LiveRange* range); | |
716 float CalculateSpillWeight(LiveRange* range); | |
717 float CalculateMaxSpillWeight(const ZoneSet<LiveRange*>& ranges); | |
718 | |
719 | |
720 bool TryAllocate(LiveRange* current, ZoneSet<LiveRange*>* conflicting); | |
721 bool TryAllocatePhysicalRegister(unsigned reg_id, LiveRange* range, | |
722 ZoneSet<LiveRange*>* conflicting); | |
723 bool HandleSpillOperands(LiveRange* range); | |
724 bool AllocateBlockedRange(LiveRange*, const ZoneSet<LiveRange*>&); | |
725 | |
726 LiveRange* SpillBetweenUntil(LiveRange* range, LifetimePosition start, | |
727 LifetimePosition until, LifetimePosition end); | |
728 void AssignRangeToRegister(int reg_id, LiveRange* range); | |
729 | |
730 ZoneVector<CoallescedLiveRanges*> allocations_; | |
731 PQueue queue_; | |
732 DISALLOW_COPY_AND_ASSIGN(GreedyAllocator); | |
733 }; | |
734 | |
735 | |
736 class OperandAssigner final : public ZoneObject { | 695 class OperandAssigner final : public ZoneObject { |
737 public: | 696 public: |
738 explicit OperandAssigner(RegisterAllocationData* data); | 697 explicit OperandAssigner(RegisterAllocationData* data); |
739 | 698 |
740 // Phase 5: assign spill splots. | 699 // Phase 5: assign spill splots. |
741 void AssignSpillSlots(); | 700 void AssignSpillSlots(); |
742 | 701 |
743 // Phase 6: commit assignment. | 702 // Phase 6: commit assignment. |
744 void CommitAssignment(); | 703 void CommitAssignment(); |
745 | 704 |
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
794 RegisterAllocationData* const data_; | 753 RegisterAllocationData* const data_; |
795 | 754 |
796 DISALLOW_COPY_AND_ASSIGN(LiveRangeConnector); | 755 DISALLOW_COPY_AND_ASSIGN(LiveRangeConnector); |
797 }; | 756 }; |
798 | 757 |
799 } // namespace compiler | 758 } // namespace compiler |
800 } // namespace internal | 759 } // namespace internal |
801 } // namespace v8 | 760 } // namespace v8 |
802 | 761 |
803 #endif // V8_REGISTER_ALLOCATOR_H_ | 762 #endif // V8_REGISTER_ALLOCATOR_H_ |
OLD | NEW |