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

Chris Lattner lattner at cs.uiuc.edu
Wed Dec 18 02:15:01 PST 2002


Changes in directory llvm/lib/CodeGen:

RegAllocLocal.cpp updated: 1.5 -> 1.6

---
Log message:

* Fix several register aliasing bugs
* Add a new option to eliminate spilling of registers that are only used 
  within a basic block.


---
Diffs of the changes:

Index: llvm/lib/CodeGen/RegAllocLocal.cpp
diff -u llvm/lib/CodeGen/RegAllocLocal.cpp:1.5 llvm/lib/CodeGen/RegAllocLocal.cpp:1.6
--- llvm/lib/CodeGen/RegAllocLocal.cpp:1.5	Mon Dec 16 22:19:40 2002
+++ llvm/lib/CodeGen/RegAllocLocal.cpp	Wed Dec 18 02:14:26 2002
@@ -10,11 +10,14 @@
 #include "llvm/Target/MachineInstrInfo.h"
 #include "llvm/Target/TargetMachine.h"
 #include "Support/Statistic.h"
+#include "Support/CommandLine.h"
 #include <iostream>
 
 namespace {
   Statistic<> NumSpilled ("ra-local", "Number of registers spilled");
   Statistic<> NumReloaded("ra-local", "Number of registers reloaded");
+  cl::opt<bool> DisableKill("no-kill", cl::Hidden, 
+                            cl::desc("Disable register kill in local-ra"));
 
   class RA : public FunctionPass {
     TargetMachine &TM;
@@ -49,15 +52,23 @@
     //
     std::vector<unsigned> PhysRegsUseOrder;
 
+    // LastUserOf map - This multimap contains the set of registers that each
+    // key instruction is the last user of.  If an instruction has an entry in
+    // this map, that means that the specified operands are killed after the 
+    // instruction is executed, thus they don't need to be spilled into memory
+    //
+    std::multimap<MachineInstr*, unsigned> LastUserOf;
+
     void MarkPhysRegRecentlyUsed(unsigned Reg) {
-      assert(std::find(PhysRegsUseOrder.begin(), PhysRegsUseOrder.end(), Reg) !=
-             PhysRegsUseOrder.end() && "Register isn't used yet!");
+      assert(!PhysRegsUseOrder.empty() && "No registers used!");
       if (PhysRegsUseOrder.back() != Reg) {
-        for (unsigned i = PhysRegsUseOrder.size(); ; --i)
-          if (PhysRegsUseOrder[i-1] == Reg) {  // remove from middle
+        for (unsigned i = PhysRegsUseOrder.size(); i != 0; --i)
+          if (areRegsEqual(Reg, PhysRegsUseOrder[i-1])) { // remove from middle
+            unsigned RegMatch = PhysRegsUseOrder[i-1];
             PhysRegsUseOrder.erase(PhysRegsUseOrder.begin()+i-1);
-            PhysRegsUseOrder.push_back(Reg);  // Add it to the end of the list
-            return;
+            PhysRegsUseOrder.push_back(RegMatch);  // Add it to the end of the list
+            if (RegMatch == Reg) 
+              return;    // Found an exact match, exit early
           }
       }
     }
@@ -88,6 +99,16 @@
     /// in predecessor basic blocks.
     void EliminatePHINodes(MachineBasicBlock &MBB);
 
+    /// CalculateLastUseOfVReg - Calculate an approximation of the killing
+    /// uses for the virtual registers in the function.  Here we try to capture
+    /// registers that are defined and only used within the same basic block.
+    /// Because we don't have use-def chains yet, we have to do this the hard
+    /// way.
+    ///
+    void CalculateLastUseOfVReg(MachineBasicBlock &MBB,
+                        std::map<unsigned, MachineInstr*> &LastUseOfVReg) const;
+
+
     /// EmitPrologue/EmitEpilogue - Use the register info object to add a
     /// prologue/epilogue to the function and save/restore any callee saved
     /// registers we are responsible for.
@@ -95,21 +116,23 @@
     void EmitPrologue();
     void EmitEpilogue(MachineBasicBlock &MBB);
 
+    /// areRegsEqual - This method returns true if the specified registers are
+    /// related to each other.  To do this, it checks to see if they are equal
+    /// or if the first register is in the alias set of the second register.
+    ///
+    bool areRegsEqual(unsigned R1, unsigned R2) const {
+      if (R1 == R2) return true;
+      if (const unsigned *AliasSet = RegInfo.getAliasSet(R2))
+        for (unsigned i = 0; AliasSet[i]; ++i)
+          if (AliasSet[i] == R1) return true;
+      return false;
+    }
+
     /// isAllocatableRegister - A register may be used by the program if it's
     /// not the stack or frame pointer.
     bool isAllocatableRegister(unsigned R) const {
       unsigned FP = RegInfo.getFramePointer(), SP = RegInfo.getStackPointer();
-      // Don't allocate the Frame or Stack pointers
-      if (R == FP || R == SP)
-        return false;
-
-      // Check to see if this register aliases the stack or frame pointer...
-      if (const unsigned *AliasSet = RegInfo.getAliasSet(R)) {
-        for (unsigned i = 0; AliasSet[i]; ++i)
-          if (AliasSet[i] == FP || AliasSet[i] == SP)
-            return false;
-      }
-      return true;
+      return !areRegsEqual(FP, R) && !areRegsEqual(SP, R);
     }
 
     /// getStackSpaceFor - This returns the offset of the specified virtual
@@ -122,6 +145,7 @@
       NumBytesAllocated = 4;   // FIXME: This is X86 specific
     }
 
+    void removePhysReg(unsigned PhysReg);
 
     /// spillVirtReg - This method spills the value specified by PhysReg into
     /// the virtual register slot specified by VirtReg.  It then updates the RA
@@ -136,8 +160,17 @@
     void spillPhysReg(MachineBasicBlock &MBB, MachineBasicBlock::iterator &I,
                       unsigned PhysReg) {
       std::map<unsigned, unsigned>::iterator PI = PhysRegsUsed.find(PhysReg);
-      if (PI != PhysRegsUsed.end())   // Only spill it if it's used!
+      if (PI != PhysRegsUsed.end()) {               // Only spill it if it's used!
         spillVirtReg(MBB, I, PI->second, PhysReg);
+      } else if (const unsigned *AliasSet = RegInfo.getAliasSet(PhysReg)) {
+        // If the selected register aliases any other registers, we must make sure
+        // that one of the aliases isn't alive...
+        for (unsigned i = 0; AliasSet[i]; ++i) {
+          PI = PhysRegsUsed.find(AliasSet[i]);
+          if (PI != PhysRegsUsed.end())     // Spill aliased register...
+            spillVirtReg(MBB, I, PI->second, AliasSet[i]);
+        }
+      }
     }
 
     void AssignVirtToPhysReg(unsigned VirtReg, unsigned PhysReg);
@@ -146,7 +179,7 @@
     /// free and available for use.  This also includes checking to see if
     /// aliased registers are all free...
     ///
-    bool RA::isPhysRegAvailable(unsigned PhysReg) const;
+    bool isPhysRegAvailable(unsigned PhysReg) const;
     
     /// getFreeReg - Find a physical register to hold the specified virtual
     /// register.  If all compatible physical registers are used, this method
@@ -196,6 +229,19 @@
 }
 
 
+/// removePhysReg - This method marks the specified physical register as no 
+/// longer being in use.
+///
+void RA::removePhysReg(unsigned PhysReg) {
+  PhysRegsUsed.erase(PhysReg);      // PhyReg no longer used
+
+  std::vector<unsigned>::iterator It =
+    std::find(PhysRegsUseOrder.begin(), PhysRegsUseOrder.end(), PhysReg);
+  assert(It != PhysRegsUseOrder.end() &&
+         "Spilled a physical register, but it was not in use list!");
+  PhysRegsUseOrder.erase(It);
+}
+
 /// spillVirtReg - This method spills the value specified by PhysReg into the
 /// virtual register slot specified by VirtReg.  It then updates the RA data
 /// structures to indicate the fact that PhysReg is now available.
@@ -213,13 +259,8 @@
     ++NumSpilled;   // Update statistics
     Virt2PhysRegMap.erase(VirtReg);   // VirtReg no longer available
   }
