Newer
Older
//===-- PreAllocSplitting.cpp - Pre-allocation Interval Spltting Pass. ----===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file implements the machine instruction level pre-register allocation
// live interval splitting pass. It finds live interval barriers, i.e.
// instructions which will kill all physical registers in certain register
// classes, and split all live intervals which cross the barrier.
//
//===----------------------------------------------------------------------===//
#define DEBUG_TYPE "pre-alloc-split"
#include "llvm/CodeGen/LiveIntervalAnalysis.h"
#include "llvm/CodeGen/LiveStackAnalysis.h"
#include "llvm/CodeGen/MachineDominators.h"
Evan Cheng
committed
#include "llvm/CodeGen/MachineFrameInfo.h"
#include "llvm/CodeGen/MachineFunctionPass.h"
#include "llvm/CodeGen/MachineLoopInfo.h"
#include "llvm/CodeGen/MachineRegisterInfo.h"
#include "llvm/CodeGen/Passes.h"
#include "llvm/CodeGen/RegisterCoalescer.h"
Evan Cheng
committed
#include "llvm/Target/TargetInstrInfo.h"
#include "llvm/Target/TargetMachine.h"
#include "llvm/Target/TargetOptions.h"
#include "llvm/Target/TargetRegisterInfo.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/Debug.h"
#include "llvm/ADT/DenseMap.h"
Evan Cheng
committed
#include "llvm/ADT/DepthFirstIterator.h"
#include "llvm/ADT/SmallPtrSet.h"
Evan Cheng
committed
#include "llvm/ADT/Statistic.h"
using namespace llvm;
static cl::opt<int> PreSplitLimit("pre-split-limit", cl::init(-1), cl::Hidden);
STATISTIC(NumSplits, "Number of intervals split");
STATISTIC(NumRemats, "Number of intervals split by rematerialization");
Owen Anderson
committed
STATISTIC(NumFolds, "Number of intervals split with spill folding");
STATISTIC(NumRenumbers, "Number of intervals renumbered into new registers");
STATISTIC(NumDeadSpills, "Number of dead spills removed");
Evan Cheng
committed
namespace {
class VISIBILITY_HIDDEN PreAllocSplitting : public MachineFunctionPass {
MachineFunction *CurrMF;
Evan Cheng
committed
const TargetMachine *TM;
const TargetInstrInfo *TII;
MachineFrameInfo *MFI;
MachineRegisterInfo *MRI;
LiveIntervals *LIs;
LiveStacks *LSs;
Evan Cheng
committed
// Barrier - Current barrier being processed.
MachineInstr *Barrier;
// BarrierMBB - Basic block where the barrier resides in.
MachineBasicBlock *BarrierMBB;
// Barrier - Current barrier index.
unsigned BarrierIdx;
// CurrLI - Current live interval being split.
LiveInterval *CurrLI;
// CurrSLI - Current stack slot live interval.
LiveInterval *CurrSLI;
// CurrSValNo - Current val# for the stack slot live interval.
VNInfo *CurrSValNo;
// IntervalSSMap - A map from live interval to spill slots.
DenseMap<unsigned, int> IntervalSSMap;
Evan Cheng
committed
// Def2SpillMap - A map from a def instruction index to spill index.
DenseMap<unsigned, unsigned> Def2SpillMap;
Evan Cheng
committed
public:
static char ID;
PreAllocSplitting() : MachineFunctionPass(&ID) {}
virtual bool runOnMachineFunction(MachineFunction &MF);
virtual void getAnalysisUsage(AnalysisUsage &AU) const {
AU.addRequired<LiveIntervals>();
AU.addPreserved<LiveIntervals>();
AU.addRequired<LiveStacks>();
AU.addPreserved<LiveStacks>();
AU.addPreserved<RegisterCoalescer>();
if (StrongPHIElim)
AU.addPreservedID(StrongPHIEliminationID);
else
AU.addPreservedID(PHIEliminationID);
AU.addRequired<MachineDominatorTree>();
AU.addRequired<MachineLoopInfo>();
AU.addPreserved<MachineDominatorTree>();
AU.addPreserved<MachineLoopInfo>();
MachineFunctionPass::getAnalysisUsage(AU);
}
virtual void releaseMemory() {
IntervalSSMap.clear();
Evan Cheng
committed
Def2SpillMap.clear();
}
virtual const char *getPassName() const {
return "Pre-Register Allocaton Live Interval Splitting";
}
Evan Cheng
committed
/// print - Implement the dump method.
virtual void print(std::ostream &O, const Module* M = 0) const {
LIs->print(O, M);
}
void print(std::ostream *O, const Module* M = 0) const {
if (O) print(*O, M);
}
private:
MachineBasicBlock::iterator
findNextEmptySlot(MachineBasicBlock*, MachineInstr*,
unsigned&);
MachineBasicBlock::iterator
Evan Cheng
committed
findSpillPoint(MachineBasicBlock*, MachineInstr*, MachineInstr*,
Evan Cheng
committed
SmallPtrSet<MachineInstr*, 4>&, unsigned&);
MachineBasicBlock::iterator
Evan Cheng
committed
findRestorePoint(MachineBasicBlock*, MachineInstr*, unsigned,
Evan Cheng
committed
SmallPtrSet<MachineInstr*, 4>&, unsigned&);
int CreateSpillStackSlot(unsigned, const TargetRegisterClass *);
Evan Cheng
committed
bool IsAvailableInStack(MachineBasicBlock*, unsigned, unsigned, unsigned,
unsigned&, int&) const;
Evan Cheng
committed
void UpdateSpillSlotInterval(VNInfo*, unsigned, unsigned);
Evan Cheng
committed
bool SplitRegLiveInterval(LiveInterval*);
bool SplitRegLiveIntervals(const TargetRegisterClass **,
SmallPtrSet<LiveInterval*, 8>&);
bool createsNewJoin(LiveRange* LR, MachineBasicBlock* DefMBB,
MachineBasicBlock* BarrierMBB);
bool Rematerialize(unsigned vreg, VNInfo* ValNo,
MachineInstr* DefMI,
MachineBasicBlock::iterator RestorePt,
unsigned RestoreIdx,
SmallPtrSet<MachineInstr*, 4>& RefsInMBB);
Owen Anderson
committed
MachineInstr* FoldSpill(unsigned vreg, const TargetRegisterClass* RC,
MachineInstr* DefMI,
MachineInstr* Barrier,
MachineBasicBlock* MBB,
int& SS,
SmallPtrSet<MachineInstr*, 4>& RefsInMBB);
Owen Anderson
committed
void RenumberValno(VNInfo* VN);
Owen Anderson
committed
void ReconstructLiveInterval(LiveInterval* LI);
bool removeDeadSpills(SmallPtrSet<LiveInterval*, 8>& split);
unsigned getNumberOfSpills(SmallPtrSet<MachineInstr*, 4>& MIs,
unsigned Reg, int FrameIndex);
Owen Anderson
committed
VNInfo* PerformPHIConstruction(MachineBasicBlock::iterator use,
MachineBasicBlock* MBB,
Owen Anderson
committed
LiveInterval* LI,
Owen Anderson
committed
SmallPtrSet<MachineInstr*, 4>& Visited,
Owen Anderson
committed
DenseMap<MachineBasicBlock*, SmallPtrSet<MachineInstr*, 2> >& Defs,
DenseMap<MachineBasicBlock*, SmallPtrSet<MachineInstr*, 2> >& Uses,
DenseMap<MachineInstr*, VNInfo*>& NewVNs,
DenseMap<MachineBasicBlock*, VNInfo*>& LiveOut,
DenseMap<MachineBasicBlock*, VNInfo*>& Phis,
bool toplevel, bool intrablock);
Owen Anderson
committed
};
} // end anonymous namespace
char PreAllocSplitting::ID = 0;
static RegisterPass<PreAllocSplitting>
X("pre-alloc-splitting", "Pre-Register Allocation Live Interval Splitting");
const PassInfo *const llvm::PreAllocSplittingID = &X;
Evan Cheng
committed
/// findNextEmptySlot - Find a gap after the given machine instruction in the
/// instruction index map. If there isn't one, return end().
MachineBasicBlock::iterator
PreAllocSplitting::findNextEmptySlot(MachineBasicBlock *MBB, MachineInstr *MI,
unsigned &SpotIndex) {
MachineBasicBlock::iterator MII = MI;
if (++MII != MBB->end()) {
unsigned Index = LIs->findGapBeforeInstr(LIs->getInstructionIndex(MII));
if (Index) {
SpotIndex = Index;
return MII;
}
}
return MBB->end();
}
Loading
Loading full blame...