Skip to content
LiveIntervalAnalysis.cpp 53.4 KiB
Newer Older
//===-- LiveIntervalAnalysis.cpp - Live Interval Analysis -----------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file was developed by the LLVM research group and is distributed under
// the University of Illinois Open Source License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file implements the LiveInterval analysis pass which is used
// by the Linear Scan Register allocator. This pass linearizes the
// basic blocks of the function in DFS order and uses the
// LiveVariables pass to conservatively compute live intervals for
// each virtual and physical register.
//
//===----------------------------------------------------------------------===//

#define DEBUG_TYPE "liveintervals"
#include "llvm/CodeGen/LiveIntervalAnalysis.h"
#include "VirtRegMap.h"
#include "llvm/Value.h"
#include "llvm/Analysis/LoopInfo.h"
#include "llvm/CodeGen/LiveVariables.h"
#include "llvm/CodeGen/MachineFrameInfo.h"
#include "llvm/CodeGen/MachineInstr.h"
#include "llvm/CodeGen/Passes.h"
#include "llvm/CodeGen/SSARegMap.h"
#include "llvm/Target/MRegisterInfo.h"
#include "llvm/Target/TargetInstrInfo.h"
#include "llvm/Target/TargetMachine.h"
Reid Spencer's avatar
Reid Spencer committed
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/Debug.h"
#include "llvm/ADT/Statistic.h"
#include "llvm/ADT/STLExtras.h"
#include <algorithm>
Jeff Cohen's avatar
Jeff Cohen committed
#include <cmath>
STATISTIC(numIntervals, "Number of original intervals");
STATISTIC(numIntervalsAfter, "Number of intervals after coalescing");
STATISTIC(numJoins    , "Number of interval joins performed");
STATISTIC(numPeep     , "Number of identity moves eliminated after coalescing");
STATISTIC(numFolded   , "Number of loads/stores folded into instructions");

  RegisterPass<LiveIntervals> X("liveintervals", "Live Interval Analysis");
  static cl::opt<bool>
  EnableJoining("join-liveintervals",
                cl::desc("Coallesce copies (default=true)"),
                cl::init(true));
