[llvm-commits] CVS: llvm/lib/CodeGen/VirtRegMap.cpp

Chris Lattner lattner at cs.uiuc.edu
Thu Feb 2 16:36:42 PST 2006



Changes in directory llvm/lib/CodeGen:

VirtRegMap.cpp updated: 1.46 -> 1.47
---
Log message:

Physregs may hold multiple stack slot values at the same time.  Keep track
of this, and use it to our advantage (bwahahah).  This allows us to eliminate another
60 instructions from smg2000 on PPC (probably significantly more on X86).  A common
old-new diff looks like this:

        stw r2, 3304(r1)
-       lwz r2, 3192(r1)
        stw r2, 3300(r1)
-       lwz r2, 3192(r1)
        stw r2, 3296(r1)
-       lwz r2, 3192(r1)
        stw r2, 3200(r1)
-       lwz r2, 3192(r1)
        stw r2, 3196(r1)
-       lwz r2, 3192(r1)
+       or r2, r2, r2
        stw r2, 3188(r1)

and

-       lwz r31, 604(r1)
-       lwz r13, 604(r1)
-       lwz r14, 604(r1)
-       lwz r15, 604(r1)
-       lwz r16, 604(r1)
-       lwz r30, 604(r1)
+       or r31, r30, r30
+       or r13, r30, r30
+       or r14, r30, r30
+       or r15, r30, r30
+       or r16, r30, r30
+       or r30, r30, r30

Removal of the R = R copies is coming next...



---
Diffs of the changes:  (+49 -37)

 VirtRegMap.cpp |   86 ++++++++++++++++++++++++++++++++-------------------------
 1 files changed, 49 insertions(+), 37 deletions(-)


Index: llvm/lib/CodeGen/VirtRegMap.cpp
diff -u llvm/lib/CodeGen/VirtRegMap.cpp:1.46 llvm/lib/CodeGen/VirtRegMap.cpp:1.47
--- llvm/lib/CodeGen/VirtRegMap.cpp:1.46	Thu Feb  2 17:29:36 2006
+++ llvm/lib/CodeGen/VirtRegMap.cpp	Thu Feb  2 18:36:31 2006
@@ -222,36 +222,60 @@
   private:
     void RewriteMBB(MachineBasicBlock &MBB, const VirtRegMap &VRM);
     void ClobberPhysReg(unsigned PR, std::map<int, unsigned> &SpillSlots,
-                        std::map<unsigned, int> &PhysRegs);
+                        std::multimap<unsigned, int> &PhysRegs);
     void ClobberPhysRegOnly(unsigned PR, std::map<int, unsigned> &SpillSlots,
-                            std::map<unsigned, int> &PhysRegs);
+                            std::multimap<unsigned, int> &PhysRegs);
+    void ModifyStackSlot(int Slot, std::map<int, unsigned> &SpillSlots,
+                         std::multimap<unsigned, int> &PhysRegs);
   };
 }
 
 void LocalSpiller::ClobberPhysRegOnly(unsigned PhysReg,
                                       std::map<int, unsigned> &SpillSlots,
-                                      std::map<unsigned, int> &PhysRegs) {
-  std::map<unsigned, int>::iterator I = PhysRegs.find(PhysReg);
-  if (I != PhysRegs.end()) {
+                              std::multimap<unsigned, int> &PhysRegsAvailable) {
+  std::map<unsigned, int>::iterator I = PhysRegsAvailable.lower_bound(PhysReg);
+  while (I != PhysRegsAvailable.end() && I->first == PhysReg) {
     int Slot = I->second;
-    PhysRegs.erase(I);
+    PhysRegsAvailable.erase(I++);
     assert(SpillSlots[Slot] == PhysReg && "Bidirectional map mismatch!");
     SpillSlots.erase(Slot);
     DEBUG(std::cerr << "PhysReg " << MRI->getName(PhysReg)
-          << " clobbered, invalidating SS#" << Slot << "\n");
+                    << " clobbered, invalidating SS#" << Slot << "\n");
 
   }
 }
 
 void LocalSpiller::ClobberPhysReg(unsigned PhysReg,
                                   std::map<int, unsigned> &SpillSlots,
-                                  std::map<unsigned, int> &PhysRegs) {
+                              std::multimap<unsigned, int> &PhysRegsAvailable) {
   for (const unsigned *AS = MRI->getAliasSet(PhysReg); *AS; ++AS)
-    ClobberPhysRegOnly(*AS, SpillSlots, PhysRegs);
-  ClobberPhysRegOnly(PhysReg, SpillSlots, PhysRegs);
+    ClobberPhysRegOnly(*AS, SpillSlots, PhysRegsAvailable);
+  ClobberPhysRegOnly(PhysReg, SpillSlots, PhysRegsAvailable);
+}
+
+/// ModifyStackSlot - This method is called when the value in a stack slot
+/// changes.  This removes information about which register the previous value
+/// for this slot lives in (as the previous value is dead now).
+void LocalSpiller::ModifyStackSlot(int Slot, std::map<int,unsigned> &SpillSlots,
+                              std::multimap<unsigned, int> &PhysRegsAvailable) {
+  std::map<int, unsigned>::iterator It = SpillSlots.find(Slot);
+  if (It == SpillSlots.end()) return;
+  unsigned Reg = It->second;
+  SpillSlots.erase(It);
+  
+  // This register may hold the value of multiple stack slots, only remove this
+  // stack slot from the set of values the register contains.
+  std::multimap<unsigned, int>::iterator I = PhysRegsAvailable.lower_bound(Reg);
+  for (; ; ++I) {
+    assert(I != PhysRegsAvailable.end() && I->first == Reg &&
+           "Map inverse broken!");
+    if (I->second == Slot) break;
+  }
+  PhysRegsAvailable.erase(I);
 }
 
 
