OLD | NEW |
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/ostreams.h" | 9 #include "src/ostreams.h" |
10 #include "src/zone-containers.h" | 10 #include "src/zone-containers.h" |
(...skipping 256 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
267 UsePosition* next_; | 267 UsePosition* next_; |
268 LifetimePosition const pos_; | 268 LifetimePosition const pos_; |
269 uint32_t flags_; | 269 uint32_t flags_; |
270 | 270 |
271 DISALLOW_COPY_AND_ASSIGN(UsePosition); | 271 DISALLOW_COPY_AND_ASSIGN(UsePosition); |
272 }; | 272 }; |
273 | 273 |
274 | 274 |
275 class SpillRange; | 275 class SpillRange; |
276 class RegisterAllocationData; | 276 class RegisterAllocationData; |
| 277 class TopLevelLiveRange; |
277 | 278 |
278 // Representation of SSA values' live ranges as a collection of (continuous) | 279 // Representation of SSA values' live ranges as a collection of (continuous) |
279 // intervals over the instruction ordering. | 280 // intervals over the instruction ordering. |
280 class LiveRange final : public ZoneObject { | 281 class LiveRange : public ZoneObject { |
281 public: | 282 public: |
282 explicit LiveRange(int id, MachineType machine_type); | |
283 | |
284 UseInterval* first_interval() const { return first_interval_; } | 283 UseInterval* first_interval() const { return first_interval_; } |
285 UsePosition* first_pos() const { return first_pos_; } | 284 UsePosition* first_pos() const { return first_pos_; } |
286 LiveRange* parent() const { return parent_; } | 285 TopLevelLiveRange* TopLevel() { return top_level_; } |
287 LiveRange* TopLevel() { return (parent_ == nullptr) ? this : parent_; } | 286 const TopLevelLiveRange* TopLevel() const { return top_level_; } |
288 const LiveRange* TopLevel() const { | 287 |
289 return (parent_ == nullptr) ? this : parent_; | 288 bool IsTopLevel() const; |
290 } | 289 |
291 LiveRange* next() const { return next_; } | 290 LiveRange* next() const { return next_; } |
292 bool IsChild() const { return parent() != nullptr; } | 291 |
293 int id() const { return id_; } | 292 int relative_id() const { return relative_id_; } |
294 bool IsFixed() const { return id_ < 0; } | 293 |
295 bool IsEmpty() const { return first_interval() == nullptr; } | 294 bool IsEmpty() const { return first_interval() == nullptr; } |
| 295 |
296 InstructionOperand GetAssignedOperand() const; | 296 InstructionOperand GetAssignedOperand() const; |
297 int spill_start_index() const { return spill_start_index_; } | |
298 | 297 |
299 MachineType machine_type() const { return MachineTypeField::decode(bits_); } | 298 MachineType machine_type() const { return MachineTypeField::decode(bits_); } |
300 | 299 |
301 int assigned_register() const { return AssignedRegisterField::decode(bits_); } | 300 int assigned_register() const { return AssignedRegisterField::decode(bits_); } |
302 bool HasRegisterAssigned() const { | 301 bool HasRegisterAssigned() const { |
303 return assigned_register() != kUnassignedRegister; | 302 return assigned_register() != kUnassignedRegister; |
304 } | 303 } |
305 void set_assigned_register(int reg); | 304 void set_assigned_register(int reg); |
306 void UnsetAssignedRegister(); | 305 void UnsetAssignedRegister(); |
307 | 306 |
308 bool spilled() const { return SpilledField::decode(bits_); } | 307 bool spilled() const { return SpilledField::decode(bits_); } |
309 void Spill(); | 308 void Spill(); |
310 | 309 |
311 RegisterKind kind() const; | 310 RegisterKind kind() const; |
312 | 311 |
313 // Correct only for parent. | |
314 bool is_phi() const { return IsPhiField::decode(bits_); } | |
315 void set_is_phi(bool value) { bits_ = IsPhiField::update(bits_, value); } | |
316 | |
317 // Correct only for parent. | |
318 bool is_non_loop_phi() const { return IsNonLoopPhiField::decode(bits_); } | |
319 void set_is_non_loop_phi(bool value) { | |
320 bits_ = IsNonLoopPhiField::update(bits_, value); | |
321 } | |
322 | |
323 // Relevant only for parent. | |
324 bool has_slot_use() const { return HasSlotUseField::decode(bits_); } | |
325 void set_has_slot_use(bool value) { | |
326 bits_ = HasSlotUseField::update(bits_, value); | |
327 } | |
328 | |
329 // Returns use position in this live range that follows both start | 312 // Returns use position in this live range that follows both start |
330 // and last processed use position. | 313 // and last processed use position. |
331 UsePosition* NextUsePosition(LifetimePosition start) const; | 314 UsePosition* NextUsePosition(LifetimePosition start) const; |
332 | 315 |
333 // Returns use position for which register is required in this live | 316 // Returns use position for which register is required in this live |
334 // range and which follows both start and last processed use position | 317 // range and which follows both start and last processed use position |
335 UsePosition* NextRegisterPosition(LifetimePosition start) const; | 318 UsePosition* NextRegisterPosition(LifetimePosition start) const; |
336 | 319 |
337 // Returns the first use position requiring stack slot, or nullptr. | 320 // Returns the first use position requiring stack slot, or nullptr. |
338 UsePosition* NextSlotPosition(LifetimePosition start) const; | 321 UsePosition* NextSlotPosition(LifetimePosition start) const; |
339 | 322 |
340 // Returns use position for which register is beneficial in this live | 323 // Returns use position for which register is beneficial in this live |
341 // range and which follows both start and last processed use position | 324 // range and which follows both start and last processed use position |
342 UsePosition* NextUsePositionRegisterIsBeneficial( | 325 UsePosition* NextUsePositionRegisterIsBeneficial( |
343 LifetimePosition start) const; | 326 LifetimePosition start) const; |
344 | 327 |
345 // Returns use position for which register is beneficial in this live | 328 // Returns use position for which register is beneficial in this live |
346 // range and which precedes start. | 329 // range and which precedes start. |
347 UsePosition* PreviousUsePositionRegisterIsBeneficial( | 330 UsePosition* PreviousUsePositionRegisterIsBeneficial( |
348 LifetimePosition start) const; | 331 LifetimePosition start) const; |
349 | 332 |
350 // Can this live range be spilled at this position. | 333 // Can this live range be spilled at this position. |
351 bool CanBeSpilled(LifetimePosition pos) const; | 334 bool CanBeSpilled(LifetimePosition pos) const; |
352 | 335 |
353 // Split this live range at the given position which must follow the start of | 336 // Splitting primitive used by both splitting and splintering members. |
354 // the range. | 337 // Performs the split, but does not link the resulting ranges. |
| 338 // The given position must follow the start of the range. |
355 // All uses following the given position will be moved from this | 339 // All uses following the given position will be moved from this |
356 // live range to the result live range. | 340 // live range to the result live range. |
357 void SplitAt(LifetimePosition position, LiveRange* result, Zone* zone); | 341 // The current range will terminate at position, while result will start from |
358 void Splinter(LifetimePosition start, LifetimePosition end, LiveRange* result, | 342 // position. |
359 Zone* zone); | 343 void DetachAt(LifetimePosition position, LiveRange* result, Zone* zone); |
360 void Merge(LiveRange* other, RegisterAllocationData* data); | 344 |
| 345 // Detaches at position, and then links the resulting ranges. Returns the |
| 346 // child, which starts at position. |
| 347 LiveRange* SplitAt(LifetimePosition position, Zone* zone); |
361 | 348 |
362 // Returns nullptr when no register is hinted, otherwise sets register_index. | 349 // Returns nullptr when no register is hinted, otherwise sets register_index. |
363 UsePosition* FirstHintPosition(int* register_index) const; | 350 UsePosition* FirstHintPosition(int* register_index) const; |
364 UsePosition* FirstHintPosition() const { | 351 UsePosition* FirstHintPosition() const { |
365 int register_index; | 352 int register_index; |
366 return FirstHintPosition(®ister_index); | 353 return FirstHintPosition(®ister_index); |
367 } | 354 } |
368 | 355 |
369 UsePosition* current_hint_position() const { | 356 UsePosition* current_hint_position() const { |
370 DCHECK(current_hint_position_ == FirstHintPosition()); | 357 DCHECK(current_hint_position_ == FirstHintPosition()); |
371 return current_hint_position_; | 358 return current_hint_position_; |
372 } | 359 } |
373 | 360 |
374 LifetimePosition Start() const { | 361 LifetimePosition Start() const { |
375 DCHECK(!IsEmpty()); | 362 DCHECK(!IsEmpty()); |
376 return first_interval()->start(); | 363 return first_interval()->start(); |
377 } | 364 } |
378 | 365 |
379 LifetimePosition End() const { | 366 LifetimePosition End() const { |
380 DCHECK(!IsEmpty()); | 367 DCHECK(!IsEmpty()); |
381 return last_interval_->end(); | 368 return last_interval_->end(); |
382 } | 369 } |
383 | 370 |
| 371 bool ShouldBeAllocatedBefore(const LiveRange* other) const; |
| 372 bool CanCover(LifetimePosition position) const; |
| 373 bool Covers(LifetimePosition position) const; |
| 374 LifetimePosition FirstIntersection(LiveRange* other) const; |
| 375 |
| 376 void Verify() const; |
| 377 |
| 378 void ConvertUsesToOperand(const InstructionOperand& op, |
| 379 const InstructionOperand& spill_op); |
| 380 void SetUseHints(int register_index); |
| 381 void UnsetUseHints() { SetUseHints(kUnassignedRegister); } |
| 382 |
| 383 // Used solely by the Greedy Allocator: |
| 384 unsigned GetSize(); |
| 385 float weight() const { return weight_; } |
| 386 void set_weight(float weight) { weight_ = weight; } |
| 387 |
| 388 static const int kInvalidSize = -1; |
| 389 static const float kInvalidWeight; |
| 390 static const float kMaxWeight; |
| 391 |
| 392 private: |
| 393 friend class TopLevelLiveRange; |
| 394 explicit LiveRange(int relative_id, MachineType machine_type, |
| 395 TopLevelLiveRange* top_level); |
| 396 |
| 397 void AppendAsChild(TopLevelLiveRange* other); |
| 398 void UpdateParentForAllChildren(TopLevelLiveRange* new_top_level); |
| 399 |
| 400 void set_spilled(bool value) { bits_ = SpilledField::update(bits_, value); } |
| 401 |
| 402 UseInterval* FirstSearchIntervalForPosition(LifetimePosition position) const; |
| 403 void AdvanceLastProcessedMarker(UseInterval* to_start_of, |
| 404 LifetimePosition but_not_past) const; |
| 405 |
| 406 typedef BitField<bool, 0, 1> SpilledField; |
| 407 typedef BitField<int32_t, 6, 6> AssignedRegisterField; |
| 408 typedef BitField<MachineType, 12, 15> MachineTypeField; |
| 409 |
| 410 int relative_id_; |
| 411 uint32_t bits_; |
| 412 UseInterval* last_interval_; |
| 413 UseInterval* first_interval_; |
| 414 UsePosition* first_pos_; |
| 415 TopLevelLiveRange* top_level_; |
| 416 LiveRange* next_; |
| 417 // This is used as a cache, it doesn't affect correctness. |
| 418 mutable UseInterval* current_interval_; |
| 419 // This is used as a cache, it doesn't affect correctness. |
| 420 mutable UsePosition* last_processed_use_; |
| 421 // This is used as a cache, it's invalid outside of BuildLiveRanges. |
| 422 mutable UsePosition* current_hint_position_; |
| 423 |
| 424 // greedy: the number of LifetimePositions covered by this range. Used to |
| 425 // prioritize selecting live ranges for register assignment, as well as |
| 426 // in weight calculations. |
| 427 int size_; |
| 428 |
| 429 // greedy: a metric for resolving conflicts between ranges with an assigned |
| 430 // register and ranges that intersect them and need a register. |
| 431 float weight_; |
| 432 |
| 433 DISALLOW_COPY_AND_ASSIGN(LiveRange); |
| 434 }; |
| 435 |
| 436 |
| 437 class TopLevelLiveRange final : public LiveRange { |
| 438 public: |
| 439 explicit TopLevelLiveRange(int vreg, MachineType machine_type); |
| 440 int spill_start_index() const { return spill_start_index_; } |
| 441 |
| 442 bool IsFixed() const { return vreg_ < 0; } |
| 443 |
| 444 bool is_phi() const { return IsPhiField::decode(bits_); } |
| 445 void set_is_phi(bool value) { bits_ = IsPhiField::update(bits_, value); } |
| 446 |
| 447 bool is_non_loop_phi() const { return IsNonLoopPhiField::decode(bits_); } |
| 448 void set_is_non_loop_phi(bool value) { |
| 449 bits_ = IsNonLoopPhiField::update(bits_, value); |
| 450 } |
| 451 |
| 452 bool has_slot_use() const { return HasSlotUseField::decode(bits_); } |
| 453 void set_has_slot_use(bool value) { |
| 454 bits_ = HasSlotUseField::update(bits_, value); |
| 455 } |
| 456 |
| 457 // Add a new interval or a new use position to this live range. |
| 458 void EnsureInterval(LifetimePosition start, LifetimePosition end, Zone* zone); |
| 459 void AddUseInterval(LifetimePosition start, LifetimePosition end, Zone* zone); |
| 460 void AddUsePosition(UsePosition* pos); |
| 461 |
| 462 // Shorten the most recently added interval by setting a new start. |
| 463 void ShortenTo(LifetimePosition start); |
| 464 |
| 465 // Detaches between start and end, and attributes the resulting range to |
| 466 // result. |
| 467 // The current range is pointed to as "splintered_from". No parent/child |
| 468 // relationship is established between this and result. |
| 469 void Splinter(LifetimePosition start, LifetimePosition end, |
| 470 TopLevelLiveRange* result, Zone* zone); |
| 471 |
| 472 // Assuming other was splintered from this range, embeds other and its |
| 473 // children as part of the children sequence of this range. |
| 474 void Merge(TopLevelLiveRange* other, RegisterAllocationData* data); |
| 475 |
| 476 // Spill range management. |
| 477 void SetSpillRange(SpillRange* spill_range); |
384 enum class SpillType { kNoSpillType, kSpillOperand, kSpillRange }; | 478 enum class SpillType { kNoSpillType, kSpillOperand, kSpillRange }; |
| 479 void set_spill_type(SpillType value) { |
| 480 bits_ = SpillTypeField::update(bits_, value); |
| 481 } |
385 SpillType spill_type() const { return SpillTypeField::decode(bits_); } | 482 SpillType spill_type() const { return SpillTypeField::decode(bits_); } |
386 InstructionOperand* GetSpillOperand() const { | 483 InstructionOperand* GetSpillOperand() const { |
387 DCHECK(spill_type() == SpillType::kSpillOperand); | 484 DCHECK(spill_type() == SpillType::kSpillOperand); |
388 return spill_operand_; | 485 return spill_operand_; |
389 } | 486 } |
390 | 487 |
391 SpillRange* GetAllocatedSpillRange() const { | 488 SpillRange* GetAllocatedSpillRange() const { |
392 DCHECK(spill_type() != SpillType::kSpillOperand); | 489 DCHECK(spill_type() != SpillType::kSpillOperand); |
393 return spill_range_; | 490 return spill_range_; |
394 } | 491 } |
395 | 492 |
396 SpillRange* GetSpillRange() const { | 493 SpillRange* GetSpillRange() const { |
397 DCHECK(spill_type() == SpillType::kSpillRange); | 494 DCHECK(spill_type() == SpillType::kSpillRange); |
398 return spill_range_; | 495 return spill_range_; |
399 } | 496 } |
400 bool HasNoSpillType() const { | 497 bool HasNoSpillType() const { |
401 return spill_type() == SpillType::kNoSpillType; | 498 return spill_type() == SpillType::kNoSpillType; |
402 } | 499 } |
403 bool HasSpillOperand() const { | 500 bool HasSpillOperand() const { |
404 return spill_type() == SpillType::kSpillOperand; | 501 return spill_type() == SpillType::kSpillOperand; |
405 } | 502 } |
406 bool HasSpillRange() const { return spill_type() == SpillType::kSpillRange; } | 503 bool HasSpillRange() const { return spill_type() == SpillType::kSpillRange; } |
407 bool MayRequireSpillRange() const { | |
408 DCHECK(!IsChild() && !IsSplinter()); | |
409 return !HasSpillOperand() && spill_range_ == nullptr; | |
410 } | |
411 | 504 |
412 AllocatedOperand GetSpillRangeOperand() const; | 505 AllocatedOperand GetSpillRangeOperand() const; |
413 | 506 |
414 void SpillAtDefinition(Zone* zone, int gap_index, | 507 void SpillAtDefinition(Zone* zone, int gap_index, |
415 InstructionOperand* operand); | 508 InstructionOperand* operand); |
416 void SetSpillOperand(InstructionOperand* operand); | 509 void SetSpillOperand(InstructionOperand* operand); |
417 void SetSpillRange(SpillRange* spill_range); | 510 void SetSpillStartIndex(int start) { |
| 511 spill_start_index_ = Min(start, spill_start_index_); |
| 512 } |
| 513 |
| 514 void SetSplinteredFrom(TopLevelLiveRange* splinter_parent); |
418 void CommitSpillsAtDefinition(InstructionSequence* sequence, | 515 void CommitSpillsAtDefinition(InstructionSequence* sequence, |
419 const InstructionOperand& operand, | 516 const InstructionOperand& operand, |
420 bool might_be_duplicated); | 517 bool might_be_duplicated); |
421 // This must be applied on top level ranges. | 518 |
422 // If all the children of this range are spilled in deferred blocks, and if | 519 // If all the children of this range are spilled in deferred blocks, and if |
423 // for any non-spilled child with a use position requiring a slot, that range | 520 // for any non-spilled child with a use position requiring a slot, that range |
424 // is contained in a deferred block, mark the range as | 521 // is contained in a deferred block, mark the range as |
425 // IsSpilledOnlyInDeferredBlocks, so that we avoid spilling at definition, | 522 // IsSpilledOnlyInDeferredBlocks, so that we avoid spilling at definition, |
426 // and instead let the LiveRangeConnector perform the spills within the | 523 // and instead let the LiveRangeConnector perform the spills within the |
427 // deferred blocks. If so, we insert here spills for non-spilled ranges | 524 // deferred blocks. If so, we insert here spills for non-spilled ranges |
428 // with slot use positions. | 525 // with slot use positions. |
429 bool TryCommitSpillInDeferredBlock(InstructionSequence* code, | 526 bool TryCommitSpillInDeferredBlock(InstructionSequence* code, |
430 const InstructionOperand& spill_operand); | 527 const InstructionOperand& spill_operand); |
431 | 528 |
432 void SetSpillStartIndex(int start) { | 529 TopLevelLiveRange* splintered_from() const { return splintered_from_; } |
433 spill_start_index_ = Min(start, spill_start_index_); | 530 bool IsSplinter() const { return splintered_from_ != nullptr; } |
| 531 bool MayRequireSpillRange() const { |
| 532 DCHECK(!IsSplinter()); |
| 533 return !HasSpillOperand() && spill_range_ == nullptr; |
434 } | 534 } |
| 535 void UpdateSpillRangePostMerge(TopLevelLiveRange* merged); |
| 536 int vreg() const { return vreg_; } |
435 | 537 |
436 bool ShouldBeAllocatedBefore(const LiveRange* other) const; | 538 int GetNextChildId() { return ++last_child_id_; } |
437 bool CanCover(LifetimePosition position) const; | 539 bool IsSpilledOnlyInDeferredBlocks() const { |
438 bool Covers(LifetimePosition position) const; | 540 return spilled_in_deferred_blocks_; |
439 LifetimePosition FirstIntersection(LiveRange* other) const; | 541 } |
440 | |
441 // Add a new interval or a new use position to this live range. | |
442 void EnsureInterval(LifetimePosition start, LifetimePosition end, Zone* zone); | |
443 void AddUseInterval(LifetimePosition start, LifetimePosition end, Zone* zone); | |
444 void AddUsePosition(UsePosition* pos); | |
445 | |
446 // Shorten the most recently added interval by setting a new start. | |
447 void ShortenTo(LifetimePosition start); | |
448 | |
449 void Verify() const; | |
450 | |
451 void ConvertUsesToOperand(const InstructionOperand& op, | |
452 const InstructionOperand& spill_op); | |
453 void SetUseHints(int register_index); | |
454 void UnsetUseHints() { SetUseHints(kUnassignedRegister); } | |
455 | 542 |
456 struct SpillAtDefinitionList; | 543 struct SpillAtDefinitionList; |
457 | 544 |
458 SpillAtDefinitionList* spills_at_definition() const { | 545 SpillAtDefinitionList* spills_at_definition() const { |
459 return spills_at_definition_; | 546 return spills_at_definition_; |
460 } | 547 } |
461 | 548 |
462 // Used solely by the Greedy Allocator: | |
463 unsigned GetSize(); | |
464 float weight() const { return weight_; } | |
465 void set_weight(float weight) { weight_ = weight; } | |
466 | |
467 bool IsSpilledOnlyInDeferredBlocks() const { | |
468 return spilled_in_deferred_block_; | |
469 } | |
470 | |
471 static const int kInvalidSize = -1; | |
472 static const float kInvalidWeight; | |
473 static const float kMaxWeight; | |
474 | |
475 LiveRange* splintered_from() const { | |
476 DCHECK(!IsChild()); | |
477 return splintered_from_; | |
478 } | |
479 bool IsSplinter() const { | |
480 DCHECK(!IsChild()); | |
481 return splintered_from_ != nullptr; | |
482 } | |
483 | |
484 void set_spill_type(SpillType value) { | |
485 bits_ = SpillTypeField::update(bits_, value); | |
486 } | |
487 | |
488 private: | 549 private: |
489 void AppendChild(LiveRange* other); | |
490 void UpdateParentForAllChildren(LiveRange* new_parent); | |
491 void UpdateSpillRangePostMerge(LiveRange* merged); | |
492 | |
493 void SetSplinteredFrom(LiveRange* splinter_parent); | |
494 | |
495 | |
496 void set_spilled(bool value) { bits_ = SpilledField::update(bits_, value); } | |
497 | |
498 UseInterval* FirstSearchIntervalForPosition(LifetimePosition position) const; | |
499 void AdvanceLastProcessedMarker(UseInterval* to_start_of, | |
500 LifetimePosition but_not_past) const; | |
501 | |
502 LiveRange* GetLastChild(); | |
503 | |
504 typedef BitField<bool, 0, 1> SpilledField; | |
505 typedef BitField<bool, 1, 1> HasSlotUseField; | 550 typedef BitField<bool, 1, 1> HasSlotUseField; |
506 typedef BitField<bool, 2, 1> IsPhiField; | 551 typedef BitField<bool, 2, 1> IsPhiField; |
507 typedef BitField<bool, 3, 1> IsNonLoopPhiField; | 552 typedef BitField<bool, 3, 1> IsNonLoopPhiField; |
508 typedef BitField<SpillType, 4, 2> SpillTypeField; | 553 typedef BitField<SpillType, 4, 2> SpillTypeField; |
509 typedef BitField<int32_t, 6, 6> AssignedRegisterField; | |
510 typedef BitField<MachineType, 12, 15> MachineTypeField; | |
511 | 554 |
512 int id_; | 555 LiveRange* GetLastChild(); |
513 int spill_start_index_; | 556 |
514 uint32_t bits_; | 557 int vreg_; |
515 UseInterval* last_interval_; | 558 int last_child_id_; |
516 UseInterval* first_interval_; | 559 TopLevelLiveRange* splintered_from_; |
517 UsePosition* first_pos_; | |
518 LiveRange* parent_; | |
519 LiveRange* next_; | |
520 LiveRange* splintered_from_; | |
521 union { | 560 union { |
522 // Correct value determined by spill_type() | 561 // Correct value determined by spill_type() |
523 InstructionOperand* spill_operand_; | 562 InstructionOperand* spill_operand_; |
524 SpillRange* spill_range_; | 563 SpillRange* spill_range_; |
525 }; | 564 }; |
526 SpillAtDefinitionList* spills_at_definition_; | 565 SpillAtDefinitionList* spills_at_definition_; |
527 // This is used as a cache, it doesn't affect correctness. | |
528 mutable UseInterval* current_interval_; | |
529 // This is used as a cache, it doesn't affect correctness. | |
530 mutable UsePosition* last_processed_use_; | |
531 // This is used as a cache, it's invalid outside of BuildLiveRanges. | |
532 mutable UsePosition* current_hint_position_; | |
533 | |
534 // greedy: the number of LifetimePositions covered by this range. Used to | |
535 // prioritize selecting live ranges for register assignment, as well as | |
536 // in weight calculations. | |
537 int size_; | |
538 | |
539 // greedy: a metric for resolving conflicts between ranges with an assigned | |
540 // register and ranges that intersect them and need a register. | |
541 float weight_; | |
542 | |
543 // TODO(mtrofin): generalize spilling after definition, currently specialized | 566 // TODO(mtrofin): generalize spilling after definition, currently specialized |
544 // just for spill in a single deferred block. | 567 // just for spill in a single deferred block. |
545 bool spilled_in_deferred_block_; | 568 bool spilled_in_deferred_blocks_; |
546 DISALLOW_COPY_AND_ASSIGN(LiveRange); | 569 int spill_start_index_; |
| 570 |
| 571 DISALLOW_COPY_AND_ASSIGN(TopLevelLiveRange); |
547 }; | 572 }; |
548 | 573 |
549 | 574 |
550 struct PrintableLiveRange { | 575 struct PrintableLiveRange { |
551 const RegisterConfiguration* register_configuration_; | 576 const RegisterConfiguration* register_configuration_; |
552 const LiveRange* range_; | 577 const LiveRange* range_; |
553 }; | 578 }; |
554 | 579 |
555 | 580 |
556 std::ostream& operator<<(std::ostream& os, | 581 std::ostream& operator<<(std::ostream& os, |
557 const PrintableLiveRange& printable_range); | 582 const PrintableLiveRange& printable_range); |
558 | 583 |
559 | 584 |
560 class SpillRange final : public ZoneObject { | 585 class SpillRange final : public ZoneObject { |
561 public: | 586 public: |
562 static const int kUnassignedSlot = -1; | 587 static const int kUnassignedSlot = -1; |
563 SpillRange(LiveRange* range, Zone* zone); | 588 SpillRange(TopLevelLiveRange* range, Zone* zone); |
564 | 589 |
565 UseInterval* interval() const { return use_interval_; } | 590 UseInterval* interval() const { return use_interval_; } |
566 // Currently, only 4 or 8 byte slots are supported. | 591 // Currently, only 4 or 8 byte slots are supported. |
567 int ByteWidth() const; | 592 int ByteWidth() const; |
568 bool IsEmpty() const { return live_ranges_.empty(); } | 593 bool IsEmpty() const { return live_ranges_.empty(); } |
569 bool TryMerge(SpillRange* other); | 594 bool TryMerge(SpillRange* other); |
570 | 595 |
571 void set_assigned_slot(int index) { | 596 void set_assigned_slot(int index) { |
572 DCHECK_EQ(kUnassignedSlot, assigned_slot_); | 597 DCHECK_EQ(kUnassignedSlot, assigned_slot_); |
573 assigned_slot_ = index; | 598 assigned_slot_ = index; |
574 } | 599 } |
575 int assigned_slot() { | 600 int assigned_slot() { |
576 DCHECK_NE(kUnassignedSlot, assigned_slot_); | 601 DCHECK_NE(kUnassignedSlot, assigned_slot_); |
577 return assigned_slot_; | 602 return assigned_slot_; |
578 } | 603 } |
579 const ZoneVector<LiveRange*>& live_ranges() const { return live_ranges_; } | 604 const ZoneVector<TopLevelLiveRange*>& live_ranges() const { |
580 ZoneVector<LiveRange*>& live_ranges() { return live_ranges_; } | 605 return live_ranges_; |
| 606 } |
| 607 ZoneVector<TopLevelLiveRange*>& live_ranges() { return live_ranges_; } |
581 int byte_width() const { return byte_width_; } | 608 int byte_width() const { return byte_width_; } |
582 RegisterKind kind() const { return kind_; } | 609 RegisterKind kind() const { return kind_; } |
583 | 610 |
584 private: | 611 private: |
585 LifetimePosition End() const { return end_position_; } | 612 LifetimePosition End() const { return end_position_; } |
586 bool IsIntersectingWith(SpillRange* other) const; | 613 bool IsIntersectingWith(SpillRange* other) const; |
587 // Merge intervals, making sure the use intervals are sorted | 614 // Merge intervals, making sure the use intervals are sorted |
588 void MergeDisjointIntervals(UseInterval* other); | 615 void MergeDisjointIntervals(UseInterval* other); |
589 | 616 |
590 ZoneVector<LiveRange*> live_ranges_; | 617 ZoneVector<TopLevelLiveRange*> live_ranges_; |
591 UseInterval* use_interval_; | 618 UseInterval* use_interval_; |
592 LifetimePosition end_position_; | 619 LifetimePosition end_position_; |
593 int assigned_slot_; | 620 int assigned_slot_; |
594 int byte_width_; | 621 int byte_width_; |
595 RegisterKind kind_; | 622 RegisterKind kind_; |
596 | 623 |
597 DISALLOW_COPY_AND_ASSIGN(SpillRange); | 624 DISALLOW_COPY_AND_ASSIGN(SpillRange); |
598 }; | 625 }; |
599 | 626 |
600 | 627 |
(...skipping 29 matching lines...) Expand all Loading... |
630 ReferenceMap* map; | 657 ReferenceMap* map; |
631 InstructionOperand* operand; | 658 InstructionOperand* operand; |
632 }; | 659 }; |
633 typedef ZoneVector<DelayedReference> DelayedReferences; | 660 typedef ZoneVector<DelayedReference> DelayedReferences; |
634 | 661 |
635 RegisterAllocationData(const RegisterConfiguration* config, | 662 RegisterAllocationData(const RegisterConfiguration* config, |
636 Zone* allocation_zone, Frame* frame, | 663 Zone* allocation_zone, Frame* frame, |
637 InstructionSequence* code, | 664 InstructionSequence* code, |
638 const char* debug_name = nullptr); | 665 const char* debug_name = nullptr); |
639 | 666 |
640 const ZoneVector<LiveRange*>& live_ranges() const { return live_ranges_; } | 667 const ZoneVector<TopLevelLiveRange*>& live_ranges() const { |
641 ZoneVector<LiveRange*>& live_ranges() { return live_ranges_; } | 668 return live_ranges_; |
642 const ZoneVector<LiveRange*>& fixed_live_ranges() const { | 669 } |
| 670 ZoneVector<TopLevelLiveRange*>& live_ranges() { return live_ranges_; } |
| 671 const ZoneVector<TopLevelLiveRange*>& fixed_live_ranges() const { |
643 return fixed_live_ranges_; | 672 return fixed_live_ranges_; |
644 } | 673 } |
645 ZoneVector<LiveRange*>& fixed_live_ranges() { return fixed_live_ranges_; } | 674 ZoneVector<TopLevelLiveRange*>& fixed_live_ranges() { |
646 ZoneVector<LiveRange*>& fixed_double_live_ranges() { | 675 return fixed_live_ranges_; |
| 676 } |
| 677 ZoneVector<TopLevelLiveRange*>& fixed_double_live_ranges() { |
647 return fixed_double_live_ranges_; | 678 return fixed_double_live_ranges_; |
648 } | 679 } |
649 const ZoneVector<LiveRange*>& fixed_double_live_ranges() const { | 680 const ZoneVector<TopLevelLiveRange*>& fixed_double_live_ranges() const { |
650 return fixed_double_live_ranges_; | 681 return fixed_double_live_ranges_; |
651 } | 682 } |
652 ZoneVector<BitVector*>& live_in_sets() { return live_in_sets_; } | 683 ZoneVector<BitVector*>& live_in_sets() { return live_in_sets_; } |
653 ZoneSet<SpillRange*>& spill_ranges() { return spill_ranges_; } | 684 ZoneSet<SpillRange*>& spill_ranges() { return spill_ranges_; } |
654 DelayedReferences& delayed_references() { return delayed_references_; } | 685 DelayedReferences& delayed_references() { return delayed_references_; } |
655 InstructionSequence* code() const { return code_; } | 686 InstructionSequence* code() const { return code_; } |
656 // This zone is for datastructures only needed during register allocation | 687 // This zone is for datastructures only needed during register allocation |
657 // phases. | 688 // phases. |
658 Zone* allocation_zone() const { return allocation_zone_; } | 689 Zone* allocation_zone() const { return allocation_zone_; } |
659 // This zone is for InstructionOperands and moves that live beyond register | 690 // This zone is for InstructionOperands and moves that live beyond register |
660 // allocation. | 691 // allocation. |
661 Zone* code_zone() const { return code()->zone(); } | 692 Zone* code_zone() const { return code()->zone(); } |
662 Frame* frame() const { return frame_; } | 693 Frame* frame() const { return frame_; } |
663 const char* debug_name() const { return debug_name_; } | 694 const char* debug_name() const { return debug_name_; } |
664 const RegisterConfiguration* config() const { return config_; } | 695 const RegisterConfiguration* config() const { return config_; } |
665 | 696 |
666 MachineType MachineTypeFor(int virtual_register); | 697 MachineType MachineTypeFor(int virtual_register); |
667 | 698 |
668 LiveRange* LiveRangeFor(int index); | 699 TopLevelLiveRange* GetOrCreateLiveRangeFor(int index); |
669 // Creates a new live range. | 700 // Creates a new live range. |
670 LiveRange* NewLiveRange(int index, MachineType machine_type); | 701 TopLevelLiveRange* NewLiveRange(int index, MachineType machine_type); |
671 LiveRange* NextLiveRange(MachineType machine_type); | 702 TopLevelLiveRange* NextLiveRange(MachineType machine_type); |
672 LiveRange* NewChildRangeFor(LiveRange* range); | |
673 | 703 |
674 SpillRange* AssignSpillRangeToLiveRange(LiveRange* range); | 704 SpillRange* AssignSpillRangeToLiveRange(TopLevelLiveRange* range); |
675 SpillRange* CreateSpillRangeForLiveRange(LiveRange* range); | 705 SpillRange* CreateSpillRangeForLiveRange(TopLevelLiveRange* range); |
676 | 706 |
677 MoveOperands* AddGapMove(int index, Instruction::GapPosition position, | 707 MoveOperands* AddGapMove(int index, Instruction::GapPosition position, |
678 const InstructionOperand& from, | 708 const InstructionOperand& from, |
679 const InstructionOperand& to); | 709 const InstructionOperand& to); |
680 | 710 |
681 bool IsReference(int virtual_register) const { | 711 bool IsReference(TopLevelLiveRange* top_range) const { |
682 return code()->IsReference(virtual_register); | 712 return code()->IsReference(top_range->vreg()); |
683 } | 713 } |
684 | 714 |
685 bool ExistsUseWithoutDefinition(); | 715 bool ExistsUseWithoutDefinition(); |
686 | 716 |
687 void MarkAllocated(RegisterKind kind, int index); | 717 void MarkAllocated(RegisterKind kind, int index); |
688 | 718 |
689 PhiMapValue* InitializePhiMap(const InstructionBlock* block, | 719 PhiMapValue* InitializePhiMap(const InstructionBlock* block, |
690 PhiInstruction* phi); | 720 PhiInstruction* phi); |
| 721 PhiMapValue* GetPhiMapValueFor(TopLevelLiveRange* top_range); |
691 PhiMapValue* GetPhiMapValueFor(int virtual_register); | 722 PhiMapValue* GetPhiMapValueFor(int virtual_register); |
692 bool IsBlockBoundary(LifetimePosition pos) const; | 723 bool IsBlockBoundary(LifetimePosition pos) const; |
693 | 724 |
694 void Print(const InstructionSequence* instructionSequence); | 725 void Print(const InstructionSequence* instructionSequence); |
695 void Print(const Instruction* instruction); | 726 void Print(const Instruction* instruction); |
696 void Print(const LiveRange* range, bool with_children = false); | 727 void Print(const LiveRange* range, bool with_children = false); |
697 void Print(const InstructionOperand& op); | 728 void Print(const InstructionOperand& op); |
698 void Print(const MoveOperands* move); | 729 void Print(const MoveOperands* move); |
699 void Print(const SpillRange* spill_range); | 730 void Print(const SpillRange* spill_range); |
700 | 731 |
701 private: | 732 private: |
| 733 int GetNextLiveRangeId(); |
| 734 |
702 Zone* const allocation_zone_; | 735 Zone* const allocation_zone_; |
703 Frame* const frame_; | 736 Frame* const frame_; |
704 InstructionSequence* const code_; | 737 InstructionSequence* const code_; |
705 const char* const debug_name_; | 738 const char* const debug_name_; |
706 const RegisterConfiguration* const config_; | 739 const RegisterConfiguration* const config_; |
707 PhiMap phi_map_; | 740 PhiMap phi_map_; |
708 ZoneVector<BitVector*> live_in_sets_; | 741 ZoneVector<BitVector*> live_in_sets_; |
709 ZoneVector<LiveRange*> live_ranges_; | 742 ZoneVector<TopLevelLiveRange*> live_ranges_; |
710 ZoneVector<LiveRange*> fixed_live_ranges_; | 743 ZoneVector<TopLevelLiveRange*> fixed_live_ranges_; |
711 ZoneVector<LiveRange*> fixed_double_live_ranges_; | 744 ZoneVector<TopLevelLiveRange*> fixed_double_live_ranges_; |
712 ZoneSet<SpillRange*> spill_ranges_; | 745 ZoneSet<SpillRange*> spill_ranges_; |
713 DelayedReferences delayed_references_; | 746 DelayedReferences delayed_references_; |
714 BitVector* assigned_registers_; | 747 BitVector* assigned_registers_; |
715 BitVector* assigned_double_registers_; | 748 BitVector* assigned_double_registers_; |
716 int virtual_register_count_; | 749 int virtual_register_count_; |
717 | 750 |
718 DISALLOW_COPY_AND_ASSIGN(RegisterAllocationData); | 751 DISALLOW_COPY_AND_ASSIGN(RegisterAllocationData); |
719 }; | 752 }; |
720 | 753 |
721 | 754 |
722 class ConstraintBuilder final : public ZoneObject { | 755 class ConstraintBuilder final : public ZoneObject { |
723 public: | 756 public: |
724 explicit ConstraintBuilder(RegisterAllocationData* data); | 757 explicit ConstraintBuilder(RegisterAllocationData* data); |
725 | 758 |
726 // Phase 1 : insert moves to account for fixed register operands. | 759 // Phase 1 : insert moves to account for fixed register operands. |
727 void MeetRegisterConstraints(); | 760 void MeetRegisterConstraints(); |
728 | 761 |
729 // Phase 2: deconstruct SSA by inserting moves in successors and the headers | 762 // Phase 2: deconstruct SSA by inserting moves in successors and the headers |
730 // of blocks containing phis. | 763 // of blocks containing phis. |
731 void ResolvePhis(); | 764 void ResolvePhis(); |
732 | 765 |
733 private: | 766 private: |
734 RegisterAllocationData* data() const { return data_; } | 767 RegisterAllocationData* data() const { return data_; } |
735 InstructionSequence* code() const { return data()->code(); } | 768 InstructionSequence* code() const { return data()->code(); } |
736 Zone* allocation_zone() const { return data()->allocation_zone(); } | 769 Zone* allocation_zone() const { return data()->allocation_zone(); } |
737 | 770 |
738 Instruction* InstructionAt(int index) { return code()->InstructionAt(index); } | |
739 bool IsReference(int virtual_register) const { | |
740 return data()->IsReference(virtual_register); | |
741 } | |
742 LiveRange* LiveRangeFor(int index) { return data()->LiveRangeFor(index); } | |
743 | |
744 InstructionOperand* AllocateFixed(UnallocatedOperand* operand, int pos, | 771 InstructionOperand* AllocateFixed(UnallocatedOperand* operand, int pos, |
745 bool is_tagged); | 772 bool is_tagged); |
746 void MeetRegisterConstraints(const InstructionBlock* block); | 773 void MeetRegisterConstraints(const InstructionBlock* block); |
747 void MeetConstraintsBefore(int index); | 774 void MeetConstraintsBefore(int index); |
748 void MeetConstraintsAfter(int index); | 775 void MeetConstraintsAfter(int index); |
749 void MeetRegisterConstraintsForLastInstructionInBlock( | 776 void MeetRegisterConstraintsForLastInstructionInBlock( |
750 const InstructionBlock* block); | 777 const InstructionBlock* block); |
751 void ResolvePhis(const InstructionBlock* block); | 778 void ResolvePhis(const InstructionBlock* block); |
752 | 779 |
753 RegisterAllocationData* const data_; | 780 RegisterAllocationData* const data_; |
(...skipping 14 matching lines...) Expand all Loading... |
768 private: | 795 private: |
769 RegisterAllocationData* data() const { return data_; } | 796 RegisterAllocationData* data() const { return data_; } |
770 InstructionSequence* code() const { return data()->code(); } | 797 InstructionSequence* code() const { return data()->code(); } |
771 Zone* allocation_zone() const { return data()->allocation_zone(); } | 798 Zone* allocation_zone() const { return data()->allocation_zone(); } |
772 Zone* code_zone() const { return code()->zone(); } | 799 Zone* code_zone() const { return code()->zone(); } |
773 const RegisterConfiguration* config() const { return data()->config(); } | 800 const RegisterConfiguration* config() const { return data()->config(); } |
774 ZoneVector<BitVector*>& live_in_sets() const { | 801 ZoneVector<BitVector*>& live_in_sets() const { |
775 return data()->live_in_sets(); | 802 return data()->live_in_sets(); |
776 } | 803 } |
777 | 804 |
778 LiveRange* LiveRangeFor(int index) { return data()->LiveRangeFor(index); } | |
779 | |
780 void Verify() const; | 805 void Verify() const; |
781 | 806 |
782 // Liveness analysis support. | 807 // Liveness analysis support. |
783 void AddInitialIntervals(const InstructionBlock* block, BitVector* live_out); | 808 void AddInitialIntervals(const InstructionBlock* block, BitVector* live_out); |
784 void ProcessInstructions(const InstructionBlock* block, BitVector* live); | 809 void ProcessInstructions(const InstructionBlock* block, BitVector* live); |
785 void ProcessPhis(const InstructionBlock* block, BitVector* live); | 810 void ProcessPhis(const InstructionBlock* block, BitVector* live); |
786 void ProcessLoopHeader(const InstructionBlock* block, BitVector* live); | 811 void ProcessLoopHeader(const InstructionBlock* block, BitVector* live); |
787 | 812 |
788 static int FixedLiveRangeID(int index) { return -index - 1; } | 813 static int FixedLiveRangeID(int index) { return -index - 1; } |
789 int FixedDoubleLiveRangeID(int index); | 814 int FixedDoubleLiveRangeID(int index); |
790 LiveRange* FixedLiveRangeFor(int index); | 815 TopLevelLiveRange* FixedLiveRangeFor(int index); |
791 LiveRange* FixedDoubleLiveRangeFor(int index); | 816 TopLevelLiveRange* FixedDoubleLiveRangeFor(int index); |
792 | 817 |
793 void MapPhiHint(InstructionOperand* operand, UsePosition* use_pos); | 818 void MapPhiHint(InstructionOperand* operand, UsePosition* use_pos); |
794 void ResolvePhiHint(InstructionOperand* operand, UsePosition* use_pos); | 819 void ResolvePhiHint(InstructionOperand* operand, UsePosition* use_pos); |
795 | 820 |
796 UsePosition* NewUsePosition(LifetimePosition pos, InstructionOperand* operand, | 821 UsePosition* NewUsePosition(LifetimePosition pos, InstructionOperand* operand, |
797 void* hint, UsePositionHintType hint_type); | 822 void* hint, UsePositionHintType hint_type); |
798 UsePosition* NewUsePosition(LifetimePosition pos) { | 823 UsePosition* NewUsePosition(LifetimePosition pos) { |
799 return NewUsePosition(pos, nullptr, nullptr, UsePositionHintType::kNone); | 824 return NewUsePosition(pos, nullptr, nullptr, UsePositionHintType::kNone); |
800 } | 825 } |
801 LiveRange* LiveRangeFor(InstructionOperand* operand); | 826 TopLevelLiveRange* LiveRangeFor(InstructionOperand* operand); |
802 // Helper methods for building intervals. | 827 // Helper methods for building intervals. |
803 UsePosition* Define(LifetimePosition position, InstructionOperand* operand, | 828 UsePosition* Define(LifetimePosition position, InstructionOperand* operand, |
804 void* hint, UsePositionHintType hint_type); | 829 void* hint, UsePositionHintType hint_type); |
805 void Define(LifetimePosition position, InstructionOperand* operand) { | 830 void Define(LifetimePosition position, InstructionOperand* operand) { |
806 Define(position, operand, nullptr, UsePositionHintType::kNone); | 831 Define(position, operand, nullptr, UsePositionHintType::kNone); |
807 } | 832 } |
808 UsePosition* Use(LifetimePosition block_start, LifetimePosition position, | 833 UsePosition* Use(LifetimePosition block_start, LifetimePosition position, |
809 InstructionOperand* operand, void* hint, | 834 InstructionOperand* operand, void* hint, |
810 UsePositionHintType hint_type); | 835 UsePositionHintType hint_type); |
811 void Use(LifetimePosition block_start, LifetimePosition position, | 836 void Use(LifetimePosition block_start, LifetimePosition position, |
(...skipping 13 matching lines...) Expand all Loading... |
825 explicit RegisterAllocator(RegisterAllocationData* data, RegisterKind kind); | 850 explicit RegisterAllocator(RegisterAllocationData* data, RegisterKind kind); |
826 | 851 |
827 protected: | 852 protected: |
828 RegisterAllocationData* data() const { return data_; } | 853 RegisterAllocationData* data() const { return data_; } |
829 InstructionSequence* code() const { return data()->code(); } | 854 InstructionSequence* code() const { return data()->code(); } |
830 RegisterKind mode() const { return mode_; } | 855 RegisterKind mode() const { return mode_; } |
831 int num_registers() const { return num_registers_; } | 856 int num_registers() const { return num_registers_; } |
832 | 857 |
833 Zone* allocation_zone() const { return data()->allocation_zone(); } | 858 Zone* allocation_zone() const { return data()->allocation_zone(); } |
834 | 859 |
835 LiveRange* LiveRangeFor(int index) { return data()->LiveRangeFor(index); } | |
836 | |
837 // Split the given range at the given position. | 860 // Split the given range at the given position. |
838 // If range starts at or after the given position then the | 861 // If range starts at or after the given position then the |
839 // original range is returned. | 862 // original range is returned. |
840 // Otherwise returns the live range that starts at pos and contains | 863 // Otherwise returns the live range that starts at pos and contains |
841 // all uses from the original range that follow pos. Uses at pos will | 864 // all uses from the original range that follow pos. Uses at pos will |
842 // still be owned by the original range after splitting. | 865 // still be owned by the original range after splitting. |
843 LiveRange* SplitRangeAt(LiveRange* range, LifetimePosition pos); | 866 LiveRange* SplitRangeAt(LiveRange* range, LifetimePosition pos); |
844 | 867 |
845 // Split the given range in a position from the interval [start, end]. | 868 // Split the given range in a position from the interval [start, end]. |
846 LiveRange* SplitBetween(LiveRange* range, LifetimePosition start, | 869 LiveRange* SplitBetween(LiveRange* range, LifetimePosition start, |
847 LifetimePosition end); | 870 LifetimePosition end); |
848 | 871 |
849 // Find a lifetime position in the interval [start, end] which | 872 // Find a lifetime position in the interval [start, end] which |
850 // is optimal for splitting: it is either header of the outermost | 873 // is optimal for splitting: it is either header of the outermost |
851 // loop covered by this interval or the latest possible position. | 874 // loop covered by this interval or the latest possible position. |
852 LifetimePosition FindOptimalSplitPos(LifetimePosition start, | 875 LifetimePosition FindOptimalSplitPos(LifetimePosition start, |
853 LifetimePosition end); | 876 LifetimePosition end); |
854 | 877 |
855 void Spill(LiveRange* range); | 878 void Spill(LiveRange* range); |
856 | 879 |
857 // If we are trying to spill a range inside the loop try to | 880 // If we are trying to spill a range inside the loop try to |
858 // hoist spill position out to the point just before the loop. | 881 // hoist spill position out to the point just before the loop. |
859 LifetimePosition FindOptimalSpillingPos(LiveRange* range, | 882 LifetimePosition FindOptimalSpillingPos(LiveRange* range, |
860 LifetimePosition pos); | 883 LifetimePosition pos); |
861 | 884 |
862 const ZoneVector<LiveRange*>& GetFixedRegisters() const; | 885 const ZoneVector<TopLevelLiveRange*>& GetFixedRegisters() const; |
863 const char* RegisterName(int allocation_index) const; | 886 const char* RegisterName(int allocation_index) const; |
864 | 887 |
865 private: | 888 private: |
866 RegisterAllocationData* const data_; | 889 RegisterAllocationData* const data_; |
867 const RegisterKind mode_; | 890 const RegisterKind mode_; |
868 const int num_registers_; | 891 const int num_registers_; |
869 | 892 |
870 DISALLOW_COPY_AND_ASSIGN(RegisterAllocator); | 893 DISALLOW_COPY_AND_ASSIGN(RegisterAllocator); |
871 }; | 894 }; |
872 | 895 |
(...skipping 23 matching lines...) Expand all Loading... |
896 void AddToUnhandledSorted(LiveRange* range); | 919 void AddToUnhandledSorted(LiveRange* range); |
897 void AddToUnhandledUnsorted(LiveRange* range); | 920 void AddToUnhandledUnsorted(LiveRange* range); |
898 void SortUnhandled(); | 921 void SortUnhandled(); |
899 bool UnhandledIsSorted(); | 922 bool UnhandledIsSorted(); |
900 void ActiveToHandled(LiveRange* range); | 923 void ActiveToHandled(LiveRange* range); |
901 void ActiveToInactive(LiveRange* range); | 924 void ActiveToInactive(LiveRange* range); |
902 void InactiveToHandled(LiveRange* range); | 925 void InactiveToHandled(LiveRange* range); |
903 void InactiveToActive(LiveRange* range); | 926 void InactiveToActive(LiveRange* range); |
904 | 927 |
905 // Helper methods for allocating registers. | 928 // Helper methods for allocating registers. |
906 bool TryReuseSpillForPhi(LiveRange* range); | 929 bool TryReuseSpillForPhi(TopLevelLiveRange* range); |
907 bool TryAllocateFreeReg(LiveRange* range); | 930 bool TryAllocateFreeReg(LiveRange* range); |
908 void AllocateBlockedReg(LiveRange* range); | 931 void AllocateBlockedReg(LiveRange* range); |
909 | 932 |
910 // Spill the given life range after position pos. | 933 // Spill the given life range after position pos. |
911 void SpillAfter(LiveRange* range, LifetimePosition pos); | 934 void SpillAfter(LiveRange* range, LifetimePosition pos); |
912 | 935 |
913 // Spill the given life range after position [start] and up to position [end]. | 936 // Spill the given life range after position [start] and up to position [end]. |
914 void SpillBetween(LiveRange* range, LifetimePosition start, | 937 void SpillBetween(LiveRange* range, LifetimePosition start, |
915 LifetimePosition end); | 938 LifetimePosition end); |
916 | 939 |
(...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1020 RegisterAllocationData* const data_; | 1043 RegisterAllocationData* const data_; |
1021 | 1044 |
1022 DISALLOW_COPY_AND_ASSIGN(LiveRangeConnector); | 1045 DISALLOW_COPY_AND_ASSIGN(LiveRangeConnector); |
1023 }; | 1046 }; |
1024 | 1047 |
1025 } // namespace compiler | 1048 } // namespace compiler |
1026 } // namespace internal | 1049 } // namespace internal |
1027 } // namespace v8 | 1050 } // namespace v8 |
1028 | 1051 |
1029 #endif // V8_REGISTER_ALLOCATOR_H_ | 1052 #endif // V8_REGISTER_ALLOCATOR_H_ |
OLD | NEW |