Home | History | Annotate | Download | only in optimizing
      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_object.h"
     22 #include "base/array_ref.h"
     23 #include "base/macros.h"
     24 #include "base/scoped_arena_containers.h"
     25 #include "register_allocator.h"
     26 
     27 namespace art {
     28 
     29 class CodeGenerator;
     30 class HBasicBlock;
     31 class HGraph;
     32 class HInstruction;
     33 class HParallelMove;
     34 class Location;
     35 class SsaLivenessAnalysis;
     36 class InterferenceNode;
     37 struct CoalesceOpportunity;
     38 enum class CoalesceKind;
     39 
     40 /**
     41  * A graph coloring register allocator.
     42  *
     43  * The algorithm proceeds as follows:
     44  * (1) Build an interference graph, where nodes represent live intervals, and edges represent
     45  *     interferences between two intervals. Coloring this graph with k colors is isomorphic to
     46  *     finding a valid register assignment with k registers.
     47  * (2) To color the graph, first prune all nodes with degree less than k, since these nodes are
     48  *     guaranteed a color. (No matter how we color their adjacent nodes, we can give them a
     49  *     different color.) As we prune nodes from the graph, more nodes may drop below degree k,
     50  *     enabling further pruning. The key is to maintain the pruning order in a stack, so that we
     51  *     can color the nodes in the reverse order.
     52  *     When there are no more nodes with degree less than k, we start pruning alternate nodes based
     53  *     on heuristics. Since these nodes are not guaranteed a color, we are careful to
     54  *     prioritize nodes that require a register. We also prioritize short intervals, because
     55  *     short intervals cannot be split very much if coloring fails (see below). "Prioritizing"
     56  *     a node amounts to pruning it later, since it will have fewer interferences if we prune other
     57  *     nodes first.
     58  * (3) We color nodes in the reverse order in which we pruned them. If we cannot assign
     59  *     a node a color, we do one of two things:
     60  *     - If the node requires a register, we consider the current coloring attempt a failure.
     61  *       However, we split the node's live interval in order to make the interference graph
     62  *       sparser, so that future coloring attempts may succeed.
     63  *     - If the node does not require a register, we simply assign it a location on the stack.
     64  *
     65  * If iterative move coalescing is enabled, the algorithm also attempts to conservatively
     66  * combine nodes in the graph that would prefer to have the same color. (For example, the output
     67  * of a phi instruction would prefer to have the same register as at least one of its inputs.)
     68  * There are several additional steps involved with this:
     69  * - We look for coalesce opportunities by examining each live interval, a step similar to that
     70  *   used by linear scan when looking for register hints.
     71  * - When pruning the graph, we maintain a worklist of coalesce opportunities, as well as a worklist
     72  *   of low degree nodes that have associated coalesce opportunities. Only when we run out of
     73  *   coalesce opportunities do we start pruning coalesce-associated nodes.
     74  * - When pruning a node, if any nodes transition from high degree to low degree, we add
     75  *   associated coalesce opportunities to the worklist, since these opportunities may now succeed.
     76  * - Whether two nodes can be combined is decided by two different heuristics--one used when
     77  *   coalescing uncolored nodes, and one used for coalescing an uncolored node with a colored node.
     78  *   It is vital that we only combine two nodes if the node that remains is guaranteed to receive
     79  *   a color. This is because additionally spilling is more costly than failing to coalesce.
     80  * - Even if nodes are not coalesced while pruning, we keep the coalesce opportunities around
     81  *   to be used as last-chance register hints when coloring. If nothing else, we try to use
     82  *   caller-save registers before callee-save registers.
     83  *
     84  * A good reference for graph coloring register allocation is
     85  * "Modern Compiler Implementation in Java" (Andrew W. Appel, 2nd Edition).
     86  */
     87 class RegisterAllocatorGraphColor : public RegisterAllocator {
     88  public:
     89   RegisterAllocatorGraphColor(ScopedArenaAllocator* allocator,
     90                               CodeGenerator* codegen,
     91                               const SsaLivenessAnalysis& analysis,
     92                               bool iterative_move_coalescing = true);
     93   ~RegisterAllocatorGraphColor() OVERRIDE;
     94 
     95   void AllocateRegisters() OVERRIDE;
     96 
     97   bool Validate(bool log_fatal_on_failure);
     98 
     99  private:
    100   // Collect all intervals and prepare for register allocation.
    101   void ProcessInstructions();
    102   void ProcessInstruction(HInstruction* instruction);
    103 
    104   // If any inputs require specific registers, block those registers
    105   // at the position of this instruction.
    106   void CheckForFixedInputs(HInstruction* instruction);
    107 
    108   // If the output of an instruction requires a specific register, split
    109   // the interval and assign the register to the first part.
    110   void CheckForFixedOutput(HInstruction* instruction);
    111 
    112   // Add all applicable safepoints to a live interval.
    113   // Currently depends on instruction processing order.
    114   void AddSafepointsFor(HInstruction* instruction);
    115 
    116   // Collect all live intervals associated with the temporary locations
    117   // needed by an instruction.
    118   void CheckForTempLiveIntervals(HInstruction* instruction);
    119 
    120   // If a safe point is needed, add a synthesized interval to later record
    121   // the number of live registers at this point.
    122   void CheckForSafepoint(HInstruction* instruction);
    123 
    124   // Split an interval, but only if `position` is inside of `interval`.
    125   // Return either the new interval, or the original interval if not split.
    126   static LiveInterval* TrySplit(LiveInterval* interval, size_t position);
    127 
    128   // To ensure every graph can be colored, split live intervals
    129   // at their register defs and uses. This creates short intervals with low
    130   // degree in the interference graph, which are prioritized during graph
    131   // coloring.
    132   void SplitAtRegisterUses(LiveInterval* interval);
    133 
    134   // If the given instruction is a catch phi, give it a spill slot.
    135   void AllocateSpillSlotForCatchPhi(HInstruction* instruction);
    136 
    137   // Ensure that the given register cannot be allocated for a given range.
    138   void BlockRegister(Location location, size_t start, size_t end);
    139   void BlockRegisters(size_t start, size_t end, bool caller_save_only = false);
    140 
    141   bool IsCallerSave(size_t reg, bool processing_core_regs);
    142 
    143   // Assigns stack slots to a list of intervals, ensuring that interfering intervals are not
    144   // assigned the same stack slot.
    145   void ColorSpillSlots(ArrayRef<LiveInterval* const> nodes, /* out */ size_t* num_stack_slots_used);
    146 
    147   // Provide stack slots to nodes that need them.
    148   void AllocateSpillSlots(ArrayRef<InterferenceNode* const> nodes);
    149 
    150   // Whether iterative move coalescing should be performed. Iterative move coalescing
    151   // improves code quality, but increases compile time.
    152   const bool iterative_move_coalescing_;
    153 
    154   // Live intervals, split by kind (core and floating point).
    155   // These should not contain high intervals, as those are represented by
    156   // the corresponding low interval throughout register allocation.
    157   ScopedArenaVector<LiveInterval*> core_intervals_;
    158   ScopedArenaVector<LiveInterval*> fp_intervals_;
    159 
    160   // Intervals for temporaries, saved for special handling in the resolution phase.
    161   ScopedArenaVector<LiveInterval*> temp_intervals_;
    162 
    163   // Safepoints, saved for special handling while processing instructions.
    164   ScopedArenaVector<HInstruction*> safepoints_;
    165 
    166   // Interference nodes representing specific registers. These are "pre-colored" nodes
    167   // in the interference graph.
    168   ScopedArenaVector<InterferenceNode*> physical_core_nodes_;
    169   ScopedArenaVector<InterferenceNode*> physical_fp_nodes_;
    170 
    171   // Allocated stack slot counters.
    172   size_t num_int_spill_slots_;
    173   size_t num_double_spill_slots_;
    174   size_t num_float_spill_slots_;
    175   size_t num_long_spill_slots_;
    176   size_t catch_phi_spill_slot_counter_;
    177 
    178   // Number of stack slots needed for the pointer to the current method.
    179   // This is 1 for 32-bit architectures, and 2 for 64-bit architectures.
    180   const size_t reserved_art_method_slots_;
    181 
    182   // Number of stack slots needed for outgoing arguments.
    183   const size_t reserved_out_slots_;
    184 
    185   friend class ColoringIteration;
    186 
    187   DISALLOW_COPY_AND_ASSIGN(RegisterAllocatorGraphColor);
    188 };
    189 
    190 }  // namespace art
    191 
    192 #endif  // ART_COMPILER_OPTIMIZING_REGISTER_ALLOCATOR_GRAPH_COLOR_H_
    193