OLD | NEW |
1 // Copyright 2015 the V8 project authors. All rights reserved. | 1 // Copyright 2015 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_GREEDY_ALLOCATOR_H_ | 5 #ifndef V8_GREEDY_ALLOCATOR_H_ |
6 #define V8_GREEDY_ALLOCATOR_H_ | 6 #define V8_GREEDY_ALLOCATOR_H_ |
7 | 7 |
| 8 #include "src/compiler/coalesced-live-ranges.h" |
8 #include "src/compiler/register-allocator.h" | 9 #include "src/compiler/register-allocator.h" |
9 #include "src/zone-containers.h" | 10 #include "src/zone-containers.h" |
10 | 11 |
11 namespace v8 { | 12 namespace v8 { |
12 namespace internal { | 13 namespace internal { |
13 namespace compiler { | 14 namespace compiler { |
14 | 15 |
15 class CoalescedLiveRanges; | 16 |
| 17 // The object of allocation scheduling. At minimum, this is a LiveRange, but |
| 18 // we may extend this to groups of LiveRanges. It has to be comparable. |
| 19 class AllocationCandidate { |
| 20 public: |
| 21 explicit AllocationCandidate(LiveRange* range) : range_(range) {} |
| 22 |
| 23 // Strict ordering operators |
| 24 bool operator<(const AllocationCandidate& other) const { |
| 25 return range_->GetSize() < other.range_->GetSize(); |
| 26 } |
| 27 |
| 28 bool operator>(const AllocationCandidate& other) const { |
| 29 return range_->GetSize() > other.range_->GetSize(); |
| 30 } |
| 31 |
| 32 LiveRange* live_range() const { return range_; } |
| 33 |
| 34 private: |
| 35 LiveRange* range_; |
| 36 }; |
| 37 |
| 38 |
| 39 // Schedule processing (allocating) of AllocationCandidates. |
| 40 class AllocationScheduler final : ZoneObject { |
| 41 public: |
| 42 explicit AllocationScheduler(Zone* zone) : queue_(zone) {} |
| 43 void Schedule(LiveRange* range); |
| 44 AllocationCandidate GetNext(); |
| 45 bool empty() const { return queue_.empty(); } |
| 46 |
| 47 private: |
| 48 typedef ZonePriorityQueue<AllocationCandidate> ScheduleQueue; |
| 49 ScheduleQueue queue_; |
| 50 |
| 51 DISALLOW_COPY_AND_ASSIGN(AllocationScheduler); |
| 52 }; |
16 | 53 |
17 | 54 |
18 // A variant of the LLVM Greedy Register Allocator. See | 55 // A variant of the LLVM Greedy Register Allocator. See |
19 // http://blog.llvm.org/2011/09/greedy-register-allocation-in-llvm-30.html | 56 // http://blog.llvm.org/2011/09/greedy-register-allocation-in-llvm-30.html |
20 class GreedyAllocator final : public RegisterAllocator { | 57 class GreedyAllocator final : public RegisterAllocator { |
21 public: | 58 public: |
22 explicit GreedyAllocator(RegisterAllocationData* data, RegisterKind kind, | 59 explicit GreedyAllocator(RegisterAllocationData* data, RegisterKind kind, |
23 Zone* local_zone); | 60 Zone* local_zone); |
24 | 61 |
25 void AllocateRegisters(); | 62 void AllocateRegisters(); |
26 | 63 |
27 private: | 64 private: |
28 LifetimePosition GetSplittablePos(LifetimePosition pos); | 65 AllocationScheduler& scheduler() { return scheduler_; } |
29 const RegisterConfiguration* config() const { return data()->config(); } | 66 CoalescedLiveRanges* current_allocations(unsigned i) { |
| 67 return allocations_[i]; |
| 68 } |
30 Zone* local_zone() const { return local_zone_; } | 69 Zone* local_zone() const { return local_zone_; } |
31 | 70 |
32 int GetHintedRegister(LiveRange* range); | 71 // Insert fixed ranges. |
| 72 void PreallocateFixedRanges(); |
33 | 73 |
34 typedef ZonePriorityQueue<std::pair<unsigned, LiveRange*>> PQueue; | 74 // Schedule unassigned live ranges for allocation. |
| 75 // TODO(mtrofin): groups. |
| 76 void ScheduleAllocationCandidates(); |
35 | 77 |
36 unsigned GetLiveRangeSize(LiveRange* range); | 78 // Find the optimal split for ranges defined by a memory operand, e.g. |
37 void Enqueue(LiveRange* range); | 79 // constants or function parameters passed on the stack. |
| 80 void SplitAndSpillRangesDefinedByMemoryOperand(); |
38 | 81 |
39 void Evict(LiveRange* range); | 82 void TryAllocateCandidate(const AllocationCandidate& candidate); |
40 float CalculateSpillWeight(LiveRange* range); | 83 void TryAllocateLiveRange(LiveRange* range); |
41 float CalculateMaxSpillWeight(const ZoneSet<LiveRange*>& ranges); | |
42 | 84 |
| 85 bool CanProcessRange(LiveRange* range) const { |
| 86 return range != nullptr && !range->IsEmpty() && range->kind() == mode(); |
| 87 } |
43 | 88 |
44 bool TryAllocate(LiveRange* current, ZoneSet<LiveRange*>* conflicting); | 89 // Calculate the weight of a candidate for allocation. |
45 bool TryAllocatePhysicalRegister(unsigned reg_id, LiveRange* range, | 90 void EnsureValidRangeWeight(LiveRange* range); |
46 ZoneSet<LiveRange*>* conflicting); | |
47 bool HandleSpillOperands(LiveRange* range); | |
48 void AllocateBlockedRange(LiveRange* current, LifetimePosition pos, | |
49 bool spill); | |
50 | 91 |
51 LiveRange* SpillBetweenUntil(LiveRange* range, LifetimePosition start, | 92 // Calculate the new weight of a range that is about to be allocated. |
52 LifetimePosition until, LifetimePosition end); | 93 float GetAllocatedRangeWeight(float candidate_weight); |
| 94 |
| 95 // This is the extension point for splitting heuristics. |
| 96 void SplitOrSpillBlockedRange(LiveRange* range); |
| 97 |
| 98 // Necessary heuristic: spill when all else failed. |
| 99 void SpillRangeAsLastResort(LiveRange* range); |
| 100 |
53 void AssignRangeToRegister(int reg_id, LiveRange* range); | 101 void AssignRangeToRegister(int reg_id, LiveRange* range); |
54 | 102 |
55 LifetimePosition FindProgressingSplitPosition(LiveRange* range, | |
56 bool* is_spill_pos); | |
57 | |
58 Zone* local_zone_; | 103 Zone* local_zone_; |
59 ZoneVector<CoalescedLiveRanges*> allocations_; | 104 ZoneVector<CoalescedLiveRanges*> allocations_; |
60 PQueue queue_; | 105 AllocationScheduler scheduler_; |
61 DISALLOW_COPY_AND_ASSIGN(GreedyAllocator); | 106 DISALLOW_COPY_AND_ASSIGN(GreedyAllocator); |
62 }; | 107 }; |
63 } // namespace compiler | 108 } // namespace compiler |
64 } // namespace internal | 109 } // namespace internal |
65 } // namespace v8 | 110 } // namespace v8 |
66 #endif // V8_GREEDY_ALLOCATOR_H_ | 111 #endif // V8_GREEDY_ALLOCATOR_H_ |
OLD | NEW |