507 lines
		
	
	
		
			18 KiB
		
	
	
	
		
			C++
		
	
	
	
			
		
		
	
	
			507 lines
		
	
	
		
			18 KiB
		
	
	
	
		
			C++
		
	
	
	
//==- RegAllocGreedy.h ------- greedy register allocator  ----------*-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 file defines the RAGreedy function pass for register allocation in
 | 
						|
// optimized builds.
 | 
						|
//===----------------------------------------------------------------------===//
 | 
						|
 | 
						|
#ifndef LLVM_CODEGEN_REGALLOCGREEDY_H_
 | 
						|
#define LLVM_CODEGEN_REGALLOCGREEDY_H_
 | 
						|
 | 
						|
#include "AllocationOrder.h"
 | 
						|
#include "InterferenceCache.h"
 | 
						|
#include "LiveDebugVariables.h"
 | 
						|
#include "RegAllocBase.h"
 | 
						|
#include "RegAllocEvictionAdvisor.h"
 | 
						|
#include "SpillPlacement.h"
 | 
						|
#include "SplitKit.h"
 | 
						|
#include "llvm/ADT/ArrayRef.h"
 | 
						|
#include "llvm/ADT/BitVector.h"
 | 
						|
#include "llvm/ADT/DenseMap.h"
 | 
						|
#include "llvm/ADT/IndexedMap.h"
 | 
						|
#include "llvm/ADT/MapVector.h"
 | 
						|
#include "llvm/ADT/SetVector.h"
 | 
						|
#include "llvm/ADT/SmallPtrSet.h"
 | 
						|
#include "llvm/ADT/SmallSet.h"
 | 
						|
#include "llvm/ADT/SmallVector.h"
 | 
						|
#include "llvm/ADT/StringRef.h"
 | 
						|
#include "llvm/Analysis/AliasAnalysis.h"
 | 
						|
#include "llvm/CodeGen/CalcSpillWeights.h"
 | 
						|
#include "llvm/CodeGen/EdgeBundles.h"
 | 
						|
#include "llvm/CodeGen/LiveInterval.h"
 | 
						|
#include "llvm/CodeGen/LiveIntervalUnion.h"
 | 
						|
#include "llvm/CodeGen/LiveIntervals.h"
 | 
						|
#include "llvm/CodeGen/LiveRangeEdit.h"
 | 
						|
#include "llvm/CodeGen/LiveRegMatrix.h"
 | 
						|
#include "llvm/CodeGen/LiveStacks.h"
 | 
						|
#include "llvm/CodeGen/MachineBasicBlock.h"
 | 
						|
#include "llvm/CodeGen/MachineBlockFrequencyInfo.h"
 | 
						|
#include "llvm/CodeGen/MachineDominators.h"
 | 
						|
#include "llvm/CodeGen/MachineFrameInfo.h"
 | 
						|
#include "llvm/CodeGen/MachineFunction.h"
 | 
						|
#include "llvm/CodeGen/MachineFunctionPass.h"
 | 
						|
#include "llvm/CodeGen/MachineLoopInfo.h"
 | 
						|
#include "llvm/CodeGen/MachineRegisterInfo.h"
 | 
						|
#include "llvm/CodeGen/RegisterClassInfo.h"
 | 
						|
#include "llvm/CodeGen/SlotIndexes.h"
 | 
						|
#include "llvm/CodeGen/Spiller.h"
 | 
						|
#include "llvm/CodeGen/TargetInstrInfo.h"
 | 
						|
#include "llvm/CodeGen/TargetRegisterInfo.h"
 | 
						|
#include "llvm/CodeGen/TargetSubtargetInfo.h"
 | 
						|
#include "llvm/CodeGen/VirtRegMap.h"
 | 
						|
#include "llvm/IR/DebugInfoMetadata.h"
 | 
						|
#include "llvm/IR/Function.h"
 | 
						|
#include "llvm/IR/LLVMContext.h"
 | 
						|
#include "llvm/MC/MCRegisterInfo.h"
 | 
						|
#include "llvm/Pass.h"
 | 
						|
#include "llvm/Support/BranchProbability.h"
 | 
						|
#include "llvm/Target/TargetMachine.h"
 | 
						|
