Skip to content
LiveIntervalAnalysis.cpp 48.2 KiB
Newer Older
//===-- LiveIntervalAnalysis.cpp - Live Interval Analysis -----------------===//
// This file 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.
//
//===----------------------------------------------------------------------===//

#include "llvm/CodeGen/LiveIntervalAnalysis.h"
#include "llvm/Value.h"
#include "llvm/Analysis/AliasAnalysis.h"
#include "llvm/CodeGen/MachineDominators.h"
#include "llvm/CodeGen/MachineRegisterInfo.h"
#include "llvm/Target/TargetRegisterInfo.h"
#include "llvm/Target/TargetInstrInfo.h"
#include "llvm/Target/TargetMachine.h"
Reid Spencer's avatar
Reid Spencer committed
#include "llvm/Support/Debug.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/ADT/DenseSet.h"
Reid Spencer's avatar
Reid Spencer committed
#include "llvm/ADT/Statistic.h"
#include "llvm/ADT/STLExtras.h"
#include "LiveRangeCalc.h"
#include <algorithm>
Jeff Cohen's avatar
Jeff Cohen committed
#include <cmath>
STATISTIC(numIntervals , "Number of original intervals");
Devang Patel's avatar
Devang Patel committed
char LiveIntervals::ID = 0;
INITIALIZE_PASS_BEGIN(LiveIntervals, "liveintervals",
                "Live Interval Analysis", false, false)
INITIALIZE_AG_DEPENDENCY(AliasAnalysis)
INITIALIZE_PASS_DEPENDENCY(LiveVariables)
INITIALIZE_PASS_DEPENDENCY(MachineDominatorTree)
INITIALIZE_PASS_DEPENDENCY(SlotIndexes)
INITIALIZE_PASS_END(LiveIntervals, "liveintervals",
                "Live Interval Analysis", false, false)
void LiveIntervals::getAnalysisUsage(AnalysisUsage &AU) const {
  AU.addRequired<AliasAnalysis>();
  AU.addPreserved<AliasAnalysis>();
  AU.addRequired<LiveVariables>();
  AU.addPreservedID(MachineLoopInfoID);
  AU.addRequiredTransitiveID(MachineDominatorsID);
  AU.addPreservedID(MachineDominatorsID);
Lang Hames's avatar
Lang Hames committed
  AU.addPreserved<SlotIndexes>();
  AU.addRequiredTransitive<SlotIndexes>();
  MachineFunctionPass::getAnalysisUsage(AU);
LiveIntervals::LiveIntervals() : MachineFunctionPass(ID),
  DomTree(0), LRCalc(0) {
  initializeLiveIntervalsPass(*PassRegistry::getPassRegistry());
}

LiveIntervals::~LiveIntervals() {
  delete LRCalc;
}

void LiveIntervals::releaseMemory() {
  for (DenseMap<unsigned, LiveInterval*>::iterator I = R2IMap.begin(),
       E = R2IMap.end(); I != E; ++I)
  RegMaskSlots.clear();
  RegMaskBits.clear();
  for (unsigned i = 0, e = RegUnitIntervals.size(); i != e; ++i)
    delete RegUnitIntervals[i];
  RegUnitIntervals.clear();

  // Release VNInfo memory regions, VNInfo objects don't need to be dtor'd.
  VNInfoAllocator.Reset();
/// runOnMachineFunction - Register allocate the whole function
///
bool LiveIntervals::runOnMachineFunction(MachineFunction &fn) {
  MF = &fn;
  MRI = &MF->getRegInfo();
  TM = &fn.getTarget();
  TRI = TM->getRegisterInfo();
  TII = TM->getInstrInfo();
  AA = &getAnalysis<AliasAnalysis>();
  LV = &getAnalysis<LiveVariables>();
  Indexes = &getAnalysis<SlotIndexes>();
  DomTree = &getAnalysis<MachineDominatorTree>();
  if (!LRCalc)
    LRCalc = new LiveRangeCalc();
  AllocatableRegs = TRI->getAllocatableSet(fn);
  ReservedRegs = TRI->getReservedRegs(fn);
  computeIntervals();
  numIntervals += getNumIntervals();
  computeLiveInRegUnits();
  DEBUG(dump());
  return true;
/// print - Implement the dump method.
void LiveIntervals::print(raw_ostream &OS, const Module* ) const {
  OS << "********** INTERVALS **********\n";
  for (unsigned Reg = 1, RegE = TRI->getNumRegs(); Reg != RegE; ++Reg)
    if (const LiveInterval *LI = R2IMap.lookup(Reg))
      OS << PrintReg(Reg, TRI) << '\t' << *LI << '\n';
  // Dump the regunits.
  for (unsigned i = 0, e = RegUnitIntervals.size(); i != e; ++i)
    if (LiveInterval *LI = RegUnitIntervals[i])
      OS << PrintRegUnit(i, TRI) << " = " << *LI << '\n';

  // Dump the virtregs.
  for (unsigned Reg = 0, RegE = MRI->getNumVirtRegs(); Reg != RegE; ++Reg)
    if (const LiveInterval *LI =
        R2IMap.lookup(TargetRegisterInfo::index2VirtReg(Reg)))
      OS << PrintReg(LI->reg) << '\t' << *LI << '\n';
  printInstrs(OS);
}

void LiveIntervals::printInstrs(raw_ostream &OS) const {
  OS << "********** MACHINEINSTRS **********\n";
void LiveIntervals::dumpInstrs() const {
David Greene's avatar
 
David Greene committed
  printInstrs(dbgs());
bool MultipleDefsBySameMI(const MachineInstr &MI, unsigned MOIdx) {
  unsigned Reg = MI.getOperand(MOIdx).getReg();
  for (unsigned i = MOIdx+1, e = MI.getNumOperands(); i < e; ++i) {
    const MachineOperand &MO = MI.getOperand(i);
    if (!MO.isReg())
      continue;
    if (MO.getReg() == Reg && MO.isDef()) {
      assert(MI.getOperand(MOIdx).getSubReg() != MO.getSubReg() &&
             MI.getOperand(MOIdx).getSubReg() &&
             (MO.getSubReg() || MO.isImplicit()));
/// isPartialRedef - Return true if the specified def at the specific index is
/// partially re-defining the specified live interval. A common case of this is
/// a definition of the sub-register.
bool LiveIntervals::isPartialRedef(SlotIndex MIIdx, MachineOperand &MO,
                                   LiveInterval &interval) {
  if (!MO.getSubReg() || MO.isEarlyClobber())
    return false;

  SlotIndex RedefIndex = MIIdx.getRegSlot();
    interval.getLiveRangeContaining(RedefIndex.getRegSlot(true));
  MachineInstr *DefMI = getInstructionFromIndex(OldLR->valno->def);
  if (DefMI != 0) {
    return DefMI->findRegisterDefOperandIdx(interval.reg) != -1;
  }
  return false;
}

void LiveIntervals::handleVirtualRegisterDef(MachineBasicBlock *mbb,
Lang Hames's avatar
Lang Hames committed
                                             SlotIndex MIIdx,
  DEBUG(dbgs() << "\t\tregister: " << PrintReg(interval.reg, TRI));
Alkis Evlogimenos's avatar
Alkis Evlogimenos committed
  // Virtual registers may be defined multiple times (due to phi
  // elimination and 2-addr elimination).  Much of what we do only has to be
  // done once for the vreg.  We use an empty interval to detect the first
Loading
Loading full blame...