|  | //===-- SpillPlacement.h - Optimal Spill Code Placement --------*- C++ -*--===// | 
|  | // | 
|  | //                     The LLVM Compiler Infrastructure | 
|  | // | 
|  | // This file is distributed under the University of Illinois Open Source | 
|  | // License. See LICENSE.TXT for details. | 
|  | // | 
|  | //===----------------------------------------------------------------------===// | 
|  | // | 
|  | // This analysis computes the optimal spill code placement between basic blocks. | 
|  | // | 
|  | // The runOnMachineFunction() method only precomputes some profiling information | 
|  | // about the CFG. The real work is done by prepare(), addConstraints(), and | 
|  | // finish() which are called by the register allocator. | 
|  | // | 
|  | // Given a variable that is live across multiple basic blocks, and given | 
|  | // constraints on the basic blocks where the variable is live, determine which | 
|  | // edge bundles should have the variable in a register and which edge bundles | 
|  | // should have the variable in a stack slot. | 
|  | // | 
|  | // The returned bit vector can be used to place optimal spill code at basic | 
|  | // block entries and exits. Spill code placement inside a basic block is not | 
|  | // considered. | 
|  | // | 
|  | //===----------------------------------------------------------------------===// | 
|  |  | 
|  | #ifndef LLVM_LIB_CODEGEN_SPILLPLACEMENT_H | 
|  | #define LLVM_LIB_CODEGEN_SPILLPLACEMENT_H | 
|  |  | 
|  | #include "llvm/ADT/ArrayRef.h" | 
|  | #include "llvm/ADT/SmallVector.h" | 
|  | #include "llvm/CodeGen/MachineFunctionPass.h" | 
|  | #include "llvm/Support/BlockFrequency.h" | 
|  |  | 
|  | namespace llvm { | 
|  |  | 
|  | class BitVector; | 
|  | class EdgeBundles; | 
|  | class MachineBasicBlock; | 
|  | class MachineLoopInfo; | 
|  | class MachineBlockFrequencyInfo; | 
|  |  | 
|  | class SpillPlacement : public MachineFunctionPass { | 
|  | struct Node; | 
|  | const MachineFunction *MF; | 
|  | const EdgeBundles *bundles; | 
|  | const MachineLoopInfo *loops; | 
|  | const MachineBlockFrequencyInfo *MBFI; | 
|  | Node *nodes; | 
|  |  | 
|  | // Nodes that are active in the current computation. Owned by the prepare() | 
|  | // caller. | 
|  | BitVector *ActiveNodes; | 
|  |  | 
|  | // Nodes with active links. Populated by scanActiveBundles. | 
|  | SmallVector<unsigned, 8> Linked; | 
|  |  | 
|  | // Nodes that went positive during the last call to scanActiveBundles or | 
|  | // iterate. | 
|  | SmallVector<unsigned, 8> RecentPositive; | 
|  |  | 
|  | // Block frequencies are computed once. Indexed by block number. | 
|  | SmallVector<BlockFrequency, 8> BlockFrequencies; | 
|  |  | 
|  | /// Decision threshold. A node gets the output value 0 if the weighted sum of | 
|  | /// its inputs falls in the open interval (-Threshold;Threshold). | 
|  | BlockFrequency Threshold; | 
|  |  | 
|  | public: | 
|  | static char ID; // Pass identification, replacement for typeid. | 
|  |  | 
|  | SpillPlacement() : MachineFunctionPass(ID), nodes(nullptr) {} | 
|  | ~SpillPlacement() override { releaseMemory(); } | 
|  |  | 
|  | /// BorderConstraint - A basic block has separate constraints for entry and | 
|  | /// exit. | 
|  | enum BorderConstraint { | 
|  | DontCare,  ///< Block doesn't care / variable not live. | 
|  | PrefReg,   ///< Block entry/exit prefers a register. | 
|  | PrefSpill, ///< Block entry/exit prefers a stack slot. | 
|  | PrefBoth,  ///< Block entry prefers both register and stack. | 
|  | MustSpill  ///< A register is impossible, variable must be spilled. | 
|  | }; | 
|  |  | 
|  | /// BlockConstraint - Entry and exit constraints for a basic block. | 
|  | struct BlockConstraint { | 
|  | unsigned Number;            ///< Basic block number (from MBB::getNumber()). | 
|  | BorderConstraint Entry : 8; ///< Constraint on block entry. | 
|  | BorderConstraint Exit : 8;  ///< Constraint on block exit. | 
|  |  | 
|  | /// True when this block changes the value of the live range. This means | 
|  | /// the block has a non-PHI def.  When this is false, a live-in value on | 
|  | /// the stack can be live-out on the stack without inserting a spill. | 
|  | bool ChangesValue; | 
|  | }; | 
|  |  | 
|  | /// prepare - Reset state and prepare for a new spill placement computation. | 
|  | /// @param RegBundles Bit vector to receive the edge bundles where the | 
|  | ///                   variable should be kept in a register. Each bit | 
|  | ///                   corresponds to an edge bundle, a set bit means the | 
|  | ///                   variable should be kept in a register through the | 
|  | ///                   bundle. A clear bit means the variable should be | 
|  | ///                   spilled. This vector is retained. | 
|  | void prepare(BitVector &RegBundles); | 
|  |  | 
|  | /// addConstraints - Add constraints and biases. This method may be called | 
|  | /// more than once to accumulate constraints. | 
|  | /// @param LiveBlocks Constraints for blocks that have the variable live in or | 
|  | ///                   live out. | 
|  | void addConstraints(ArrayRef<BlockConstraint> LiveBlocks); | 
|  |  | 
|  | /// addPrefSpill - Add PrefSpill constraints to all blocks listed.  This is | 
|  | /// equivalent to calling addConstraint with identical BlockConstraints with | 
|  | /// Entry = Exit = PrefSpill, and ChangesValue = false. | 
|  | /// | 
|  | /// @param Blocks Array of block numbers that prefer to spill in and out. | 
|  | /// @param Strong When true, double the negative bias for these blocks. | 
|  | void addPrefSpill(ArrayRef<unsigned> Blocks, bool Strong); | 
|  |  | 
|  | /// addLinks - Add transparent blocks with the given numbers. | 
|  | void addLinks(ArrayRef<unsigned> Links); | 
|  |  | 
|  | /// scanActiveBundles - Perform an initial scan of all bundles activated by | 
|  | /// addConstraints and addLinks, updating their state. Add all the bundles | 
|  | /// that now prefer a register to RecentPositive. | 
|  | /// Prepare internal data structures for iterate. | 
|  | /// Return true is there are any positive nodes. | 
|  | bool scanActiveBundles(); | 
|  |  | 
|  | /// iterate - Update the network iteratively until convergence, or new bundles | 
|  | /// are found. | 
|  | void iterate(); | 
|  |  | 
|  | /// getRecentPositive - Return an array of bundles that became positive during | 
|  | /// the previous call to scanActiveBundles or iterate. | 
|  | ArrayRef<unsigned> getRecentPositive() { return RecentPositive; } | 
|  |  | 
|  | /// finish - Compute the optimal spill code placement given the | 
|  | /// constraints. No MustSpill constraints will be violated, and the smallest | 
|  | /// possible number of PrefX constraints will be violated, weighted by | 
|  | /// expected execution frequencies. | 
|  | /// The selected bundles are returned in the bitvector passed to prepare(). | 
|  | /// @return True if a perfect solution was found, allowing the variable to be | 
|  | ///         in a register through all relevant bundles. | 
|  | bool finish(); | 
|  |  | 
|  | /// getBlockFrequency - Return the estimated block execution frequency per | 
|  | /// function invocation. | 
|  | BlockFrequency getBlockFrequency(unsigned Number) const { | 
|  | return BlockFrequencies[Number]; | 
|  | } | 
|  |  | 
|  | private: | 
|  | bool runOnMachineFunction(MachineFunction&) override; | 
|  | void getAnalysisUsage(AnalysisUsage&) const override; | 
|  | void releaseMemory() override; | 
|  |  | 
|  | void activate(unsigned); | 
|  | void setThreshold(const BlockFrequency &Entry); | 
|  | }; | 
|  |  | 
|  | } // end namespace llvm | 
|  |  | 
|  | #endif |