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

Chris Lattner lattner at cs.uiuc.edu
Tue Dec 24 23:06:01 PST 2002


Changes in directory llvm/lib/CodeGen:

RegAllocLocal.cpp updated: 1.7 -> 1.8

---
Log message:

Adjust to simpler spill interface
Only spill and reload caller saved registers that are actually modified.


---
Diffs of the changes:

Index: llvm/lib/CodeGen/RegAllocLocal.cpp
diff -u llvm/lib/CodeGen/RegAllocLocal.cpp:1.7 llvm/lib/CodeGen/RegAllocLocal.cpp:1.8
--- llvm/lib/CodeGen/RegAllocLocal.cpp:1.7	Mon Dec 23 18:04:55 2002
+++ llvm/lib/CodeGen/RegAllocLocal.cpp	Tue Dec 24 23:05:46 2002
@@ -7,11 +7,13 @@
 
 #include "llvm/CodeGen/MachineFunction.h"
 #include "llvm/CodeGen/MachineInstr.h"
+#include "llvm/CodeGen/SSARegMap.h"
 #include "llvm/Target/MachineInstrInfo.h"
 #include "llvm/Target/TargetMachine.h"
 #include "Support/Statistic.h"
 #include "Support/CommandLine.h"
 #include <iostream>
+#include <set>
 
 namespace {
   Statistic<> NumSpilled ("ra-local", "Number of registers spilled");
@@ -25,6 +27,14 @@
     const MRegisterInfo &RegInfo;
     const MachineInstrInfo &MIInfo;
     unsigned NumBytesAllocated;
+
+    // PhysRegsModified - Keep track of which physical registers are actually
+    // modified by the function we are code generating.  This set allows us to
+    // only spill caller-saved registers that we actually change.
+    //
+    // FIXME: this would be much nicer & faster as a bitset.
+    //
+    std::set<unsigned> PhysRegsModified;
     
     // Maps SSA Regs => offsets on the stack where these values are stored
     std::map<unsigned, unsigned> VirtReg2OffsetMap;
@@ -111,11 +121,12 @@
 
 
     /// 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.
+    /// prologue/epilogue to the function and save/restore the callee saved
+    /// registers specified by the CSRegs list.
     ///
-    void EmitPrologue();
-    void EmitEpilogue(MachineBasicBlock &MBB);
+    void EmitPrologue(const std::vector<unsigned> &CSRegs);
+    void EmitEpilogue(MachineBasicBlock &MBB,
+		      const std::vector<unsigned> &CSRegs);
 
     /// 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
@@ -251,12 +262,13 @@
                       unsigned VirtReg, unsigned PhysReg) {
   // If this is just a marker register, we don't need to spill it.
   if (VirtReg != 0) {
-    const TargetRegisterClass *RegClass = MF->getRegClass(VirtReg);
+    const TargetRegisterClass *RegClass =
+      MF->getSSARegMap()->getRegClass(VirtReg);
     unsigned stackOffset = getStackSpaceFor(VirtReg, RegClass);
 
     // Add move instruction(s)
-    I = RegInfo.storeReg2RegOffset(MBB, I, PhysReg, RegInfo.getFramePointer(),
-                                   -stackOffset, RegClass->getDataSize());
+    RegInfo.storeReg2RegOffset(MBB, I, PhysReg, RegInfo.getFramePointer(),
+			       -stackOffset, RegClass);
     ++NumSpilled;   // Update statistics
     Virt2PhysRegMap.erase(VirtReg);   // VirtReg no longer available
   }
@@ -289,7 +301,8 @@
 ///
 unsigned RA::getFreeReg(MachineBasicBlock &MBB, MachineBasicBlock::iterator &I,
                         unsigned VirtReg) {
-  const TargetRegisterClass *RegClass = MF->getRegClass(VirtReg);
+  const TargetRegisterClass *RegClass =
+    MF->getSSARegMap()->getRegClass(VirtReg);
   unsigned PhysReg = 0;
 
   // First check to see if we have a free register of the requested type...
@@ -377,12 +390,12 @@
 
   unsigned PhysReg = getFreeReg(MBB, I, VirtReg);
 
-  const TargetRegisterClass *RegClass = MF->getRegClass(VirtReg);
-  unsigned StackOffset = getStackSpaceFor(VirtReg, RegClass);
+  const TargetRegisterClass *RC = MF->getSSARegMap()->getRegClass(VirtReg);
+  unsigned StackOffset = getStackSpaceFor(VirtReg, RC);
 
   // Add move instruction(s)
-  I = RegInfo.loadRegOffset2Reg(MBB, I, PhysReg, RegInfo.getFramePointer(),
-                                -StackOffset, RegClass->getDataSize());
+  RegInfo.loadRegOffset2Reg(MBB, I, PhysReg, RegInfo.getFramePointer(),
+			    -StackOffset, RC);
   ++NumReloaded;    // Update statistics
   return PhysReg;
 }
@@ -474,17 +487,17 @@
         if (!MII.isBranch(opMI->getOpcode()))
           ++opI;
 
-        unsigned dataSize = MF->getRegClass(virtualReg)->getDataSize();
+        const TargetRegisterClass *RC =
+	  MF->getSSARegMap()->getRegClass(virtualReg);
 
         // Retrieve the constant value from this op, move it to target
         // register of the phi
         if (opVal.isImmediate()) {
-          opI = RegInfo.moveImm2Reg(opBlock, opI, virtualReg,
-                                    (unsigned) opVal.getImmedValue(),
-                                    dataSize);
+          RegInfo.moveImm2Reg(opBlock, opI, virtualReg,
+			      (unsigned) opVal.getImmedValue(), RC);
         } else {
-          opI = RegInfo.moveReg2Reg(opBlock, opI, virtualReg,
-                                    opVal.getAllocatedRegNum(), dataSize);
+          RegInfo.moveReg2Reg(opBlock, opI, virtualReg,
+			      opVal.getAllocatedRegNum(), RC);
         }
       }
     }
