11cb0ef41Sopenharmony_ci// Copyright 2020 the V8 project authors. All rights reserved.
21cb0ef41Sopenharmony_ci// Use of this source code is governed by a BSD-style license that can be
31cb0ef41Sopenharmony_ci// found in the LICENSE file.
41cb0ef41Sopenharmony_ci
51cb0ef41Sopenharmony_ci#ifndef V8_COMPILER_BACKEND_MID_TIER_REGISTER_ALLOCATOR_H_
61cb0ef41Sopenharmony_ci#define V8_COMPILER_BACKEND_MID_TIER_REGISTER_ALLOCATOR_H_
71cb0ef41Sopenharmony_ci
81cb0ef41Sopenharmony_ci#include "src/base/compiler-specific.h"
91cb0ef41Sopenharmony_ci#include "src/common/globals.h"
101cb0ef41Sopenharmony_ci#include "src/compiler/backend/instruction.h"
111cb0ef41Sopenharmony_ci#include "src/compiler/backend/register-allocation.h"
121cb0ef41Sopenharmony_ci#include "src/flags/flags.h"
131cb0ef41Sopenharmony_ci#include "src/utils/bit-vector.h"
141cb0ef41Sopenharmony_ci#include "src/zone/zone-containers.h"
151cb0ef41Sopenharmony_ci#include "src/zone/zone.h"
161cb0ef41Sopenharmony_ci
171cb0ef41Sopenharmony_cinamespace v8 {
181cb0ef41Sopenharmony_cinamespace internal {
191cb0ef41Sopenharmony_ci
201cb0ef41Sopenharmony_ciclass TickCounter;
211cb0ef41Sopenharmony_ci
221cb0ef41Sopenharmony_cinamespace compiler {
231cb0ef41Sopenharmony_ci
241cb0ef41Sopenharmony_ciclass BlockState;
251cb0ef41Sopenharmony_ciclass VirtualRegisterData;
261cb0ef41Sopenharmony_ci
271cb0ef41Sopenharmony_ci// The MidTierRegisterAllocator is a register allocator specifically designed to
281cb0ef41Sopenharmony_ci// perform register allocation as fast as possible while minimizing spill moves.
291cb0ef41Sopenharmony_ci
301cb0ef41Sopenharmony_ciclass MidTierRegisterAllocationData final : public RegisterAllocationData {
311cb0ef41Sopenharmony_ci public:
321cb0ef41Sopenharmony_ci  MidTierRegisterAllocationData(const RegisterConfiguration* config,
331cb0ef41Sopenharmony_ci                                Zone* allocation_zone, Frame* frame,
341cb0ef41Sopenharmony_ci                                InstructionSequence* code,
351cb0ef41Sopenharmony_ci                                TickCounter* tick_counter,
361cb0ef41Sopenharmony_ci                                const char* debug_name = nullptr);
371cb0ef41Sopenharmony_ci  MidTierRegisterAllocationData(const MidTierRegisterAllocationData&) = delete;
381cb0ef41Sopenharmony_ci  MidTierRegisterAllocationData& operator=(
391cb0ef41Sopenharmony_ci      const MidTierRegisterAllocationData&) = delete;
401cb0ef41Sopenharmony_ci
411cb0ef41Sopenharmony_ci  static MidTierRegisterAllocationData* cast(RegisterAllocationData* data) {
421cb0ef41Sopenharmony_ci    DCHECK_EQ(data->type(), Type::kMidTier);
431cb0ef41Sopenharmony_ci    return static_cast<MidTierRegisterAllocationData*>(data);
441cb0ef41Sopenharmony_ci  }
451cb0ef41Sopenharmony_ci
461cb0ef41Sopenharmony_ci  VirtualRegisterData& VirtualRegisterDataFor(int virtual_register);
471cb0ef41Sopenharmony_ci
481cb0ef41Sopenharmony_ci  // Add a gap move between the given operands |from| and |to|.
491cb0ef41Sopenharmony_ci  MoveOperands* AddGapMove(int instr_index, Instruction::GapPosition position,
501cb0ef41Sopenharmony_ci                           const InstructionOperand& from,
511cb0ef41Sopenharmony_ci                           const InstructionOperand& to);
521cb0ef41Sopenharmony_ci
531cb0ef41Sopenharmony_ci  // Adds a gap move where both sides are PendingOperand operands.
541cb0ef41Sopenharmony_ci  MoveOperands* AddPendingOperandGapMove(int instr_index,
551cb0ef41Sopenharmony_ci                                         Instruction::GapPosition position);
561cb0ef41Sopenharmony_ci
571cb0ef41Sopenharmony_ci  // Helpers to get a block from an |rpo_number| or |instr_index|.
581cb0ef41Sopenharmony_ci  const InstructionBlock* GetBlock(const RpoNumber rpo_number);
591cb0ef41Sopenharmony_ci  const InstructionBlock* GetBlock(int instr_index);
601cb0ef41Sopenharmony_ci
611cb0ef41Sopenharmony_ci  // Returns a bitvector representing all the blocks that are dominated by the
621cb0ef41Sopenharmony_ci  // output of the instruction in |block|.
631cb0ef41Sopenharmony_ci  const BitVector* GetBlocksDominatedBy(const InstructionBlock* block);
641cb0ef41Sopenharmony_ci
651cb0ef41Sopenharmony_ci  // List of all instruction indexs that require a reference map.
661cb0ef41Sopenharmony_ci  ZoneVector<int>& reference_map_instructions() {
671cb0ef41Sopenharmony_ci    return reference_map_instructions_;
681cb0ef41Sopenharmony_ci  }
691cb0ef41Sopenharmony_ci
701cb0ef41Sopenharmony_ci  // Returns a bitvector representing the virtual registers that were spilled.
711cb0ef41Sopenharmony_ci  BitVector& spilled_virtual_registers() { return spilled_virtual_registers_; }
721cb0ef41Sopenharmony_ci
731cb0ef41Sopenharmony_ci  // This zone is for data structures only needed during register allocation
741cb0ef41Sopenharmony_ci  // phases.
751cb0ef41Sopenharmony_ci  Zone* allocation_zone() const { return allocation_zone_; }
761cb0ef41Sopenharmony_ci
771cb0ef41Sopenharmony_ci  // This zone is for InstructionOperands and moves that live beyond register
781cb0ef41Sopenharmony_ci  // allocation.
791cb0ef41Sopenharmony_ci  Zone* code_zone() const { return code()->zone(); }
801cb0ef41Sopenharmony_ci
811cb0ef41Sopenharmony_ci  BlockState& block_state(RpoNumber rpo_number);
821cb0ef41Sopenharmony_ci
831cb0ef41Sopenharmony_ci  InstructionSequence* code() const { return code_; }
841cb0ef41Sopenharmony_ci  Frame* frame() const { return frame_; }
851cb0ef41Sopenharmony_ci  const char* debug_name() const { return debug_name_; }
861cb0ef41Sopenharmony_ci  const RegisterConfiguration* config() const { return config_; }
871cb0ef41Sopenharmony_ci  TickCounter* tick_counter() { return tick_counter_; }
881cb0ef41Sopenharmony_ci
891cb0ef41Sopenharmony_ci private:
901cb0ef41Sopenharmony_ci  Zone* const allocation_zone_;
911cb0ef41Sopenharmony_ci  Frame* const frame_;
921cb0ef41Sopenharmony_ci  InstructionSequence* const code_;
931cb0ef41Sopenharmony_ci  const char* const debug_name_;
941cb0ef41Sopenharmony_ci  const RegisterConfiguration* const config_;
951cb0ef41Sopenharmony_ci
961cb0ef41Sopenharmony_ci  ZoneVector<VirtualRegisterData> virtual_register_data_;
971cb0ef41Sopenharmony_ci  ZoneVector<BlockState> block_states_;
981cb0ef41Sopenharmony_ci  ZoneVector<int> reference_map_instructions_;
991cb0ef41Sopenharmony_ci  BitVector spilled_virtual_registers_;
1001cb0ef41Sopenharmony_ci
1011cb0ef41Sopenharmony_ci  TickCounter* const tick_counter_;
1021cb0ef41Sopenharmony_ci};
1031cb0ef41Sopenharmony_ci
1041cb0ef41Sopenharmony_ci// Phase 1: Process instruction outputs to determine how each virtual register
1051cb0ef41Sopenharmony_ci// is defined.
1061cb0ef41Sopenharmony_civoid DefineOutputs(MidTierRegisterAllocationData* data);
1071cb0ef41Sopenharmony_ci
1081cb0ef41Sopenharmony_ci// Phase 2: Allocate registers to instructions.
1091cb0ef41Sopenharmony_civoid AllocateRegisters(MidTierRegisterAllocationData* data);
1101cb0ef41Sopenharmony_ci
1111cb0ef41Sopenharmony_ci// Phase 3: assign spilled operands to specific spill slots.
1121cb0ef41Sopenharmony_civoid AllocateSpillSlots(MidTierRegisterAllocationData* data);
1131cb0ef41Sopenharmony_ci
1141cb0ef41Sopenharmony_ci// Phase 4: Populate reference maps for spilled references.
1151cb0ef41Sopenharmony_civoid PopulateReferenceMaps(MidTierRegisterAllocationData* data);
1161cb0ef41Sopenharmony_ci
1171cb0ef41Sopenharmony_ci}  // namespace compiler
1181cb0ef41Sopenharmony_ci}  // namespace internal
1191cb0ef41Sopenharmony_ci}  // namespace v8
1201cb0ef41Sopenharmony_ci
1211cb0ef41Sopenharmony_ci#endif  // V8_COMPILER_BACKEND_MID_TIER_REGISTER_ALLOCATOR_H_
122