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

Side by Side Diff: src/compiler/greedy-allocator.cc

Issue 1219063017: [turbofan] Unit tests for live range conflicts. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Incorporated feedback. Created 5 years, 5 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
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 #include "src/compiler/greedy-allocator.h" 5 #include "src/compiler/greedy-allocator.h"
6 #include "src/compiler/register-allocator.h" 6 #include "src/compiler/register-allocator.h"
7 7
8 namespace v8 { 8 namespace v8 {
9 namespace internal { 9 namespace internal {
10 namespace compiler { 10 namespace compiler {
11 11
12 #define TRACE(...) \ 12 #define TRACE(...) \
13 do { \ 13 do { \
14 if (FLAG_trace_alloc) PrintF(__VA_ARGS__); \ 14 if (FLAG_trace_alloc) PrintF(__VA_ARGS__); \
15 } while (false) 15 } while (false)
16 16
17 17
18 const float GreedyAllocator::kAllocatedRangeMultiplier = 10.0;
19
20
18 namespace { 21 namespace {
19 22
20 23
21 void UpdateOperands(LiveRange* range, RegisterAllocationData* data) { 24 void UpdateOperands(LiveRange* range, RegisterAllocationData* data) {
22 int reg_id = range->assigned_register(); 25 int reg_id = range->assigned_register();
23 range->SetUseHints(reg_id); 26 range->SetUseHints(reg_id);
24 if (range->is_phi()) { 27 if (range->is_phi()) {
25 data->GetPhiMapValueFor(range->id())->set_assigned_register(reg_id); 28 data->GetPhiMapValueFor(range->id())->set_assigned_register(reg_id);
26 } 29 }
27 } 30 }
(...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after
124 allocations_(local_zone), 127 allocations_(local_zone),
125 scheduler_(local_zone) {} 128 scheduler_(local_zone) {}
126 129
127 130
128 void GreedyAllocator::AssignRangeToRegister(int reg_id, LiveRange* range) { 131 void GreedyAllocator::AssignRangeToRegister(int reg_id, LiveRange* range) {
129 TRACE("Assigning register %s to live range %d\n", RegisterName(reg_id), 132 TRACE("Assigning register %s to live range %d\n", RegisterName(reg_id),
130 range->id()); 133 range->id());
131 134
132 DCHECK(!range->HasRegisterAssigned()); 135 DCHECK(!range->HasRegisterAssigned());
133 136
134 current_allocations(reg_id)->AllocateRange(range); 137 AllocateRegisterToRange(reg_id, range);
135 138
136 TRACE("Assigning %s to range %d\n", RegisterName(reg_id), range->id()); 139 TRACE("Assigning %s to range %d\n", RegisterName(reg_id), range->id());
137 range->set_assigned_register(reg_id); 140 range->set_assigned_register(reg_id);
138
139 DCHECK(current_allocations(reg_id)->VerifyAllocationsAreValid());
140 } 141 }
141 142
142 143
143 void GreedyAllocator::PreallocateFixedRanges() { 144 void GreedyAllocator::PreallocateFixedRanges() {
144 allocations_.resize(num_registers()); 145 allocations_.resize(num_registers());
145 for (int i = 0; i < num_registers(); i++) { 146 for (int i = 0; i < num_registers(); i++) {
146 allocations_[i] = new (local_zone()) CoalescedLiveRanges(local_zone()); 147 allocations_[i] = new (local_zone()) CoalescedLiveRanges(local_zone());
147 } 148 }
148 149
149 for (LiveRange* fixed_range : GetFixedRegisters()) { 150 for (LiveRange* fixed_range : GetFixedRegisters()) {
150 if (fixed_range != nullptr) { 151 if (fixed_range != nullptr) {
151 DCHECK_EQ(mode(), fixed_range->kind()); 152 DCHECK_EQ(mode(), fixed_range->kind());
152 DCHECK(fixed_range->IsFixed()); 153 DCHECK(fixed_range->IsFixed());
153 154
154 int reg_nr = fixed_range->assigned_register(); 155 int reg_nr = fixed_range->assigned_register();
155 EnsureValidRangeWeight(fixed_range); 156 EnsureValidRangeWeight(fixed_range);
156 current_allocations(reg_nr)->AllocateRange(fixed_range); 157 AllocateRegisterToRange(reg_nr, fixed_range);
157 } 158 }
158 } 159 }
159 } 160 }
160 161
161 162
162 void GreedyAllocator::ScheduleAllocationCandidates() { 163 void GreedyAllocator::ScheduleAllocationCandidates() {
163 for (auto range : data()->live_ranges()) { 164 for (auto range : data()->live_ranges()) {
164 if (CanProcessRange(range) && !range->spilled()) { 165 if (CanProcessRange(range) && !range->spilled()) {
165 scheduler().Schedule(range); 166 scheduler().Schedule(range);
166 } 167 }
(...skipping 16 matching lines...) Expand all
183 int evictable_reg = -1; 184 int evictable_reg = -1;
184 EnsureValidRangeWeight(range); 185 EnsureValidRangeWeight(range);
185 DCHECK(range->weight() != LiveRange::kInvalidWeight); 186 DCHECK(range->weight() != LiveRange::kInvalidWeight);
186 187
187 float smallest_weight = LiveRange::kMaxWeight; 188 float smallest_weight = LiveRange::kMaxWeight;
188 189
189 // Seek either the first free register, or, from the set of registers 190 // Seek either the first free register, or, from the set of registers
190 // where the maximum conflict is lower than the candidate's weight, the one 191 // where the maximum conflict is lower than the candidate's weight, the one
191 // with the smallest such weight. 192 // with the smallest such weight.
192 for (int i = 0; i < num_registers(); i++) { 193 for (int i = 0; i < num_registers(); i++) {
193 float max_conflict_weight = 194 float max_conflict_weight = GetMaximumConflictingWeight(i, range);
194 current_allocations(i)->GetMaximumConflictingWeight(range);
195 if (max_conflict_weight == LiveRange::kInvalidWeight) { 195 if (max_conflict_weight == LiveRange::kInvalidWeight) {
196 free_reg = i; 196 free_reg = i;
197 break; 197 break;
198 } 198 }
199 if (max_conflict_weight < range->weight() && 199 if (max_conflict_weight < range->weight() &&
200 max_conflict_weight < smallest_weight) { 200 max_conflict_weight < smallest_weight) {
201 smallest_weight = max_conflict_weight; 201 smallest_weight = max_conflict_weight;
202 evictable_reg = i; 202 evictable_reg = i;
203 } 203 }
204 } 204 }
205 205
206 // We have a free register, so we use it. 206 // We have a free register, so we use it.
207 if (free_reg >= 0) { 207 if (free_reg >= 0) {
208 TRACE("Found free register %s for live range %d\n", RegisterName(free_reg), 208 TRACE("Found free register %s for live range %d\n", RegisterName(free_reg),
209 range->id()); 209 range->id());
210 AssignRangeToRegister(free_reg, range); 210 AssignRangeToRegister(free_reg, range);
211 return; 211 return;
212 } 212 }
213 213
214 // We found a register to perform evictions, so we evict and allocate our 214 // We found a register to perform evictions, so we evict and allocate our
215 // candidate. 215 // candidate.
216 if (evictable_reg >= 0) { 216 if (evictable_reg >= 0) {
217 TRACE("Found evictable register %s for live range %d\n", 217 TRACE("Found evictable register %s for live range %d\n",
218 RegisterName(free_reg), range->id()); 218 RegisterName(free_reg), range->id());
219 current_allocations(evictable_reg) 219 EvictAndRescheduleConflicts(evictable_reg, range);
220 ->EvictAndRescheduleConflicts(range, &scheduler());
221 AssignRangeToRegister(evictable_reg, range); 220 AssignRangeToRegister(evictable_reg, range);
222 return; 221 return;
223 } 222 }
224 223
225 // The range needs to be split or spilled. 224 // The range needs to be split or spilled.
226 SplitOrSpillBlockedRange(range); 225 SplitOrSpillBlockedRange(range);
227 } 226 }
228 227
229 228
229 void GreedyAllocator::EvictAndRescheduleConflicts(unsigned reg_id,
230 const LiveRange* range) {
231 current_allocations(reg_id)->RemoveConflicts(range, [this](LiveRange* range) {
232 DCHECK(range->HasRegisterAssigned());
233 CHECK(!range->IsFixed());
234 range->UnsetAssignedRegister();
235 UpdateWeightAtEviction(range);
236 scheduler().Schedule(range);
237 TRACE("Evicted range %d.\n", range->id());
238 });
239 }
240
241
230 void GreedyAllocator::SplitAndSpillRangesDefinedByMemoryOperand() { 242 void GreedyAllocator::SplitAndSpillRangesDefinedByMemoryOperand() {
231 size_t initial_range_count = data()->live_ranges().size(); 243 size_t initial_range_count = data()->live_ranges().size();
232 for (size_t i = 0; i < initial_range_count; ++i) { 244 for (size_t i = 0; i < initial_range_count; ++i) {
233 auto range = data()->live_ranges()[i]; 245 auto range = data()->live_ranges()[i];
234 if (!CanProcessRange(range)) continue; 246 if (!CanProcessRange(range)) continue;
235 if (range->HasNoSpillType()) continue; 247 if (range->HasNoSpillType()) continue;
236 248
237 LifetimePosition start = range->Start(); 249 LifetimePosition start = range->Start();
238 TRACE("Live range %d is defined by a spill operand.\n", range->id()); 250 TRACE("Live range %d is defined by a spill operand.\n", range->id());
239 auto next_pos = start; 251 auto next_pos = start;
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after
291 data()->MarkAllocated(mode(), static_cast<int>(i)); 303 data()->MarkAllocated(mode(), static_cast<int>(i));
292 } 304 }
293 } 305 }
294 allocations_.clear(); 306 allocations_.clear();
295 307
296 TRACE("End allocating function %s with the Greedy Allocator\n", 308 TRACE("End allocating function %s with the Greedy Allocator\n",
297 data()->debug_name()); 309 data()->debug_name());
298 } 310 }
299 311
300 312
313 float GreedyAllocator::GetMaximumConflictingWeight(
314 unsigned reg_id, const LiveRange* range) const {
315 float ret = LiveRange::kInvalidWeight;
316
317 current_allocations(reg_id)
318 ->VisitConflicts(range, [&ret](const LiveRange* conflict) {
319 DCHECK_NE(conflict->weight(), LiveRange::kInvalidWeight);
320 ret = Max(ret, conflict->weight());
321 return (ret != LiveRange::kMaxWeight);
322 });
323
324 return ret;
325 }
326
327
301 void GreedyAllocator::EnsureValidRangeWeight(LiveRange* range) { 328 void GreedyAllocator::EnsureValidRangeWeight(LiveRange* range) {
302 // The live range weight will be invalidated when ranges are created or split. 329 // The live range weight will be invalidated when ranges are created or split.
303 // Otherwise, it is consistently updated when the range is allocated or 330 // Otherwise, it is consistently updated when the range is allocated or
304 // unallocated. 331 // unallocated.
305 if (range->weight() != LiveRange::kInvalidWeight) return; 332 if (range->weight() != LiveRange::kInvalidWeight) return;
306 333
307 if (range->IsFixed()) { 334 if (range->IsFixed()) {
308 range->set_weight(LiveRange::kMaxWeight); 335 range->set_weight(LiveRange::kMaxWeight);
309 return; 336 return;
310 } 337 }
(...skipping 30 matching lines...) Expand all
341 scheduler().Schedule(range); 368 scheduler().Schedule(range);
342 return; 369 return;
343 } 370 }
344 SpillRangeAsLastResort(range); 371 SpillRangeAsLastResort(range);
345 } 372 }
346 373
347 374
348 } // namespace compiler 375 } // namespace compiler
349 } // namespace internal 376 } // namespace internal
350 } // namespace v8 377 } // namespace v8
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698