- class SimpleSpiller : public Spiller {
- public:
- bool runOnMachineFunction(MachineFunction& mf, const VirtRegMap& vrm) {
- DEBUG(std::cerr << "********** REWRITE MACHINE CODE **********\n");
- DEBUG(std::cerr << "********** Function: "
- << mf.getFunction()->getName() << '\n');
- const TargetMachine& tm = mf.getTarget();
- const MRegisterInfo& mri = *tm.getRegisterInfo();
-
- typedef DenseMap<bool, VirtReg2IndexFunctor> Loaded;
- Loaded loaded;
-
- for (MachineFunction::iterator mbbi = mf.begin(),
- mbbe = mf.end(); mbbi != mbbe; ++mbbi) {
- DEBUG(std::cerr << mbbi->getBasicBlock()->getName() << ":\n");
- for (MachineBasicBlock::iterator mii = mbbi->begin(),
- mie = mbbi->end(); mii != mie; ++mii) {
- loaded.grow(mf.getSSARegMap()->getLastVirtReg());
- for (unsigned i = 0,e = mii->getNumOperands(); i != e; ++i){
- MachineOperand& mop = mii->getOperand(i);
- if (mop.isRegister() && mop.getReg() &&
- MRegisterInfo::isVirtualRegister(mop.getReg())) {
- unsigned virtReg = mop.getReg();
- unsigned physReg = vrm.getPhys(virtReg);
- if (mop.isUse() &&
- vrm.hasStackSlot(mop.getReg()) &&
- !loaded[virtReg]) {
- mri.loadRegFromStackSlot(
- *mbbi,
- mii,
- physReg,
- vrm.getStackSlot(virtReg),
- mf.getSSARegMap()->getRegClass(virtReg));
- loaded[virtReg] = true;
- DEBUG(std::cerr << '\t';
- prior(mii)->print(std::cerr, tm));
- ++numLoads;
- }
- if (mop.isDef() &&
- vrm.hasStackSlot(mop.getReg())) {
- mri.storeRegToStackSlot(
- *mbbi,
- next(mii),
- physReg,
- vrm.getStackSlot(virtReg),
- mf.getSSARegMap()->getRegClass(virtReg));
- ++numStores;
- }
- mii->SetMachineOperandReg(i, physReg);
- }
- }
- DEBUG(std::cerr << '\t'; mii->print(std::cerr, tm));
- loaded.clear();
- }
- }
- return true;
+ // StackSlot - The spill slot of the value being reused.
+ unsigned StackSlot;
+
+ // PhysRegReused - The physical register the value was available in.
+ unsigned PhysRegReused;
+
+ // AssignedPhysReg - The physreg that was assigned for use by the reload.
+ unsigned AssignedPhysReg;
+
+ // VirtReg - The virtual register itself.
+ unsigned VirtReg;
+
+ ReusedOp(unsigned o, unsigned ss, unsigned prr, unsigned apr,
+ unsigned vreg)
+ : Operand(o), StackSlot(ss), PhysRegReused(prr), AssignedPhysReg(apr),
+ VirtReg(vreg) {}
+ };
+
+ /// ReuseInfo - This maintains a collection of ReuseOp's for each operand that
+ /// is reused instead of reloaded.
+ class VISIBILITY_HIDDEN ReuseInfo {
+ MachineInstr &MI;
+ std::vector<ReusedOp> Reuses;
+ BitVector PhysRegsClobbered;
+ public:
+ ReuseInfo(MachineInstr &mi, const MRegisterInfo *mri) : MI(mi) {
+ PhysRegsClobbered.resize(mri->getNumRegs());
+ }
+
+ bool hasReuses() const {
+ return !Reuses.empty();
+ }
+
+ /// addReuse - If we choose to reuse a virtual register that is already
+ /// available instead of reloading it, remember that we did so.
+ void addReuse(unsigned OpNo, unsigned StackSlot,
+ unsigned PhysRegReused, unsigned AssignedPhysReg,
+ unsigned VirtReg) {
+ // If the reload is to the assigned register anyway, no undo will be
+ // required.
+ if (PhysRegReused == AssignedPhysReg) return;
+
+ // Otherwise, remember this.
+ Reuses.push_back(ReusedOp(OpNo, StackSlot, PhysRegReused,
+ AssignedPhysReg, VirtReg));
+ }
+
+ void markClobbered(unsigned PhysReg) {
+ PhysRegsClobbered.set(PhysReg);
+ }
+
+ bool isClobbered(unsigned PhysReg) const {
+ return PhysRegsClobbered.test(PhysReg);
+ }
+
+ /// GetRegForReload - We are about to emit a reload into PhysReg. If there
+ /// is some other operand that is using the specified register, either pick
+ /// a new register to use, or evict the previous reload and use this reg.
+ unsigned GetRegForReload(unsigned PhysReg, MachineInstr *MI,
+ AvailableSpills &Spills,
+ std::map<int, MachineInstr*> &MaybeDeadStores,
+ SmallSet<unsigned, 8> &Rejected) {
+ if (Reuses.empty()) return PhysReg; // This is most often empty.
+
+ for (unsigned ro = 0, e = Reuses.size(); ro != e; ++ro) {
+ ReusedOp &Op = Reuses[ro];
+ // If we find some other reuse that was supposed to use this register
+ // exactly for its reload, we can change this reload to use ITS reload
+ // register. That is, unless its reload register has already been
+ // considered and subsequently rejected because it has also been reused
+ // by another operand.
+ if (Op.PhysRegReused == PhysReg &&
+ Rejected.count(Op.AssignedPhysReg) == 0) {
+ // Yup, use the reload register that we didn't use before.
+ unsigned NewReg = Op.AssignedPhysReg;
+ Rejected.insert(PhysReg);
+ return GetRegForReload(NewReg, MI, Spills, MaybeDeadStores, Rejected);
+ } else {
+ // Otherwise, we might also have a problem if a previously reused
+ // value aliases the new register. If so, codegen the previous reload
+ // and use this one.
+ unsigned PRRU = Op.PhysRegReused;
+ const MRegisterInfo *MRI = Spills.getRegInfo();
+ if (MRI->areAliases(PRRU, PhysReg)) {
+ // Okay, we found out that an alias of a reused register
+ // was used. This isn't good because it means we have
+ // to undo a previous reuse.
+ MachineBasicBlock *MBB = MI->getParent();
+ const TargetRegisterClass *AliasRC =
+ MBB->getParent()->getSSARegMap()->getRegClass(Op.VirtReg);
+
+ // Copy Op out of the vector and remove it, we're going to insert an
+ // explicit load for it.
+ ReusedOp NewOp = Op;
+ Reuses.erase(Reuses.begin()+ro);
+
+ // Ok, we're going to try to reload the assigned physreg into the
+ // slot that we were supposed to in the first place. However, that
+ // register could hold a reuse. Check to see if it conflicts or
+ // would prefer us to use a different register.
+ unsigned NewPhysReg = GetRegForReload(NewOp.AssignedPhysReg,
+ MI, Spills, MaybeDeadStores, Rejected);
+
+ MRI->loadRegFromStackSlot(*MBB, MI, NewPhysReg,
+ NewOp.StackSlot, AliasRC);
+ Spills.ClobberPhysReg(NewPhysReg);
+ Spills.ClobberPhysReg(NewOp.PhysRegReused);
+
+ // Any stores to this stack slot are not dead anymore.
+ MaybeDeadStores.erase(NewOp.StackSlot);
+
+ MI->getOperand(NewOp.Operand).setReg(NewPhysReg);
+
+ Spills.addAvailable(NewOp.StackSlot, MI, NewPhysReg);
+ ++NumLoads;
+ DEBUG(MachineBasicBlock::iterator MII = MI;
+ DOUT << '\t' << *prior(MII));
+
+ DOUT << "Reuse undone!\n";
+ --NumReused;
+
+ // Finally, PhysReg is now available, go ahead and use it.
+ return PhysReg;
+ }