Index: src/compiler/greedy-allocator.h |
diff --git a/src/compiler/greedy-allocator.h b/src/compiler/greedy-allocator.h |
deleted file mode 100644 |
index b61ba4242f3f684b879475670427c65376d985e9..0000000000000000000000000000000000000000 |
--- a/src/compiler/greedy-allocator.h |
+++ /dev/null |
@@ -1,199 +0,0 @@ |
-// Copyright 2015 the V8 project authors. All rights reserved. |
-// Use of this source code is governed by a BSD-style license that can be |
-// found in the LICENSE file. |
- |
-#ifndef V8_GREEDY_ALLOCATOR_H_ |
-#define V8_GREEDY_ALLOCATOR_H_ |
- |
-#include "src/compiler/coalesced-live-ranges.h" |
-#include "src/compiler/register-allocator.h" |
-#include "src/zone-containers.h" |
- |
-namespace v8 { |
-namespace internal { |
-namespace compiler { |
- |
- |
-// The object of allocation scheduling. At minimum, this is a LiveRange, but |
-// we may extend this to groups of LiveRanges. It has to be comparable. |
-class AllocationCandidate { |
- public: |
- explicit AllocationCandidate(LiveRange* range) |
- : is_group_(false), size_(range->GetSize()) { |
- candidate_.range_ = range; |
- } |
- |
- explicit AllocationCandidate(LiveRangeGroup* ranges) |
- : is_group_(true), size_(CalculateGroupSize(ranges)) { |
- candidate_.group_ = ranges; |
- } |
- |
- // Strict ordering operators |
- bool operator<(const AllocationCandidate& other) const { |
- return size() < other.size(); |
- } |
- |
- bool operator>(const AllocationCandidate& other) const { |
- return size() > other.size(); |
- } |
- |
- bool is_group() const { return is_group_; } |
- LiveRange* live_range() const { return candidate_.range_; } |
- LiveRangeGroup* group() const { return candidate_.group_; } |
- |
- private: |
- unsigned CalculateGroupSize(LiveRangeGroup* group) { |
- unsigned ret = 0; |
- for (LiveRange* range : group->ranges()) { |
- ret += range->GetSize(); |
- } |
- return ret; |
- } |
- |
- unsigned size() const { return size_; } |
- bool is_group_; |
- unsigned size_; |
- union { |
- LiveRange* range_; |
- LiveRangeGroup* group_; |
- } candidate_; |
-}; |
- |
- |
-// Schedule processing (allocating) of AllocationCandidates. |
-class AllocationScheduler final : ZoneObject { |
- public: |
- explicit AllocationScheduler(Zone* zone) : queue_(zone) {} |
- void Schedule(LiveRange* range); |
- void Schedule(LiveRangeGroup* group); |
- AllocationCandidate GetNext(); |
- bool empty() const { return queue_.empty(); } |
- |
- private: |
- typedef ZonePriorityQueue<AllocationCandidate> ScheduleQueue; |
- ScheduleQueue queue_; |
- |
- DISALLOW_COPY_AND_ASSIGN(AllocationScheduler); |
-}; |
- |
- |
-// A variant of the LLVM Greedy Register Allocator. See |
-// http://blog.llvm.org/2011/09/greedy-register-allocation-in-llvm-30.html |
-class GreedyAllocator final : public RegisterAllocator { |
- public: |
- explicit GreedyAllocator(RegisterAllocationData* data, RegisterKind kind, |
- Zone* local_zone); |
- |
- void AllocateRegisters(); |
- |
- private: |
- static const float kAllocatedRangeMultiplier; |
- |
- static void UpdateWeightAtAllocation(LiveRange* range) { |
- DCHECK_NE(range->weight(), LiveRange::kInvalidWeight); |
- range->set_weight(range->weight() * kAllocatedRangeMultiplier); |
- } |
- |
- |
- static void UpdateWeightAtEviction(LiveRange* range) { |
- DCHECK_NE(range->weight(), LiveRange::kInvalidWeight); |
- range->set_weight(range->weight() / kAllocatedRangeMultiplier); |
- } |
- |
- AllocationScheduler& scheduler() { return scheduler_; } |
- CoalescedLiveRanges* current_allocations(unsigned i) { |
- return allocations_[i]; |
- } |
- |
- CoalescedLiveRanges* current_allocations(unsigned i) const { |
- return allocations_[i]; |
- } |
- |
- Zone* local_zone() const { return local_zone_; } |
- ZoneVector<LiveRangeGroup*>& groups() { return groups_; } |
- const ZoneVector<LiveRangeGroup*>& groups() const { return groups_; } |
- |
- // Insert fixed ranges. |
- void PreallocateFixedRanges(); |
- |
- void GroupLiveRanges(); |
- |
- // Schedule unassigned live ranges for allocation. |
- void ScheduleAllocationCandidates(); |
- |
- void AllocateRegisterToRange(unsigned reg_id, LiveRange* range) { |
- UpdateWeightAtAllocation(range); |
- current_allocations(reg_id)->AllocateRange(range); |
- } |
- // Evict and reschedule conflicts of a given range, at a given register. |
- void EvictAndRescheduleConflicts(unsigned reg_id, const LiveRange* range); |
- |
- void TryAllocateCandidate(const AllocationCandidate& candidate); |
- void TryAllocateLiveRange(LiveRange* range); |
- void TryAllocateGroup(LiveRangeGroup* group); |
- |
- // Calculate the weight of a candidate for allocation. |
- void EnsureValidRangeWeight(LiveRange* range); |
- |
- // Calculate the new weight of a range that is about to be allocated. |
- float GetAllocatedRangeWeight(float candidate_weight); |
- |
- // Returns kInvalidWeight if there are no conflicts, or the largest weight of |
- // a range conflicting with the given range, at the given register. |
- float GetMaximumConflictingWeight(unsigned reg_id, const LiveRange* range, |
- float competing_weight) const; |
- |
- // Returns kInvalidWeight if there are no conflicts, or the largest weight of |
- // a range conflicting with the given range, at the given register. |
- float GetMaximumConflictingWeight(unsigned reg_id, |
- const LiveRangeGroup* group, |
- float group_weight) const; |
- |
- // This is the extension point for splitting heuristics. |
- void SplitOrSpillBlockedRange(LiveRange* range); |
- |
- // Find a good position where to fill, after a range was spilled after a call. |
- LifetimePosition FindSplitPositionAfterCall(const LiveRange* range, |
- int call_index); |
- // Split a range around all calls it passes over. Returns true if any changes |
- // were made, or false if no calls were found. |
- bool TrySplitAroundCalls(LiveRange* range); |
- |
- // Find a split position at the outmost loop. |
- LifetimePosition FindSplitPositionBeforeLoops(LiveRange* range); |
- |
- // Finds the first call instruction in the path of this range. Splits before |
- // and requeues that segment (if any), spills the section over the call, and |
- // returns the section after the call. The return is: |
- // - same range, if no call was found |
- // - nullptr, if the range finished at the call and there's no "after the |
- // call" portion. |
- // - the portion after the call. |
- LiveRange* GetRemainderAfterSplittingAroundFirstCall(LiveRange* range); |
- |
- // While we attempt to merge spill ranges later on in the allocation pipeline, |
- // we want to ensure group elements get merged. Waiting until later may hinder |
- // merge-ability, since the pipeline merger (being naive) may create conflicts |
- // between spill ranges of group members. |
- void TryReuseSpillRangesForGroups(); |
- |
- LifetimePosition GetLastResortSplitPosition(const LiveRange* range); |
- |
- bool IsProgressPossible(const LiveRange* range); |
- |
- // Necessary heuristic: spill when all else failed. |
- void SpillRangeAsLastResort(LiveRange* range); |
- |
- void AssignRangeToRegister(int reg_id, LiveRange* range); |
- |
- Zone* local_zone_; |
- ZoneVector<CoalescedLiveRanges*> allocations_; |
- AllocationScheduler scheduler_; |
- ZoneVector<LiveRangeGroup*> groups_; |
- |
- DISALLOW_COPY_AND_ASSIGN(GreedyAllocator); |
-}; |
-} // namespace compiler |
-} // namespace internal |
-} // namespace v8 |
-#endif // V8_GREEDY_ALLOCATOR_H_ |