123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172 |
- //===- SpillPlacement.h - Optimal Spill Code Placement ---------*- C++ -*--===//
- //
- // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
- // See https://llvm.org/LICENSE.txt for license information.
- // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
- //
- //===----------------------------------------------------------------------===//
- //
- // 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/ADT/SparseSet.h"
- #include "llvm/CodeGen/MachineFunctionPass.h"
- #include "llvm/Support/BlockFrequency.h"
- namespace llvm {
- class BitVector;
- class EdgeBundles;
- class MachineBlockFrequencyInfo;
- class MachineFunction;
- class MachineLoopInfo;
- class SpillPlacement : public MachineFunctionPass {
- struct Node;
- const MachineFunction *MF;
- const EdgeBundles *bundles;
- const MachineLoopInfo *loops;
- const MachineBlockFrequencyInfo *MBFI;
- Node *nodes = nullptr;
- // 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;
- /// List of nodes that need to be updated in ::iterate.
- SparseSet<unsigned> TodoList;
- public:
- static char ID; // Pass identification, replacement for typeid.
- SpillPlacement() : MachineFunctionPass(ID) {}
- ~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;
- void print(raw_ostream &OS) const;
- void dump() const;
- };
- /// 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 &mf) override;
- void getAnalysisUsage(AnalysisUsage &AU) const override;
- void releaseMemory() override;
- void activate(unsigned n);
- void setThreshold(const BlockFrequency &Entry);
- bool update(unsigned n);
- };
- } // end namespace llvm
- #endif // LLVM_LIB_CODEGEN_SPILLPLACEMENT_H
|