| //===-- 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 "llvm/CodeGen/LiveIntervalAnalysis.h" |
| #include "llvm/CodeGen/MachineFrameInfo.h" |
| #include "llvm/CodeGen/MachineFunction.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/raw_ostream.h" |
| |
| using namespace llvm; |
| |
| namespace { |
| enum SpillerName { trivial, standard }; |
| } |
| |
| 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"), |
| clEnumValEnd), |
| cl::init(standard)); |
| |
| Spiller::~Spiller() {} |
| |
| namespace { |
| |
| /// Utility class for spillers. |
| class SpillerBase : public Spiller { |
| protected: |
| |
| MachineFunction *mf; |
| LiveIntervals *lis; |
| MachineFrameInfo *mfi; |
| MachineRegisterInfo *mri; |
| const TargetInstrInfo *tii; |
| VirtRegMap *vrm; |
| |
| /// Construct a spiller base. |
| SpillerBase(MachineFunction *mf, LiveIntervals *lis, VirtRegMap *vrm) |
| : mf(mf), lis(lis), vrm(vrm) |
| { |
| mfi = mf->getFrameInfo(); |
| mri = &mf->getRegInfo(); |
| tii = mf->getTarget().getInstrInfo(); |
| } |
| |
| /// 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. |
| std::vector<LiveInterval*> trivialSpillEverywhere(LiveInterval *li) { |
| DEBUG(errs() << "Spilling everywhere " << *li << "\n"); |
| |
| assert(li->weight != HUGE_VALF && |
| "Attempting to spill already spilled value."); |
| |
| assert(!li->isStackSlot() && |
| "Trying to spill a stack slot."); |
| |
| DEBUG(errs() << "Trivial spill everywhere of reg" << li->reg << "\n"); |
| |
| std::vector<LiveInterval*> added; |
| |
| 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(errs() << " 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); |
| MachineInstr *loadInstr(prior(miItr)); |
| SlotIndex loadIndex = |
| lis->InsertMachineInstrInMaps(loadInstr).getDefIndex(); |
| SlotIndex endIndex = loadIndex.getNextIndex(); |
| VNInfo *loadVNI = |
| newLI->getNextValue(loadIndex, 0, true, lis->getVNInfoAllocator()); |
| loadVNI->addKill(endIndex); |
| newLI->addRange(LiveRange(loadIndex, endIndex, loadVNI)); |
| } |
| |
| // Insert store if necessary. |
| if (hasDef) { |
| tii->storeRegToStackSlot(*mi->getParent(), llvm::next(miItr), newVReg, true, |
| ss, trc); |
| MachineInstr *storeInstr(llvm::next(miItr)); |
| SlotIndex storeIndex = |
| lis->InsertMachineInstrInMaps(storeInstr).getDefIndex(); |
| SlotIndex beginIndex = storeIndex.getPrevIndex(); |
| VNInfo *storeVNI = |
| newLI->getNextValue(beginIndex, 0, true, lis->getVNInfoAllocator()); |
| storeVNI->addKill(storeIndex); |
| newLI->addRange(LiveRange(beginIndex, storeIndex, storeVNI)); |
| } |
| |
| added.push_back(newLI); |
| } |
| |
| return added; |
| } |
| |
| }; |
| |
| |
| /// Spills any live range using the spill-everywhere method with no attempt at |
| /// folding. |
| class TrivialSpiller : public SpillerBase { |
| public: |
| |
| TrivialSpiller(MachineFunction *mf, LiveIntervals *lis, VirtRegMap *vrm) |
| : SpillerBase(mf, lis, vrm) {} |
| |
| std::vector<LiveInterval*> spill(LiveInterval *li, |
| SmallVectorImpl<LiveInterval*> &spillIs) { |
| // Ignore spillIs - we don't use it. |
| return trivialSpillEverywhere(li); |
| } |
| |
| }; |
| |
| /// Falls back on LiveIntervals::addIntervalsForSpills. |
| class StandardSpiller : public Spiller { |
| private: |
| LiveIntervals *lis; |
| const MachineLoopInfo *loopInfo; |
| VirtRegMap *vrm; |
| public: |
| StandardSpiller(MachineFunction *mf, LiveIntervals *lis, |
| const MachineLoopInfo *loopInfo, VirtRegMap *vrm) |
| : lis(lis), loopInfo(loopInfo), vrm(vrm) {} |
| |
| /// Falls back on LiveIntervals::addIntervalsForSpills. |
| std::vector<LiveInterval*> spill(LiveInterval *li, |
| SmallVectorImpl<LiveInterval*> &spillIs) { |
| return lis->addIntervalsForSpills(*li, spillIs, loopInfo, *vrm); |
| } |
| |
| }; |
| |
| } |
| |
| llvm::Spiller* llvm::createSpiller(MachineFunction *mf, LiveIntervals *lis, |
| const MachineLoopInfo *loopInfo, |
| VirtRegMap *vrm) { |
| switch (spillerOpt) { |
| case trivial: return new TrivialSpiller(mf, lis, vrm); break; |
| case standard: return new StandardSpiller(mf, lis, loopInfo, vrm); break; |
| default: llvm_unreachable("Unreachable!"); break; |
| } |
| } |