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/zone-containers.h" | 9 #include "src/zone-containers.h" |
10 | 10 |
11 namespace v8 { | 11 namespace v8 { |
12 namespace internal { | 12 namespace internal { |
13 namespace compiler { | 13 namespace compiler { |
14 | 14 |
15 class PipelineStatistics; | |
16 | |
17 enum RegisterKind { | 15 enum RegisterKind { |
18 UNALLOCATED_REGISTERS, | 16 UNALLOCATED_REGISTERS, |
19 GENERAL_REGISTERS, | 17 GENERAL_REGISTERS, |
20 DOUBLE_REGISTERS | 18 DOUBLE_REGISTERS |
21 }; | 19 }; |
22 | 20 |
23 | 21 |
24 // This class represents a single point of a InstructionOperand's lifetime. For | 22 // This class represents a single point of a InstructionOperand's lifetime. For |
25 // each instruction there are exactly two lifetime positions: the beginning and | 23 // each instruction there are exactly two lifetime positions: the beginning and |
26 // the end of the instruction. Lifetime positions for different instructions are | 24 // the end of the instruction. Lifetime positions for different instructions are |
(...skipping 286 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
313 InstructionOperand* current_hint_operand_; | 311 InstructionOperand* current_hint_operand_; |
314 InstructionOperand* spill_operand_; | 312 InstructionOperand* spill_operand_; |
315 int spill_start_index_; | 313 int spill_start_index_; |
316 | 314 |
317 friend class RegisterAllocator; // Assigns to kind_. | 315 friend class RegisterAllocator; // Assigns to kind_. |
318 | 316 |
319 DISALLOW_COPY_AND_ASSIGN(LiveRange); | 317 DISALLOW_COPY_AND_ASSIGN(LiveRange); |
320 }; | 318 }; |
321 | 319 |
322 | 320 |
323 class RegisterAllocator FINAL { | 321 class RegisterAllocator FINAL : public ZoneObject { |
324 public: | 322 public: |
325 explicit RegisterAllocator(const RegisterConfiguration* config, | 323 explicit RegisterAllocator(const RegisterConfiguration* config, |
326 Zone* local_zone, Frame* frame, | 324 Zone* local_zone, Frame* frame, |
327 InstructionSequence* code, | 325 InstructionSequence* code, |
328 const char* debug_name = nullptr); | 326 const char* debug_name = nullptr); |
329 | 327 |
330 bool Allocate(PipelineStatistics* stats = NULL); | |
331 bool AllocationOk() { return allocation_ok_; } | 328 bool AllocationOk() { return allocation_ok_; } |
332 BitVector* assigned_registers() { return assigned_registers_; } | |
333 BitVector* assigned_double_registers() { return assigned_double_registers_; } | |
334 | 329 |
335 const ZoneList<LiveRange*>& live_ranges() const { return live_ranges_; } | 330 const ZoneList<LiveRange*>& live_ranges() const { return live_ranges_; } |
336 const ZoneVector<LiveRange*>& fixed_live_ranges() const { | 331 const ZoneVector<LiveRange*>& fixed_live_ranges() const { |
337 return fixed_live_ranges_; | 332 return fixed_live_ranges_; |
338 } | 333 } |
339 const ZoneVector<LiveRange*>& fixed_double_live_ranges() const { | 334 const ZoneVector<LiveRange*>& fixed_double_live_ranges() const { |
340 return fixed_double_live_ranges_; | 335 return fixed_double_live_ranges_; |
341 } | 336 } |
342 InstructionSequence* code() const { return code_; } | 337 InstructionSequence* code() const { return code_; } |
343 // This zone is for datastructures only needed during register allocation. | 338 // This zone is for datastructures only needed during register allocation. |
344 Zone* local_zone() const { return local_zone_; } | 339 Zone* local_zone() const { return local_zone_; } |
345 | 340 |
| 341 // Phase 1 : insert moves to account for fixed register operands. |
| 342 void MeetRegisterConstraints(); |
| 343 |
| 344 // Phase 2: deconstruct SSA by inserting moves in successors and the headers |
| 345 // of blocks containing phis. |
| 346 void ResolvePhis(); |
| 347 |
| 348 // Phase 3: compute liveness of all virtual register. |
| 349 void BuildLiveRanges(); |
| 350 bool ExistsUseWithoutDefinition(); |
| 351 |
| 352 // Phase 4: compute register assignments. |
| 353 void AllocateGeneralRegisters(); |
| 354 void AllocateDoubleRegisters(); |
| 355 |
| 356 // Phase 5: compute values for pointer maps. |
| 357 void PopulatePointerMaps(); // TODO(titzer): rename to PopulateReferenceMaps. |
| 358 |
| 359 // Phase 6: reconnect split ranges with moves. |
| 360 void ConnectRanges(); |
| 361 |
| 362 // Phase 7: insert moves to connect ranges across basic blocks. |
| 363 void ResolveControlFlow(); |
| 364 |
346 private: | 365 private: |
347 int GetVirtualRegister() { | 366 int GetVirtualRegister() { |
348 int vreg = code()->NextVirtualRegister(); | 367 int vreg = code()->NextVirtualRegister(); |
349 if (vreg >= UnallocatedOperand::kMaxVirtualRegisters) { | 368 if (vreg >= UnallocatedOperand::kMaxVirtualRegisters) { |
350 allocation_ok_ = false; | 369 allocation_ok_ = false; |
351 // Maintain the invariant that we return something below the maximum. | 370 // Maintain the invariant that we return something below the maximum. |
352 return 0; | 371 return 0; |
353 } | 372 } |
354 return vreg; | 373 return vreg; |
355 } | 374 } |
356 | 375 |
357 // Checks whether the value of a given virtual register is a reference. | 376 // Checks whether the value of a given virtual register is a reference. |
358 // TODO(titzer): rename this to IsReference. | 377 // TODO(titzer): rename this to IsReference. |
359 bool HasTaggedValue(int virtual_register) const; | 378 bool HasTaggedValue(int virtual_register) const; |
360 | 379 |
361 // Returns the register kind required by the given virtual register. | 380 // Returns the register kind required by the given virtual register. |
362 RegisterKind RequiredRegisterKind(int virtual_register) const; | 381 RegisterKind RequiredRegisterKind(int virtual_register) const; |
363 | 382 |
364 // This zone is for InstructionOperands and moves that live beyond register | 383 // This zone is for InstructionOperands and moves that live beyond register |
365 // allocation. | 384 // allocation. |
366 Zone* code_zone() const { return code()->zone(); } | 385 Zone* code_zone() const { return code()->zone(); } |
367 | 386 |
| 387 BitVector* assigned_registers() { return assigned_registers_; } |
| 388 BitVector* assigned_double_registers() { return assigned_double_registers_; } |
| 389 |
368 #ifdef DEBUG | 390 #ifdef DEBUG |
369 void Verify() const; | 391 void Verify() const; |
370 #endif | 392 #endif |
371 | 393 |
372 void MeetRegisterConstraints(); | |
373 void ResolvePhis(); | |
374 void BuildLiveRanges(); | |
375 void AllocateGeneralRegisters(); | |
376 void AllocateDoubleRegisters(); | |
377 void ConnectRanges(); | |
378 void ResolveControlFlow(); | |
379 void PopulatePointerMaps(); // TODO(titzer): rename to PopulateReferenceMaps. | |
380 void AllocateRegisters(); | 394 void AllocateRegisters(); |
381 bool CanEagerlyResolveControlFlow(const InstructionBlock* block) const; | 395 bool CanEagerlyResolveControlFlow(const InstructionBlock* block) const; |
382 bool SafePointsAreInOrder() const; | 396 bool SafePointsAreInOrder() const; |
383 | 397 |
384 // Liveness analysis support. | 398 // Liveness analysis support. |
385 void InitializeLivenessAnalysis(); | 399 void InitializeLivenessAnalysis(); |
386 BitVector* ComputeLiveOut(const InstructionBlock* block); | 400 BitVector* ComputeLiveOut(const InstructionBlock* block); |
387 void AddInitialIntervals(const InstructionBlock* block, BitVector* live_out); | 401 void AddInitialIntervals(const InstructionBlock* block, BitVector* live_out); |
388 bool IsOutputRegisterOf(Instruction* instr, int index); | 402 bool IsOutputRegisterOf(Instruction* instr, int index); |
389 bool IsOutputDoubleRegisterOf(Instruction* instr, int index); | 403 bool IsOutputDoubleRegisterOf(Instruction* instr, int index); |
390 void ProcessInstructions(const InstructionBlock* block, BitVector* live); | 404 void ProcessInstructions(const InstructionBlock* block, BitVector* live); |
391 bool ExistsUseWithoutDefinition(); | |
392 void MeetRegisterConstraints(const InstructionBlock* block); | 405 void MeetRegisterConstraints(const InstructionBlock* block); |
393 void MeetConstraintsBetween(Instruction* first, Instruction* second, | 406 void MeetConstraintsBetween(Instruction* first, Instruction* second, |
394 int gap_index); | 407 int gap_index); |
395 void MeetRegisterConstraintsForLastInstructionInBlock( | 408 void MeetRegisterConstraintsForLastInstructionInBlock( |
396 const InstructionBlock* block); | 409 const InstructionBlock* block); |
397 void ResolvePhis(const InstructionBlock* block); | 410 void ResolvePhis(const InstructionBlock* block); |
398 | 411 |
399 // Helper methods for building intervals. | 412 // Helper methods for building intervals. |
400 InstructionOperand* AllocateFixed(UnallocatedOperand* operand, int pos, | 413 InstructionOperand* AllocateFixed(UnallocatedOperand* operand, int pos, |
401 bool is_tagged); | 414 bool is_tagged); |
(...skipping 133 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
535 #endif | 548 #endif |
536 | 549 |
537 DISALLOW_COPY_AND_ASSIGN(RegisterAllocator); | 550 DISALLOW_COPY_AND_ASSIGN(RegisterAllocator); |
538 }; | 551 }; |
539 | 552 |
540 } | 553 } |
541 } | 554 } |
542 } // namespace v8::internal::compiler | 555 } // namespace v8::internal::compiler |
543 | 556 |
544 #endif // V8_REGISTER_ALLOCATOR_H_ | 557 #endif // V8_REGISTER_ALLOCATOR_H_ |
OLD | NEW |