10b57cec5SDimitry Andric //===- SpillPlacement.h - Optimal Spill Code Placement ---------*- C++ -*--===// 20b57cec5SDimitry Andric // 30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 60b57cec5SDimitry Andric // 70b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 80b57cec5SDimitry Andric // 90b57cec5SDimitry Andric // This analysis computes the optimal spill code placement between basic blocks. 100b57cec5SDimitry Andric // 110b57cec5SDimitry Andric // The runOnMachineFunction() method only precomputes some profiling information 120b57cec5SDimitry Andric // about the CFG. The real work is done by prepare(), addConstraints(), and 130b57cec5SDimitry Andric // finish() which are called by the register allocator. 140b57cec5SDimitry Andric // 150b57cec5SDimitry Andric // Given a variable that is live across multiple basic blocks, and given 160b57cec5SDimitry Andric // constraints on the basic blocks where the variable is live, determine which 170b57cec5SDimitry Andric // edge bundles should have the variable in a register and which edge bundles 180b57cec5SDimitry Andric // should have the variable in a stack slot. 190b57cec5SDimitry Andric // 200b57cec5SDimitry Andric // The returned bit vector can be used to place optimal spill code at basic 210b57cec5SDimitry Andric // block entries and exits. Spill code placement inside a basic block is not 220b57cec5SDimitry Andric // considered. 230b57cec5SDimitry Andric // 240b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 250b57cec5SDimitry Andric 260b57cec5SDimitry Andric #ifndef LLVM_LIB_CODEGEN_SPILLPLACEMENT_H 270b57cec5SDimitry Andric #define LLVM_LIB_CODEGEN_SPILLPLACEMENT_H 280b57cec5SDimitry Andric 290b57cec5SDimitry Andric #include "llvm/ADT/ArrayRef.h" 300b57cec5SDimitry Andric #include "llvm/ADT/SmallVector.h" 310b57cec5SDimitry Andric #include "llvm/ADT/SparseSet.h" 320b57cec5SDimitry Andric #include "llvm/CodeGen/MachineFunctionPass.h" 330b57cec5SDimitry Andric #include "llvm/Support/BlockFrequency.h" 340b57cec5SDimitry Andric 350b57cec5SDimitry Andric namespace llvm { 360b57cec5SDimitry Andric 370b57cec5SDimitry Andric class BitVector; 380b57cec5SDimitry Andric class EdgeBundles; 390b57cec5SDimitry Andric class MachineBlockFrequencyInfo; 400b57cec5SDimitry Andric class MachineFunction; 410b57cec5SDimitry Andric 420b57cec5SDimitry Andric class SpillPlacement : public MachineFunctionPass { 430b57cec5SDimitry Andric struct Node; 4406c3fb27SDimitry Andric const MachineFunction *MF = nullptr; 4506c3fb27SDimitry Andric const EdgeBundles *bundles = nullptr; 4606c3fb27SDimitry Andric const MachineBlockFrequencyInfo *MBFI = nullptr; 470b57cec5SDimitry Andric Node *nodes = nullptr; 480b57cec5SDimitry Andric 490b57cec5SDimitry Andric // Nodes that are active in the current computation. Owned by the prepare() 500b57cec5SDimitry Andric // caller. 5106c3fb27SDimitry Andric BitVector *ActiveNodes = nullptr; 520b57cec5SDimitry Andric 530b57cec5SDimitry Andric // Nodes with active links. Populated by scanActiveBundles. 540b57cec5SDimitry Andric SmallVector<unsigned, 8> Linked; 550b57cec5SDimitry Andric 560b57cec5SDimitry Andric // Nodes that went positive during the last call to scanActiveBundles or 570b57cec5SDimitry Andric // iterate. 580b57cec5SDimitry Andric SmallVector<unsigned, 8> RecentPositive; 590b57cec5SDimitry Andric 600b57cec5SDimitry Andric // Block frequencies are computed once. Indexed by block number. 610b57cec5SDimitry Andric SmallVector<BlockFrequency, 8> BlockFrequencies; 620b57cec5SDimitry Andric 630b57cec5SDimitry Andric /// Decision threshold. A node gets the output value 0 if the weighted sum of 640b57cec5SDimitry Andric /// its inputs falls in the open interval (-Threshold;Threshold). 650b57cec5SDimitry Andric BlockFrequency Threshold; 660b57cec5SDimitry Andric 670b57cec5SDimitry Andric /// List of nodes that need to be updated in ::iterate. 680b57cec5SDimitry Andric SparseSet<unsigned> TodoList; 690b57cec5SDimitry Andric 700b57cec5SDimitry Andric public: 710b57cec5SDimitry Andric static char ID; // Pass identification, replacement for typeid. 720b57cec5SDimitry Andric 730b57cec5SDimitry Andric SpillPlacement() : MachineFunctionPass(ID) {} 740b57cec5SDimitry Andric ~SpillPlacement() override { releaseMemory(); } 750b57cec5SDimitry Andric 760b57cec5SDimitry Andric /// BorderConstraint - A basic block has separate constraints for entry and 770b57cec5SDimitry Andric /// exit. 780b57cec5SDimitry Andric enum BorderConstraint { 790b57cec5SDimitry Andric DontCare, ///< Block doesn't care / variable not live. 800b57cec5SDimitry Andric PrefReg, ///< Block entry/exit prefers a register. 810b57cec5SDimitry Andric PrefSpill, ///< Block entry/exit prefers a stack slot. 820b57cec5SDimitry Andric PrefBoth, ///< Block entry prefers both register and stack. 830b57cec5SDimitry Andric MustSpill ///< A register is impossible, variable must be spilled. 840b57cec5SDimitry Andric }; 850b57cec5SDimitry Andric 860b57cec5SDimitry Andric /// BlockConstraint - Entry and exit constraints for a basic block. 870b57cec5SDimitry Andric struct BlockConstraint { 880b57cec5SDimitry Andric unsigned Number; ///< Basic block number (from MBB::getNumber()). 890b57cec5SDimitry Andric BorderConstraint Entry : 8; ///< Constraint on block entry. 900b57cec5SDimitry Andric BorderConstraint Exit : 8; ///< Constraint on block exit. 910b57cec5SDimitry Andric 920b57cec5SDimitry Andric /// True when this block changes the value of the live range. This means 930b57cec5SDimitry Andric /// the block has a non-PHI def. When this is false, a live-in value on 940b57cec5SDimitry Andric /// the stack can be live-out on the stack without inserting a spill. 950b57cec5SDimitry Andric bool ChangesValue; 96fe6060f1SDimitry Andric 97fe6060f1SDimitry Andric void print(raw_ostream &OS) const; 98fe6060f1SDimitry Andric void dump() const; 990b57cec5SDimitry Andric }; 1000b57cec5SDimitry Andric 1010b57cec5SDimitry Andric /// prepare - Reset state and prepare for a new spill placement computation. 1020b57cec5SDimitry Andric /// @param RegBundles Bit vector to receive the edge bundles where the 1030b57cec5SDimitry Andric /// variable should be kept in a register. Each bit 1040b57cec5SDimitry Andric /// corresponds to an edge bundle, a set bit means the 1050b57cec5SDimitry Andric /// variable should be kept in a register through the 1060b57cec5SDimitry Andric /// bundle. A clear bit means the variable should be 1070b57cec5SDimitry Andric /// spilled. This vector is retained. 1080b57cec5SDimitry Andric void prepare(BitVector &RegBundles); 1090b57cec5SDimitry Andric 1100b57cec5SDimitry Andric /// addConstraints - Add constraints and biases. This method may be called 1110b57cec5SDimitry Andric /// more than once to accumulate constraints. 1120b57cec5SDimitry Andric /// @param LiveBlocks Constraints for blocks that have the variable live in or 1130b57cec5SDimitry Andric /// live out. 1140b57cec5SDimitry Andric void addConstraints(ArrayRef<BlockConstraint> LiveBlocks); 1150b57cec5SDimitry Andric 1160b57cec5SDimitry Andric /// addPrefSpill - Add PrefSpill constraints to all blocks listed. This is 1170b57cec5SDimitry Andric /// equivalent to calling addConstraint with identical BlockConstraints with 1180b57cec5SDimitry Andric /// Entry = Exit = PrefSpill, and ChangesValue = false. 1190b57cec5SDimitry Andric /// 1200b57cec5SDimitry Andric /// @param Blocks Array of block numbers that prefer to spill in and out. 1210b57cec5SDimitry Andric /// @param Strong When true, double the negative bias for these blocks. 1220b57cec5SDimitry Andric void addPrefSpill(ArrayRef<unsigned> Blocks, bool Strong); 1230b57cec5SDimitry Andric 1240b57cec5SDimitry Andric /// addLinks - Add transparent blocks with the given numbers. 1250b57cec5SDimitry Andric void addLinks(ArrayRef<unsigned> Links); 1260b57cec5SDimitry Andric 1270b57cec5SDimitry Andric /// scanActiveBundles - Perform an initial scan of all bundles activated by 1280b57cec5SDimitry Andric /// addConstraints and addLinks, updating their state. Add all the bundles 1290b57cec5SDimitry Andric /// that now prefer a register to RecentPositive. 1300b57cec5SDimitry Andric /// Prepare internal data structures for iterate. 1310b57cec5SDimitry Andric /// Return true is there are any positive nodes. 1320b57cec5SDimitry Andric bool scanActiveBundles(); 1330b57cec5SDimitry Andric 1340b57cec5SDimitry Andric /// iterate - Update the network iteratively until convergence, or new bundles 1350b57cec5SDimitry Andric /// are found. 1360b57cec5SDimitry Andric void iterate(); 1370b57cec5SDimitry Andric 1380b57cec5SDimitry Andric /// getRecentPositive - Return an array of bundles that became positive during 1390b57cec5SDimitry Andric /// the previous call to scanActiveBundles or iterate. 1400b57cec5SDimitry Andric ArrayRef<unsigned> getRecentPositive() { return RecentPositive; } 1410b57cec5SDimitry Andric 1420b57cec5SDimitry Andric /// finish - Compute the optimal spill code placement given the 1430b57cec5SDimitry Andric /// constraints. No MustSpill constraints will be violated, and the smallest 1440b57cec5SDimitry Andric /// possible number of PrefX constraints will be violated, weighted by 1450b57cec5SDimitry Andric /// expected execution frequencies. 1460b57cec5SDimitry Andric /// The selected bundles are returned in the bitvector passed to prepare(). 1470b57cec5SDimitry Andric /// @return True if a perfect solution was found, allowing the variable to be 1480b57cec5SDimitry Andric /// in a register through all relevant bundles. 1490b57cec5SDimitry Andric bool finish(); 1500b57cec5SDimitry Andric 1510b57cec5SDimitry Andric /// getBlockFrequency - Return the estimated block execution frequency per 1520b57cec5SDimitry Andric /// function invocation. 1530b57cec5SDimitry Andric BlockFrequency getBlockFrequency(unsigned Number) const { 1540b57cec5SDimitry Andric return BlockFrequencies[Number]; 1550b57cec5SDimitry Andric } 1560b57cec5SDimitry Andric 1570b57cec5SDimitry Andric private: 1580b57cec5SDimitry Andric bool runOnMachineFunction(MachineFunction &mf) override; 1590b57cec5SDimitry Andric void getAnalysisUsage(AnalysisUsage &AU) const override; 1600b57cec5SDimitry Andric void releaseMemory() override; 1610b57cec5SDimitry Andric 1620b57cec5SDimitry Andric void activate(unsigned n); 163*5f757f3fSDimitry Andric void setThreshold(BlockFrequency Entry); 1640b57cec5SDimitry Andric 1650b57cec5SDimitry Andric bool update(unsigned n); 1660b57cec5SDimitry Andric }; 1670b57cec5SDimitry Andric 1680b57cec5SDimitry Andric } // end namespace llvm 1690b57cec5SDimitry Andric 1700b57cec5SDimitry Andric #endif // LLVM_LIB_CODEGEN_SPILLPLACEMENT_H 171