Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(222)

Side by Side Diff: src/compiler/coalesced-live-ranges.cc

Issue 1205173002: [turbofan] Greedy allocator refactoring. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Created 5 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
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
3 // found in the LICENSE file.
4
5 #include "src/compiler/coalesced-live-ranges.h"
6 #include "src/compiler/greedy-allocator.h"
7 #include "src/compiler/register-allocator.h"
8
9 namespace v8 {
10 namespace internal {
11 namespace compiler {
12
13
14 const float CoalescedLiveRanges::kMaxWeight = std::numeric_limits<float>::max();
15 const float CoalescedLiveRanges::kAllocatedRangeMultiplier = 10.0;
16 const float CoalescedLiveRanges::kInvalidWeight = -1.0;
17
18 void CoalescedLiveRanges::AllocateRange(LiveRange* range, float weight) {
19 AllocatedRange to_insert(range, GetAllocatedRangeWeight(weight));
20 for (auto interval = range->first_interval(); interval != nullptr;
21 interval = interval->next()) {
22 storage().insert({interval->start(), interval->end(), to_insert});
23 }
24 }
25
26
27 void CoalescedLiveRanges::AllocateFixedRange(LiveRange* range) {
28 AllocateRange(range, kMaxWeight);
29 }
30
31
32 void CoalescedLiveRanges::Remove(LiveRange* range) {
33 for (auto interval = range->first_interval(); interval != nullptr;
34 interval = interval->next()) {
35 storage().erase(
36 {interval->start(), interval->end(), AllocatedRange::Invalid()});
37 }
38 range->UnsetAssignedRegister();
39 }
40
41
42 float CoalescedLiveRanges::GetMaximumConflictingWeight(
43 const LiveRange* range) const {
44 float ret = kInvalidWeight;
45 auto end = storage().end();
46 for (auto query = range->first_interval(); query != nullptr;
47 query = query->next()) {
48 auto conflict = GetFirstConflict(query);
49
50 if (conflict == end) continue;
51 for (; QueryIntersectsAllocatedInterval(query, conflict); ++conflict) {
52 // It is possible we'll visit the same range multiple times, because
53 // successive (not necessarily consecutive) intervals belong to the same
54 // range, or because different intervals of the query range have the same
55 // range as conflict.
56 ret = Max(ret, conflict->range.weight());
57 if (ret == kMaxWeight) break;
58 }
59 }
60 return ret;
61 }
62
63
64 void CoalescedLiveRanges::EvictAndRescheduleConflicts(
65 LiveRange* range, AllocationScheduler* scheduler) {
66 auto end = storage().end();
67
68 for (auto query = range->first_interval(); query != nullptr;
69 query = query->next()) {
70 auto conflict = GetFirstConflict(query);
71 if (conflict == end) continue;
72 for (; QueryIntersectsAllocatedInterval(query, conflict);) {
73 LiveRange* conflict_range = conflict->range.live_range();
74 // Bypass successive intervals belonging to the same range, because we're
75 // about to remove this range, and we don't want the storage iterator to
76 // become invalid.
77 while (conflict != end &&
78 conflict->range.live_range() == conflict_range) {
79 ++conflict;
80 }
81
82 DCHECK(conflict_range->HasRegisterAssigned());
83 CHECK(!conflict_range->IsFixed());
84 Remove(conflict_range);
85 scheduler->Schedule(conflict_range);
86 }
87 }
88 }
89
90
91 bool CoalescedLiveRanges::VerifyAllocationsAreValid() const {
92 LifetimePosition last_end = LifetimePosition::GapFromInstructionIndex(0);
93 for (auto i : storage_) {
94 if (i.start < last_end) {
95 return false;
96 }
97 last_end = i.end;
98 }
99 return true;
100 }
101
102
103 float CoalescedLiveRanges::GetAllocatedRangeWeight(float weight) {
104 return weight * kAllocatedRangeMultiplier;
105 }
106
107 CoalescedLiveRanges::interval_iterator CoalescedLiveRanges::GetFirstConflict(
108 const UseInterval* query) const {
109 DCHECK(query != nullptr);
110 auto end = storage().end();
111 LifetimePosition q_start = query->start();
112 LifetimePosition q_end = query->end();
113
114 if (storage().empty() || storage().rbegin()->end <= q_start ||
115 storage().begin()->start >= q_end) {
116 return end;
117 }
118
119 auto ret = storage().upper_bound(AsAllocatedInterval(q_start));
120 // ret is either at the end (no start strictly greater than q_start) or
121 // at some position with the aforementioned property. In either case, the
122 // allocated interval before this one may intersect our query:
123 // either because, although it starts before this query's start, it ends
124 // after; or because it starts exactly at the query start. So unless we're
125 // right at the beginning of the storage - meaning the first allocated
126 // interval is also starting after this query's start - see what's behind.
127 if (ret != storage().begin()) {
128 --ret;
129 if (!QueryIntersectsAllocatedInterval(query, ret)) {
130 // The interval behind wasn't intersecting, so move back.
131 ++ret;
132 }
133 }
134 if (ret != end && QueryIntersectsAllocatedInterval(query, ret)) return ret;
135 return end;
136 }
137
138
139 } // namespace compiler
140 } // namespace internal
141 } // namespace v8
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698