Skip to content
RegAllocLinearScan.cpp 50.6 KiB
Newer Older
//===-- RegAllocLinearScan.cpp - Linear Scan register allocator -----------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file implements a linear scan register allocator.
//
//===----------------------------------------------------------------------===//
#include "Spiller.h"
#include "llvm/CodeGen/LiveIntervalAnalysis.h"
#include "llvm/CodeGen/LiveStackAnalysis.h"
#include "llvm/CodeGen/MachineFunctionPass.h"
#include "llvm/CodeGen/MachineInstr.h"
#include "llvm/CodeGen/MachineLoopInfo.h"
#include "llvm/CodeGen/MachineRegisterInfo.h"
#include "llvm/CodeGen/RegAllocRegistry.h"
David Greene's avatar
 
David Greene committed
#include "llvm/CodeGen/RegisterCoalescer.h"
#include "llvm/Target/TargetRegisterInfo.h"
#include "llvm/Target/TargetOptions.h"
#include "llvm/Target/TargetInstrInfo.h"
#include "llvm/ADT/EquivalenceClasses.h"
#include "llvm/ADT/SmallSet.h"
Reid Spencer's avatar
Reid Spencer committed
#include "llvm/ADT/Statistic.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/Compiler.h"
Duraid Madina's avatar
Duraid Madina committed
#include <memory>
Jeff Cohen's avatar
Jeff Cohen committed
#include <cmath>
STATISTIC(NumIters     , "Number of iterations performed");
STATISTIC(NumBacktracks, "Number of times we had to backtrack");
STATISTIC(NumCoalesce,   "Number of copies coalesced");
STATISTIC(NumDowngrade,  "Number of registers downgraded");
static cl::opt<bool>
NewHeuristic("new-spilling-heuristic",
             cl::desc("Use new spilling heuristic"),
             cl::init(false), cl::Hidden);

static cl::opt<bool>
PreSplitIntervals("pre-alloc-split",
                  cl::desc("Pre-register allocation live interval splitting"),
                  cl::init(false), cl::Hidden);

static cl::opt<bool>
NewSpillFramework("new-spill-framework",
                  cl::desc("New spilling framework"),
                  cl::init(false), cl::Hidden);

static RegisterRegAlloc
linearscanRegAlloc("linearscan", "linear scan register allocator",
                   createLinearScanRegisterAllocator);
namespace {
  struct VISIBILITY_HIDDEN RALinScan : public MachineFunctionPass {
Devang Patel's avatar
Devang Patel committed
    static char ID;
    RALinScan() : MachineFunctionPass(&ID) {}
    typedef std::pair<LiveInterval*, LiveInterval::iterator> IntervalPtr;
    typedef SmallVector<IntervalPtr, 32> IntervalPtrs;
    /// RelatedRegClasses - This structure is built the first time a function is
    /// compiled, and keeps track of which register classes have registers that
    /// belong to multiple classes or have aliases that are in other classes.
    EquivalenceClasses<const TargetRegisterClass*> RelatedRegClasses;
    DenseMap<unsigned, const TargetRegisterClass*> OneClassForEachPhysReg;
    // NextReloadMap - For each register in the map, it maps to the another
    // register which is defined by a reload from the same stack slot and
    // both reloads are in the same basic block.
    DenseMap<unsigned, unsigned> NextReloadMap;

    // DowngradedRegs - A set of registers which are being "downgraded", i.e.
    // un-favored for allocation.
    SmallSet<unsigned, 8> DowngradedRegs;

    // DowngradeMap - A map from virtual registers to physical registers being
    // downgraded for the virtual registers.
    DenseMap<unsigned, unsigned> DowngradeMap;

    MachineFunction* mf_;
    const TargetMachine* tm_;
    const TargetRegisterInfo* tri_;
    const TargetInstrInfo* tii_;
    BitVector allocatableRegs_;
    LiveIntervals* li_;
    const MachineLoopInfo *loopInfo;

    /// handled_ - Intervals are added to the handled_ set in the order of their
    /// start value.  This is uses for backtracking.
    std::vector<LiveInterval*> handled_;

    /// fixed_ - Intervals that correspond to machine registers.
    ///
    IntervalPtrs fixed_;

    /// active_ - Intervals that are currently being processed, and which have a
    /// live range active for the current point.
    IntervalPtrs active_;

    /// inactive_ - Intervals that are currently being processed, but which have
    /// a hold at the current point.
    IntervalPtrs inactive_;

    typedef std::priority_queue<LiveInterval*,
                                greater_ptr<LiveInterval> > IntervalHeap;
    IntervalHeap unhandled_;

    /// regUse_ - Tracks register usage.
    SmallVector<unsigned, 32> regUse_;
    SmallVector<unsigned, 32> regUseBackUp_;

    /// vrm_ - Tracks register assignments.
    VirtRegMap* vrm_;
    std::auto_ptr<VirtRegRewriter> rewriter_;
    std::auto_ptr<Spiller> spiller_;

  public:
    virtual const char* getPassName() const {
      return "Linear Scan Register Allocator";
    }
    virtual void getAnalysisUsage(AnalysisUsage &AU) const {
      AU.addRequired<LiveIntervals>();
      if (StrongPHIElim)
        AU.addRequiredID(StrongPHIEliminationID);
David Greene's avatar
 
David Greene committed
      // Make sure PassManager knows which analyses to make available
      // to coalescing and which analyses coalescing invalidates.
      AU.addRequiredTransitive<RegisterCoalescer>();
      if (PreSplitIntervals)
        AU.addRequiredID(PreAllocSplittingID);
      AU.addRequired<LiveStacks>();
      AU.addPreserved<LiveStacks>();
      AU.addRequired<MachineLoopInfo>();
      AU.addPreserved<MachineLoopInfo>();
      AU.addRequired<VirtRegMap>();
      AU.addPreserved<VirtRegMap>();
      AU.addPreservedID(MachineDominatorsID);
      MachineFunctionPass::getAnalysisUsage(AU);
    }

    /// runOnMachineFunction - register allocate the whole function
    bool runOnMachineFunction(MachineFunction&);

  private:
    /// linearScan - the linear scan algorithm
    void linearScan();

    /// initIntervalSets - initialize the interval sets.
    ///
    void initIntervalSets();

    /// processActiveIntervals - expire old intervals and move non-overlapping
    /// ones to the inactive list.
    void processActiveIntervals(unsigned CurPoint);
    /// processInactiveIntervals - expire old intervals and move overlapping
    /// ones to the active list.
    void processInactiveIntervals(unsigned CurPoint);
    /// hasNextReloadInterval - Return the next liveinterval that's being
    /// defined by a reload from the same SS as the specified one.
    LiveInterval *hasNextReloadInterval(LiveInterval *cur);

    /// DowngradeRegister - Downgrade a register for allocation.
    void DowngradeRegister(LiveInterval *li, unsigned Reg);

    /// UpgradeRegister - Upgrade a register for allocation.
    void UpgradeRegister(unsigned Reg);

    /// assignRegOrStackSlotAtInterval - assign a register if one
    /// is available, or spill.
    void assignRegOrStackSlotAtInterval(LiveInterval* cur);

    void updateSpillWeights(std::vector<float> &Weights,
                            unsigned reg, float weight,
                            const TargetRegisterClass *RC);

    /// findIntervalsToSpill - Determine the intervals to spill for the
    /// specified interval. It's passed the physical registers whose spill
Loading
Loading full blame...