| //===-- llvm/CodeGen/Spiller.cpp - Spiller -------------------------------===// | |
| // | |
| // The LLVM Compiler Infrastructure | |
| // | |
| // This file is distributed under the University of Illinois Open Source | |
| // License. See LICENSE.TXT for details. | |
| // | |
| //===----------------------------------------------------------------------===// | |
| #define DEBUG_TYPE "spiller" | |
| #include "Spiller.h" | |
| #include "VirtRegMap.h" | |
| #include "LiveRangeEdit.h" | |
| #include "llvm/CodeGen/LiveIntervalAnalysis.h" | |
| #include "llvm/CodeGen/LiveStackAnalysis.h" | |
| #include "llvm/CodeGen/MachineFrameInfo.h" | |
| #include "llvm/CodeGen/MachineFunction.h" | |
| #include "llvm/CodeGen/MachineInstrBuilder.h" | |
| #include "llvm/CodeGen/MachineLoopInfo.h" | |
| #include "llvm/CodeGen/MachineRegisterInfo.h" | |
| #include "llvm/Target/TargetMachine.h" | |
| #include "llvm/Target/TargetInstrInfo.h" | |
| #include "llvm/Support/CommandLine.h" | |
| #include "llvm/Support/Debug.h" | |
| #include "llvm/Support/ErrorHandling.h" | |
| #include "llvm/Support/raw_ostream.h" | |
| using namespace llvm; | |
| namespace { | |
| enum SpillerName { trivial, standard, inline_ }; | |
| } | |
| static cl::opt<SpillerName> | |
| spillerOpt("spiller", | |
| cl::desc("Spiller to use: (default: standard)"), | |
| cl::Prefix, | |
| cl::values(clEnumVal(trivial, "trivial spiller"), | |
| clEnumVal(standard, "default spiller"), | |
| clEnumValN(inline_, "inline", "inline spiller"), | |
| clEnumValEnd), | |
| cl::init(standard)); | |
| // Spiller virtual destructor implementation. | |
| Spiller::~Spiller() {} | |
| namespace { | |
| /// Utility class for spillers. | |
| class SpillerBase : public Spiller { | |
| protected: | |
| MachineFunctionPass *pass; | |
| MachineFunction *mf; | |
| VirtRegMap *vrm; | |
| LiveIntervals *lis; | |
| MachineFrameInfo *mfi; | |
| MachineRegisterInfo *mri; | |
| const TargetInstrInfo *tii; | |
| const TargetRegisterInfo *tri; | |
| /// Construct a spiller base. | |
| SpillerBase(MachineFunctionPass &pass, MachineFunction &mf, VirtRegMap &vrm) | |
| : pass(&pass), mf(&mf), vrm(&vrm) | |
| { | |
| lis = &pass.getAnalysis<LiveIntervals>(); | |
| mfi = mf.getFrameInfo(); | |
| mri = &mf.getRegInfo(); | |
| tii = mf.getTarget().getInstrInfo(); | |
| tri = mf.getTarget().getRegisterInfo(); | |
| } | |
| /// Add spill ranges for every use/def of the live interval, inserting loads | |
| /// immediately before each use, and stores after each def. No folding or | |
| /// remat is attempted. | |
| void trivialSpillEverywhere(LiveInterval *li, | |
| SmallVectorImpl<LiveInterval*> &newIntervals) { | |
| DEBUG(dbgs() << "Spilling everywhere " << *li << "\n"); | |
| assert(li->weight != HUGE_VALF && | |
| "Attempting to spill already spilled value."); | |
| assert(!TargetRegisterInfo::isStackSlot(li->reg) && | |
| "Trying to spill a stack slot."); | |
| DEBUG(dbgs() << "Trivial spill everywhere of reg" << li->reg << "\n"); | |
| const TargetRegisterClass *trc = mri->getRegClass(li->reg); | |
| unsigned ss = vrm->assignVirt2StackSlot(li->reg); | |
| // Iterate over reg uses/defs. | |
| for (MachineRegisterInfo::reg_iterator | |
| regItr = mri->reg_begin(li->reg); regItr != mri->reg_end();) { | |
| // Grab the use/def instr. | |
| MachineInstr *mi = &*regItr; | |
| DEBUG(dbgs() << " Processing " << *mi); | |
| // Step regItr to the next use/def instr. | |
| do { | |
| ++regItr; | |
| } while (regItr != mri->reg_end() && (&*regItr == mi)); | |
| // Collect uses & defs for this instr. | |
| SmallVector<unsigned, 2> indices; | |
| bool hasUse = false; | |
| bool hasDef = false; | |
| for (unsigned i = 0; i != mi->getNumOperands(); ++i) { | |
| MachineOperand &op = mi->getOperand(i); | |
| if (!op.isReg() || op.getReg() != li->reg) | |
| continue; | |
| hasUse |= mi->getOperand(i).isUse(); | |
| hasDef |= mi->getOperand(i).isDef(); | |
| indices.push_back(i); | |
| } | |
| // Create a new vreg & interval for this instr. | |
| unsigned newVReg = mri->createVirtualRegister(trc); | |
| vrm->grow(); | |
| vrm->assignVirt2StackSlot(newVReg, ss); | |
| LiveInterval *newLI = &lis->getOrCreateInterval(newVReg); | |
| newLI->weight = HUGE_VALF; | |
| // Update the reg operands & kill flags. | |
| for (unsigned i = 0; i < indices.size(); ++i) { | |
| unsigned mopIdx = indices[i]; | |
| MachineOperand &mop = mi->getOperand(mopIdx); | |
| mop.setReg(newVReg); | |
| if (mop.isUse() && !mi->isRegTiedToDefOperand(mopIdx)) { | |
| mop.setIsKill(true); | |
| } | |
| } | |
| assert(hasUse || hasDef); | |
| // Insert reload if necessary. | |
| MachineBasicBlock::iterator miItr(mi); | |
| if (hasUse) { | |
| tii->loadRegFromStackSlot(*mi->getParent(), miItr, newVReg, ss, trc, | |
| tri); | |
| MachineInstr *loadInstr(prior(miItr)); | |
| SlotIndex loadIndex = | |
| lis->InsertMachineInstrInMaps(loadInstr).getDefIndex(); | |
| vrm->addSpillSlotUse(ss, loadInstr); | |
| SlotIndex endIndex = loadIndex.getNextIndex(); | |
| VNInfo *loadVNI = | |
| newLI->getNextValue(loadIndex, 0, lis->getVNInfoAllocator()); | |
| newLI->addRange(LiveRange(loadIndex, endIndex, loadVNI)); | |
| } | |
| // Insert store if necessary. | |
| if (hasDef) { | |
| tii->storeRegToStackSlot(*mi->getParent(), llvm::next(miItr), newVReg, | |
| true, ss, trc, tri); | |
| MachineInstr *storeInstr(llvm::next(miItr)); | |
| SlotIndex storeIndex = | |
| lis->InsertMachineInstrInMaps(storeInstr).getDefIndex(); | |
| vrm->addSpillSlotUse(ss, storeInstr); | |
| SlotIndex beginIndex = storeIndex.getPrevIndex(); | |
| VNInfo *storeVNI = | |
| newLI->getNextValue(beginIndex, 0, lis->getVNInfoAllocator()); | |
| newLI->addRange(LiveRange(beginIndex, storeIndex, storeVNI)); | |
| } | |
| newIntervals.push_back(newLI); | |
| } | |
| } | |
| }; | |
| } // end anonymous namespace | |
| namespace { | |
| /// Spills any live range using the spill-everywhere method with no attempt at | |
| /// folding. | |
| class TrivialSpiller : public SpillerBase { | |
| public: | |
| TrivialSpiller(MachineFunctionPass &pass, MachineFunction &mf, | |
| VirtRegMap &vrm) | |
| : SpillerBase(pass, mf, vrm) {} | |
| void spill(LiveRangeEdit &LRE) { | |
| // Ignore spillIs - we don't use it. | |
| trivialSpillEverywhere(&LRE.getParent(), *LRE.getNewVRegs()); | |
| } | |
| }; | |
| } // end anonymous namespace | |
| namespace { | |
| /// Falls back on LiveIntervals::addIntervalsForSpills. | |
| class StandardSpiller : public Spiller { | |
| protected: | |
| MachineFunction *mf; | |
| LiveIntervals *lis; | |
| LiveStacks *lss; | |
| MachineLoopInfo *loopInfo; | |
| VirtRegMap *vrm; | |
| public: | |
| StandardSpiller(MachineFunctionPass &pass, MachineFunction &mf, | |
| VirtRegMap &vrm) | |
| : mf(&mf), | |
| lis(&pass.getAnalysis<LiveIntervals>()), | |
| lss(&pass.getAnalysis<LiveStacks>()), | |
| loopInfo(pass.getAnalysisIfAvailable<MachineLoopInfo>()), | |
| vrm(&vrm) {} | |
| /// Falls back on LiveIntervals::addIntervalsForSpills. | |
| void spill(LiveRangeEdit &LRE) { | |
| std::vector<LiveInterval*> added = | |
| lis->addIntervalsForSpills(LRE.getParent(), LRE.getUselessVRegs(), | |
| loopInfo, *vrm); | |
| LRE.getNewVRegs()->insert(LRE.getNewVRegs()->end(), | |
| added.begin(), added.end()); | |
| // Update LiveStacks. | |
| int SS = vrm->getStackSlot(LRE.getReg()); | |
| if (SS == VirtRegMap::NO_STACK_SLOT) | |
| return; | |
| const TargetRegisterClass *RC = mf->getRegInfo().getRegClass(LRE.getReg()); | |
| LiveInterval &SI = lss->getOrCreateInterval(SS, RC); | |
| if (!SI.hasAtLeastOneValue()) | |
| SI.getNextValue(SlotIndex(), 0, lss->getVNInfoAllocator()); | |
| SI.MergeRangesInAsValue(LRE.getParent(), SI.getValNumInfo(0)); | |
| } | |
| }; | |
| } // end anonymous namespace | |
| llvm::Spiller* llvm::createSpiller(MachineFunctionPass &pass, | |
| MachineFunction &mf, | |
| VirtRegMap &vrm) { | |
| switch (spillerOpt) { | |
| default: assert(0 && "unknown spiller"); | |
| case trivial: return new TrivialSpiller(pass, mf, vrm); | |
| case standard: return new StandardSpiller(pass, mf, vrm); | |
| case inline_: return createInlineSpiller(pass, mf, vrm); | |
| } | |
| } |