diff options
Diffstat (limited to 'llvm/lib/CodeGen/SpillPlacement.h')
| -rw-r--r-- | llvm/lib/CodeGen/SpillPlacement.h | 169 | 
1 files changed, 169 insertions, 0 deletions
| diff --git a/llvm/lib/CodeGen/SpillPlacement.h b/llvm/lib/CodeGen/SpillPlacement.h new file mode 100644 index 0000000000000..aa0e07ef92e34 --- /dev/null +++ b/llvm/lib/CodeGen/SpillPlacement.h @@ -0,0 +1,169 @@ +//===- 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; +  }; + +  /// 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 | 