+
 // ReusedOp - For each reused operand, we keep track of a bit of information, in
 // case we need to rollback upon processing a new operand.  See comments below.
 namespace {
@@ -289,8 +313,9 @@
   std::map<int, unsigned> SpillSlotsAvailable;
 
   // PhysRegsAvailable - This is the inverse of SpillSlotsAvailable, indicating
-  // which physregs are in use holding a stack slot value.
-  std::map<unsigned, int> PhysRegsAvailable;
+  // which stack slot values are currently held by a physreg.  This is used to
+  // invalidate entries in SpillSlotsAvailable when a physreg is modified.
+  std::multimap<unsigned, int> PhysRegsAvailable;
 
   DEBUG(std::cerr << MBB.getBasicBlock()->getName() << ":\n");
 
@@ -427,12 +452,13 @@
               MaybeDeadStores.erase(Op.StackSlot);
 
               MI.SetMachineOperandReg(Op.Operand, Op.AssignedPhysReg);
-              PhysRegsAvailable[Op.AssignedPhysReg] = Op.StackSlot;
+              PhysRegsAvailable.insert(std::make_pair(Op.AssignedPhysReg,
+                                                      Op.StackSlot));
               SpillSlotsAvailable[Op.StackSlot] = Op.AssignedPhysReg;
               PhysRegsAvailable.erase(Op.PhysRegReused);
               DEBUG(std::cerr << "Remembering SS#" << Op.StackSlot
-                    << " in physreg "
-                    << MRI->getName(Op.AssignedPhysReg) << "\n");
+                              << " in physreg "
+                              << MRI->getName(Op.AssignedPhysReg) << "\n");
               ++NumLoads;
               DEBUG(std::cerr << '\t' << *prior(MII));
 
@@ -452,7 +478,7 @@
       MaybeDeadStores.erase(StackSlot);
 
       MI.SetMachineOperandReg(i, PhysReg);