-  PhysRegsUsed.erase(PhysReg);      // PhyReg no longer used
 
-  std::vector<unsigned>::iterator It =
-    std::find(PhysRegsUseOrder.begin(), PhysRegsUseOrder.end(), PhysReg);
-  assert(It != PhysRegsUseOrder.end() &&
-         "Spilled a physical register, but it was not in use list!");
-  PhysRegsUseOrder.erase(It);
+  removePhysReg(PhysReg);
 }
 
 
@@ -300,13 +341,6 @@
     // At this point PhysRegsUseOrder[i] is the least recently used register of
     // compatible register class.  Spill it to memory and reap its remains.
     spillPhysReg(MBB, I, PhysReg);
-
-    // If the selected register aliases any other registers, we must make sure
-    // to spill them as well...
-    if (const unsigned *AliasSet = RegInfo.getAliasSet(PhysReg))
-      for (unsigned i = 0; AliasSet[i]; ++i)
-        if (PhysRegsUsed.count(AliasSet[i]))     // Spill aliased register...
-          spillPhysReg(MBB, I, AliasSet[i]);
   }
 
   // Now that we know which register we need to assign this to, do it now!
@@ -352,6 +386,41 @@
   return PhysReg;
 }
 
+/// CalculateLastUseOfVReg - Calculate an approximation of the killing uses for
+/// the virtual registers in the function.  Here we try to capture registers 
+/// that are defined and only used within the same basic block.  Because we 
+/// don't have use-def chains yet, we have to do this the hard way.
+///
+void RA::CalculateLastUseOfVReg(MachineBasicBlock &MBB, 
+                      std::map<unsigned, MachineInstr*> &LastUseOfVReg) const {
+  // Calculate the last machine instruction in this basic block that uses the
+  // specified virtual register defined in this basic block.
+  std::map<unsigned, MachineInstr*> LastLocalUses;
+
+  for (MachineBasicBlock::iterator I = MBB.begin(), E = MBB.end(); I != E;++I){
+    MachineInstr *MI = *I;
+    for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) {
+      MachineOperand &Op = MI->getOperand(i);
+      if (Op.isVirtualRegister()) {
+        if (Op.opIsDef()) {   // Definition of a new virtual reg?
+          LastLocalUses[Op.getAllocatedRegNum()] = 0;  // Record it
+        } else {              // Use of a virtual reg.
+          std::map<unsigned, MachineInstr*>::iterator It = 
+                               LastLocalUses.find(Op.getAllocatedRegNum());
+          if (It != LastLocalUses.end())  // Local use?
+            It->second = MI;              // Update last use
+          else
+            LastUseOfVReg[Op.getAllocatedRegNum()] = 0;
+        }
+      }
+    }
+  }
+
+  // Move local uses over... if there are any uses of a local already in the 
+  // lastuse map, the newly inserted entry is ignored.
+  LastUseOfVReg.insert(LastLocalUses.begin(), LastLocalUses.end());
+}
+ 
 
 /// EliminatePHINodes - Eliminate phi nodes by inserting copy instructions in
 /// predecessor basic blocks.