@@ -514,6 +527,7 @@
         spillPhysReg(MBB, I, Reg);
         PhysRegsUsed[Reg] = 0;            // It is free and reserved now
         PhysRegsUseOrder.push_back(Reg);
+	PhysRegsModified.insert(Reg);     // Register is modified by current Fn
       }
 
     // Loop over the implicit defs, spilling them, as above.
@@ -531,7 +545,8 @@
 	  removePhysReg(Reg);
 	}
 	PhysRegsUseOrder.push_back(Reg);
-	PhysRegsUsed[Reg] = 0;           // It is free and reserved now
+	PhysRegsUsed[Reg] = 0;            // It is free and reserved now
+	PhysRegsModified.insert(Reg);     // Register is modified by current Fn
       }
 
     // Loop over the implicit uses, making sure that they are at the head of the
@@ -550,6 +565,7 @@
         unsigned VirtSrcReg = MI->getOperand(i).getAllocatedRegNum();
         unsigned PhysSrcReg = reloadVirtReg(MBB, I, VirtSrcReg);
         MI->SetMachineOperandReg(i, PhysSrcReg);  // Assign the input register
+	PhysRegsModified.insert(PhysSrcReg);      // Register is modified
       }
     
     // Okay, we have allocated all of the source operands and spilled any values
@@ -579,6 +595,7 @@
         } else {
           DestPhysReg = getFreeReg(MBB, I, DestVirtReg);
         }
+	PhysRegsModified.insert(DestPhysReg);      // Register is modified
         MI->SetMachineOperandReg(i, DestPhysReg);  // Assign the output register
       }
 
@@ -625,23 +642,18 @@
 /// EmitPrologue - Use the register info object to add a prologue to the
 /// function and save any callee saved registers we are responsible for.
 ///