void LiveIntervals::getAnalysisUsage(AnalysisUsage &AU) const {
  AU.addRequired<LiveVariables>();
  AU.addPreservedID(PHIEliminationID);
  AU.addRequiredID(PHIEliminationID);
  AU.addRequiredID(TwoAddressInstructionPassID);
  AU.addRequired<LoopInfo>();
  MachineFunctionPass::getAnalysisUsage(AU);
void LiveIntervals::releaseMemory() {
  mi2iMap_.clear();
  i2miMap_.clear();
  r2iMap_.clear();
  r2rMap_.clear();
static bool isZeroLengthInterval(LiveInterval *li) {
  for (LiveInterval::Ranges::const_iterator
         i = li->ranges.begin(), e = li->ranges.end(); i != e; ++i)
    if (i->end - i->start > LiveIntervals::InstrSlots::NUM)
      return false;
  return true;
}


/// runOnMachineFunction - Register allocate the whole function
///
bool LiveIntervals::runOnMachineFunction(MachineFunction &fn) {
  mf_ = &fn;
  tm_ = &fn.getTarget();
  mri_ = tm_->getRegisterInfo();
  lv_ = &getAnalysis<LiveVariables>();
  allocatableRegs_ = mri_->getAllocatableSet(fn);
  r2rMap_.grow(mf_->getSSARegMap()->getLastVirtReg());
  // Number MachineInstrs and MachineBasicBlocks.
  // Initialize MBB indexes to a sentinal.
  MBB2IdxMap.resize(mf_->getNumBlockIDs(), ~0U);
  
  unsigned MIIndex = 0;
  for (MachineFunction::iterator MBB = mf_->begin(), E = mf_->end();
       MBB != E; ++MBB) {
    // Set the MBB2IdxMap entry for this MBB.
    MBB2IdxMap[MBB->getNumber()] = MIIndex;
Reid Spencer's avatar
Reid Spencer committed
    // If this BB has any live ins, insert a dummy instruction at the
    // beginning of the function that we will pretend "defines" the values. This
    // is to make the interval analysis simpler by providing a number.
    if (MBB->livein_begin() != MBB->livein_end()) {
      unsigned FirstLiveIn = *MBB->livein_begin();

      // Find a reg class that contains this live in.
      const TargetRegisterClass *RC = 0;
      for (MRegisterInfo::regclass_iterator RCI = mri_->regclass_begin(),
             RCE = mri_->regclass_end(); RCI != RCE; ++RCI)
        if ((*RCI)->contains(FirstLiveIn)) {
          RC = *RCI;
          break;
        }

      MachineInstr *OldFirstMI = MBB->begin();
      mri_->copyRegToReg(*MBB, MBB->begin(),
                         FirstLiveIn, FirstLiveIn, RC);
      assert(OldFirstMI != MBB->begin() &&
             "copyRetToReg didn't insert anything!");
    }
    
    for (MachineBasicBlock::iterator I = MBB->begin(), E = MBB->end();
         I != E; ++I) {
      bool inserted = mi2iMap_.insert(std::make_pair(I, MIIndex)).second;
      assert(inserted && "multiple MachineInstr -> index mappings");
      i2miMap_.push_back(I);
      MIIndex += InstrSlots::NUM;
  computeIntervals();
  numIntervals += getNumIntervals();
  DOUT << "********** INTERVALS **********\n";
  for (iterator I = begin(), E = end(); I != E; ++I) {
    I->second.print(DOUT, mri_);
    DOUT << "\n";
  }
  // Join (coallesce) intervals if requested.
  if (EnableJoining) joinIntervals();

  numIntervalsAfter += getNumIntervals();

  // perform a final pass over the instructions and compute spill
Chris Lattner's avatar
Chris Lattner committed
  // weights, coalesce virtual registers and remove identity moves.
  const LoopInfo &loopInfo = getAnalysis<LoopInfo>();

  for (MachineFunction::iterator mbbi = mf_->begin(), mbbe = mf_->end();
       mbbi != mbbe; ++mbbi) {
    MachineBasicBlock* mbb = mbbi;
    unsigned loopDepth = loopInfo.getLoopDepth(mbb->getBasicBlock());

    for (MachineBasicBlock::iterator mii = mbb->begin(), mie = mbb->end();
         mii != mie; ) {
      // if the move will be an identity move delete it
      unsigned srcReg, dstReg, RegRep;
      if (tii_->isMoveInstr(*mii, srcReg, dstReg) &&
          (RegRep = rep(srcReg)) == rep(dstReg)) {
        // remove from def list
Reid Spencer's avatar
Reid Spencer committed
        getOrCreateInterval(RegRep);
        mii = mbbi->erase(mii);
        ++numPeep;
      }
      else {
Chris Lattner's avatar
Chris Lattner committed
        for (unsigned i = 0, e = mii->getNumOperands(); i != e; ++i) {
          const MachineOperand &mop = mii->getOperand(i);
          if (mop.isRegister() && mop.getReg() &&
              MRegisterInfo::isVirtualRegister(mop.getReg())) {
            // replace register with representative register
            unsigned reg = rep(mop.getReg());
            mii->getOperand(i).setReg(reg);

            LiveInterval &RegInt = getInterval(reg);
            RegInt.weight +=
              (mop.isUse() + mop.isDef()) * pow(10.0F, (int)loopDepth);
Reid Spencer's avatar
Reid Spencer committed
  
  for (iterator I = begin(), E = end(); I != E; ++I) {
    LiveInterval &LI = I->second;
    if (MRegisterInfo::isVirtualRegister(LI.reg)) {
Chris Lattner's avatar
Chris Lattner committed
      // If the live interval length is essentially zero, i.e. in every live
      // range the use follows def immediately, it doesn't make sense to spill
      // it and hope it will be easier to allocate for this li.
        LI.weight = HUGE_VALF;
      // Divide the weight of the interval by its size.  This encourages 
      // spilling of intervals that are large and have few uses, and
      // discourages spilling of small intervals with many uses.
Loading
Loading full blame...