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

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

Issue 1111563004: [turbofan] Cleanup LiveRange a bit. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Created 5 years, 7 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/graph-visualizer.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 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
53 int ToInstructionIndex() const { 53 int ToInstructionIndex() const {
54 DCHECK(IsValid()); 54 DCHECK(IsValid());
55 return value_ / kStep; 55 return value_ / kStep;
56 } 56 }
57 57
58 // Returns true if this lifetime position corresponds to a START value 58 // Returns true if this lifetime position corresponds to a START value
59 bool IsStart() const { return (value_ & (kHalfStep - 1)) == 0; } 59 bool IsStart() const { return (value_ & (kHalfStep - 1)) == 0; }
60 // Returns true if this lifetime position corresponds to a gap START value 60 // Returns true if this lifetime position corresponds to a gap START value
61 bool IsFullStart() const { return (value_ & (kStep - 1)) == 0; } 61 bool IsFullStart() const { return (value_ & (kStep - 1)) == 0; }
62 62
63 bool IsGapPosition() { return (value_ & 0x2) == 0; } 63 bool IsGapPosition() const { return (value_ & 0x2) == 0; }
64 bool IsInstructionPosition() { return !IsGapPosition(); } 64 bool IsInstructionPosition() const { return !IsGapPosition(); }
65 65
66 // Returns the lifetime position for the current START. 66 // Returns the lifetime position for the current START.
67 LifetimePosition Start() const { 67 LifetimePosition Start() const {
68 DCHECK(IsValid()); 68 DCHECK(IsValid());
69 return LifetimePosition(value_ & ~(kHalfStep - 1)); 69 return LifetimePosition(value_ & ~(kHalfStep - 1));
70 } 70 }
71 71
72 // Returns the lifetime position for the current gap START. 72 // Returns the lifetime position for the current gap START.
73 LifetimePosition FullStart() const { 73 LifetimePosition FullStart() const {
74 DCHECK(IsValid()); 74 DCHECK(IsValid());
(...skipping 205 matching lines...) Expand 10 before | Expand all | Expand 10 after
280 LiveRange* TopLevel() { return (parent_ == nullptr) ? this : parent_; } 280 LiveRange* TopLevel() { return (parent_ == nullptr) ? this : parent_; }
281 const LiveRange* TopLevel() const { 281 const LiveRange* TopLevel() const {
282 return (parent_ == nullptr) ? this : parent_; 282 return (parent_ == nullptr) ? this : parent_;
283 } 283 }
284 LiveRange* next() const { return next_; } 284 LiveRange* next() const { return next_; }
285 bool IsChild() const { return parent() != nullptr; } 285 bool IsChild() const { return parent() != nullptr; }
286 int id() const { return id_; } 286 int id() const { return id_; }
287 bool IsFixed() const { return id_ < 0; } 287 bool IsFixed() const { return id_ < 0; }
288 bool IsEmpty() const { return first_interval() == nullptr; } 288 bool IsEmpty() const { return first_interval() == nullptr; }
289 InstructionOperand GetAssignedOperand() const; 289 InstructionOperand GetAssignedOperand() const;
290 int assigned_register() const { return assigned_register_; }
291 int spill_start_index() const { return spill_start_index_; } 290 int spill_start_index() const { return spill_start_index_; }
291
292 int assigned_register() const { return AssignedRegisterField::decode(bits_); }
293 bool HasRegisterAssigned() const {
294 return assigned_register() != kUnassignedRegister;
295 }
292 void set_assigned_register(int reg); 296 void set_assigned_register(int reg);
293 void UnsetAssignedRegister(); 297 void UnsetAssignedRegister();
294 void MakeSpilled(); 298
295 bool is_phi() const { return is_phi_; } 299 bool spilled() const { return SpilledField::decode(bits_); }
296 void set_is_phi(bool is_phi) { is_phi_ = is_phi; } 300 void Spill();
297 bool is_non_loop_phi() const { return is_non_loop_phi_; } 301
298 void set_is_non_loop_phi(bool is_non_loop_phi) { 302 RegisterKind kind() const { return RegisterKindField::decode(bits_); }
299 is_non_loop_phi_ = is_non_loop_phi; 303 void set_kind(RegisterKind kind) {
304 bits_ = RegisterKindField::update(bits_, kind);
300 } 305 }
301 bool has_slot_use() const { return has_slot_use_; } 306
302 void set_has_slot_use(bool has_slot_use) { has_slot_use_ = has_slot_use; } 307 // Correct only for parent.
308 bool is_phi() const { return IsPhiField::decode(bits_); }
309 void set_is_phi(bool value) { bits_ = IsPhiField::update(bits_, value); }
310
311 // Correct only for parent.
312 bool is_non_loop_phi() const { return IsNonLoopPhiField::decode(bits_); }
313 void set_is_non_loop_phi(bool value) {
314 bits_ = IsNonLoopPhiField::update(bits_, value);
315 }
316
317 // Relevant only for parent.
318 bool has_slot_use() const { return HasSlotUseField::decode(bits_); }
319 void set_has_slot_use(bool value) {
320 bits_ = HasSlotUseField::update(bits_, value);
321 }
303 322
304 // Returns use position in this live range that follows both start 323 // Returns use position in this live range that follows both start
305 // and last processed use position. 324 // and last processed use position.
306 UsePosition* NextUsePosition(LifetimePosition start) const; 325 UsePosition* NextUsePosition(LifetimePosition start) const;
307 326
308 // Returns use position for which register is required in this live 327 // Returns use position for which register is required in this live
309 // range and which follows both start and last processed use position 328 // range and which follows both start and last processed use position
310 UsePosition* NextRegisterPosition(LifetimePosition start) const; 329 UsePosition* NextRegisterPosition(LifetimePosition start) const;
311 330
312 // Returns use position for which register is beneficial in this live 331 // Returns use position for which register is beneficial in this live
313 // range and which follows both start and last processed use position 332 // range and which follows both start and last processed use position
314 UsePosition* NextUsePositionRegisterIsBeneficial( 333 UsePosition* NextUsePositionRegisterIsBeneficial(
315 LifetimePosition start) const; 334 LifetimePosition start) const;
316 335
317 // Returns use position for which register is beneficial in this live 336 // Returns use position for which register is beneficial in this live
318 // range and which precedes start. 337 // range and which precedes start.
319 UsePosition* PreviousUsePositionRegisterIsBeneficial( 338 UsePosition* PreviousUsePositionRegisterIsBeneficial(
320 LifetimePosition start) const; 339 LifetimePosition start) const;
321 340
322 // Can this live range be spilled at this position. 341 // Can this live range be spilled at this position.
323 bool CanBeSpilled(LifetimePosition pos) const; 342 bool CanBeSpilled(LifetimePosition pos) const;
324 343
325 // Split this live range at the given position which must follow the start of 344 // Split this live range at the given position which must follow the start of
326 // the range. 345 // the range.
327 // All uses following the given position will be moved from this 346 // All uses following the given position will be moved from this
328 // live range to the result live range. 347 // live range to the result live range.
329 void SplitAt(LifetimePosition position, LiveRange* result, Zone* zone); 348 void SplitAt(LifetimePosition position, LiveRange* result, Zone* zone);
330 349
331 RegisterKind Kind() const { return kind_; }
332 bool HasRegisterAssigned() const {
333 return assigned_register_ != kUnassignedRegister;
334 }
335 bool IsSpilled() const { return spilled_; }
336
337 // Returns nullptr when no register is hinted, otherwise sets register_index. 350 // Returns nullptr when no register is hinted, otherwise sets register_index.
338 UsePosition* FirstHintPosition(int* register_index) const; 351 UsePosition* FirstHintPosition(int* register_index) const;
339 UsePosition* FirstHintPosition() const { 352 UsePosition* FirstHintPosition() const {
340 int register_index; 353 int register_index;
341 return FirstHintPosition(&register_index); 354 return FirstHintPosition(&register_index);
342 } 355 }
343 356
344 UsePosition* current_hint_position() const { 357 UsePosition* current_hint_position() const {
345 DCHECK(current_hint_position_ == FirstHintPosition()); 358 DCHECK(current_hint_position_ == FirstHintPosition());
346 return current_hint_position_; 359 return current_hint_position_;
347 } 360 }
348 361
349 LifetimePosition Start() const { 362 LifetimePosition Start() const {
350 DCHECK(!IsEmpty()); 363 DCHECK(!IsEmpty());
351 return first_interval()->start(); 364 return first_interval()->start();
352 } 365 }
353 366
354 LifetimePosition End() const { 367 LifetimePosition End() const {
355 DCHECK(!IsEmpty()); 368 DCHECK(!IsEmpty());
356 return last_interval_->end(); 369 return last_interval_->end();
357 } 370 }
358 371
359 enum class SpillType { kNoSpillType, kSpillOperand, kSpillRange }; 372 enum class SpillType { kNoSpillType, kSpillOperand, kSpillRange };
360 SpillType spill_type() const { return spill_type_; } 373 SpillType spill_type() const { return SpillTypeField::decode(bits_); }
361 InstructionOperand* GetSpillOperand() const { 374 InstructionOperand* GetSpillOperand() const {
362 DCHECK(spill_type_ == SpillType::kSpillOperand); 375 DCHECK(spill_type() == SpillType::kSpillOperand);
363 return spill_operand_; 376 return spill_operand_;
364 } 377 }
365 SpillRange* GetSpillRange() const { 378 SpillRange* GetSpillRange() const {
366 DCHECK(spill_type_ == SpillType::kSpillRange); 379 DCHECK(spill_type() == SpillType::kSpillRange);
367 return spill_range_; 380 return spill_range_;
368 } 381 }
369 bool HasNoSpillType() const { return spill_type_ == SpillType::kNoSpillType; } 382 bool HasNoSpillType() const {
383 return spill_type() == SpillType::kNoSpillType;
384 }
370 bool HasSpillOperand() const { 385 bool HasSpillOperand() const {
371 return spill_type_ == SpillType::kSpillOperand; 386 return spill_type() == SpillType::kSpillOperand;
372 } 387 }
373 bool HasSpillRange() const { return spill_type_ == SpillType::kSpillRange; } 388 bool HasSpillRange() const { return spill_type() == SpillType::kSpillRange; }
374 389
375 void SpillAtDefinition(Zone* zone, int gap_index, 390 void SpillAtDefinition(Zone* zone, int gap_index,
376 InstructionOperand* operand); 391 InstructionOperand* operand);
377 void SetSpillOperand(InstructionOperand* operand); 392 void SetSpillOperand(InstructionOperand* operand);
378 void SetSpillRange(SpillRange* spill_range); 393 void SetSpillRange(SpillRange* spill_range);
379 void CommitSpillOperand(AllocatedOperand* operand); 394 void CommitSpillOperand(AllocatedOperand* operand);
380 void CommitSpillsAtDefinition(InstructionSequence* sequence, 395 void CommitSpillsAtDefinition(InstructionSequence* sequence,
381 InstructionOperand* operand, 396 InstructionOperand* operand,
382 bool might_be_duplicated); 397 bool might_be_duplicated);
383 398
(...skipping 14 matching lines...) Expand all
398 // Shorten the most recently added interval by setting a new start. 413 // Shorten the most recently added interval by setting a new start.
399 void ShortenTo(LifetimePosition start); 414 void ShortenTo(LifetimePosition start);
400 415
401 void Verify() const; 416 void Verify() const;
402 417
403 void ConvertUsesToOperand(const InstructionOperand& op, 418 void ConvertUsesToOperand(const InstructionOperand& op,
404 InstructionOperand* spill_op); 419 InstructionOperand* spill_op);
405 void SetUseHints(int register_index); 420 void SetUseHints(int register_index);
406 void UnsetUseHints() { SetUseHints(kUnassignedRegister); } 421 void UnsetUseHints() { SetUseHints(kUnassignedRegister); }
407 422
408 void set_kind(RegisterKind kind) { kind_ = kind; }
409
410 private: 423 private:
411 struct SpillAtDefinitionList; 424 struct SpillAtDefinitionList;
412 425
426 void set_spill_type(SpillType value) {
427 bits_ = SpillTypeField::update(bits_, value);
428 }
429
430 void set_spilled(bool value) { bits_ = SpilledField::update(bits_, value); }
431
413 UseInterval* FirstSearchIntervalForPosition(LifetimePosition position) const; 432 UseInterval* FirstSearchIntervalForPosition(LifetimePosition position) const;
414 void AdvanceLastProcessedMarker(UseInterval* to_start_of, 433 void AdvanceLastProcessedMarker(UseInterval* to_start_of,
415 LifetimePosition but_not_past) const; 434 LifetimePosition but_not_past) const;
416 435
417 // TODO(dcarney): pack this structure better. 436 typedef BitField<bool, 0, 1> SpilledField;
437 typedef BitField<bool, 1, 1> HasSlotUseField;
438 typedef BitField<bool, 2, 1> IsPhiField;
439 typedef BitField<bool, 3, 1> IsNonLoopPhiField;
440 typedef BitField<RegisterKind, 4, 2> RegisterKindField;
441 typedef BitField<SpillType, 6, 2> SpillTypeField;
442 typedef BitField<int32_t, 8, 6> AssignedRegisterField;
443
418 int id_; 444 int id_;
419 bool spilled_ : 1; 445 int spill_start_index_;
420 bool has_slot_use_ : 1; // Relevant only for parent. 446 uint32_t bits_;
421 bool is_phi_ : 1; // Correct only for parent.
422 bool is_non_loop_phi_ : 1; // Correct only for parent.
423 RegisterKind kind_;
424 int assigned_register_;
425 UseInterval* last_interval_; 447 UseInterval* last_interval_;
426 UseInterval* first_interval_; 448 UseInterval* first_interval_;
427 UsePosition* first_pos_; 449 UsePosition* first_pos_;
428 LiveRange* parent_; 450 LiveRange* parent_;
429 LiveRange* next_; 451 LiveRange* next_;
452 union {
453 // Correct value determined by spill_type()
454 InstructionOperand* spill_operand_;
455 SpillRange* spill_range_;
456 };
457 SpillAtDefinitionList* spills_at_definition_;
430 // This is used as a cache, it doesn't affect correctness. 458 // This is used as a cache, it doesn't affect correctness.
431 mutable UseInterval* current_interval_; 459 mutable UseInterval* current_interval_;
432 // This is used as a cache, it doesn't affect correctness. 460 // This is used as a cache, it doesn't affect correctness.
433 mutable UsePosition* last_processed_use_; 461 mutable UsePosition* last_processed_use_;
434 // This is used as a cache, it's invalid outside of BuildLiveRanges. 462 // This is used as a cache, it's invalid outside of BuildLiveRanges.
435 mutable UsePosition* current_hint_position_; 463 mutable UsePosition* current_hint_position_;
436 int spill_start_index_;
437 SpillType spill_type_;
438 union {
439 InstructionOperand* spill_operand_;
440 SpillRange* spill_range_;
441 };
442 SpillAtDefinitionList* spills_at_definition_;
443 464
444 DISALLOW_COPY_AND_ASSIGN(LiveRange); 465 DISALLOW_COPY_AND_ASSIGN(LiveRange);
445 }; 466 };
446 467
447 468
448 class SpillRange final : public ZoneObject { 469 class SpillRange final : public ZoneObject {
449 public: 470 public:
450 SpillRange(LiveRange* range, Zone* zone); 471 SpillRange(LiveRange* range, Zone* zone);
451 472
452 UseInterval* interval() const { return use_interval_; } 473 UseInterval* interval() const { return use_interval_; }
453 RegisterKind Kind() const { return live_ranges_[0]->Kind(); } 474 RegisterKind kind() const { return live_ranges_[0]->kind(); }
454 bool IsEmpty() const { return live_ranges_.empty(); } 475 bool IsEmpty() const { return live_ranges_.empty(); }
455 bool TryMerge(SpillRange* other); 476 bool TryMerge(SpillRange* other);
456 void SetOperand(AllocatedOperand* op); 477 void SetOperand(AllocatedOperand* op);
457 478
458 private: 479 private:
459 LifetimePosition End() const { return end_position_; } 480 LifetimePosition End() const { return end_position_; }
460 ZoneVector<LiveRange*>& live_ranges() { return live_ranges_; } 481 ZoneVector<LiveRange*>& live_ranges() { return live_ranges_; }
461 bool IsIntersectingWith(SpillRange* other) const; 482 bool IsIntersectingWith(SpillRange* other) const;
462 // Merge intervals, making sure the use intervals are sorted 483 // Merge intervals, making sure the use intervals are sorted
463 void MergeDisjointIntervals(UseInterval* other); 484 void MergeDisjointIntervals(UseInterval* other);
(...skipping 422 matching lines...) Expand 10 before | Expand all | Expand 10 after
886 RegisterAllocationData* const data_; 907 RegisterAllocationData* const data_;
887 908
888 DISALLOW_COPY_AND_ASSIGN(LiveRangeConnector); 909 DISALLOW_COPY_AND_ASSIGN(LiveRangeConnector);
889 }; 910 };
890 911
891 } // namespace compiler 912 } // namespace compiler
892 } // namespace internal 913 } // namespace internal
893 } // namespace v8 914 } // namespace v8
894 915
895 #endif // V8_REGISTER_ALLOCATOR_H_ 916 #endif // V8_REGISTER_ALLOCATOR_H_
OLDNEW
« no previous file with comments | « src/compiler/graph-visualizer.cc ('k') | src/compiler/register-allocator.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698