| OLD | NEW |
| 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file |
| 2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
| 3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
| 4 | 4 |
| 5 #ifndef VM_FLOW_GRAPH_ALLOCATOR_H_ | 5 #ifndef VM_FLOW_GRAPH_ALLOCATOR_H_ |
| 6 #define VM_FLOW_GRAPH_ALLOCATOR_H_ | 6 #define VM_FLOW_GRAPH_ALLOCATOR_H_ |
| 7 | 7 |
| 8 #include "vm/growable_array.h" | 8 #include "vm/growable_array.h" |
| 9 #include "vm/intermediate_language.h" | 9 #include "vm/intermediate_language.h" |
| 10 | 10 |
| (...skipping 135 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 146 | 146 |
| 147 // Try to find a free register for an unallocated live range. | 147 // Try to find a free register for an unallocated live range. |
| 148 bool AllocateFreeRegister(LiveRange* unallocated); | 148 bool AllocateFreeRegister(LiveRange* unallocated); |
| 149 | 149 |
| 150 // Try to find a register that can be used by a given live range. | 150 // Try to find a register that can be used by a given live range. |
| 151 // If all registers are occupied consider evicting interference for | 151 // If all registers are occupied consider evicting interference for |
| 152 // a register that is going to be used as far from the start of | 152 // a register that is going to be used as far from the start of |
| 153 // the unallocated live range as possible. | 153 // the unallocated live range as possible. |
| 154 void AllocateAnyRegister(LiveRange* unallocated); | 154 void AllocateAnyRegister(LiveRange* unallocated); |
| 155 | 155 |
| 156 // Returns true if the given range has only unconstrained uses in |
| 157 // the given loop. |
| 158 bool RangeHasOnlyUnconstrainedUsesInLoop(LiveRange* range, intptr_t loop_id); |
| 159 |
| 160 // Returns true if there is a register blocked by a range that |
| 161 // has only unconstrained uses in the loop. Such range is a good |
| 162 // eviction candidate when allocator tries to allocate loop phi. |
| 163 // Spilling loop phi will have a bigger negative impact on the |
| 164 // performance because it introduces multiple operations with memory |
| 165 // inside the loop body and on the back edge. |
| 166 bool HasCheapEvictionCandidate(LiveRange* phi_range); |
| 167 bool IsCheapToEvictRegisterInLoop(BlockInfo* loop, intptr_t reg); |
| 168 |
| 156 // Assign selected non-free register to an unallocated live range and | 169 // Assign selected non-free register to an unallocated live range and |
| 157 // evict any interference that can be evicted by splitting and spilling | 170 // evict any interference that can be evicted by splitting and spilling |
| 158 // parts of interfering live ranges. Place non-spilled parts into | 171 // parts of interfering live ranges. Place non-spilled parts into |
| 159 // the list of unallocated ranges. | 172 // the list of unallocated ranges. |
| 160 void AssignNonFreeRegister(LiveRange* unallocated, intptr_t reg); | 173 void AssignNonFreeRegister(LiveRange* unallocated, intptr_t reg); |
| 161 bool EvictIntersection(LiveRange* allocated, LiveRange* unallocated); | 174 bool EvictIntersection(LiveRange* allocated, LiveRange* unallocated); |
| 162 void RemoveEvicted(intptr_t reg, intptr_t first_evicted); | 175 void RemoveEvicted(intptr_t reg, intptr_t first_evicted); |
| 163 | 176 |
| 164 // Find first intersection between unallocated live range and | 177 // Find first intersection between unallocated live range and |
| 165 // live ranges currently allocated to the given register. | 178 // live ranges currently allocated to the given register. |
| (...skipping 132 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 298 // outer loop not to themselves. | 311 // outer loop not to themselves. |
| 299 BlockInfo* loop() const { return loop_; } | 312 BlockInfo* loop() const { return loop_; } |
| 300 | 313 |
| 301 void mark_loop_header() { is_loop_header_ = true; } | 314 void mark_loop_header() { is_loop_header_ = true; } |
| 302 void set_loop(BlockInfo* loop) { | 315 void set_loop(BlockInfo* loop) { |
| 303 ASSERT(loop_ == NULL); | 316 ASSERT(loop_ == NULL); |
| 304 ASSERT((loop == NULL) || loop->is_loop_header()); | 317 ASSERT((loop == NULL) || loop->is_loop_header()); |
| 305 loop_ = loop; | 318 loop_ = loop; |
| 306 } | 319 } |
| 307 | 320 |
| 321 BlockEntryInstr* last_block() const { return last_block_; } |
| 322 void set_last_block(BlockEntryInstr* last_block) { |
| 323 last_block_ = last_block; |
| 324 } |
| 325 |
| 326 intptr_t loop_id() const { return loop_id_; } |
| 327 void set_loop_id(intptr_t loop_id) { loop_id_ = loop_id; } |
| 328 |
| 308 private: | 329 private: |
| 309 BlockEntryInstr* entry_; | 330 BlockEntryInstr* entry_; |
| 310 BlockInfo* loop_; | 331 BlockInfo* loop_; |
| 311 bool is_loop_header_; | 332 bool is_loop_header_; |
| 312 | 333 |
| 334 BlockEntryInstr* last_block_; |
| 335 intptr_t loop_id_; |
| 336 |
| 313 DISALLOW_COPY_AND_ASSIGN(BlockInfo); | 337 DISALLOW_COPY_AND_ASSIGN(BlockInfo); |
| 314 }; | 338 }; |
| 315 | 339 |
| 316 | 340 |
| 317 // UsePosition represents a single use of an SSA value by some instruction. | 341 // UsePosition represents a single use of an SSA value by some instruction. |
| 318 // It points to a location slot which either tells register allocator | 342 // It points to a location slot which either tells register allocator |
| 319 // where instruction expects the value (if slot contains a fixed location) or | 343 // where instruction expects the value (if slot contains a fixed location) or |
| 320 // asks register allocator to allocate storage (register or spill slot) for | 344 // asks register allocator to allocate storage (register or spill slot) for |
| 321 // this use with certain properties (if slot contains an unallocated location). | 345 // this use with certain properties (if slot contains an unallocated location). |
| 322 class UsePosition : public ZoneAllocated { | 346 class UsePosition : public ZoneAllocated { |
| (...skipping 137 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 460 : vreg_(vreg), | 484 : vreg_(vreg), |
| 461 representation_(rep), | 485 representation_(rep), |
| 462 assigned_location_(), | 486 assigned_location_(), |
| 463 spill_slot_(), | 487 spill_slot_(), |
| 464 uses_(NULL), | 488 uses_(NULL), |
| 465 first_use_interval_(NULL), | 489 first_use_interval_(NULL), |
| 466 last_use_interval_(NULL), | 490 last_use_interval_(NULL), |
| 467 first_safepoint_(NULL), | 491 first_safepoint_(NULL), |
| 468 last_safepoint_(NULL), | 492 last_safepoint_(NULL), |
| 469 next_sibling_(NULL), | 493 next_sibling_(NULL), |
| 494 has_only_any_uses_in_loops_(0), |
| 495 is_loop_phi_(false), |
| 470 finger_() { | 496 finger_() { |
| 471 } | 497 } |
| 472 | 498 |
| 473 static LiveRange* MakeTemp(intptr_t pos, Location* location_slot); | 499 static LiveRange* MakeTemp(intptr_t pos, Location* location_slot); |
| 474 | 500 |
| 475 intptr_t vreg() const { return vreg_; } | 501 intptr_t vreg() const { return vreg_; } |
| 476 Location::Representation representation() const { return representation_; } | 502 Location::Representation representation() const { return representation_; } |
| 477 LiveRange* next_sibling() const { return next_sibling_; } | 503 LiveRange* next_sibling() const { return next_sibling_; } |
| 478 UsePosition* first_use() const { return uses_; } | 504 UsePosition* first_use() const { return uses_; } |
| 479 void set_first_use(UsePosition* use) { uses_ = use; } | 505 void set_first_use(UsePosition* use) { uses_ = use; } |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 517 return (Start() <= pos) && (pos < End()); | 543 return (Start() <= pos) && (pos < End()); |
| 518 } | 544 } |
| 519 | 545 |
| 520 // True if the range contains the given position. | 546 // True if the range contains the given position. |
| 521 bool Contains(intptr_t pos) const; | 547 bool Contains(intptr_t pos) const; |
| 522 | 548 |
| 523 Location spill_slot() const { | 549 Location spill_slot() const { |
| 524 return spill_slot_; | 550 return spill_slot_; |
| 525 } | 551 } |
| 526 | 552 |
| 553 bool HasOnlyUnconstrainedUsesInLoop(intptr_t loop_id) const { |
| 554 if (loop_id < kBitsPerWord) { |
| 555 const intptr_t mask = static_cast<intptr_t>(1) << loop_id; |
| 556 return (has_only_any_uses_in_loops_ & mask) != 0; |
| 557 } |
| 558 return false; |
| 559 } |
| 560 |
| 561 void MarkHasOnlyUnconstrainedUsesInLoop(intptr_t loop_id) { |
| 562 if (loop_id < kBitsPerWord) { |
| 563 has_only_any_uses_in_loops_ |= static_cast<intptr_t>(1) << loop_id; |
| 564 } |
| 565 } |
| 566 |
| 567 bool is_loop_phi() const { return is_loop_phi_; } |
| 568 void mark_loop_phi() { |
| 569 is_loop_phi_ = true; |
| 570 } |
| 571 |
| 527 private: | 572 private: |
| 528 LiveRange(intptr_t vreg, | 573 LiveRange(intptr_t vreg, |
| 529 Location::Representation rep, | 574 Location::Representation rep, |
| 530 UsePosition* uses, | 575 UsePosition* uses, |
| 531 UseInterval* first_use_interval, | 576 UseInterval* first_use_interval, |
| 532 UseInterval* last_use_interval, | 577 UseInterval* last_use_interval, |
| 533 SafepointPosition* first_safepoint, | 578 SafepointPosition* first_safepoint, |
| 534 LiveRange* next_sibling) | 579 LiveRange* next_sibling) |
| 535 : vreg_(vreg), | 580 : vreg_(vreg), |
| 536 representation_(rep), | 581 representation_(rep), |
| 537 assigned_location_(), | 582 assigned_location_(), |
| 538 uses_(uses), | 583 uses_(uses), |
| 539 first_use_interval_(first_use_interval), | 584 first_use_interval_(first_use_interval), |
| 540 last_use_interval_(last_use_interval), | 585 last_use_interval_(last_use_interval), |
| 541 first_safepoint_(first_safepoint), | 586 first_safepoint_(first_safepoint), |
| 542 last_safepoint_(NULL), | 587 last_safepoint_(NULL), |
| 543 next_sibling_(next_sibling), | 588 next_sibling_(next_sibling), |
| 589 has_only_any_uses_in_loops_(0), |
| 590 is_loop_phi_(false), |
| 544 finger_() { | 591 finger_() { |
| 545 } | 592 } |
| 546 | 593 |
| 547 const intptr_t vreg_; | 594 const intptr_t vreg_; |
| 548 Location::Representation representation_; | 595 Location::Representation representation_; |
| 549 Location assigned_location_; | 596 Location assigned_location_; |
| 550 Location spill_slot_; | 597 Location spill_slot_; |
| 551 | 598 |
| 552 UsePosition* uses_; | 599 UsePosition* uses_; |
| 553 UseInterval* first_use_interval_; | 600 UseInterval* first_use_interval_; |
| 554 UseInterval* last_use_interval_; | 601 UseInterval* last_use_interval_; |
| 555 | 602 |
| 556 SafepointPosition* first_safepoint_; | 603 SafepointPosition* first_safepoint_; |
| 557 SafepointPosition* last_safepoint_; | 604 SafepointPosition* last_safepoint_; |
| 558 | 605 |
| 559 LiveRange* next_sibling_; | 606 LiveRange* next_sibling_; |
| 560 | 607 |
| 608 intptr_t has_only_any_uses_in_loops_; |
| 609 bool is_loop_phi_; |
| 610 |
| 561 AllocationFinger finger_; | 611 AllocationFinger finger_; |
| 562 | 612 |
| 563 DISALLOW_COPY_AND_ASSIGN(LiveRange); | 613 DISALLOW_COPY_AND_ASSIGN(LiveRange); |
| 564 }; | 614 }; |
| 565 | 615 |
| 566 | 616 |
| 567 } // namespace dart | 617 } // namespace dart |
| 568 | 618 |
| 569 #endif // VM_FLOW_GRAPH_ALLOCATOR_H_ | 619 #endif // VM_FLOW_GRAPH_ALLOCATOR_H_ |
| OLD | NEW |