#include <algorithm>
 | 
						|
#include <cassert>
 | 
						|
#include <cstdint>
 | 
						|
#include <memory>
 | 
						|
#include <queue>
 | 
						|
#include <tuple>
 | 
						|
#include <utility>
 | 
						|
 | 
						|
namespace llvm {
 | 
						|
class LLVM_LIBRARY_VISIBILITY RAGreedy : public MachineFunctionPass,
 | 
						|
                                         public RegAllocBase,
 | 
						|
                                         private LiveRangeEdit::Delegate {
 | 
						|
  // Interface to eviction advisers
 | 
						|
public:
 | 
						|
  /// Track allocation stage and eviction loop prevention during allocation.
 | 
						|
  class ExtraRegInfo final {
 | 
						|
    // RegInfo - Keep additional information about each live range.
 | 
						|
    struct RegInfo {
 | 
						|
      LiveRangeStage Stage = RS_New;
 | 
						|
 | 
						|
      // Cascade - Eviction loop prevention. See
 | 
						|
      // canEvictInterferenceBasedOnCost().
 | 
						|
      unsigned Cascade = 0;
 | 
						|
 | 
						|
      RegInfo() = default;
 | 
						|
    };
 | 
						|
 | 
						|
    IndexedMap<RegInfo, VirtReg2IndexFunctor> Info;
 | 
						|
    unsigned NextCascade = 1;
 | 
						|
 | 
						|
  public:
 | 
						|
    ExtraRegInfo() = default;
 | 
						|
    ExtraRegInfo(const ExtraRegInfo &) = delete;
 | 
						|
 | 
						|
    LiveRangeStage getStage(Register Reg) const { return Info[Reg].Stage; }
 | 
						|
 | 
						|
    LiveRangeStage getStage(const LiveInterval &VirtReg) const {
 | 
						|
      return getStage(VirtReg.reg());
 | 
						|
    }
 | 
						|
 | 
						|
    void setStage(Register Reg, LiveRangeStage Stage) {
 | 
						|
      Info.grow(Reg.id());
 | 
						|
      Info[Reg].Stage = Stage;
 | 
						|
    }
 | 
						|
 | 
						|
    void setStage(const LiveInterval &VirtReg, LiveRangeStage Stage) {
 | 
						|
      setStage(VirtReg.reg(), Stage);
 | 
						|
    }
 | 
						|
 | 
						|
    /// Return the current stage of the register, if present, otherwise
 | 
						|
    /// initialize it and return that.
 | 
						|
    LiveRangeStage getOrInitStage(Register Reg) {
 | 
						|
      Info.grow(Reg.id());
 | 
						|
      return getStage(Reg);
 | 
						|
    }
 | 
						|
 | 
						|
    unsigned getCascade(Register Reg) const { return Info[Reg].Cascade; }
 | 
						|
 | 
						|
    void setCascade(Register Reg, unsigned Cascade) {
 | 
						|
      Info.grow(Reg.id());
 | 
						|
      Info[Reg].Cascade = Cascade;
 | 
						|
    }
 | 
						|
 | 
						|
    unsigned getOrAssignNewCascade(Register Reg) {
 | 
						|
      unsigned Cascade = getCascade(Reg);
 | 
						|
      if (!Cascade) {
 | 
						|
        Cascade = NextCascade++;
 | 
						|
        setCascade(Reg, Cascade);
 | 
						|
      }
 | 
						|
      return Cascade;
 | 
						|
    }
 | 
						|
 | 
						|
    unsigned getCascadeOrCurrentNext(Register Reg) const {
 | 
						|
      unsigned Cascade = getCascade(Reg);
 | 
						|
      if (!Cascade)
 | 
						|
        Cascade = NextCascade;
 | 
						|
      return Cascade;
 | 
						|
    }
 | 
						|
 | 
						|
    template <typename Iterator>
 | 
						|
    void setStage(Iterator Begin, Iterator End, LiveRangeStage NewStage) {
 | 
						|
      for (; Begin != End; ++Begin) {
 | 
						|
        Register Reg = *Begin;
 | 
						|
        Info.grow(Reg.id());
 | 
						|
        if (Info[Reg].Stage == RS_New)
 | 
						|
          Info[Reg].Stage = NewStage;
 | 
						|
      }
 | 
						|
    }
 | 
						|
    void LRE_DidCloneVirtReg(Register New, Register Old);
 | 
						|
  };
 | 
						|
 | 
						|
  LiveRegMatrix *getInterferenceMatrix() const { return Matrix; }
 | 
						|
  LiveIntervals *getLiveIntervals() const { return LIS; }
 | 
						|
  VirtRegMap *getVirtRegMap() const { return VRM; }
 | 
						|
  const RegisterClassInfo &getRegClassInfo() const { return RegClassInfo; }
 | 
						|
  const ExtraRegInfo &getExtraInfo() const { return *ExtraInfo; }
 | 
						|
  // end (interface to eviction advisers)
 | 
						|
 | 
						|
private:
 | 
						|
  // Convenient shortcuts.
 | 
						|
  using PQueue = std::priority_queue<std::pair<unsigned, unsigned>>;
 | 
						|
  using SmallLISet = SmallPtrSet<LiveInterval *, 4>;
 | 
						|
 | 
						|
  // context
 | 
						|
  MachineFunction *MF;
 | 
						|
 | 
						|
  // Shortcuts to some useful interface.
 | 
						|
  const TargetInstrInfo *TII;
 | 
						|
  const TargetRegisterInfo *TRI;
 | 
						|
  RegisterClassInfo RCI;
 | 
						|
 | 
						|
  // analyses
 | 
						|
  SlotIndexes *Indexes;
 | 
						|
  MachineBlockFrequencyInfo *MBFI;
 | 
						|
  MachineDominatorTree *DomTree;
 | 
						|
  MachineLoopInfo *Loops;
 | 
						|
  MachineOptimizationRemarkEmitter *ORE;
 | 
						|
  EdgeBundles *Bundles;
 | 
						|
  SpillPlacement *SpillPlacer;
 | 
						|
  LiveDebugVariables *DebugVars;
 | 
						|
  AliasAnalysis *AA;
 | 
						|
 | 
						|
  // state
 | 
						|
  std::unique_ptr<Spiller> SpillerInstance;
 | 
						|
  PQueue Queue;
 | 
						|
  std::unique_ptr<VirtRegAuxInfo> VRAI;
 | 
						|
  Optional<ExtraRegInfo> ExtraInfo;
 | 
						|
  std::unique_ptr<RegAllocEvictionAdvisor> EvictAdvisor;
 | 
						|
 | 
						|
  // Enum CutOffStage to keep a track whether the register allocation failed
 | 
						|
  // because of the cutoffs encountered in last chance recoloring.
 | 
						|
  // Note: This is used as bitmask. New value should be next power of 2.
 | 
						|
  enum CutOffStage {
 | 
						|
    // No cutoffs encountered
 | 
						|
    CO_None = 0,
 | 
						|
 | 
						|
    // lcr-max-depth cutoff encountered
 | 
						|
    CO_Depth = 1,
 | 
						|
 | 
						|
    // lcr-max-interf cutoff encountered
 | 
						|
    CO_Interf = 2
 | 
						|
  };
 | 
						|
 | 
						|
  uint8_t CutOffInfo;
 | 
						|
 | 
						|
#ifndef NDEBUG
 | 
						|
  static const char *const StageName[];
 | 
						|
#endif
 | 
						|
 | 
						|
  /// EvictionTrack - Keeps track of past evictions in order to optimize region
 | 
						|
  /// split decision.
 | 
						|
  class EvictionTrack {
 | 
						|
 | 
						|
  public:
 | 
						|
    using EvictorInfo =
 | 
						|
        std::pair<Register /* evictor */, MCRegister /* physreg */>;
 | 
						|
    using EvicteeInfo = llvm::DenseMap<Register /* evictee */, EvictorInfo>;
 | 
						|
 | 
						|
  private:
 | 
						|
    /// Each Vreg that has been evicted in the last stage of selectOrSplit will
 | 
						|
    /// be mapped to the evictor Vreg and the PhysReg it was evicted from.
 | 
						|
    EvicteeInfo Evictees;
 | 
						|
 | 
						|
  public:
 | 
						|
    /// Clear all eviction information.
 | 
						|
    void clear() { Evictees.clear(); }
 | 
						|
 | 
						|
    ///  Clear eviction information for the given evictee Vreg.
 | 
						|
    /// E.g. when Vreg get's a new allocation, the old eviction info is no
 | 
						|
    /// longer relevant.
 | 
						|
    /// \param Evictee The evictee Vreg for whom we want to clear collected
 | 
						|
    /// eviction info.
 | 
						|
    void clearEvicteeInfo(Register Evictee) { Evictees.erase(Evictee); }
 | 
						|
 | 
						|
    /// Track new eviction.
 | 
						|
    /// The Evictor vreg has evicted the Evictee vreg from Physreg.
 | 
						|
    /// \param PhysReg The physical register Evictee was evicted from.
 | 
						|
    /// \param Evictor The evictor Vreg that evicted Evictee.
 | 
						|
    /// \param Evictee The evictee Vreg.
 | 
						|
    void addEviction(MCRegister PhysReg, Register Evictor, Register Evictee) {
 | 
						|
      Evictees[Evictee].first = Evictor;
 | 
						|
      Evictees[Evictee].second = PhysReg;
 | 
						|
    }
 | 
						|
 | 
						|
    /// Return the Evictor Vreg which evicted Evictee Vreg from PhysReg.
 | 
						|
    /// \param Evictee The evictee vreg.
 | 
						|
    /// \return The Evictor vreg which evicted Evictee vreg from PhysReg. 0 if
 | 
						|
    /// nobody has evicted Evictee from PhysReg.
 | 
						|
    EvictorInfo getEvictor(Register Evictee) {
 | 
						|
      if (Evictees.count(Evictee)) {
 | 
						|
        return Evictees[Evictee];
 | 
						|
      }
 | 
						|
 | 
						|
      return EvictorInfo(0, 0);
 | 
						|
    }
 | 
						|
  };
 | 
						|
 | 
						|
  // Keeps track of past evictions in order to optimize region split decision.
 | 
						|
  EvictionTrack LastEvicted;
 | 
						|
 | 
						|
  // splitting state.
 | 
						|
  std::unique_ptr<SplitAnalysis> SA;
 | 
						|
  std::unique_ptr<SplitEditor> SE;
 | 
						|
 | 
						|
  /// Cached per-block interference maps
 | 
						|
  InterferenceCache IntfCache;
 | 
						|
 | 
						|
  /// All basic blocks where the current register has uses.
 | 
						|
  SmallVector<SpillPlacement::BlockConstraint, 8> SplitConstraints;
 | 
						|
 | 
						|
  /// Global live range splitting candidate info.
 | 
						|
  struct GlobalSplitCandidate {
 | 
						|
    // Register intended for assignment, or 0.
 | 
						|
    MCRegister PhysReg;
 | 
						|
 | 
						|
    // SplitKit interval index for this candidate.
 | 
						|
    unsigned IntvIdx;
 | 
						|
 | 
						|
    // Interference for PhysReg.
 | 
						|
    InterferenceCache::Cursor Intf;
 | 
						|
 | 
						|
    // Bundles where this candidate should be live.
 | 
						|
    BitVector LiveBundles;
 | 
						|
    SmallVector<unsigned, 8> ActiveBlocks;
 | 
						|
 | 
						|
    void reset(InterferenceCache &Cache, MCRegister Reg) {
 | 
						|
      PhysReg = Reg;
 | 
						|
      IntvIdx = 0;
 | 
						|
      Intf.setPhysReg(Cache, Reg);
 | 
						|
      LiveBundles.clear();
 | 
						|
      ActiveBlocks.clear();
 | 
						|
    }
 | 
						|
 | 
						|
    // Set B[I] = C for every live bundle where B[I] was NoCand.
 | 
						|
    unsigned getBundles(SmallVectorImpl<unsigned> &B, unsigned C) {
 | 
						|
      unsigned Count = 0;
 | 
						|
      for (unsigned I : LiveBundles.set_bits())
 | 
						|
        if (B[I] == NoCand) {
 | 
						|
          B[I] = C;
 | 
						|
          Count++;
 | 
						|
        }
 | 
						|
      return Count;
 | 
						|
    }
 | 
						|
  };
 | 
						|
 | 
						|
  /// Candidate info for each PhysReg in AllocationOrder.
 | 
						|
  /// This vector never shrinks, but grows to the size of the largest register
 | 
						|
  /// class.
 | 
						|
  SmallVector<GlobalSplitCandidate, 32> GlobalCand;
 | 
						|
 | 
						|
  enum : unsigned { NoCand = ~0u };
 | 
						|
 | 
						|
  /// Candidate map. Each edge bundle is assigned to a GlobalCand entry, or to
 | 
						|
  /// NoCand which indicates the stack interval.
 | 
						|
  SmallVector<unsigned, 32> BundleCand;
 | 
						|
 | 
						|
  /// Callee-save register cost, calculated once per machine function.
 | 
						|
  BlockFrequency CSRCost;
 | 
						|
 | 
						|
  /// Enable or not the consideration of the cost of local intervals created
 | 
						|
  /// by a split candidate when choosing the best split candidate.
 | 
						|
  bool EnableAdvancedRASplitCost;
 | 
						|
 | 
						|
  /// Set of broken hints that may be reconciled later because of eviction.
 | 
						|
  SmallSetVector<LiveInterval *, 8> SetOfBrokenHints;
 | 
						|
 | 
						|
  /// The register cost values. This list will be recreated for each Machine
 | 
						|
  /// Function
 | 
						|
  ArrayRef<uint8_t> RegCosts;
 | 
						|
 | 
						|
public:
 | 
						|
  RAGreedy(const RegClassFilterFunc F = allocateAllRegClasses);
 | 
						|
 | 
						|
  /// Return the pass name.
 | 
						|
  StringRef getPassName() const override { return "Greedy Register Allocator"; }
 | 
						|
 | 
						|
  /// RAGreedy analysis usage.
 | 
						|
  void getAnalysisUsage(AnalysisUsage &AU) const override;
 | 
						|
  void releaseMemory() override;
 | 
						|
  Spiller &spiller() override { return *SpillerInstance; }
 | 
						|
  void enqueueImpl(LiveInterval *LI) override;
 | 
						|
  LiveInterval *dequeue() override;
 | 
						|
  MCRegister selectOrSplit(LiveInterval &,
 | 
						|
                           SmallVectorImpl<Register> &) override;
 | 
						|
  void aboutToRemoveInterval(LiveInterval &) override;
 | 
						|
 | 
						|
  /// Perform register allocation.
 | 
						|
  bool runOnMachineFunction(MachineFunction &mf) override;
 | 
						|
 | 
						|
  MachineFunctionProperties getRequiredProperties() const override {
 | 
						|
    return MachineFunctionProperties().set(
 | 
						|
        MachineFunctionProperties::Property::NoPHIs);
 | 
						|
  }
 | 
						|
 | 
						|
  MachineFunctionProperties getClearedProperties() const override {
 | 
						|
    return MachineFunctionProperties().set(
 | 
						|
        MachineFunctionProperties::Property::IsSSA);
 | 
						|
  }
 | 
						|
 | 
						|
  static char ID;
 | 
						|
 | 
						|
private:
 | 
						|
  MCRegister selectOrSplitImpl(LiveInterval &, SmallVectorImpl<Register> &,
 | 
						|
                               SmallVirtRegSet &, unsigned = 0);
 | 
						|
 | 
						|
  bool LRE_CanEraseVirtReg(Register) override;
 | 
						|
  void LRE_WillShrinkVirtReg(Register) override;
 | 
						|
  void LRE_DidCloneVirtReg(Register, Register) override;
 | 
						|
  void enqueue(PQueue &CurQueue, LiveInterval *LI);
 | 
						|
  LiveInterval *dequeue(PQueue &CurQueue);
 | 
						|
 | 
						|
  BlockFrequency calcSpillCost();
 | 
						|
  bool addSplitConstraints(InterferenceCache::Cursor, BlockFrequency &);
 | 
						|
  bool addThroughConstraints(InterferenceCache::Cursor, ArrayRef<unsigned>);
 | 
						|
  bool growRegion(GlobalSplitCandidate &Cand);
 | 
						|
  bool splitCanCauseEvictionChain(Register Evictee, GlobalSplitCandidate &Cand,
 | 
						|
                                  unsigned BBNumber,
 | 
						|
                                  const AllocationOrder &Order);
 | 
						|
  bool splitCanCauseLocalSpill(unsigned VirtRegToSplit,
 | 
						|
                               GlobalSplitCandidate &Cand, unsigned BBNumber,
 | 
						|
                               const AllocationOrder &Order);
 | 
						|
  BlockFrequency calcGlobalSplitCost(GlobalSplitCandidate &,
 | 
						|
                                     const AllocationOrder &Order,
 | 
						|
                                     bool *CanCauseEvictionChain);
 | 
						|
  bool calcCompactRegion(GlobalSplitCandidate &);
 | 
						|
  void splitAroundRegion(LiveRangeEdit &, ArrayRef<unsigned>);
 | 
						|
  void calcGapWeights(MCRegister, SmallVectorImpl<float> &);
 | 
						|
  bool canEvictInterferenceInRange(const LiveInterval &VirtReg,
 | 
						|
                                   MCRegister PhysReg, SlotIndex Start,
 | 
						|
                                   SlotIndex End, EvictionCost &MaxCost) const;
 | 
						|
  MCRegister getCheapestEvicteeWeight(const AllocationOrder &Order,
 | 
						|
                                      const LiveInterval &VirtReg,
 | 
						|
                                      SlotIndex Start, SlotIndex End,
 | 
						|
                                      float *BestEvictWeight) const;
 | 
						|
  void evictInterference(LiveInterval &, MCRegister,
 | 
						|
                         SmallVectorImpl<Register> &);
 | 
						|
  bool mayRecolorAllInterferences(MCRegister PhysReg, LiveInterval &VirtReg,
 | 
						|
                                  SmallLISet &RecoloringCandidates,
 | 
						|
                                  const SmallVirtRegSet &FixedRegisters);
 | 
						|
 | 
						|
  MCRegister tryAssign(LiveInterval &, AllocationOrder &,
 | 
						|
                       SmallVectorImpl<Register> &, const SmallVirtRegSet &);
 | 
						|
  MCRegister tryEvict(LiveInterval &, AllocationOrder &,
 | 
						|
                      SmallVectorImpl<Register> &, uint8_t,
 | 
						|
                      const SmallVirtRegSet &);
 | 
						|
  MCRegister tryRegionSplit(LiveInterval &, AllocationOrder &,
 | 
						|
                            SmallVectorImpl<Register> &);
 | 
						|
  /// Calculate cost of region splitting.
 | 
						|
  unsigned calculateRegionSplitCost(LiveInterval &VirtReg,
 | 
						|
                                    AllocationOrder &Order,
 | 
						|
                                    BlockFrequency &BestCost,
 | 
						|
                                    unsigned &NumCands, bool IgnoreCSR,
 | 
						|
                                    bool *CanCauseEvictionChain = nullptr);
 | 
						|
  /// Perform region splitting.
 | 
						|
  unsigned doRegionSplit(LiveInterval &VirtReg, unsigned BestCand,
 | 
						|
                         bool HasCompact, SmallVectorImpl<Register> &NewVRegs);
 | 
						|
  /// Check other options before using a callee-saved register for the first
 | 
						|
  /// time.
 | 
						|
  MCRegister tryAssignCSRFirstTime(LiveInterval &VirtReg,
 | 
						|
                                   AllocationOrder &Order, MCRegister PhysReg,
 | 
						|
                                   uint8_t &CostPerUseLimit,
 | 
						|
                                   SmallVectorImpl<Register> &NewVRegs);
 | 
						|
  void initializeCSRCost();
 | 
						|
  unsigned tryBlockSplit(LiveInterval &, AllocationOrder &,
 | 
						|
                         SmallVectorImpl<Register> &);
 | 
						|
  unsigned tryInstructionSplit(LiveInterval &, AllocationOrder &,
 | 
						|
                               SmallVectorImpl<Register> &);
 | 
						|
  unsigned tryLocalSplit(LiveInterval &, AllocationOrder &,
 | 
						|
                         SmallVectorImpl<Register> &);
 | 
						|
  unsigned trySplit(LiveInterval &, AllocationOrder &,
 | 
						|
                    SmallVectorImpl<Register> &, const SmallVirtRegSet &);
 | 
						|
  unsigned tryLastChanceRecoloring(LiveInterval &, AllocationOrder &,
 | 
						|
                                   SmallVectorImpl<Register> &,
 | 
						|
                                   SmallVirtRegSet &, unsigned);
 | 
						|
  bool tryRecoloringCandidates(PQueue &, SmallVectorImpl<Register> &,
 | 
						|
                               SmallVirtRegSet &, unsigned);
 | 
						|
  void tryHintRecoloring(LiveInterval &);
 | 
						|
  void tryHintsRecoloring();
 | 
						|
 | 
						|
  /// Model the information carried by one end of a copy.
 | 
						|
  struct HintInfo {
 | 
						|
    /// The frequency of the copy.
 | 
						|
    BlockFrequency Freq;
 | 
						|
    /// The virtual register or physical register.
 | 
						|
    Register Reg;
 | 
						|
    /// Its currently assigned register.
 | 
						|
    /// In case of a physical register Reg == PhysReg.
 | 
						|
    MCRegister PhysReg;
 | 
						|
 | 
						|
    HintInfo(BlockFrequency Freq, Register Reg, MCRegister PhysReg)
 | 
						|
        : Freq(Freq), Reg(Reg), PhysReg(PhysReg) {}
 | 
						|
  };
 | 
						|
  using HintsInfo = SmallVector<HintInfo, 4>;
 | 
						|
 | 
						|
  BlockFrequency getBrokenHintFreq(const HintsInfo &, MCRegister);
 | 
						|
  void collectHintInfo(Register, HintsInfo &);
 | 
						|
 | 
						|
  /// Greedy RA statistic to remark.
 | 
						|
  struct RAGreedyStats {
 | 
						|
    unsigned Reloads = 0;
 | 
						|
    unsigned FoldedReloads = 0;
 | 
						|
    unsigned ZeroCostFoldedReloads = 0;
 | 
						|
    unsigned Spills = 0;
 | 
						|
    unsigned FoldedSpills = 0;
 | 
						|
    unsigned Copies = 0;
 | 
						|
    float ReloadsCost = 0.0f;
 | 
						|
    float FoldedReloadsCost = 0.0f;
 | 
						|
    float SpillsCost = 0.0f;
 | 
						|
    float FoldedSpillsCost = 0.0f;
 | 
						|
    float CopiesCost = 0.0f;
 | 
						|
 | 
						|
    bool isEmpty() {
 | 
						|
      return !(Reloads || FoldedReloads || Spills || FoldedSpills ||
 | 
						|
               ZeroCostFoldedReloads || Copies);
 | 
						|
    }
 | 
						|
 | 
						|
    void add(RAGreedyStats other) {
 | 
						|
      Reloads += other.Reloads;
 | 
						|
      FoldedReloads += other.FoldedReloads;
 | 
						|
      ZeroCostFoldedReloads += other.ZeroCostFoldedReloads;
 | 
						|
      Spills += other.Spills;
 | 
						|
      FoldedSpills += other.FoldedSpills;
 | 
						|
      Copies += other.Copies;
 | 
						|
      ReloadsCost += other.ReloadsCost;
 | 
						|
      FoldedReloadsCost += other.FoldedReloadsCost;
 | 
						|
      SpillsCost += other.SpillsCost;
 | 
						|
      FoldedSpillsCost += other.FoldedSpillsCost;
 | 
						|
      CopiesCost += other.CopiesCost;
 | 
						|
    }
 | 
						|
 | 
						|
    void report(MachineOptimizationRemarkMissed &R);
 | 
						|
  };
 | 
						|
 | 
						|
  /// Compute statistic for a basic block.
 | 
						|
  RAGreedyStats computeStats(MachineBasicBlock &MBB);
 | 
						|
 | 
						|
  /// Compute and report statistic through a remark.
 | 
						|
  RAGreedyStats reportStats(MachineLoop *L);
 | 
						|
 | 
						|
  /// Report the statistic for each loop.
 | 
						|
  void reportStats();
 | 
						|
};
 | 
						|
} // namespace llvm
 | 
						|
#endif // #ifndef LLVM_CODEGEN_REGALLOCGREEDY_H_
 |