xref: /aosp_15_r20/art/compiler/optimizing/register_allocator.h (revision 795d594fd825385562da6b089ea9b2033f3abf5a)
1*795d594fSAndroid Build Coastguard Worker /*
2*795d594fSAndroid Build Coastguard Worker  * Copyright (C) 2016 The Android Open Source Project
3*795d594fSAndroid Build Coastguard Worker  *
4*795d594fSAndroid Build Coastguard Worker  * Licensed under the Apache License, Version 2.0 (the "License");
5*795d594fSAndroid Build Coastguard Worker  * you may not use this file except in compliance with the License.
6*795d594fSAndroid Build Coastguard Worker  * You may obtain a copy of the License at
7*795d594fSAndroid Build Coastguard Worker  *
8*795d594fSAndroid Build Coastguard Worker  *      http://www.apache.org/licenses/LICENSE-2.0
9*795d594fSAndroid Build Coastguard Worker  *
10*795d594fSAndroid Build Coastguard Worker  * Unless required by applicable law or agreed to in writing, software
11*795d594fSAndroid Build Coastguard Worker  * distributed under the License is distributed on an "AS IS" BASIS,
12*795d594fSAndroid Build Coastguard Worker  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*795d594fSAndroid Build Coastguard Worker  * See the License for the specific language governing permissions and
14*795d594fSAndroid Build Coastguard Worker  * limitations under the License.
15*795d594fSAndroid Build Coastguard Worker  */
16*795d594fSAndroid Build Coastguard Worker 
17*795d594fSAndroid Build Coastguard Worker #ifndef ART_COMPILER_OPTIMIZING_REGISTER_ALLOCATOR_H_
18*795d594fSAndroid Build Coastguard Worker #define ART_COMPILER_OPTIMIZING_REGISTER_ALLOCATOR_H_
19*795d594fSAndroid Build Coastguard Worker 
20*795d594fSAndroid Build Coastguard Worker #include "arch/instruction_set.h"
21*795d594fSAndroid Build Coastguard Worker #include "base/array_ref.h"
22*795d594fSAndroid Build Coastguard Worker #include "base/arena_object.h"
23*795d594fSAndroid Build Coastguard Worker #include "base/macros.h"
24*795d594fSAndroid Build Coastguard Worker 
25*795d594fSAndroid Build Coastguard Worker namespace art HIDDEN {
26*795d594fSAndroid Build Coastguard Worker 
27*795d594fSAndroid Build Coastguard Worker class CodeGenerator;
28*795d594fSAndroid Build Coastguard Worker class HBasicBlock;
29*795d594fSAndroid Build Coastguard Worker class HGraph;
30*795d594fSAndroid Build Coastguard Worker class HInstruction;
31*795d594fSAndroid Build Coastguard Worker class HParallelMove;
32*795d594fSAndroid Build Coastguard Worker class LiveInterval;
33*795d594fSAndroid Build Coastguard Worker class Location;
34*795d594fSAndroid Build Coastguard Worker class SsaLivenessAnalysis;
35*795d594fSAndroid Build Coastguard Worker 
36*795d594fSAndroid Build Coastguard Worker /**
37*795d594fSAndroid Build Coastguard Worker  * Base class for any register allocator.
38*795d594fSAndroid Build Coastguard Worker  */
39*795d594fSAndroid Build Coastguard Worker class RegisterAllocator : public DeletableArenaObject<kArenaAllocRegisterAllocator> {
40*795d594fSAndroid Build Coastguard Worker  public:
41*795d594fSAndroid Build Coastguard Worker   enum class RegisterType {
42*795d594fSAndroid Build Coastguard Worker     kCoreRegister,
43*795d594fSAndroid Build Coastguard Worker     kFpRegister
44*795d594fSAndroid Build Coastguard Worker   };
45*795d594fSAndroid Build Coastguard Worker 
46*795d594fSAndroid Build Coastguard Worker   static std::unique_ptr<RegisterAllocator> Create(ScopedArenaAllocator* allocator,
47*795d594fSAndroid Build Coastguard Worker                                                    CodeGenerator* codegen,
48*795d594fSAndroid Build Coastguard Worker                                                    const SsaLivenessAnalysis& analysis);
49*795d594fSAndroid Build Coastguard Worker 
50*795d594fSAndroid Build Coastguard Worker   virtual ~RegisterAllocator();
51*795d594fSAndroid Build Coastguard Worker 
52*795d594fSAndroid Build Coastguard Worker   // Main entry point for the register allocator. Given the liveness analysis,
53*795d594fSAndroid Build Coastguard Worker   // allocates registers to live intervals.
54*795d594fSAndroid Build Coastguard Worker   virtual void AllocateRegisters() = 0;
55*795d594fSAndroid Build Coastguard Worker 
56*795d594fSAndroid Build Coastguard Worker   // Validate that the register allocator did not allocate the same register to
57*795d594fSAndroid Build Coastguard Worker   // intervals that intersect each other. Returns false if it failed.
58*795d594fSAndroid Build Coastguard Worker   virtual bool Validate(bool log_fatal_on_failure) = 0;
59*795d594fSAndroid Build Coastguard Worker 
60*795d594fSAndroid Build Coastguard Worker   // Verifies that live intervals do not conflict. Used by unit testing.
61*795d594fSAndroid Build Coastguard Worker   static bool ValidateIntervals(ArrayRef<LiveInterval* const> intervals,
62*795d594fSAndroid Build Coastguard Worker                                 size_t number_of_spill_slots,
63*795d594fSAndroid Build Coastguard Worker                                 size_t number_of_out_slots,
64*795d594fSAndroid Build Coastguard Worker                                 const CodeGenerator& codegen,
65*795d594fSAndroid Build Coastguard Worker                                 const SsaLivenessAnalysis* liveness,  // Can be null in tests.
66*795d594fSAndroid Build Coastguard Worker                                 RegisterType register_type,
67*795d594fSAndroid Build Coastguard Worker                                 bool log_fatal_on_failure);
68*795d594fSAndroid Build Coastguard Worker 
69*795d594fSAndroid Build Coastguard Worker   static constexpr const char* kRegisterAllocatorPassName = "register";
70*795d594fSAndroid Build Coastguard Worker 
71*795d594fSAndroid Build Coastguard Worker  protected:
72*795d594fSAndroid Build Coastguard Worker   RegisterAllocator(ScopedArenaAllocator* allocator,
73*795d594fSAndroid Build Coastguard Worker                     CodeGenerator* codegen,
74*795d594fSAndroid Build Coastguard Worker                     const SsaLivenessAnalysis& analysis);
75*795d594fSAndroid Build Coastguard Worker 
76*795d594fSAndroid Build Coastguard Worker   // Split `interval` at the position `position`. The new interval starts at `position`.
77*795d594fSAndroid Build Coastguard Worker   // If `position` is at the start of `interval`, returns `interval` with its
78*795d594fSAndroid Build Coastguard Worker   // register location(s) cleared.
79*795d594fSAndroid Build Coastguard Worker   static LiveInterval* Split(LiveInterval* interval, size_t position);
80*795d594fSAndroid Build Coastguard Worker 
81*795d594fSAndroid Build Coastguard Worker   // Split `interval` at a position between `from` and `to`. The method will try
82*795d594fSAndroid Build Coastguard Worker   // to find an optimal split position.
83*795d594fSAndroid Build Coastguard Worker   LiveInterval* SplitBetween(LiveInterval* interval, size_t from, size_t to);
84*795d594fSAndroid Build Coastguard Worker 
85*795d594fSAndroid Build Coastguard Worker   // Helper for calling the right typed codegen function for dumping a register.
DumpRegister(std::ostream & stream,int reg,RegisterType register_type)86*795d594fSAndroid Build Coastguard Worker   void DumpRegister(std::ostream& stream, int reg, RegisterType register_type) const {
87*795d594fSAndroid Build Coastguard Worker     DumpRegister(stream, reg, register_type, codegen_);
88*795d594fSAndroid Build Coastguard Worker   }
89*795d594fSAndroid Build Coastguard Worker   static void DumpRegister(
90*795d594fSAndroid Build Coastguard Worker       std::ostream& stream, int reg, RegisterType register_type, const CodeGenerator* codegen);
91*795d594fSAndroid Build Coastguard Worker 
92*795d594fSAndroid Build Coastguard Worker   // Get a mask of all registers for an interval.
93*795d594fSAndroid Build Coastguard Worker   // Most intervals either have or do not have a register, but we're using special fixed
94*795d594fSAndroid Build Coastguard Worker   // intervals with type `Void` to mark large sets of blocked registers for calls, catch
95*795d594fSAndroid Build Coastguard Worker   // blocks and irreducible loop headers to save memory and improve performance.
96*795d594fSAndroid Build Coastguard Worker   uint32_t GetRegisterMask(LiveInterval* interval, RegisterType register_type) const;
97*795d594fSAndroid Build Coastguard Worker 
98*795d594fSAndroid Build Coastguard Worker   ScopedArenaAllocator* const allocator_;
99*795d594fSAndroid Build Coastguard Worker   CodeGenerator* const codegen_;
100*795d594fSAndroid Build Coastguard Worker   const SsaLivenessAnalysis& liveness_;
101*795d594fSAndroid Build Coastguard Worker 
102*795d594fSAndroid Build Coastguard Worker   // Cached values calculated from codegen data.
103*795d594fSAndroid Build Coastguard Worker   const size_t num_core_registers_;
104*795d594fSAndroid Build Coastguard Worker   const size_t num_fp_registers_;
105*795d594fSAndroid Build Coastguard Worker   const uint32_t core_registers_blocked_for_call_;
106*795d594fSAndroid Build Coastguard Worker   const uint32_t fp_registers_blocked_for_call_;
107*795d594fSAndroid Build Coastguard Worker };
108*795d594fSAndroid Build Coastguard Worker 
109*795d594fSAndroid Build Coastguard Worker }  // namespace art
110*795d594fSAndroid Build Coastguard Worker 
111*795d594fSAndroid Build Coastguard Worker #endif  // ART_COMPILER_OPTIMIZING_REGISTER_ALLOCATOR_H_
112