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

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

Powered by Google App Engine
This is Rietveld 408576698