Author: evancheng Date: Tue Aug 14 18:25:37 2007 New Revision: 41086 URL: http://llvm.org/viewvc/llvm-project?rev=41086&view=rev Log: - If a def is dead, do not spill it. - If the defs of a spilled rematerializable MI are dead after the spill store is deleted, delete the def MI as well.
Modified: llvm/trunk/lib/CodeGen/VirtRegMap.cpp Modified: llvm/trunk/lib/CodeGen/VirtRegMap.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/VirtRegMap.cpp?rev=41086&r1=41085&r2=41086&view=diff ============================================================================== --- llvm/trunk/lib/CodeGen/VirtRegMap.cpp (original) +++ llvm/trunk/lib/CodeGen/VirtRegMap.cpp Tue Aug 14 18:25:37 2007 @@ -36,6 +36,7 @@ STATISTIC(NumSpills, "Number of register spills"); STATISTIC(NumReMats, "Number of re-materialization"); +STATISTIC(NumDRM , "Number of re-materializable defs elided"); STATISTIC(NumStores, "Number of stores added"); STATISTIC(NumLoads , "Number of loads added"); STATISTIC(NumReused, "Number of values reused"); @@ -434,38 +435,14 @@ /// marked kill, then invalidate the information. static void InvalidateKills(MachineInstr &MI, BitVector &RegKills, std::vector<MachineOperand*> &KillOps, - MachineInstr *NewDef = NULL) { + SmallVector<unsigned, 1> *KillRegs = NULL) { for (unsigned i = 0, e = MI.getNumOperands(); i != e; ++i) { MachineOperand &MO = MI.getOperand(i); if (!MO.isReg() || !MO.isUse() || !MO.isKill()) continue; unsigned Reg = MO.getReg(); - if (NewDef) { - // Due to remat, it's possible this reg isn't being reused. That is, - // the def of this reg (by prev MI) is now dead. - bool FoundUse = false, Done = false; - MachineBasicBlock::iterator I = MI, E = NewDef; - ++I; ++E; - for (; !Done && I != E; ++I) { - MachineInstr *NMI = I; - for (unsigned j = 0, ee = NMI->getNumOperands(); j != ee; ++j) { - MachineOperand &MO = NMI->getOperand(j); - if (!MO.isReg() || MO.getReg() != Reg) - continue; - if (MO.isUse()) - FoundUse = true; - Done = true; // Stop after scanning all the operands of this MI. - } - } - if (!FoundUse) { - // Def is dead! - MachineBasicBlock::iterator MII = MI; - MachineInstr *DefMI = prior(MII); - MachineOperand *DefOp = DefMI->findRegisterDefOperand(Reg); - assert(DefOp && "Missing def?"); - DefOp->setIsDead(); - } - } + if (KillRegs) + KillRegs->push_back(Reg); if (KillOps[Reg] == &MO) { RegKills.reset(Reg); KillOps[Reg] = NULL; @@ -473,6 +450,51 @@ } } +/// InvalidateRegDef - If the def operand of the specified def MI is now dead +/// (since it's spill instruction is removed), mark it isDead. Also checks if +/// the def MI has other definition operands that are not dead. Returns it by +/// reference. +static bool InvalidateRegDef(MachineBasicBlock::iterator I, + MachineInstr &NewDef, unsigned Reg, + bool &HasLiveDef) { + // Due to remat, it's possible this reg isn't being reused. That is, + // the def of this reg (by prev MI) is now dead. + MachineInstr *DefMI = I; + MachineOperand *DefOp = NULL; + for (unsigned i = 0, e = DefMI->getNumOperands(); i != e; ++i) { + MachineOperand &MO = DefMI->getOperand(i); + if (MO.isReg() && MO.isDef()) { + if (MO.getReg() == Reg) + DefOp = &MO; + else if (!MO.isDead()) + HasLiveDef = true; + } + } + if (!DefOp) + return false; + + bool FoundUse = false, Done = false; + MachineBasicBlock::iterator E = NewDef; + ++I; ++E; + for (; !Done && I != E; ++I) { + MachineInstr *NMI = I; + for (unsigned j = 0, ee = NMI->getNumOperands(); j != ee; ++j) { + MachineOperand &MO = NMI->getOperand(j); + if (!MO.isReg() || MO.getReg() != Reg) + continue; + if (MO.isUse()) + FoundUse = true; + Done = true; // Stop after scanning all the operands of this MI. + } + } + if (!FoundUse) { + // Def is dead! + DefOp->setIsDead(); + return true; + } + return false; +} + /// UpdateKills - Track and update kill info. If a MI reads a register that is /// marked kill, then it must be due to register reuse. Transfer the kill info /// over. @@ -707,6 +729,9 @@ std::vector<MachineInstr*> MaybeDeadStores; MaybeDeadStores.resize(MF.getFrameInfo()->getObjectIndexEnd(), NULL); + // ReMatDefs - These are rematerializable def MIs which are not deleted. + SmallSet<MachineInstr*, 4> ReMatDefs; + // Keep track of kill information. BitVector RegKills(MRI->getNumRegs()); std::vector<MachineOperand*> KillOps; @@ -1077,6 +1102,10 @@ continue; } + bool DoReMat = VRM.isReMaterialized(VirtReg); + if (DoReMat) + ReMatDefs.insert(&MI); + // The only vregs left are stack slot definitions. int StackSlot = VRM.getStackSlot(VirtReg); const TargetRegisterClass *RC = MF.getSSARegMap()->getRegClass(VirtReg); @@ -1099,43 +1128,68 @@ MF.setPhysRegUsed(PhysReg); ReusedOperands.markClobbered(PhysReg); - MRI->storeRegToStackSlot(MBB, next(MII), PhysReg, StackSlot, RC); - DOUT << "Store:\t" << *next(MII); MI.getOperand(i).setReg(PhysReg); + if (!MO.isDead()) { + MRI->storeRegToStackSlot(MBB, next(MII), PhysReg, StackSlot, RC); + DOUT << "Store:\t" << *next(MII); + + // If there is a dead store to this stack slot, nuke it now. + MachineInstr *&LastStore = MaybeDeadStores[StackSlot]; + if (LastStore) { + DOUT << "Removed dead store:\t" << *LastStore; + ++NumDSE; + SmallVector<unsigned, 1> KillRegs; + InvalidateKills(*LastStore, RegKills, KillOps, &KillRegs); + MachineBasicBlock::iterator PrevMII = LastStore; + bool CheckDef = PrevMII != MBB.begin(); + if (CheckDef) + --PrevMII; + MBB.erase(LastStore); + VRM.RemoveFromFoldedVirtMap(LastStore); + if (CheckDef) { + // Look at defs of killed registers on the store. Mark the defs + // as dead since the store has been deleted and they aren't + // being reused. + for (unsigned j = 0, ee = KillRegs.size(); j != ee; ++j) { + bool HasOtherDef = false; + if (InvalidateRegDef(PrevMII, MI, KillRegs[j], HasOtherDef)) { + MachineInstr *DeadDef = PrevMII; + if (ReMatDefs.count(DeadDef) && !HasOtherDef) { + // FIXME: This assumes a remat def does not have side + // effects. + MBB.erase(DeadDef); + VRM.RemoveFromFoldedVirtMap(DeadDef); + ++NumDRM; + } + } + } + } + } + LastStore = next(MII); - // If there is a dead store to this stack slot, nuke it now. - MachineInstr *&LastStore = MaybeDeadStores[StackSlot]; - if (LastStore) { - DOUT << "Removed dead store:\t" << *LastStore; - ++NumDSE; - InvalidateKills(*LastStore, RegKills, KillOps, &MI); - MBB.erase(LastStore); - VRM.RemoveFromFoldedVirtMap(LastStore); - } - LastStore = next(MII); + // If the stack slot value was previously available in some other + // register, change it now. Otherwise, make the register available, + // in PhysReg. + Spills.ModifyStackSlotOrReMat(StackSlot); + Spills.ClobberPhysReg(PhysReg); + Spills.addAvailable(StackSlot, LastStore, PhysReg); + ++NumStores; - // If the stack slot value was previously available in some other - // register, change it now. Otherwise, make the register available, - // in PhysReg. - Spills.ModifyStackSlotOrReMat(StackSlot); - Spills.ClobberPhysReg(PhysReg); - Spills.addAvailable(StackSlot, LastStore, PhysReg); - ++NumStores; - - // Check to see if this is a noop copy. If so, eliminate the - // instruction before considering the dest reg to be changed. - { - unsigned Src, Dst; - if (TII->isMoveInstr(MI, Src, Dst) && Src == Dst) { - ++NumDCE; - DOUT << "Removing now-noop copy: " << MI; - MBB.erase(&MI); - Erased = true; - VRM.RemoveFromFoldedVirtMap(&MI); - UpdateKills(*LastStore, RegKills, KillOps); - goto ProcessNextInst; + // Check to see if this is a noop copy. If so, eliminate the + // instruction before considering the dest reg to be changed. + { + unsigned Src, Dst; + if (TII->isMoveInstr(MI, Src, Dst) && Src == Dst) { + ++NumDCE; + DOUT << "Removing now-noop copy: " << MI; + MBB.erase(&MI); + Erased = true; + VRM.RemoveFromFoldedVirtMap(&MI); + UpdateKills(*LastStore, RegKills, KillOps); + goto ProcessNextInst; + } } - } + } } } ProcessNextInst: _______________________________________________ llvm-commits mailing list llvm-commits@cs.uiuc.edu http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits