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