Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-05-10 08:43:36

0001 //===- SpillPlacement.h - Optimal Spill Code Placement ---------*- C++ -*--===//
0002 //
0003 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
0004 // See https://llvm.org/LICENSE.txt for license information.
0005 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
0006 //
0007 //===----------------------------------------------------------------------===//
0008 //
0009 // This analysis computes the optimal spill code placement between basic blocks.
0010 //
0011 // The runOnMachineFunction() method only precomputes some profiling information
0012 // about the CFG. The real work is done by prepare(), addConstraints(), and
0013 // finish() which are called by the register allocator.
0014 //
0015 // Given a variable that is live across multiple basic blocks, and given
0016 // constraints on the basic blocks where the variable is live, determine which
0017 // edge bundles should have the variable in a register and which edge bundles
0018 // should have the variable in a stack slot.
0019 //
0020 // The returned bit vector can be used to place optimal spill code at basic
0021 // block entries and exits. Spill code placement inside a basic block is not
0022 // considered.
0023 //
0024 //===----------------------------------------------------------------------===//
0025 
0026 #ifndef LLVM_LIB_CODEGEN_SPILLPLACEMENT_H
0027 #define LLVM_LIB_CODEGEN_SPILLPLACEMENT_H
0028 
0029 #include "llvm/ADT/ArrayRef.h"
0030 #include "llvm/ADT/SmallVector.h"
0031 #include "llvm/ADT/SparseSet.h"
0032 #include "llvm/CodeGen/MachineFunctionAnalysis.h"
0033 #include "llvm/CodeGen/MachineFunctionPass.h"
0034 #include "llvm/Support/BlockFrequency.h"
0035 
0036 namespace llvm {
0037 
0038 class BitVector;
0039 class EdgeBundles;
0040 class MachineBlockFrequencyInfo;
0041 class MachineFunction;
0042 class SpillPlacementWrapperLegacy;
0043 class SpillPlacementAnalysis;
0044 
0045 class SpillPlacement {
0046   friend class SpillPlacementWrapperLegacy;
0047   friend class SpillPlacementAnalysis;
0048 
0049   struct Node;
0050 
0051   const MachineFunction *MF = nullptr;
0052   const EdgeBundles *bundles = nullptr;
0053   const MachineBlockFrequencyInfo *MBFI = nullptr;
0054 
0055   std::unique_ptr<Node[]> nodes;
0056 
0057   // Nodes that are active in the current computation. Owned by the prepare()
0058   // caller.
0059   BitVector *ActiveNodes = nullptr;
0060 
0061   // Nodes with active links. Populated by scanActiveBundles.
0062   SmallVector<unsigned, 8> Linked;
0063 
0064   // Nodes that went positive during the last call to scanActiveBundles or
0065   // iterate.
0066   SmallVector<unsigned, 8> RecentPositive;
0067 
0068   // Block frequencies are computed once. Indexed by block number.
0069   SmallVector<BlockFrequency, 8> BlockFrequencies;
0070 
0071   /// Decision threshold. A node gets the output value 0 if the weighted sum of
0072   /// its inputs falls in the open interval (-Threshold;Threshold).
0073   BlockFrequency Threshold;
0074 
0075   /// List of nodes that need to be updated in ::iterate.
0076   SparseSet<unsigned> TodoList;
0077 
0078 public:
0079   /// BorderConstraint - A basic block has separate constraints for entry and
0080   /// exit.
0081   enum BorderConstraint {
0082     DontCare,  ///< Block doesn't care / variable not live.
0083     PrefReg,   ///< Block entry/exit prefers a register.
0084     PrefSpill, ///< Block entry/exit prefers a stack slot.
0085     PrefBoth,  ///< Block entry prefers both register and stack.
0086     MustSpill  ///< A register is impossible, variable must be spilled.
0087   };
0088 
0089   /// BlockConstraint - Entry and exit constraints for a basic block.
0090   struct BlockConstraint {
0091     unsigned Number;            ///< Basic block number (from MBB::getNumber()).
0092     BorderConstraint Entry : 8; ///< Constraint on block entry.
0093     BorderConstraint Exit : 8;  ///< Constraint on block exit.
0094 
0095     /// True when this block changes the value of the live range. This means
0096     /// the block has a non-PHI def.  When this is false, a live-in value on
0097     /// the stack can be live-out on the stack without inserting a spill.
0098     bool ChangesValue;
0099 
0100     void print(raw_ostream &OS) const;
0101     void dump() const;
0102   };
0103 
0104   /// prepare - Reset state and prepare for a new spill placement computation.
0105   /// @param RegBundles Bit vector to receive the edge bundles where the
0106   ///                   variable should be kept in a register. Each bit
0107   ///                   corresponds to an edge bundle, a set bit means the
0108   ///                   variable should be kept in a register through the
0109   ///                   bundle. A clear bit means the variable should be
0110   ///                   spilled. This vector is retained.
0111   void prepare(BitVector &RegBundles);
0112 
0113   /// addConstraints - Add constraints and biases. This method may be called
0114   /// more than once to accumulate constraints.
0115   /// @param LiveBlocks Constraints for blocks that have the variable live in or
0116   ///                   live out.
0117   void addConstraints(ArrayRef<BlockConstraint> LiveBlocks);
0118 
0119   /// addPrefSpill - Add PrefSpill constraints to all blocks listed.  This is
0120   /// equivalent to calling addConstraint with identical BlockConstraints with
0121   /// Entry = Exit = PrefSpill, and ChangesValue = false.
0122   ///
0123   /// @param Blocks Array of block numbers that prefer to spill in and out.
0124   /// @param Strong When true, double the negative bias for these blocks.
0125   void addPrefSpill(ArrayRef<unsigned> Blocks, bool Strong);
0126 
0127   /// addLinks - Add transparent blocks with the given numbers.
0128   void addLinks(ArrayRef<unsigned> Links);
0129 
0130   /// scanActiveBundles - Perform an initial scan of all bundles activated by
0131   /// addConstraints and addLinks, updating their state. Add all the bundles
0132   /// that now prefer a register to RecentPositive.
0133   /// Prepare internal data structures for iterate.
0134   /// Return true is there are any positive nodes.
0135   bool scanActiveBundles();
0136 
0137   /// iterate - Update the network iteratively until convergence, or new bundles
0138   /// are found.
0139   void iterate();
0140 
0141   /// getRecentPositive - Return an array of bundles that became positive during
0142   /// the previous call to scanActiveBundles or iterate.
0143   ArrayRef<unsigned> getRecentPositive() { return RecentPositive; }
0144 
0145   /// finish - Compute the optimal spill code placement given the
0146   /// constraints. No MustSpill constraints will be violated, and the smallest
0147   /// possible number of PrefX constraints will be violated, weighted by
0148   /// expected execution frequencies.
0149   /// The selected bundles are returned in the bitvector passed to prepare().
0150   /// @return True if a perfect solution was found, allowing the variable to be
0151   ///         in a register through all relevant bundles.
0152   bool finish();
0153 
0154   /// getBlockFrequency - Return the estimated block execution frequency per
0155   /// function invocation.
0156   BlockFrequency getBlockFrequency(unsigned Number) const {
0157     return BlockFrequencies[Number];
0158   }
0159 
0160   bool invalidate(MachineFunction &MF, const PreservedAnalyses &PA,
0161                   MachineFunctionAnalysisManager::Invalidator &Inv);
0162 
0163   SpillPlacement(SpillPlacement &&);
0164   ~SpillPlacement();
0165 
0166 private:
0167   SpillPlacement();
0168 
0169   void releaseMemory();
0170 
0171   void run(MachineFunction &MF, EdgeBundles *Bundles,
0172            MachineBlockFrequencyInfo *MBFI);
0173   void activate(unsigned n);
0174   void setThreshold(BlockFrequency Entry);
0175 
0176   bool update(unsigned n);
0177 };
0178 
0179 class SpillPlacementWrapperLegacy : public MachineFunctionPass {
0180 public:
0181   static char ID;
0182   SpillPlacementWrapperLegacy() : MachineFunctionPass(ID) {}
0183 
0184   SpillPlacement &getResult() { return Impl; }
0185   const SpillPlacement &getResult() const { return Impl; }
0186 
0187 private:
0188   SpillPlacement Impl;
0189   bool runOnMachineFunction(MachineFunction &MF) override;
0190   void getAnalysisUsage(AnalysisUsage &AU) const override;
0191   void releaseMemory() override { Impl.releaseMemory(); }
0192 };
0193 
0194 class SpillPlacementAnalysis
0195     : public AnalysisInfoMixin<SpillPlacementAnalysis> {
0196   friend AnalysisInfoMixin<SpillPlacementAnalysis>;
0197   static AnalysisKey Key;
0198 
0199 public:
0200   using Result = SpillPlacement;
0201   SpillPlacement run(MachineFunction &, MachineFunctionAnalysisManager &);
0202 };
0203 
0204 } // end namespace llvm
0205 
0206 #endif // LLVM_LIB_CODEGEN_SPILLPLACEMENT_H