[llvm-commits] [llvm] r41086 - /llvm/trunk/lib/CodeGen/VirtRegMap.cpp

Evan Cheng evan.cheng at apple.com
Tue Aug 14 16:25:37 PDT 2007


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:





More information about the llvm-commits mailing list