@@ -364,7 +433,6 @@
     // Unlink the PHI node from the basic block... but don't delete the PHI yet
     MBB.erase(MBB.begin());
     
-    DEBUG(std::cerr << "num ops: " << MI->getNumOperands() << "\n");
     assert(MI->getOperand(0).isVirtualRegister() &&
            "PHI node doesn't write virt reg?");
 
@@ -448,9 +516,15 @@
     if (const unsigned *ImplicitDefs = MID.ImplicitDefs)
       for (unsigned i = 0; ImplicitDefs[i]; ++i) {
         unsigned Reg = ImplicitDefs[i];
-        spillPhysReg(MBB, I, Reg);
-        PhysRegsUsed[Reg] = 0;  // It's free now, and it's reserved
-        PhysRegsUseOrder.push_back(Reg);
+
+        // We don't want to spill implicit definitions if they were explicitly
+        // chosen.  For this reason, check to see now if the register we are
+        // to spill has a vreg of 0.
+        if (PhysRegsUsed.count(Reg) && PhysRegsUsed[Reg] != 0) {
+          spillPhysReg(MBB, I, Reg);
+          PhysRegsUsed[Reg] = 0;  // It's free now, and it's reserved
+          PhysRegsUseOrder.push_back(Reg);
+        }
       }
 
     // Loop over the implicit uses, making sure that they are at the head of the
