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