xref: /aosp_15_r20/external/llvm/lib/CodeGen/SpillPlacement.h (revision 9880d6810fe72a1726cb53787c6711e909410d58)
1*9880d681SAndroid Build Coastguard Worker //===-- SpillPlacement.h - Optimal Spill Code Placement --------*- C++ -*--===//
2*9880d681SAndroid Build Coastguard Worker //
3*9880d681SAndroid Build Coastguard Worker //                     The LLVM Compiler Infrastructure
4*9880d681SAndroid Build Coastguard Worker //
5*9880d681SAndroid Build Coastguard Worker // This file is distributed under the University of Illinois Open Source
6*9880d681SAndroid Build Coastguard Worker // License. See LICENSE.TXT for details.
7*9880d681SAndroid Build Coastguard Worker //
8*9880d681SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
9*9880d681SAndroid Build Coastguard Worker //
10*9880d681SAndroid Build Coastguard Worker // This analysis computes the optimal spill code placement between basic blocks.
11*9880d681SAndroid Build Coastguard Worker //
12*9880d681SAndroid Build Coastguard Worker // The runOnMachineFunction() method only precomputes some profiling information
13*9880d681SAndroid Build Coastguard Worker // about the CFG. The real work is done by prepare(), addConstraints(), and
14*9880d681SAndroid Build Coastguard Worker // finish() which are called by the register allocator.
15*9880d681SAndroid Build Coastguard Worker //
16*9880d681SAndroid Build Coastguard Worker // Given a variable that is live across multiple basic blocks, and given
17*9880d681SAndroid Build Coastguard Worker // constraints on the basic blocks where the variable is live, determine which
18*9880d681SAndroid Build Coastguard Worker // edge bundles should have the variable in a register and which edge bundles
19*9880d681SAndroid Build Coastguard Worker // should have the variable in a stack slot.
20*9880d681SAndroid Build Coastguard Worker //
21*9880d681SAndroid Build Coastguard Worker // The returned bit vector can be used to place optimal spill code at basic
22*9880d681SAndroid Build Coastguard Worker // block entries and exits. Spill code placement inside a basic block is not
23*9880d681SAndroid Build Coastguard Worker // considered.
24*9880d681SAndroid Build Coastguard Worker //
25*9880d681SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
26*9880d681SAndroid Build Coastguard Worker 
27*9880d681SAndroid Build Coastguard Worker #ifndef LLVM_LIB_CODEGEN_SPILLPLACEMENT_H
28*9880d681SAndroid Build Coastguard Worker #define LLVM_LIB_CODEGEN_SPILLPLACEMENT_H
29*9880d681SAndroid Build Coastguard Worker 
30*9880d681SAndroid Build Coastguard Worker #include "llvm/ADT/ArrayRef.h"
31*9880d681SAndroid Build Coastguard Worker #include "llvm/ADT/SmallVector.h"
32*9880d681SAndroid Build Coastguard Worker #include "llvm/ADT/SparseSet.h"
33*9880d681SAndroid Build Coastguard Worker #include "llvm/CodeGen/MachineFunctionPass.h"
34*9880d681SAndroid Build Coastguard Worker #include "llvm/Support/BlockFrequency.h"
35*9880d681SAndroid Build Coastguard Worker 
36*9880d681SAndroid Build Coastguard Worker namespace llvm {
37*9880d681SAndroid Build Coastguard Worker 
38*9880d681SAndroid Build Coastguard Worker class BitVector;
39*9880d681SAndroid Build Coastguard Worker class EdgeBundles;
40*9880d681SAndroid Build Coastguard Worker class MachineBasicBlock;
41*9880d681SAndroid Build Coastguard Worker class MachineLoopInfo;
42*9880d681SAndroid Build Coastguard Worker class MachineBlockFrequencyInfo;
43*9880d681SAndroid Build Coastguard Worker 
44*9880d681SAndroid Build Coastguard Worker class SpillPlacement : public MachineFunctionPass {
45*9880d681SAndroid Build Coastguard Worker   struct Node;
46*9880d681SAndroid Build Coastguard Worker   const MachineFunction *MF;
47*9880d681SAndroid Build Coastguard Worker   const EdgeBundles *bundles;
48*9880d681SAndroid Build Coastguard Worker   const MachineLoopInfo *loops;
49*9880d681SAndroid Build Coastguard Worker   const MachineBlockFrequencyInfo *MBFI;
50*9880d681SAndroid Build Coastguard Worker   Node *nodes;
51*9880d681SAndroid Build Coastguard Worker 
52*9880d681SAndroid Build Coastguard Worker   // Nodes that are active in the current computation. Owned by the prepare()
53*9880d681SAndroid Build Coastguard Worker   // caller.
54*9880d681SAndroid Build Coastguard Worker   BitVector *ActiveNodes;
55*9880d681SAndroid Build Coastguard Worker 
56*9880d681SAndroid Build Coastguard Worker   // Nodes with active links. Populated by scanActiveBundles.
57*9880d681SAndroid Build Coastguard Worker   SmallVector<unsigned, 8> Linked;
58*9880d681SAndroid Build Coastguard Worker 
59*9880d681SAndroid Build Coastguard Worker   // Nodes that went positive during the last call to scanActiveBundles or
60*9880d681SAndroid Build Coastguard Worker   // iterate.
61*9880d681SAndroid Build Coastguard Worker   SmallVector<unsigned, 8> RecentPositive;
62*9880d681SAndroid Build Coastguard Worker 
63*9880d681SAndroid Build Coastguard Worker   // Block frequencies are computed once. Indexed by block number.
64*9880d681SAndroid Build Coastguard Worker   SmallVector<BlockFrequency, 8> BlockFrequencies;
65*9880d681SAndroid Build Coastguard Worker 
66*9880d681SAndroid Build Coastguard Worker   /// Decision threshold. A node gets the output value 0 if the weighted sum of
67*9880d681SAndroid Build Coastguard Worker   /// its inputs falls in the open interval (-Threshold;Threshold).
68*9880d681SAndroid Build Coastguard Worker   BlockFrequency Threshold;
69*9880d681SAndroid Build Coastguard Worker 
70*9880d681SAndroid Build Coastguard Worker   /// List of nodes that need to be updated in ::iterate.
71*9880d681SAndroid Build Coastguard Worker   SparseSet<unsigned> TodoList;
72*9880d681SAndroid Build Coastguard Worker 
73*9880d681SAndroid Build Coastguard Worker public:
74*9880d681SAndroid Build Coastguard Worker   static char ID; // Pass identification, replacement for typeid.
75*9880d681SAndroid Build Coastguard Worker 
SpillPlacement()76*9880d681SAndroid Build Coastguard Worker   SpillPlacement() : MachineFunctionPass(ID), nodes(nullptr) {}
~SpillPlacement()77*9880d681SAndroid Build Coastguard Worker   ~SpillPlacement() override { releaseMemory(); }
78*9880d681SAndroid Build Coastguard Worker 
79*9880d681SAndroid Build Coastguard Worker   /// BorderConstraint - A basic block has separate constraints for entry and
80*9880d681SAndroid Build Coastguard Worker   /// exit.
81*9880d681SAndroid Build Coastguard Worker   enum BorderConstraint {
82*9880d681SAndroid Build Coastguard Worker     DontCare,  ///< Block doesn't care / variable not live.
83*9880d681SAndroid Build Coastguard Worker     PrefReg,   ///< Block entry/exit prefers a register.
84*9880d681SAndroid Build Coastguard Worker     PrefSpill, ///< Block entry/exit prefers a stack slot.
85*9880d681SAndroid Build Coastguard Worker     PrefBoth,  ///< Block entry prefers both register and stack.
86*9880d681SAndroid Build Coastguard Worker     MustSpill  ///< A register is impossible, variable must be spilled.
87*9880d681SAndroid Build Coastguard Worker   };
88*9880d681SAndroid Build Coastguard Worker 
89*9880d681SAndroid Build Coastguard Worker   /// BlockConstraint - Entry and exit constraints for a basic block.
90*9880d681SAndroid Build Coastguard Worker   struct BlockConstraint {
91*9880d681SAndroid Build Coastguard Worker     unsigned Number;            ///< Basic block number (from MBB::getNumber()).
92*9880d681SAndroid Build Coastguard Worker     BorderConstraint Entry : 8; ///< Constraint on block entry.
93*9880d681SAndroid Build Coastguard Worker     BorderConstraint Exit : 8;  ///< Constraint on block exit.
94*9880d681SAndroid Build Coastguard Worker 
95*9880d681SAndroid Build Coastguard Worker     /// True when this block changes the value of the live range. This means
96*9880d681SAndroid Build Coastguard Worker     /// the block has a non-PHI def.  When this is false, a live-in value on
97*9880d681SAndroid Build Coastguard Worker     /// the stack can be live-out on the stack without inserting a spill.
98*9880d681SAndroid Build Coastguard Worker     bool ChangesValue;
99*9880d681SAndroid Build Coastguard Worker   };
100*9880d681SAndroid Build Coastguard Worker 
101*9880d681SAndroid Build Coastguard Worker   /// prepare - Reset state and prepare for a new spill placement computation.
102*9880d681SAndroid Build Coastguard Worker   /// @param RegBundles Bit vector to receive the edge bundles where the
103*9880d681SAndroid Build Coastguard Worker   ///                   variable should be kept in a register. Each bit
104*9880d681SAndroid Build Coastguard Worker   ///                   corresponds to an edge bundle, a set bit means the
105*9880d681SAndroid Build Coastguard Worker   ///                   variable should be kept in a register through the
106*9880d681SAndroid Build Coastguard Worker   ///                   bundle. A clear bit means the variable should be
107*9880d681SAndroid Build Coastguard Worker   ///                   spilled. This vector is retained.
108*9880d681SAndroid Build Coastguard Worker   void prepare(BitVector &RegBundles);
109*9880d681SAndroid Build Coastguard Worker 
110*9880d681SAndroid Build Coastguard Worker   /// addConstraints - Add constraints and biases. This method may be called
111*9880d681SAndroid Build Coastguard Worker   /// more than once to accumulate constraints.
112*9880d681SAndroid Build Coastguard Worker   /// @param LiveBlocks Constraints for blocks that have the variable live in or
113*9880d681SAndroid Build Coastguard Worker   ///                   live out.
114*9880d681SAndroid Build Coastguard Worker   void addConstraints(ArrayRef<BlockConstraint> LiveBlocks);
115*9880d681SAndroid Build Coastguard Worker 
116*9880d681SAndroid Build Coastguard Worker   /// addPrefSpill - Add PrefSpill constraints to all blocks listed.  This is
117*9880d681SAndroid Build Coastguard Worker   /// equivalent to calling addConstraint with identical BlockConstraints with
118*9880d681SAndroid Build Coastguard Worker   /// Entry = Exit = PrefSpill, and ChangesValue = false.
119*9880d681SAndroid Build Coastguard Worker   ///
120*9880d681SAndroid Build Coastguard Worker   /// @param Blocks Array of block numbers that prefer to spill in and out.
121*9880d681SAndroid Build Coastguard Worker   /// @param Strong When true, double the negative bias for these blocks.
122*9880d681SAndroid Build Coastguard Worker   void addPrefSpill(ArrayRef<unsigned> Blocks, bool Strong);
123*9880d681SAndroid Build Coastguard Worker 
124*9880d681SAndroid Build Coastguard Worker   /// addLinks - Add transparent blocks with the given numbers.
125*9880d681SAndroid Build Coastguard Worker   void addLinks(ArrayRef<unsigned> Links);
126*9880d681SAndroid Build Coastguard Worker 
127*9880d681SAndroid Build Coastguard Worker   /// scanActiveBundles - Perform an initial scan of all bundles activated by
128*9880d681SAndroid Build Coastguard Worker   /// addConstraints and addLinks, updating their state. Add all the bundles
129*9880d681SAndroid Build Coastguard Worker   /// that now prefer a register to RecentPositive.
130*9880d681SAndroid Build Coastguard Worker   /// Prepare internal data structures for iterate.
131*9880d681SAndroid Build Coastguard Worker   /// Return true is there are any positive nodes.
132*9880d681SAndroid Build Coastguard Worker   bool scanActiveBundles();
133*9880d681SAndroid Build Coastguard Worker 
134*9880d681SAndroid Build Coastguard Worker   /// iterate - Update the network iteratively until convergence, or new bundles
135*9880d681SAndroid Build Coastguard Worker   /// are found.
136*9880d681SAndroid Build Coastguard Worker   void iterate();
137*9880d681SAndroid Build Coastguard Worker 
138*9880d681SAndroid Build Coastguard Worker   /// getRecentPositive - Return an array of bundles that became positive during
139*9880d681SAndroid Build Coastguard Worker   /// the previous call to scanActiveBundles or iterate.
getRecentPositive()140*9880d681SAndroid Build Coastguard Worker   ArrayRef<unsigned> getRecentPositive() { return RecentPositive; }
141*9880d681SAndroid Build Coastguard Worker 
142*9880d681SAndroid Build Coastguard Worker   /// finish - Compute the optimal spill code placement given the
143*9880d681SAndroid Build Coastguard Worker   /// constraints. No MustSpill constraints will be violated, and the smallest
144*9880d681SAndroid Build Coastguard Worker   /// possible number of PrefX constraints will be violated, weighted by
145*9880d681SAndroid Build Coastguard Worker   /// expected execution frequencies.
146*9880d681SAndroid Build Coastguard Worker   /// The selected bundles are returned in the bitvector passed to prepare().
147*9880d681SAndroid Build Coastguard Worker   /// @return True if a perfect solution was found, allowing the variable to be
148*9880d681SAndroid Build Coastguard Worker   ///         in a register through all relevant bundles.
149*9880d681SAndroid Build Coastguard Worker   bool finish();
150*9880d681SAndroid Build Coastguard Worker 
151*9880d681SAndroid Build Coastguard Worker   /// getBlockFrequency - Return the estimated block execution frequency per
152*9880d681SAndroid Build Coastguard Worker   /// function invocation.
getBlockFrequency(unsigned Number)153*9880d681SAndroid Build Coastguard Worker   BlockFrequency getBlockFrequency(unsigned Number) const {
154*9880d681SAndroid Build Coastguard Worker     return BlockFrequencies[Number];
155*9880d681SAndroid Build Coastguard Worker   }
156*9880d681SAndroid Build Coastguard Worker 
157*9880d681SAndroid Build Coastguard Worker private:
158*9880d681SAndroid Build Coastguard Worker   bool runOnMachineFunction(MachineFunction&) override;
159*9880d681SAndroid Build Coastguard Worker   void getAnalysisUsage(AnalysisUsage&) const override;
160*9880d681SAndroid Build Coastguard Worker   void releaseMemory() override;
161*9880d681SAndroid Build Coastguard Worker 
162*9880d681SAndroid Build Coastguard Worker   void activate(unsigned);
163*9880d681SAndroid Build Coastguard Worker   void setThreshold(const BlockFrequency &Entry);
164*9880d681SAndroid Build Coastguard Worker 
165*9880d681SAndroid Build Coastguard Worker   bool update(unsigned);
166*9880d681SAndroid Build Coastguard Worker };
167*9880d681SAndroid Build Coastguard Worker 
168*9880d681SAndroid Build Coastguard Worker } // end namespace llvm
169*9880d681SAndroid Build Coastguard Worker 
170*9880d681SAndroid Build Coastguard Worker #endif
171