register_allocator_graph_color.h revision d9ffd0dd7266f6a5e76f29d98dbe1a04f64cbb9b
1/*
2 * Copyright (C) 2016 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#ifndef ART_COMPILER_OPTIMIZING_REGISTER_ALLOCATOR_GRAPH_COLOR_H_
18#define ART_COMPILER_OPTIMIZING_REGISTER_ALLOCATOR_GRAPH_COLOR_H_
19
20#include "arch/instruction_set.h"
21#include "base/arena_containers.h"
22#include "base/arena_object.h"
23#include "base/macros.h"
24#include "primitive.h"
25#include "register_allocator.h"
26
27namespace art {
28
29class CodeGenerator;
30class HBasicBlock;
31class HGraph;
32class HInstruction;
33class HParallelMove;
34class Location;
35class SsaLivenessAnalysis;
36class InterferenceNode;
37
38/**
39 * A graph coloring register allocator.
40 *
41 * The algorithm proceeds as follows:
42 * (1) Build an interference graph, where nodes represent live intervals, and edges represent
43 *     interferences between two intervals. Coloring this graph with k colors is isomorphic to
44 *     finding a valid register assignment with k registers.
45 * (2) To color the graph, first prune all nodes with degree less than k, since these nodes are
46 *     guaranteed a color. (No matter how we color their adjacent nodes, we can give them a
47 *     different color.) As we prune nodes from the graph, more nodes may drop below degree k,
48 *     enabling further pruning. The key is to maintain the pruning order in a stack, so that we
49 *     can color the nodes in the reverse order.
50 *     When there are no more nodes with degree less than k, we start pruning alternate nodes based
51 *     on heuristics. Since these nodes are not guaranteed a color, we are careful to
52 *     prioritize nodes that require a register. We also prioritize short intervals, because
53 *     short intervals cannot be split very much if coloring fails (see below). "Prioritizing"
54 *     a node amounts to pruning it later, since it will have fewer interferences if we prune other
55 *     nodes first.
56 * (3) We color nodes in the reverse order in which we pruned them. If we cannot assign
57 *     a node a color, we do one of two things:
58 *     - If the node requires a register, we consider the current coloring attempt a failure.
59 *       However, we split the node's live interval in order to make the interference graph
60 *       sparser, so that future coloring attempts may succeed.
61 *     - If the node does not require a register, we simply assign it a location on the stack.
62 *
63 * A good reference for graph coloring register allocation is
64 * "Modern Compiler Implementation in Java" (Andrew W. Appel, 2nd Edition).
65 */
66class RegisterAllocatorGraphColor : public RegisterAllocator {
67 public:
68  RegisterAllocatorGraphColor(ArenaAllocator* allocator,
69                              CodeGenerator* codegen,
70                              const SsaLivenessAnalysis& analysis);
71  ~RegisterAllocatorGraphColor() OVERRIDE {}
72
73  void AllocateRegisters() OVERRIDE;
74
75  bool Validate(bool log_fatal_on_failure);
76
77 private:
78  // Collect all intervals and prepare for register allocation.
79  void ProcessInstructions();
80  void ProcessInstruction(HInstruction* instruction);
81
82  // If any inputs require specific registers, block those registers
83  // at the position of this instruction.
84  void CheckForFixedInputs(HInstruction* instruction);
85
86  // If the output of an instruction requires a specific register, split
87  // the interval and assign the register to the first part.
88  void CheckForFixedOutput(HInstruction* instruction);
89
90  // Add all applicable safepoints to a live interval.
91  // Currently depends on instruction processing order.
92  void AddSafepointsFor(HInstruction* instruction);
93
94  // Collect all live intervals associated with the temporary locations
95  // needed by an instruction.
96  void CheckForTempLiveIntervals(HInstruction* instruction);
97
98  // If a safe point is needed, add a synthesized interval to later record
99  // the number of live registers at this point.
100  void CheckForSafepoint(HInstruction* instruction);
101
102  // Split an interval, but only if `position` is inside of `interval`.
103  // Return either the new interval, or the original interval if not split.
104  static LiveInterval* TrySplit(LiveInterval* interval, size_t position);
105
106  // To ensure every graph can be colored, split live intervals
107  // at their register defs and uses. This creates short intervals with low
108  // degree in the interference graph, which are prioritized during graph
109  // coloring.
110  void SplitAtRegisterUses(LiveInterval* interval);
111
112  // If the given instruction is a catch phi, give it a spill slot.
113  void AllocateSpillSlotForCatchPhi(HInstruction* instruction);
114
115  // Ensure that the given register cannot be allocated for a given range.
116  void BlockRegister(Location location, size_t start, size_t end);
117  void BlockRegisters(size_t start, size_t end, bool caller_save_only = false);
118
119  // Use the intervals collected from instructions to construct an
120  // interference graph mapping intervals to adjacency lists.
121  // Also, collect synthesized safepoint nodes, used to keep
122  // track of live intervals across safepoints.
123  void BuildInterferenceGraph(const ArenaVector<LiveInterval*>& intervals,
124                              ArenaVector<InterferenceNode*>* prunable_nodes,
125                              ArenaVector<InterferenceNode*>* safepoints);
126
127  // Prune nodes from the interference graph to be colored later. Build
128  // a stack (pruned_nodes) containing these intervals in an order determined
129  // by various heuristics.
130  void PruneInterferenceGraph(const ArenaVector<InterferenceNode*>& prunable_nodes,
131                              size_t num_registers,
132                              ArenaStdStack<InterferenceNode*>* pruned_nodes);
133
134  // Process pruned_intervals to color the interference graph, spilling when
135  // necessary. Return true if successful. Else, split some intervals to make
136  // the interference graph sparser.
137  bool ColorInterferenceGraph(ArenaStdStack<InterferenceNode*>* pruned_nodes,
138                              size_t num_registers);
139
140  // Return the maximum number of registers live at safepoints,
141  // based on the outgoing interference edges of safepoint nodes.
142  size_t ComputeMaxSafepointLiveRegisters(const ArenaVector<InterferenceNode*>& safepoints);
143
144  // If necessary, add the given interval to the list of spilled intervals,
145  // and make sure it's ready to be spilled to the stack.
146  void AllocateSpillSlotFor(LiveInterval* interval);
147
148  // Live intervals, split by kind (core and floating point).
149  // These should not contain high intervals, as those are represented by
150  // the corresponding low interval throughout register allocation.
151  ArenaVector<LiveInterval*> core_intervals_;
152  ArenaVector<LiveInterval*> fp_intervals_;
153
154  // Intervals for temporaries, saved for special handling in the resolution phase.
155  ArenaVector<LiveInterval*> temp_intervals_;
156
157  // Safepoints, saved for special handling while processing instructions.
158  ArenaVector<HInstruction*> safepoints_;
159
160  // Live intervals for specific registers. These become pre-colored nodes
161  // in the interference graph.
162  ArenaVector<LiveInterval*> physical_core_intervals_;
163  ArenaVector<LiveInterval*> physical_fp_intervals_;
164
165  // Allocated stack slot counters.
166  size_t int_spill_slot_counter_;
167  size_t double_spill_slot_counter_;
168  size_t float_spill_slot_counter_;
169  size_t long_spill_slot_counter_;
170  size_t catch_phi_spill_slot_counter_;
171
172  // Number of stack slots needed for the pointer to the current method.
173  // This is 1 for 32-bit architectures, and 2 for 64-bit architectures.
174  const size_t reserved_art_method_slots_;
175
176  // Number of stack slots needed for outgoing arguments.
177  const size_t reserved_out_slots_;
178
179  // The number of globally blocked core and floating point registers, such as the stack pointer.
180  size_t number_of_globally_blocked_core_regs_;
181  size_t number_of_globally_blocked_fp_regs_;
182
183  // The maximum number of registers live at safe points. Needed by the code generator.
184  size_t max_safepoint_live_core_regs_;
185  size_t max_safepoint_live_fp_regs_;
186
187  // An arena allocator used for a single graph coloring attempt.
188  // Many data structures are cleared between graph coloring attempts, so we reduce
189  // total memory usage by using a new arena allocator for each attempt.
190  ArenaAllocator* coloring_attempt_allocator_;
191
192  DISALLOW_COPY_AND_ASSIGN(RegisterAllocatorGraphColor);
193};
194
195}  // namespace art
196
197#endif  // ART_COMPILER_OPTIMIZING_REGISTER_ALLOCATOR_GRAPH_COLOR_H_
198