@@ -475,7 +549,7 @@
     // that would be destroyed by defs of this instruction.  Loop over the
     // implicit defs and assign them to a register, spilling the incoming value
     // if we need to scavange a register.
-
+    //
     for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i)
       if (MI->getOperand(i).opIsDef() &&
           !MI->getOperand(i).isPhysicalRegister()) {
@@ -500,6 +574,23 @@
         }
         MI->SetMachineOperandReg(i, DestPhysReg);  // Assign the output register
       }
+
+    if (!DisableKill) {
+      // If this instruction is the last user of anything in registers, kill the 
+      // value, freeing the register being used, so it doesn't need to be spilled
+      // to memory at the end of the block.
+      std::multimap<MachineInstr*, unsigned>::iterator LUOI = 
+             LastUserOf.lower_bound(MI);
+      for (; LUOI != LastUserOf.end() && LUOI->first == MI; ++MI) {// entry found?
+        unsigned VirtReg = LUOI->second;
+        unsigned PhysReg = Virt2PhysRegMap[VirtReg];
+        if (PhysReg) {
+          DEBUG(std::cout << "V: " << VirtReg << " P: " << PhysReg << " Last use of: " << *MI);
+          removePhysReg(PhysReg);
+        }
+        Virt2PhysRegMap.erase(VirtReg);
+      }
+    }
   }
 
   // Rewind the iterator to point to the first flow control instruction...
@@ -578,13 +669,30 @@
   MF = &Fn;
 
   // First pass: eliminate PHI instructions by inserting copies into predecessor
-  // blocks.
-  // FIXME: In this pass, count how many uses of each VReg exist!
+  // blocks, and calculate a simple approximation of killing uses for virtual 
+  // registers.
+  //
+  std::map<unsigned, MachineInstr*> LastUseOfVReg;
   for (MachineFunction::iterator MBB = Fn.begin(), MBBe = Fn.end();
        MBB != MBBe; ++MBB) {
+    if (!DisableKill)
+      CalculateLastUseOfVReg(*MBB, LastUseOfVReg);
     EliminatePHINodes(*MBB);
   }
 
+  // At this point LastUseOfVReg has been filled in to contain the last 
+  // MachineInstr user of the specified virtual register, if that user is 
+  // within the same basic block as the definition (otherwise it contains
+  // null).  Invert this mapping now:
+  if (!DisableKill)
+    for (std::map<unsigned, MachineInstr*>::iterator I = LastUseOfVReg.begin(),
+         E = LastUseOfVReg.end(); I != E; ++I)
+      if (I->second)
+        LastUserOf.insert(std::make_pair(I->second, I->first));
+
+  // We're done with the temporary list now.
+  LastUseOfVReg.clear();
+
   // Loop over all of the basic blocks, eliminating virtual register references
   for (MachineFunction::iterator MBB = Fn.begin(), MBBe = Fn.end();
        MBB != MBBe; ++MBB)
@@ -604,6 +712,7 @@
       EmitEpilogue(*MBB);
   }
 
+  LastUserOf.clear();
   cleanupAfterFunction();
   return true;
 }





More information about the llvm-commits mailing list