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

Side by Side Diff: src/compiler/register-allocator.h

Issue 725083004: [turbofan] More aggressive reuse of spill slots in the register allocator. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Created 6 years, 1 month 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/pipeline.cc ('k') | src/compiler/register-allocator.cc » ('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 2014 the V8 project authors. All rights reserved. 1 // Copyright 2014 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_REGISTER_ALLOCATOR_H_ 5 #ifndef V8_REGISTER_ALLOCATOR_H_
6 #define V8_REGISTER_ALLOCATOR_H_ 6 #define V8_REGISTER_ALLOCATOR_H_
7 7
8 #include "src/compiler/instruction.h" 8 #include "src/compiler/instruction.h"
9 #include "src/zone-containers.h" 9 #include "src/zone-containers.h"
10 10
(...skipping 153 matching lines...) Expand 10 before | Expand all | Expand 10 after
164 InstructionOperand* const hint_; 164 InstructionOperand* const hint_;
165 LifetimePosition const pos_; 165 LifetimePosition const pos_;
166 UsePosition* next_; 166 UsePosition* next_;
167 bool requires_reg_ : 1; 167 bool requires_reg_ : 1;
168 bool register_beneficial_ : 1; 168 bool register_beneficial_ : 1;
169 169
170 private: 170 private:
171 DISALLOW_COPY_AND_ASSIGN(UsePosition); 171 DISALLOW_COPY_AND_ASSIGN(UsePosition);
172 }; 172 };
173 173
174 class SpillRange;
174 175
175 // Representation of SSA values' live ranges as a collection of (continuous) 176 // Representation of SSA values' live ranges as a collection of (continuous)
176 // intervals over the instruction ordering. 177 // intervals over the instruction ordering.
177 class LiveRange FINAL : public ZoneObject { 178 class LiveRange FINAL : public ZoneObject {
178 public: 179 public:
179 static const int kInvalidAssignment = 0x7fffffff; 180 static const int kInvalidAssignment = 0x7fffffff;
180 181
181 LiveRange(int id, Zone* zone); 182 LiveRange(int id, Zone* zone);
182 183
183 UseInterval* first_interval() const { return first_interval_; } 184 UseInterval* first_interval() const { return first_interval_; }
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after
250 251
251 LifetimePosition End() const { 252 LifetimePosition End() const {
252 DCHECK(!IsEmpty()); 253 DCHECK(!IsEmpty());
253 return last_interval_->end(); 254 return last_interval_->end();
254 } 255 }
255 256
256 bool HasAllocatedSpillOperand() const; 257 bool HasAllocatedSpillOperand() const;
257 InstructionOperand* GetSpillOperand() const { return spill_operand_; } 258 InstructionOperand* GetSpillOperand() const { return spill_operand_; }
258 void SetSpillOperand(InstructionOperand* operand); 259 void SetSpillOperand(InstructionOperand* operand);
259 260
261 void SetSpillRange(SpillRange* spill_range) { spill_range_ = spill_range; }
262 SpillRange* GetSpillRange() const { return spill_range_; }
263 void CommitSpillOperand(InstructionOperand* operand);
264
260 void SetSpillStartIndex(int start) { 265 void SetSpillStartIndex(int start) {
261 spill_start_index_ = Min(start, spill_start_index_); 266 spill_start_index_ = Min(start, spill_start_index_);
262 } 267 }
263 268
264 bool ShouldBeAllocatedBefore(const LiveRange* other) const; 269 bool ShouldBeAllocatedBefore(const LiveRange* other) const;
265 bool CanCover(LifetimePosition position) const; 270 bool CanCover(LifetimePosition position) const;
266 bool Covers(LifetimePosition position); 271 bool Covers(LifetimePosition position);
267 LifetimePosition FirstIntersection(LiveRange* other); 272 LifetimePosition FirstIntersection(LiveRange* other);
268 273
269 // Add a new interval or a new use position to this live range. 274 // Add a new interval or a new use position to this live range.
270 void EnsureInterval(LifetimePosition start, LifetimePosition end, Zone* zone); 275 void EnsureInterval(LifetimePosition start, LifetimePosition end, Zone* zone);
271 void AddUseInterval(LifetimePosition start, LifetimePosition end, Zone* zone); 276 void AddUseInterval(LifetimePosition start, LifetimePosition end, Zone* zone);
272 void AddUsePosition(LifetimePosition pos, InstructionOperand* operand, 277 void AddUsePosition(LifetimePosition pos, InstructionOperand* operand,
273 InstructionOperand* hint, Zone* zone); 278 InstructionOperand* hint, Zone* zone);
274 279
275 // Shorten the most recently added interval by setting a new start. 280 // Shorten the most recently added interval by setting a new start.
276 void ShortenTo(LifetimePosition start); 281 void ShortenTo(LifetimePosition start);
277 282
278 #ifdef DEBUG 283 #ifdef DEBUG
279 // True if target overlaps an existing interval. 284 // True if target overlaps an existing interval.
280 bool HasOverlap(UseInterval* target) const; 285 bool HasOverlap(UseInterval* target) const;
281 void Verify() const; 286 void Verify() const;
282 #endif 287 #endif
283 288
284 private: 289 private:
285 void ConvertOperands(Zone* zone); 290 void ConvertOperands(Zone* zone);
291 void ConvertUsesToOperand(InstructionOperand* op);
286 UseInterval* FirstSearchIntervalForPosition(LifetimePosition position) const; 292 UseInterval* FirstSearchIntervalForPosition(LifetimePosition position) const;
287 void AdvanceLastProcessedMarker(UseInterval* to_start_of, 293 void AdvanceLastProcessedMarker(UseInterval* to_start_of,
288 LifetimePosition but_not_past) const; 294 LifetimePosition but_not_past) const;
289 295
290 int id_; 296 int id_;
291 bool spilled_; 297 bool spilled_;
292 RegisterKind kind_; 298 RegisterKind kind_;
293 int assigned_register_; 299 int assigned_register_;
294 UseInterval* last_interval_; 300 UseInterval* last_interval_;
295 UseInterval* first_interval_; 301 UseInterval* first_interval_;
296 UsePosition* first_pos_; 302 UsePosition* first_pos_;
297 LiveRange* parent_; 303 LiveRange* parent_;
298 LiveRange* next_; 304 LiveRange* next_;
299 // This is used as a cache, it doesn't affect correctness. 305 // This is used as a cache, it doesn't affect correctness.
300 mutable UseInterval* current_interval_; 306 mutable UseInterval* current_interval_;
301 UsePosition* last_processed_use_; 307 UsePosition* last_processed_use_;
302 // This is used as a cache, it's invalid outside of BuildLiveRanges. 308 // This is used as a cache, it's invalid outside of BuildLiveRanges.
303 InstructionOperand* current_hint_operand_; 309 InstructionOperand* current_hint_operand_;
304 InstructionOperand* spill_operand_; 310 InstructionOperand* spill_operand_;
305 int spill_start_index_; 311 int spill_start_index_;
312 SpillRange* spill_range_;
306 313
307 friend class RegisterAllocator; // Assigns to kind_. 314 friend class RegisterAllocator; // Assigns to kind_.
308 315
309 DISALLOW_COPY_AND_ASSIGN(LiveRange); 316 DISALLOW_COPY_AND_ASSIGN(LiveRange);
310 }; 317 };
311 318
312 319
320 class SpillRange : public ZoneObject {
321 public:
322 SpillRange(LiveRange* range, int id, Zone* zone);
323 bool TryMerge(SpillRange* other, Zone* zone);
324 void SetOperand(InstructionOperand* op);
325 bool IsEmpty() { return live_ranges_.length() == 0; }
326 int id() const { return id_; }
327 UseInterval* interval() { return use_interval_; }
328 RegisterKind Kind() const { return live_ranges_.at(0)->Kind(); }
329 LifetimePosition End() const { return end_position_; }
330 bool IsIntersectingWith(SpillRange* other);
331
332 private:
333 int id_;
334 ZoneList<LiveRange*> live_ranges_;
335 UseInterval* use_interval_;
336 LifetimePosition end_position_;
337
338 // Merge intervals, making sure the use intervals are sorted
339 void MergeDisjointIntervals(UseInterval* other, Zone* zone);
340 };
341
342
313 class RegisterAllocator FINAL : public ZoneObject { 343 class RegisterAllocator FINAL : public ZoneObject {
314 public: 344 public:
315 explicit RegisterAllocator(const RegisterConfiguration* config, 345 explicit RegisterAllocator(const RegisterConfiguration* config,
316 Zone* local_zone, Frame* frame, 346 Zone* local_zone, Frame* frame,
317 InstructionSequence* code, 347 InstructionSequence* code,
318 const char* debug_name = nullptr); 348 const char* debug_name = nullptr);
319 349
320 bool AllocationOk() { return allocation_ok_; } 350 bool AllocationOk() { return allocation_ok_; }
321 351
322 const ZoneList<LiveRange*>& live_ranges() const { return live_ranges_; } 352 const ZoneList<LiveRange*>& live_ranges() const { return live_ranges_; }
(...skipping 11 matching lines...) Expand all
334 void MeetRegisterConstraints(); 364 void MeetRegisterConstraints();
335 365
336 // Phase 2: compute liveness of all virtual register. 366 // Phase 2: compute liveness of all virtual register.
337 void BuildLiveRanges(); 367 void BuildLiveRanges();
338 bool ExistsUseWithoutDefinition(); 368 bool ExistsUseWithoutDefinition();
339 369
340 // Phase 3: compute register assignments. 370 // Phase 3: compute register assignments.
341 void AllocateGeneralRegisters(); 371 void AllocateGeneralRegisters();
342 void AllocateDoubleRegisters(); 372 void AllocateDoubleRegisters();
343 373
344 // Phase 4: compute values for pointer maps. 374 // Phase 4: reassign spill splots for maximal reuse.
375 void ReuseSpillSlots();
376
377 // Phase 5: compute values for pointer maps.
345 void PopulatePointerMaps(); // TODO(titzer): rename to PopulateReferenceMaps. 378 void PopulatePointerMaps(); // TODO(titzer): rename to PopulateReferenceMaps.
346 379
347 // Phase 5: reconnect split ranges with moves. 380 // Phase 6: reconnect split ranges with moves.
348 void ConnectRanges(); 381 void ConnectRanges();
349 382
350 // Phase 6: insert moves to connect ranges across basic blocks. 383 // Phase 7: insert moves to connect ranges across basic blocks.
351 void ResolveControlFlow(); 384 void ResolveControlFlow();
352 385
353 private: 386 private:
354 int GetVirtualRegister() { 387 int GetVirtualRegister() {
355 int vreg = code()->NextVirtualRegister(); 388 int vreg = code()->NextVirtualRegister();
356 if (vreg >= UnallocatedOperand::kMaxVirtualRegisters) { 389 if (vreg >= UnallocatedOperand::kMaxVirtualRegisters) {
357 allocation_ok_ = false; 390 allocation_ok_ = false;
358 // Maintain the invariant that we return something below the maximum. 391 // Maintain the invariant that we return something below the maximum.
359 return 0; 392 return 0;
360 } 393 }
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after
412 void AddToActive(LiveRange* range); 445 void AddToActive(LiveRange* range);
413 void AddToInactive(LiveRange* range); 446 void AddToInactive(LiveRange* range);
414 void AddToUnhandledSorted(LiveRange* range); 447 void AddToUnhandledSorted(LiveRange* range);
415 void AddToUnhandledUnsorted(LiveRange* range); 448 void AddToUnhandledUnsorted(LiveRange* range);
416 void SortUnhandled(); 449 void SortUnhandled();
417 bool UnhandledIsSorted(); 450 bool UnhandledIsSorted();
418 void ActiveToHandled(LiveRange* range); 451 void ActiveToHandled(LiveRange* range);
419 void ActiveToInactive(LiveRange* range); 452 void ActiveToInactive(LiveRange* range);
420 void InactiveToHandled(LiveRange* range); 453 void InactiveToHandled(LiveRange* range);
421 void InactiveToActive(LiveRange* range); 454 void InactiveToActive(LiveRange* range);
422 void FreeSpillSlot(LiveRange* range);
423 InstructionOperand* TryReuseSpillSlot(LiveRange* range);
424 455
425 // Helper methods for allocating registers. 456 // Helper methods for allocating registers.
426 bool TryAllocateFreeReg(LiveRange* range); 457 bool TryAllocateFreeReg(LiveRange* range);
427 void AllocateBlockedReg(LiveRange* range); 458 void AllocateBlockedReg(LiveRange* range);
459 SpillRange* AssignSpillRangeToLiveRange(LiveRange* range);
428 460
429 // Live range splitting helpers. 461 // Live range splitting helpers.
430 462
431 // Split the given range at the given position. 463 // Split the given range at the given position.
432 // If range starts at or after the given position then the 464 // If range starts at or after the given position then the
433 // original range is returned. 465 // original range is returned.
434 // Otherwise returns the live range that starts at pos and contains 466 // Otherwise returns the live range that starts at pos and contains
435 // all uses from the original range that follow pos. Uses at pos will 467 // all uses from the original range that follow pos. Uses at pos will
436 // still be owned by the original range after splitting. 468 // still be owned by the original range after splitting.
437 LiveRange* SplitRangeAt(LiveRange* range, LifetimePosition pos); 469 LiveRange* SplitRangeAt(LiveRange* range, LifetimePosition pos);
(...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after
514 // Liveness analysis results. 546 // Liveness analysis results.
515 ZoneList<LiveRange*> live_ranges_; 547 ZoneList<LiveRange*> live_ranges_;
516 548
517 // Lists of live ranges 549 // Lists of live ranges
518 ZoneVector<LiveRange*> fixed_live_ranges_; 550 ZoneVector<LiveRange*> fixed_live_ranges_;
519 ZoneVector<LiveRange*> fixed_double_live_ranges_; 551 ZoneVector<LiveRange*> fixed_double_live_ranges_;
520 ZoneList<LiveRange*> unhandled_live_ranges_; 552 ZoneList<LiveRange*> unhandled_live_ranges_;
521 ZoneList<LiveRange*> active_live_ranges_; 553 ZoneList<LiveRange*> active_live_ranges_;
522 ZoneList<LiveRange*> inactive_live_ranges_; 554 ZoneList<LiveRange*> inactive_live_ranges_;
523 ZoneList<LiveRange*> reusable_slots_; 555 ZoneList<LiveRange*> reusable_slots_;
556 ZoneList<SpillRange*> spill_ranges_;
524 557
525 RegisterKind mode_; 558 RegisterKind mode_;
526 int num_registers_; 559 int num_registers_;
527 560
528 BitVector* assigned_registers_; 561 BitVector* assigned_registers_;
529 BitVector* assigned_double_registers_; 562 BitVector* assigned_double_registers_;
530 563
531 // Indicates success or failure during register allocation. 564 // Indicates success or failure during register allocation.
532 bool allocation_ok_; 565 bool allocation_ok_;
533 566
534 #ifdef DEBUG 567 #ifdef DEBUG
535 LifetimePosition allocation_finger_; 568 LifetimePosition allocation_finger_;
536 #endif 569 #endif
537 570
538 DISALLOW_COPY_AND_ASSIGN(RegisterAllocator); 571 DISALLOW_COPY_AND_ASSIGN(RegisterAllocator);
539 }; 572 };
540 573
541 } 574 }
542 } 575 }
543 } // namespace v8::internal::compiler 576 } // namespace v8::internal::compiler
544 577
545 #endif // V8_REGISTER_ALLOCATOR_H_ 578 #endif // V8_REGISTER_ALLOCATOR_H_
OLDNEW
« no previous file with comments | « src/compiler/pipeline.cc ('k') | src/compiler/register-allocator.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698