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) : storage_(zone) {} | |
43 void Schedule(LiveRange* range); | |
44 AllocationCandidate GetNext(); | |
45 bool empty() const { return storage_.empty(); } | |
46 | |
47 private: | |
48 typedef ZonePriorityQueue<AllocationCandidate> ScheduleStorage; | |
Jarin
2015/06/29 05:25:16
ScheduleStorage -> ScheduleQueue
Mircea Trofin
2015/06/29 13:20:16
Done.
| |
49 ScheduleStorage storage_; | |
Jarin
2015/06/29 05:25:16
storage_ -> queue_
Mircea Trofin
2015/06/29 13:20:16
Done.
| |
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 HandleBlockedRange(LiveRange* range); | |
Jarin
2015/06/29 05:25:16
HandleBlockedRange -> SplitOrSpillBlockedRange?
Mircea Trofin
2015/06/29 13:20:16
Done.
| |
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 |