• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2020 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #ifndef V8_COMPILER_BACKEND_MID_TIER_REGISTER_ALLOCATOR_H_
6 #define V8_COMPILER_BACKEND_MID_TIER_REGISTER_ALLOCATOR_H_
7 
8 #include "src/base/compiler-specific.h"
9 #include "src/common/globals.h"
10 #include "src/compiler/backend/instruction.h"
11 #include "src/compiler/backend/register-allocation.h"
12 #include "src/flags/flags.h"
13 #include "src/utils/bit-vector.h"
14 #include "src/zone/zone-containers.h"
15 #include "src/zone/zone.h"
16 
17 namespace v8 {
18 namespace internal {
19 
20 class TickCounter;
21 
22 namespace compiler {
23 
24 class BlockState;
25 class VirtualRegisterData;
26 
27 // The MidTierRegisterAllocator is a register allocator specifically designed to
28 // perform register allocation as fast as possible while minimizing spill moves.
29 
30 class MidTierRegisterAllocationData final : public RegisterAllocationData {
31  public:
32   MidTierRegisterAllocationData(const RegisterConfiguration* config,
33                                 Zone* allocation_zone, Frame* frame,
34                                 InstructionSequence* code,
35                                 TickCounter* tick_counter,
36                                 const char* debug_name = nullptr);
37   MidTierRegisterAllocationData(const MidTierRegisterAllocationData&) = delete;
38   MidTierRegisterAllocationData& operator=(
39       const MidTierRegisterAllocationData&) = delete;
40 
cast(RegisterAllocationData * data)41   static MidTierRegisterAllocationData* cast(RegisterAllocationData* data) {
42     DCHECK_EQ(data->type(), Type::kMidTier);
43     return static_cast<MidTierRegisterAllocationData*>(data);
44   }
45 
46   VirtualRegisterData& VirtualRegisterDataFor(int virtual_register);
47   MachineRepresentation RepresentationFor(int virtual_register);
48 
49   // Add a gap move between the given operands |from| and |to|.
50   MoveOperands* AddGapMove(int instr_index, Instruction::GapPosition position,
51                            const InstructionOperand& from,
52                            const InstructionOperand& to);
53 
54   // Adds a gap move where both sides are PendingOperand operands.
55   MoveOperands* AddPendingOperandGapMove(int instr_index,
56                                          Instruction::GapPosition position);
57 
58   // Helpers to get a block from an |rpo_number| or |instr_index|.
59   const InstructionBlock* GetBlock(const RpoNumber rpo_number);
60   const InstructionBlock* GetBlock(int instr_index);
61 
62   // Returns a bitvector representing all the blocks that are dominated by the
63   // output of the instruction in |block|.
64   const BitVector* GetBlocksDominatedBy(const InstructionBlock* block);
65 
66   // List of all instruction indexs that require a reference map.
reference_map_instructions()67   ZoneVector<int>& reference_map_instructions() {
68     return reference_map_instructions_;
69   }
70 
71   // Returns a bitvector representing the virtual registers that were spilled.
spilled_virtual_registers()72   BitVector& spilled_virtual_registers() { return spilled_virtual_registers_; }
73 
74   // This zone is for data structures only needed during register allocation
75   // phases.
allocation_zone()76   Zone* allocation_zone() const { return allocation_zone_; }
77 
78   // This zone is for InstructionOperands and moves that live beyond register
79   // allocation.
code_zone()80   Zone* code_zone() const { return code()->zone(); }
81 
82   BlockState& block_state(RpoNumber rpo_number);
83 
code()84   InstructionSequence* code() const { return code_; }
frame()85   Frame* frame() const { return frame_; }
debug_name()86   const char* debug_name() const { return debug_name_; }
config()87   const RegisterConfiguration* config() const { return config_; }
tick_counter()88   TickCounter* tick_counter() { return tick_counter_; }
89 
90  private:
91   Zone* const allocation_zone_;
92   Frame* const frame_;
93   InstructionSequence* const code_;
94   const char* const debug_name_;
95   const RegisterConfiguration* const config_;
96 
97   ZoneVector<VirtualRegisterData> virtual_register_data_;
98   ZoneVector<BlockState> block_states_;
99   ZoneVector<int> reference_map_instructions_;
100   BitVector spilled_virtual_registers_;
101 
102   TickCounter* const tick_counter_;
103 };
104 
105 // Phase 1: Process instruction outputs to determine how each virtual register
106 // is defined.
107 void DefineOutputs(MidTierRegisterAllocationData* data);
108 
109 // Phase 2: Allocate registers to instructions.
110 void AllocateRegisters(MidTierRegisterAllocationData* data);
111 
112 // Phase 3: assign spilled operands to specific spill slots.
113 void AllocateSpillSlots(MidTierRegisterAllocationData* data);
114 
115 // Phase 4: Populate reference maps for spilled references.
116 void PopulateReferenceMaps(MidTierRegisterAllocationData* data);
117 
118 }  // namespace compiler
119 }  // namespace internal
120 }  // namespace v8
121 
122 #endif  // V8_COMPILER_BACKEND_MID_TIER_REGISTER_ALLOCATOR_H_
123