-void RA::EmitPrologue() {
-  // Get a list of the callee saved registers, so that we can save them on entry
-  // to the function.
-  //
-
+void RA::EmitPrologue(const std::vector<unsigned> &CSRegs) {
   MachineBasicBlock &MBB = MF->front();   // Prolog goes in entry BB
   MachineBasicBlock::iterator I = MBB.begin();
 
-  const unsigned *CSRegs = RegInfo.getCalleeSaveRegs();
-  for (unsigned i = 0; CSRegs[i]; ++i) {
+  for (unsigned i = 0, e = CSRegs.size(); i != e; ++i) {
     const TargetRegisterClass *RegClass = RegInfo.getRegClass(CSRegs[i]);
     unsigned Offset = getStackSpaceFor(CSRegs[i], RegClass);
 
     // Insert the spill to the stack frame...
     ++NumSpilled;
-    I = RegInfo.storeReg2RegOffset(MBB, I, CSRegs[i], RegInfo.getFramePointer(),
-                                   -Offset, RegClass->getDataSize());
+    RegInfo.storeReg2RegOffset(MBB, I, CSRegs[i], RegInfo.getFramePointer(),
+			       -Offset, RegClass);
   }
 
   // Add prologue to the function...
@@ -652,17 +664,17 @@
 /// EmitEpilogue - Use the register info object to add a epilogue to the
 /// function and restore any callee saved registers we are responsible for.
 ///
-void RA::EmitEpilogue(MachineBasicBlock &MBB) {
+void RA::EmitEpilogue(MachineBasicBlock &MBB,
+		      const std::vector<unsigned> &CSRegs) {
   // Insert instructions before the return.
   MachineBasicBlock::iterator I = MBB.end()-1;
 
-  const unsigned *CSRegs = RegInfo.getCalleeSaveRegs();
-  for (unsigned i = 0; CSRegs[i]; ++i) {
+  for (unsigned i = 0, e = CSRegs.size(); i != e; ++i) {
     const TargetRegisterClass *RegClass = RegInfo.getRegClass(CSRegs[i]);
     unsigned Offset = getStackSpaceFor(CSRegs[i], RegClass);
     ++NumReloaded;
-    I = RegInfo.loadRegOffset2Reg(MBB, I, CSRegs[i], RegInfo.getFramePointer(),
-                                  -Offset, RegClass->getDataSize());
+    RegInfo.loadRegOffset2Reg(MBB, I, CSRegs[i], RegInfo.getFramePointer(),
+			      -Offset, RegClass);
     --I;  // Insert in reverse order
   }
 
@@ -706,9 +718,25 @@
        MBB != MBBe; ++MBB)
     AllocateBasicBlock(*MBB);
 
+  // Figure out which callee saved registers are modified by the current
+  // function, thus needing to be saved and restored in the prolog/epilog.
+  //
+  const unsigned *CSRegs = RegInfo.getCalleeSaveRegs();
+  std::vector<unsigned> RegsToSave;
+  for (unsigned i = 0; CSRegs[i]; ++i) {
+    unsigned Reg = CSRegs[i];
+    if (PhysRegsModified.count(Reg))  // If modified register...
+      RegsToSave.push_back(Reg);
+    else if (const unsigned *AliasSet = RegInfo.getAliasSet(Reg))
+      for (unsigned j = 0; AliasSet[j]; ++j)     // Check alias registers too...
+	if (PhysRegsModified.count(AliasSet[j])) {
+	  RegsToSave.push_back(Reg);
+	  break;
+	}
+  }
 
   // Emit a prologue for the function...
-  EmitPrologue();
+  EmitPrologue(RegsToSave);
 
   const MachineInstrInfo &MII = TM.getInstrInfo();
 
@@ -717,9 +745,10 @@
        MBB != MBBe; ++MBB) {
     // If last instruction is a return instruction, add an epilogue
     if (MII.isReturn(MBB->back()->getOpcode()))
-      EmitEpilogue(*MBB);
+      EmitEpilogue(*MBB, RegsToSave);
   }
 
+  PhysRegsModified.clear();
   LastUserOf.clear();
   cleanupAfterFunction();
   return true;





More information about the llvm-commits mailing list