-      PhysRegsAvailable[PhysReg] = StackSlot;
+      PhysRegsAvailable.insert(std::make_pair(PhysReg, StackSlot));
       SpillSlotsAvailable[StackSlot] = PhysReg;
       DEBUG(std::cerr << "Remembering SS#" << StackSlot <<" in physreg "
                       << MRI->getName(PhysReg) << "\n");
@@ -530,11 +556,8 @@
       // If the spill slot value is available, and this is a new definition of
       // the value, the value is not available anymore.
       if (MR & VirtRegMap::isMod) {
-        std::map<int, unsigned>::iterator It = SpillSlotsAvailable.find(SS);
-        if (It != SpillSlotsAvailable.end()) {
-          PhysRegsAvailable.erase(It->second);
-          SpillSlotsAvailable.erase(It);
-        }
+        // Notice that the value in this stack slot has been modified.
+        ModifyStackSlot(SS, SpillSlotsAvailable, PhysRegsAvailable);
         
         // If this is *just* a mod of the value, check to see if this is just a
         // store to the spill slot (i.e. the spill got merged into the copy). If
@@ -545,21 +568,16 @@
           if (unsigned SrcReg = TII->isStoreToStackSlot(&MI, StackSlot)) {
             assert(MRegisterInfo::isPhysicalRegister(SrcReg) &&
                    "Src hasn't been allocated yet?");
-            // Okay, this is certainly a store of SrcReg to [FrameIdx].  Mark
+            // Okay, this is certainly a store of SrcReg to [StackSlot].  Mark
             // this as a potentially dead store in case there is a subsequent
             // store into the stack slot without a read from it.
             MaybeDeadStores[StackSlot] = &MI;
 
-            // FIXME: PhysRegsAvailable is a 1-1 map, not a N-1 map, which means
-            // that we have to *forget* that SrcReg contains the old value it
-            // does.
-            ClobberPhysRegOnly(SrcReg, SpillSlotsAvailable, PhysRegsAvailable);
-            
             // If the stack slot value was previously available in some other
             // register, change it now.  Otherwise, make the register available,
             // in PhysReg.
             SpillSlotsAvailable[StackSlot] = SrcReg;
-            PhysRegsAvailable[SrcReg] = StackSlot;
+            PhysRegsAvailable.insert(std::make_pair(SrcReg, StackSlot));
             DEBUG(std::cerr << "Updating SS#" << StackSlot << " in physreg "
                             << MRI->getName(SrcReg) << " for virtreg #"
                             << VirtReg << "\n" << MI);
@@ -596,7 +614,7 @@
 
         if (!TakenCareOf) {
           // The only vregs left are stack slot definitions.
-          int StackSlot    = VRM.getStackSlot(VirtReg);
+          int StackSlot = VRM.getStackSlot(VirtReg);
           const TargetRegisterClass *RC =
             MBB.getParent()->getSSARegMap()->getRegClass(VirtReg);
           unsigned PhysReg;
@@ -626,16 +644,10 @@
           // If the stack slot value was previously available in some other
           // register, change it now.  Otherwise, make the register available,
           // in PhysReg.
-          std::map<int, unsigned>::iterator SSA =
-            SpillSlotsAvailable.find(StackSlot);
-          if (SSA != SpillSlotsAvailable.end()) {
-            // Remove the record for physreg.
-            PhysRegsAvailable.erase(SSA->second);
-            SpillSlotsAvailable.erase(SSA);
-          }
+          ModifyStackSlot(StackSlot, SpillSlotsAvailable, PhysRegsAvailable);
           ClobberPhysReg(PhysReg, SpillSlotsAvailable, PhysRegsAvailable);
 
-          PhysRegsAvailable[PhysReg] = StackSlot;
+          PhysRegsAvailable.insert(std::make_pair(PhysReg, StackSlot));
           SpillSlotsAvailable[StackSlot] = PhysReg;
           DEBUG(std::cerr << "Updating SS#" << StackSlot <<" in physreg "
                           << MRI->getName(PhysReg) << " for virtreg #"






More information about the llvm-commits mailing list