| 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 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 69 // required to resolve data flow between split siblings when allocation | 69 // required to resolve data flow between split siblings when allocation |
| 70 // is finished. | 70 // is finished. |
| 71 // For specific examples see comments inside ProcessOneInstruction. | 71 // For specific examples see comments inside ProcessOneInstruction. |
| 72 // Additionally creates parallel moves at the joins' predecessors | 72 // Additionally creates parallel moves at the joins' predecessors |
| 73 // that will be used for phi resolution. | 73 // that will be used for phi resolution. |
| 74 void NumberInstructions(); | 74 void NumberInstructions(); |
| 75 Instruction* InstructionAt(intptr_t pos) const; | 75 Instruction* InstructionAt(intptr_t pos) const; |
| 76 bool IsBlockEntry(intptr_t pos) const; | 76 bool IsBlockEntry(intptr_t pos) const; |
| 77 | 77 |
| 78 LiveRange* GetLiveRange(intptr_t vreg); | 78 LiveRange* GetLiveRange(intptr_t vreg); |
| 79 LiveRange* MakeLiveRangeForTemporary(); |
| 79 | 80 |
| 80 // Visit instructions in the postorder and build live ranges for | 81 // Visit instructions in the postorder and build live ranges for |
| 81 // all SSA values. | 82 // all SSA values. |
| 82 void BuildLiveRanges(); | 83 void BuildLiveRanges(); |
| 83 Instruction* ConnectOutgoingPhiMoves(BlockEntryInstr* block); | 84 Instruction* ConnectOutgoingPhiMoves(BlockEntryInstr* block); |
| 84 void ProcessOneInstruction(BlockEntryInstr* block, Instruction* instr); | 85 void ProcessOneInstruction(BlockEntryInstr* block, Instruction* instr); |
| 85 void ConnectIncomingPhiMoves(BlockEntryInstr* block); | 86 void ConnectIncomingPhiMoves(BlockEntryInstr* block); |
| 86 void BlockLocation(Location loc, intptr_t pos); | 87 void BlockLocation(Location loc, intptr_t pos); |
| 87 | 88 |
| 88 // Process live ranges sorted by their start and assign registers | 89 // Process live ranges sorted by their start and assign registers |
| 89 // to them | 90 // to them |
| 90 void AllocateCPURegisters(); | 91 void AllocateCPURegisters(); |
| 91 void AdvanceActiveIntervals(const intptr_t start); | 92 void AdvanceActiveIntervals(const intptr_t start); |
| 92 | 93 |
| 93 // Connect split siblings over non-linear control flow edges. | 94 // Connect split siblings over non-linear control flow edges. |
| 94 void ResolveControlFlow(); | 95 void ResolveControlFlow(); |
| 95 void ConnectSplitSiblings(LiveRange* range, | 96 void ConnectSplitSiblings(LiveRange* range, |
| 96 BlockEntryInstr* source_block, | 97 BlockEntryInstr* source_block, |
| 97 BlockEntryInstr* target_block); | 98 BlockEntryInstr* target_block); |
| 98 | 99 |
| 99 | 100 |
| 100 // Update location slot corresponding to the use with location allocated for | 101 // Update location slot corresponding to the use with location allocated for |
| 101 // the use's live range. | 102 // the use's live range. |
| 102 void ConvertUseTo(UsePosition* use, Location loc); | 103 void ConvertUseTo(UsePosition* use, Location loc); |
| 103 void ConvertAllUses(LiveRange* range); | 104 void ConvertAllUses(LiveRange* range); |
| 104 | 105 |
| 105 // Add live range to the list of unallocated live ranges to be processed | 106 // Add live range to the list of unallocated live ranges to be processed |
| 106 // by the allocator. | 107 // by the allocator. |
| 107 void AddToUnallocated(LiveRange* range); | 108 void AddToUnallocated(LiveRange* range); |
| 108 #ifdef DEBUG | 109 #if defined(DEBUG) |
| 109 bool UnallocatedIsSorted(); | 110 bool UnallocatedIsSorted(); |
| 110 #endif | 111 #endif |
| 111 | 112 |
| 112 // Try to find a free register for an unallocated live range. | 113 // Try to find a free register for an unallocated live range. |
| 113 bool AllocateFreeRegister(LiveRange* unallocated); | 114 bool AllocateFreeRegister(LiveRange* unallocated); |
| 114 | 115 |
| 115 // Try to find a register that can be used by a given live range. | 116 // Try to find a register that can be used by a given live range. |
| 116 // If all registers are occupied consider evicting interference for | 117 // If all registers are occupied consider evicting interference for |
| 117 // a register that is going to be used as far from the start of | 118 // a register that is going to be used as far from the start of |
| 118 // the unallocated live range as possible. | 119 // the unallocated live range as possible. |
| (...skipping 14 matching lines...) Expand all Loading... |
| 133 | 134 |
| 134 bool UpdateFreeUntil(Register reg, | 135 bool UpdateFreeUntil(Register reg, |
| 135 LiveRange* unallocated, | 136 LiveRange* unallocated, |
| 136 intptr_t* cur_free_until, | 137 intptr_t* cur_free_until, |
| 137 intptr_t* cur_blocked_at); | 138 intptr_t* cur_blocked_at); |
| 138 | 139 |
| 139 // Split given live range in an optimal position between given positions. | 140 // Split given live range in an optimal position between given positions. |
| 140 LiveRange* SplitBetween(LiveRange* range, intptr_t from, intptr_t to); | 141 LiveRange* SplitBetween(LiveRange* range, intptr_t from, intptr_t to); |
| 141 | 142 |
| 142 // Find a spill slot that can be used by the given live range. | 143 // Find a spill slot that can be used by the given live range. |
| 143 intptr_t AllocateSpillSlotFor(LiveRange* range); | 144 void AllocateSpillSlotFor(LiveRange* range); |
| 144 | 145 |
| 145 // Allocate the given live range to a spill slot. | 146 // Allocate the given live range to a spill slot. |
| 146 void Spill(LiveRange* range); | 147 void Spill(LiveRange* range); |
| 147 | 148 |
| 148 // Spill the given live range from the given position onwards. | 149 // Spill the given live range from the given position onwards. |
| 149 void SpillAfter(LiveRange* range, intptr_t from); | 150 void SpillAfter(LiveRange* range, intptr_t from); |
| 150 | 151 |
| 151 // Spill the given live range from the given position until some | 152 // Spill the given live range from the given position until some |
| 152 // position preceeding the to position. | 153 // position preceeding the to position. |
| 153 void SpillBetween(LiveRange* range, intptr_t from, intptr_t to); | 154 void SpillBetween(LiveRange* range, intptr_t from, intptr_t to); |
| (...skipping 29 matching lines...) Expand all Loading... |
| 183 // SSA values. | 184 // SSA values. |
| 184 const intptr_t vreg_count_; | 185 const intptr_t vreg_count_; |
| 185 | 186 |
| 186 // LiveRanges corresponding to SSA values. | 187 // LiveRanges corresponding to SSA values. |
| 187 GrowableArray<LiveRange*> live_ranges_; | 188 GrowableArray<LiveRange*> live_ranges_; |
| 188 | 189 |
| 189 // Worklist for register allocator. Always maintained sorted according | 190 // Worklist for register allocator. Always maintained sorted according |
| 190 // to ShouldBeAllocatedBefore predicate. | 191 // to ShouldBeAllocatedBefore predicate. |
| 191 GrowableArray<LiveRange*> unallocated_; | 192 GrowableArray<LiveRange*> unallocated_; |
| 192 | 193 |
| 194 #if defined(DEBUG) |
| 195 GrowableArray<LiveRange*> temporaries_; |
| 196 #endif |
| 197 |
| 198 GrowableArray<LiveRange*> spilled_; |
| 199 |
| 193 // Per register lists of allocated live ranges. Contain only those | 200 // Per register lists of allocated live ranges. Contain only those |
| 194 // ranges that can be affected by future allocation decisions. | 201 // ranges that can be affected by future allocation decisions. |
| 195 // Those live ranges that end before the start of the current live range are | 202 // Those live ranges that end before the start of the current live range are |
| 196 // removed from the list and will not be affected. | 203 // removed from the list and will not be affected. |
| 197 GrowableArray<LiveRange*> cpu_regs_[kNumberOfCpuRegisters]; | 204 GrowableArray<LiveRange*> cpu_regs_[kNumberOfCpuRegisters]; |
| 198 | 205 |
| 199 // List of used spill slots. Contain positions after which spill slots | 206 // List of used spill slots. Contain positions after which spill slots |
| 200 // become free and can be reused for allocation. | 207 // become free and can be reused for allocation. |
| 201 GrowableArray<intptr_t> spill_slots_; | 208 GrowableArray<intptr_t> spill_slots_; |
| 202 | 209 |
| (...skipping 111 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 314 DISALLOW_COPY_AND_ASSIGN(AllocationFinger); | 321 DISALLOW_COPY_AND_ASSIGN(AllocationFinger); |
| 315 }; | 322 }; |
| 316 | 323 |
| 317 | 324 |
| 318 // LiveRange represents a sequence of UseIntervals for a given SSA value. | 325 // LiveRange represents a sequence of UseIntervals for a given SSA value. |
| 319 class LiveRange : public ZoneAllocated { | 326 class LiveRange : public ZoneAllocated { |
| 320 public: | 327 public: |
| 321 explicit LiveRange(intptr_t vreg) | 328 explicit LiveRange(intptr_t vreg) |
| 322 : vreg_(vreg), | 329 : vreg_(vreg), |
| 323 assigned_location_(), | 330 assigned_location_(), |
| 331 spill_slot_(), |
| 324 uses_(NULL), | 332 uses_(NULL), |
| 325 first_use_interval_(NULL), | 333 first_use_interval_(NULL), |
| 326 last_use_interval_(NULL), | 334 last_use_interval_(NULL), |
| 327 next_sibling_(NULL), | 335 next_sibling_(NULL), |
| 328 finger_() { | 336 finger_() { |
| 329 } | 337 } |
| 330 | 338 |
| 331 static LiveRange* MakeTemp(intptr_t pos, Location* location_slot); | 339 static LiveRange* MakeTemp(intptr_t pos, Location* location_slot); |
| 332 | 340 |
| 333 intptr_t vreg() const { return vreg_; } | 341 intptr_t vreg() const { return vreg_; } |
| 334 LiveRange* next_sibling() const { return next_sibling_; } | 342 LiveRange* next_sibling() const { return next_sibling_; } |
| 335 UsePosition* first_use() const { return uses_; } | 343 UsePosition* first_use() const { return uses_; } |
| 336 void set_first_use(UsePosition* use) { uses_ = use; } | 344 void set_first_use(UsePosition* use) { uses_ = use; } |
| 337 UseInterval* first_use_interval() const { return first_use_interval_; } | 345 UseInterval* first_use_interval() const { return first_use_interval_; } |
| 338 UseInterval* last_use_interval() const { return last_use_interval_; } | 346 UseInterval* last_use_interval() const { return last_use_interval_; } |
| 339 Location assigned_location() const { return assigned_location_; } | 347 Location assigned_location() const { return assigned_location_; } |
| 340 intptr_t Start() const { return first_use_interval()->start(); } | 348 intptr_t Start() const { return first_use_interval()->start(); } |
| 341 intptr_t End() const { return last_use_interval()->end(); } | 349 intptr_t End() const { return last_use_interval()->end(); } |
| 342 | 350 |
| 343 AllocationFinger* finger() { return &finger_; } | 351 AllocationFinger* finger() { return &finger_; } |
| 344 | 352 |
| 345 void set_assigned_location(Location location) { | 353 void set_assigned_location(Location location) { |
| 346 assigned_location_ = location; | 354 assigned_location_ = location; |
| 347 } | 355 } |
| 348 | 356 |
| 357 void set_spill_slot(Location spill_slot) { |
| 358 spill_slot_ = spill_slot; |
| 359 } |
| 360 |
| 349 void DefineAt(intptr_t pos); | 361 void DefineAt(intptr_t pos); |
| 350 | 362 |
| 351 void AddUse(intptr_t pos, Location* location_slot); | 363 void AddUse(intptr_t pos, Location* location_slot); |
| 352 void AddUseInterval(intptr_t start, intptr_t end); | 364 void AddUseInterval(intptr_t start, intptr_t end); |
| 353 | 365 |
| 354 void Print(); | 366 void Print(); |
| 355 | 367 |
| 356 void AssignLocation(UseInterval* use, Location loc); | 368 void AssignLocation(UseInterval* use, Location loc); |
| 357 | 369 |
| 358 LiveRange* SplitAt(intptr_t pos); | 370 LiveRange* SplitAt(intptr_t pos); |
| 359 | 371 |
| 360 bool CanCover(intptr_t pos) const { | 372 bool CanCover(intptr_t pos) const { |
| 361 return (Start() <= pos) && (pos < End()); | 373 return (Start() <= pos) && (pos < End()); |
| 362 } | 374 } |
| 363 | 375 |
| 376 Location spill_slot() const { |
| 377 return spill_slot_; |
| 378 } |
| 379 |
| 364 private: | 380 private: |
| 365 LiveRange(intptr_t vreg, | 381 LiveRange(intptr_t vreg, |
| 366 UsePosition* uses, | 382 UsePosition* uses, |
| 367 UseInterval* first_use_interval, | 383 UseInterval* first_use_interval, |
| 368 UseInterval* last_use_interval, | 384 UseInterval* last_use_interval, |
| 369 LiveRange* next_sibling) | 385 LiveRange* next_sibling) |
| 370 : vreg_(vreg), | 386 : vreg_(vreg), |
| 371 assigned_location_(), | 387 assigned_location_(), |
| 372 uses_(uses), | 388 uses_(uses), |
| 373 first_use_interval_(first_use_interval), | 389 first_use_interval_(first_use_interval), |
| 374 last_use_interval_(last_use_interval), | 390 last_use_interval_(last_use_interval), |
| 375 next_sibling_(next_sibling), | 391 next_sibling_(next_sibling), |
| 376 finger_() { | 392 finger_() { |
| 377 } | 393 } |
| 378 | 394 |
| 379 const intptr_t vreg_; | 395 const intptr_t vreg_; |
| 380 Location assigned_location_; | 396 Location assigned_location_; |
| 397 Location spill_slot_; |
| 381 | 398 |
| 382 UsePosition* uses_; | 399 UsePosition* uses_; |
| 383 UseInterval* first_use_interval_; | 400 UseInterval* first_use_interval_; |
| 384 UseInterval* last_use_interval_; | 401 UseInterval* last_use_interval_; |
| 385 | 402 |
| 386 LiveRange* next_sibling_; | 403 LiveRange* next_sibling_; |
| 387 | 404 |
| 388 AllocationFinger finger_; | 405 AllocationFinger finger_; |
| 389 | 406 |
| 390 DISALLOW_COPY_AND_ASSIGN(LiveRange); | 407 DISALLOW_COPY_AND_ASSIGN(LiveRange); |
| 391 }; | 408 }; |
| 392 | 409 |
| 393 | 410 |
| 394 } // namespace dart | 411 } // namespace dart |
| 395 | 412 |
| 396 #endif // VM_FLOW_GRAPH_ALLOCATOR_H_ | 413 #endif // VM_FLOW_GRAPH_ALLOCATOR_H_ |
| OLD | NEW |