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 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
87 LiveRange* MakeLiveRangeForTemporary(); | 87 LiveRange* MakeLiveRangeForTemporary(); |
88 | 88 |
89 // Visit instructions in the postorder and build live ranges for | 89 // Visit instructions in the postorder and build live ranges for |
90 // all SSA values. | 90 // all SSA values. |
91 void BuildLiveRanges(); | 91 void BuildLiveRanges(); |
92 Instruction* ConnectOutgoingPhiMoves(BlockEntryInstr* block); | 92 Instruction* ConnectOutgoingPhiMoves(BlockEntryInstr* block); |
93 void ProcessEnvironmentUses(BlockEntryInstr* block, Instruction* current); | 93 void ProcessEnvironmentUses(BlockEntryInstr* block, Instruction* current); |
94 void ProcessOneInstruction(BlockEntryInstr* block, Instruction* instr); | 94 void ProcessOneInstruction(BlockEntryInstr* block, Instruction* instr); |
95 void ConnectIncomingPhiMoves(BlockEntryInstr* block); | 95 void ConnectIncomingPhiMoves(BlockEntryInstr* block); |
96 void BlockLocation(Location loc, intptr_t from, intptr_t to); | 96 void BlockLocation(Location loc, intptr_t from, intptr_t to); |
| 97 void BlockRegisterLocation(Location loc, |
| 98 intptr_t from, |
| 99 intptr_t to, |
| 100 bool* blocked_registers, |
| 101 LiveRange** blocking_ranges); |
| 102 |
| 103 intptr_t NumberOfRegisters() const { return number_of_registers_; } |
97 | 104 |
98 // Find all safepoints that are covered by this live range. | 105 // Find all safepoints that are covered by this live range. |
99 void AssignSafepoints(LiveRange* range); | 106 void AssignSafepoints(LiveRange* range); |
100 | 107 |
| 108 void PrepareForAllocation(Location::Kind register_kind, |
| 109 intptr_t number_of_registers, |
| 110 const GrowableArray<LiveRange*>& unallocated, |
| 111 LiveRange** blocking_ranges, |
| 112 bool* blocked_registers); |
| 113 |
| 114 |
101 // Process live ranges sorted by their start and assign registers | 115 // Process live ranges sorted by their start and assign registers |
102 // to them | 116 // to them |
103 void AllocateCPURegisters(); | 117 void AllocateUnallocatedRanges(); |
104 void AdvanceActiveIntervals(const intptr_t start); | 118 void AdvanceActiveIntervals(const intptr_t start); |
105 | 119 |
106 // Connect split siblings over non-linear control flow edges. | 120 // Connect split siblings over non-linear control flow edges. |
107 void ResolveControlFlow(); | 121 void ResolveControlFlow(); |
108 void ConnectSplitSiblings(LiveRange* range, | 122 void ConnectSplitSiblings(LiveRange* range, |
109 BlockEntryInstr* source_block, | 123 BlockEntryInstr* source_block, |
110 BlockEntryInstr* target_block); | 124 BlockEntryInstr* target_block); |
111 | 125 |
112 | 126 |
113 // Update location slot corresponding to the use with location allocated for | 127 // Update location slot corresponding to the use with location allocated for |
114 // the use's live range. | 128 // the use's live range. |
115 void ConvertUseTo(UsePosition* use, Location loc); | 129 void ConvertUseTo(UsePosition* use, Location loc); |
116 void ConvertAllUses(LiveRange* range); | 130 void ConvertAllUses(LiveRange* range); |
117 | 131 |
118 // Add live range to the list of unallocated live ranges to be processed | 132 // Add live range to the list of unallocated live ranges to be processed |
119 // by the allocator. | 133 // by the allocator. |
120 void AddToUnallocated(LiveRange* range); | 134 void AddToUnallocated(LiveRange* range); |
| 135 void CompleteRange(LiveRange* range, Location::Kind kind); |
121 #if defined(DEBUG) | 136 #if defined(DEBUG) |
122 bool UnallocatedIsSorted(); | 137 bool UnallocatedIsSorted(); |
123 #endif | 138 #endif |
124 | 139 |
125 // Try to find a free register for an unallocated live range. | 140 // Try to find a free register for an unallocated live range. |
126 bool AllocateFreeRegister(LiveRange* unallocated); | 141 bool AllocateFreeRegister(LiveRange* unallocated); |
127 | 142 |
128 // Try to find a register that can be used by a given live range. | 143 // Try to find a register that can be used by a given live range. |
129 // If all registers are occupied consider evicting interference for | 144 // If all registers are occupied consider evicting interference for |
130 // a register that is going to be used as far from the start of | 145 // a register that is going to be used as far from the start of |
131 // the unallocated live range as possible. | 146 // the unallocated live range as possible. |
132 void AllocateAnyRegister(LiveRange* unallocated); | 147 void AllocateAnyRegister(LiveRange* unallocated); |
133 | 148 |
134 // Assign selected non-free register to an unallocated live range and | 149 // Assign selected non-free register to an unallocated live range and |
135 // evict any interference that can be evicted by splitting and spilling | 150 // evict any interference that can be evicted by splitting and spilling |
136 // parts of interfering live ranges. Place non-spilled parts into | 151 // parts of interfering live ranges. Place non-spilled parts into |
137 // the list of unallocated ranges. | 152 // the list of unallocated ranges. |
138 void AssignNonFreeRegister(LiveRange* unallocated, Register reg); | 153 void AssignNonFreeRegister(LiveRange* unallocated, intptr_t reg); |
139 bool EvictIntersection(LiveRange* allocated, LiveRange* unallocated); | 154 bool EvictIntersection(LiveRange* allocated, LiveRange* unallocated); |
140 void RemoveEvicted(Register reg, intptr_t first_evicted); | 155 void RemoveEvicted(intptr_t reg, intptr_t first_evicted); |
141 | 156 |
142 // Find first intersection between unallocated live range and | 157 // Find first intersection between unallocated live range and |
143 // live ranges currently allocated to the given register. | 158 // live ranges currently allocated to the given register. |
144 intptr_t FirstIntersectionWithAllocated(Register reg, | 159 intptr_t FirstIntersectionWithAllocated(intptr_t reg, |
145 LiveRange* unallocated); | 160 LiveRange* unallocated); |
146 | 161 |
147 bool UpdateFreeUntil(Register reg, | 162 bool UpdateFreeUntil(intptr_t reg, |
148 LiveRange* unallocated, | 163 LiveRange* unallocated, |
149 intptr_t* cur_free_until, | 164 intptr_t* cur_free_until, |
150 intptr_t* cur_blocked_at); | 165 intptr_t* cur_blocked_at); |
151 | 166 |
152 // Split given live range in an optimal position between given positions. | 167 // Split given live range in an optimal position between given positions. |
153 LiveRange* SplitBetween(LiveRange* range, intptr_t from, intptr_t to); | 168 LiveRange* SplitBetween(LiveRange* range, intptr_t from, intptr_t to); |
154 | 169 |
155 // Find a spill slot that can be used by the given live range. | 170 // Find a spill slot that can be used by the given live range. |
156 void AllocateSpillSlotFor(LiveRange* range); | 171 void AllocateSpillSlotFor(LiveRange* range); |
157 | 172 |
158 // Allocate the given live range to a spill slot. | 173 // Allocate the given live range to a spill slot. |
159 void Spill(LiveRange* range); | 174 void Spill(LiveRange* range); |
160 | 175 |
161 // Spill the given live range from the given position onwards. | 176 // Spill the given live range from the given position onwards. |
162 void SpillAfter(LiveRange* range, intptr_t from); | 177 void SpillAfter(LiveRange* range, intptr_t from); |
163 | 178 |
164 // Spill the given live range from the given position until some | 179 // Spill the given live range from the given position until some |
165 // position preceding the to position. | 180 // position preceding the to position. |
166 void SpillBetween(LiveRange* range, intptr_t from, intptr_t to); | 181 void SpillBetween(LiveRange* range, intptr_t from, intptr_t to); |
167 | 182 |
168 // Mark the live range as a live object pointer at all safepoints | 183 // Mark the live range as a live object pointer at all safepoints |
169 // contained in the range. | 184 // contained in the range. |
170 void MarkAsObjectAtSafepoints(LiveRange* range); | 185 void MarkAsObjectAtSafepoints(LiveRange* range); |
171 | 186 |
172 MoveOperands* AddMoveAt(intptr_t pos, Location to, Location from); | 187 MoveOperands* AddMoveAt(intptr_t pos, Location to, Location from); |
173 | 188 |
| 189 Location MakeRegisterLocation(intptr_t reg) { |
| 190 return Location::MachineRegisterLocation(register_kind_, reg); |
| 191 } |
| 192 |
174 void PrintLiveRanges(); | 193 void PrintLiveRanges(); |
175 | 194 |
176 const FlowGraph& flow_graph_; | 195 const FlowGraph& flow_graph_; |
177 const GrowableArray<BlockEntryInstr*>& block_order_; | 196 const GrowableArray<BlockEntryInstr*>& block_order_; |
178 const GrowableArray<BlockEntryInstr*>& postorder_; | 197 const GrowableArray<BlockEntryInstr*>& postorder_; |
179 | 198 |
180 // Mapping between lifetime positions and instructions. | 199 // Mapping between lifetime positions and instructions. |
181 GrowableArray<Instruction*> instructions_; | 200 GrowableArray<Instruction*> instructions_; |
182 | 201 |
183 // Mapping between lifetime positions and blocks containing them. | 202 // Mapping between lifetime positions and blocks containing them. |
(...skipping 13 matching lines...) Expand all Loading... |
197 // that are used by this block or its successors. | 216 // that are used by this block or its successors. |
198 GrowableArray<BitVector*> live_in_; | 217 GrowableArray<BitVector*> live_in_; |
199 | 218 |
200 // Number of virtual registers. Currently equal to the number of | 219 // Number of virtual registers. Currently equal to the number of |
201 // SSA values. | 220 // SSA values. |
202 const intptr_t vreg_count_; | 221 const intptr_t vreg_count_; |
203 | 222 |
204 // LiveRanges corresponding to SSA values. | 223 // LiveRanges corresponding to SSA values. |
205 GrowableArray<LiveRange*> live_ranges_; | 224 GrowableArray<LiveRange*> live_ranges_; |
206 | 225 |
207 // Worklist for register allocator. Always maintained sorted according | 226 GrowableArray<LiveRange*> unallocated_cpu_; |
208 // to ShouldBeAllocatedBefore predicate. | 227 GrowableArray<LiveRange*> unallocated_xmm_; |
209 GrowableArray<LiveRange*> unallocated_; | 228 |
| 229 LiveRange* cpu_regs_[kNumberOfCpuRegisters]; |
| 230 LiveRange* xmm_regs_[kNumberOfXmmRegisters]; |
| 231 |
| 232 bool blocked_cpu_registers_[kNumberOfCpuRegisters]; |
| 233 bool blocked_xmm_registers_[kNumberOfXmmRegisters]; |
210 | 234 |
211 #if defined(DEBUG) | 235 #if defined(DEBUG) |
212 GrowableArray<LiveRange*> temporaries_; | 236 GrowableArray<LiveRange*> temporaries_; |
213 #endif | 237 #endif |
214 | 238 |
215 // List of spilled live ranges. | 239 // List of spilled live ranges. |
216 GrowableArray<LiveRange*> spilled_; | 240 GrowableArray<LiveRange*> spilled_; |
217 | 241 |
218 // List of instructions containing calls. | 242 // List of instructions containing calls. |
219 GrowableArray<Instruction*> safepoints_; | 243 GrowableArray<Instruction*> safepoints_; |
220 | 244 |
| 245 Location::Kind register_kind_; |
| 246 |
| 247 intptr_t number_of_registers_; |
| 248 |
221 // Per register lists of allocated live ranges. Contain only those | 249 // Per register lists of allocated live ranges. Contain only those |
222 // ranges that can be affected by future allocation decisions. | 250 // ranges that can be affected by future allocation decisions. |
223 // Those live ranges that end before the start of the current live range are | 251 // Those live ranges that end before the start of the current live range are |
224 // removed from the list and will not be affected. | 252 // removed from the list and will not be affected. |
225 GrowableArray<LiveRange*> cpu_regs_[kNumberOfCpuRegisters]; | 253 GrowableArray<LiveRange*> registers_[kNumberOfCpuRegisters]; |
| 254 |
| 255 bool blocked_registers_[kNumberOfCpuRegisters]; |
| 256 |
| 257 |
| 258 // Worklist for register allocator. Always maintained sorted according |
| 259 // to ShouldBeAllocatedBefore predicate. |
| 260 GrowableArray<LiveRange*> unallocated_; |
226 | 261 |
227 // List of used spill slots. Contains positions after which spill slots | 262 // List of used spill slots. Contains positions after which spill slots |
228 // become free and can be reused for allocation. | 263 // become free and can be reused for allocation. |
229 GrowableArray<intptr_t> spill_slots_; | 264 GrowableArray<intptr_t> spill_slots_; |
| 265 intptr_t cpu_spill_slot_count_; |
230 | 266 |
231 bool blocked_cpu_regs_[kNumberOfCpuRegisters]; | |
232 | 267 |
233 DISALLOW_COPY_AND_ASSIGN(FlowGraphAllocator); | 268 DISALLOW_COPY_AND_ASSIGN(FlowGraphAllocator); |
234 }; | 269 }; |
235 | 270 |
236 | 271 |
237 // Additional information about a block that is not contained in a | 272 // Additional information about a block that is not contained in a |
238 // block entry. | 273 // block entry. |
239 class BlockInfo : public ZoneAllocated { | 274 class BlockInfo : public ZoneAllocated { |
240 public: | 275 public: |
241 explicit BlockInfo(BlockEntryInstr* entry) | 276 explicit BlockInfo(BlockEntryInstr* entry) |
(...skipping 26 matching lines...) Expand all Loading... |
268 | 303 |
269 | 304 |
270 // UsePosition represents a single use of an SSA value by some instruction. | 305 // UsePosition represents a single use of an SSA value by some instruction. |
271 // It points to a location slot which either tells register allocator | 306 // It points to a location slot which either tells register allocator |
272 // where instruction expects the value (if slot contains a fixed location) or | 307 // where instruction expects the value (if slot contains a fixed location) or |
273 // asks register allocator to allocate storage (register or spill slot) for | 308 // asks register allocator to allocate storage (register or spill slot) for |
274 // this use with certain properties (if slot contains an unallocated location). | 309 // this use with certain properties (if slot contains an unallocated location). |
275 class UsePosition : public ZoneAllocated { | 310 class UsePosition : public ZoneAllocated { |
276 public: | 311 public: |
277 UsePosition(intptr_t pos, UsePosition* next, Location* location_slot) | 312 UsePosition(intptr_t pos, UsePosition* next, Location* location_slot) |
278 : pos_(pos), location_slot_(location_slot), hint_(NULL), next_(next) { } | 313 : pos_(pos), location_slot_(location_slot), hint_(NULL), next_(next) { |
| 314 ASSERT(location_slot != NULL); |
| 315 } |
279 | 316 |
280 Location* location_slot() const { return location_slot_; } | 317 Location* location_slot() const { return location_slot_; } |
281 void set_location_slot(Location* location_slot) { | 318 void set_location_slot(Location* location_slot) { |
282 location_slot_ = location_slot; | 319 location_slot_ = location_slot; |
283 } | 320 } |
284 | 321 |
285 Location hint() const { | 322 Location hint() const { |
286 ASSERT(HasHint()); | 323 ASSERT(HasHint()); |
287 return *hint_; | 324 return *hint_; |
288 } | 325 } |
(...skipping 217 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
506 | 543 |
507 AllocationFinger finger_; | 544 AllocationFinger finger_; |
508 | 545 |
509 DISALLOW_COPY_AND_ASSIGN(LiveRange); | 546 DISALLOW_COPY_AND_ASSIGN(LiveRange); |
510 }; | 547 }; |
511 | 548 |
512 | 549 |
513 } // namespace dart | 550 } // namespace dart |
514 | 551 |
515 #endif // VM_FLOW_GRAPH_ALLOCATOR_H_ | 552 #endif // VM_FLOW_GRAPH_ALLOCATOR_H_ |
OLD | NEW |