Scavenge a register using the register scavenger when needed.
authorEvan Cheng <evan.cheng@apple.com>
Tue, 6 Mar 2007 10:03:56 +0000 (10:03 +0000)
committerEvan Cheng <evan.cheng@apple.com>
Tue, 6 Mar 2007 10:03:56 +0000 (10:03 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@34966 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Target/ARM/ARMRegisterInfo.cpp
lib/Target/ARM/ARMRegisterInfo.h

index dc7e82b86ce4c31cb77e30108e9ffde913d7deb2..260a0b36f250764d46d1cdfde856b926e7cec3bf 100644 (file)
@@ -85,11 +85,6 @@ ARMRegisterInfo::ARMRegisterInfo(const TargetInstrInfo &tii,
   : ARMGenRegisterInfo(ARM::ADJCALLSTACKDOWN, ARM::ADJCALLSTACKUP),
     TII(tii), STI(sti),
     FramePtr(STI.useThumbBacktraces() ? ARM::R7 : ARM::R11) {
-  RS = (EnableScavenging) ? new RegScavenger() : NULL;
-}
-
-ARMRegisterInfo::~ARMRegisterInfo() {
-  delete RS;
 }
 
 bool ARMRegisterInfo::spillCalleeSavedRegisters(MachineBasicBlock &MBB,
@@ -328,6 +323,25 @@ BitVector ARMRegisterInfo::getReservedRegs(const MachineFunction &MF) const {
   return Reserved;
 }
 
+bool
+ARMRegisterInfo::isReservedReg(const MachineFunction &MF, unsigned Reg) const {
+  switch (Reg) {
+  default: break;
+  case ARM::SP:
+  case ARM::PC:
+    return true;
+  case ARM::R7:
+  case ARM::R11:
+    if (FramePtr == Reg && (STI.isTargetDarwin() || hasFP(MF)))
+      return true;
+    break;
+  case ARM::R9:
+    return STI.isR9Reserved();
+  }
+
+  return false;
+}
+
 bool
 ARMRegisterInfo::requiresRegisterScavenging(const MachineFunction &MF) const {
   const ARMFunctionInfo *AFI = MF.getInfo<ARMFunctionInfo>();
@@ -918,15 +932,34 @@ void ARMRegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II,
     // to form it with a series of ADDri's.  Do this by taking 8-bit chunks
     // out of 'Offset'.
     unsigned ScratchReg = findScratchRegister(RS, &ARM::GPRRegClass, AFI);
-    assert(ScratchReg && "Unable to find a free register!");
+    if (ScratchReg == 0)
+      // No register is "free". Scavenge a register.
+      ScratchReg = RS->scavengeRegister(&ARM::GPRRegClass, II);
     emitARMRegPlusImmediate(MBB, II, ScratchReg, FrameReg,
                             isSub ? -Offset : Offset, TII);
     MI.getOperand(i).ChangeToRegister(ScratchReg, false, false, true);
   }
 }
 
-void ARMRegisterInfo::
-processFunctionBeforeCalleeSavedScan(MachineFunction &MF) const {
+static unsigned estimateStackSize(MachineFunction &MF, MachineFrameInfo *MFI) {
+  const MachineFrameInfo *FFI = MF.getFrameInfo();
+  int Offset = 0;
+  for (int i = FFI->getObjectIndexBegin(); i != 0; ++i) {
+    int FixedOff = -FFI->getObjectOffset(i);
+    if (FixedOff > Offset) Offset = FixedOff;
+  }
+  for (unsigned i = 0, e = FFI->getObjectIndexEnd(); i != e; ++i) {
+    Offset += FFI->getObjectSize(i);
+    unsigned Align = FFI->getObjectAlignment(i);
+    // Adjust to alignment boundary
+    Offset = (Offset+Align-1)/Align*Align;
+  }
+  return (unsigned)Offset;
+}
+
+void
+ARMRegisterInfo::processFunctionBeforeCalleeSavedScan(MachineFunction &MF,
+                                                      RegScavenger *RS) const {
   // This tells PEI to spill the FP as if it is any other callee-save register
   // to take advantage the eliminateFrameIndex machinery. This also ensures it
   // is spilled in the order specified by getCalleeSavedRegs() to make it easier
@@ -1020,6 +1053,7 @@ processFunctionBeforeCalleeSavedScan(MachineFunction &MF) const {
     }
   }
 
+  bool ExtraCSSpill = false;
   if (!CanEliminateFrame || hasFP(MF)) {
     AFI->setHasStackFrame(true);
 
@@ -1032,6 +1066,7 @@ processFunctionBeforeCalleeSavedScan(MachineFunction &MF) const {
       UnspilledCS1GPRs.erase(std::find(UnspilledCS1GPRs.begin(),
                                     UnspilledCS1GPRs.end(), (unsigned)ARM::LR));
       ForceLRSpill = false;
+      ExtraCSSpill = true;
     }
 
     // Darwin ABI requires FP to point to the stack slot that contains the
@@ -1050,10 +1085,74 @@ processFunctionBeforeCalleeSavedScan(MachineFunction &MF) const {
         unsigned Reg = UnspilledCS1GPRs.front();
         MF.changePhyRegUsed(Reg, true);
         AFI->setCSRegisterIsSpilled(Reg);
+        if (!isReservedReg(MF, Reg))
+          ExtraCSSpill = true;
       } else if (!UnspilledCS2GPRs.empty()) {
         unsigned Reg = UnspilledCS2GPRs.front();
         MF.changePhyRegUsed(Reg, true);
         AFI->setCSRegisterIsSpilled(Reg);
+        if (!isReservedReg(MF, Reg))
+          ExtraCSSpill = true;
+      }
+    }
+
+    // Estimate if we might need to scavenge a register at some point in order
+    // to materialize a stack offset. If so, either spill one additiona
+    // callee-saved register or reserve a special spill slot to facilitate
+    // register scavenging.
+    if (RS && !ExtraCSSpill && !AFI->isThumbFunction()) {
+      MachineFrameInfo  *MFI = MF.getFrameInfo();
+      unsigned Size = estimateStackSize(MF, MFI);
+      unsigned Limit = (1 << 12) - 1;
+      for (MachineFunction::iterator BB = MF.begin(),E = MF.end();BB != E; ++BB)
+        for (MachineBasicBlock::iterator I= BB->begin(); I != BB->end(); ++I) {
+          for (unsigned i = 0, e = I->getNumOperands(); i != e; ++i)
+            if (I->getOperand(i).isFrameIndex()) {
+              unsigned Opcode = I->getOpcode();
+              const TargetInstrDescriptor &Desc = TII.get(Opcode);
+              unsigned AddrMode = (Desc.TSFlags & ARMII::AddrModeMask);
+              if (AddrMode == ARMII::AddrMode3) {
+                Limit = (1 << 8) - 1;
+                goto DoneEstimating;
+              } else if (AddrMode == ARMII::AddrMode5) {
+                Limit = ((1 << 8) - 1) * 4;
+                goto DoneEstimating;
+              }
+            }
+        }
+    DoneEstimating:
+      if (Size >= Limit) {
+        // If any non-reserved CS register isn't spilled, just spill one or two
+        // extra. That should take care of it!
+        unsigned NumExtras = TargetAlign / 4;
+        SmallVector<unsigned, 2> Extras;
+        while (NumExtras && !UnspilledCS1GPRs.empty()) {
+          unsigned Reg = UnspilledCS1GPRs.back();
+          UnspilledCS1GPRs.pop_back();
+          if (!isReservedReg(MF, Reg)) {
+            Extras.push_back(Reg);
+            NumExtras--;
+          }
+        }
+        while (NumExtras && !UnspilledCS2GPRs.empty()) {
+          unsigned Reg = UnspilledCS2GPRs.back();
+          UnspilledCS2GPRs.pop_back();
+          if (!isReservedReg(MF, Reg)) {
+            Extras.push_back(Reg);
+            NumExtras--;
+          }
+        }
+        if (Extras.size() && NumExtras == 0) {
+          for (unsigned i = 0, e = Extras.size(); i != e; ++i) {
+            MF.changePhyRegUsed(Extras[i], true);
+            AFI->setCSRegisterIsSpilled(Extras[i]);
+          }
+        } else {
+          // Reserve a slot closest to SP or frame pointer.
+          const TargetRegisterClass *RC = &ARM::GPRRegClass;
+          RS->setScavengingFrameIndex(MFI->CreateStackObject(RC->getSize(),
+                                                           RC->getAlignment()));
+        }
       }
     }
   }
index 0193093025f3547bb6cfd9b277516a48401d943e..3187db8c36168146b9d8c721883743150619c6a7 100644 (file)
@@ -27,17 +27,12 @@ struct ARMRegisterInfo : public ARMGenRegisterInfo {
   const TargetInstrInfo &TII;
   const ARMSubtarget &STI;
 private:
-  /// RS - An instance of the register scavenger.
-  RegScavenger *RS;
-
   /// FramePtr - ARM physical register used as frame ptr.
   unsigned FramePtr;
 
 public:
   ARMRegisterInfo(const TargetInstrInfo &tii, const ARMSubtarget &STI);
 
-  ~ARMRegisterInfo();
-
   /// getRegisterNumbering - Given the enum value for some register, e.g.
   /// ARM::LR, return the number that it corresponds to (e.g. 14).
   static unsigned getRegisterNumbering(unsigned RegEnum);
@@ -74,6 +69,8 @@ public:
 
   BitVector getReservedRegs(const MachineFunction &MF) const;
 
+  bool isReservedReg(const MachineFunction &MF, unsigned Reg) const;
+
   bool requiresRegisterScavenging(const MachineFunction &MF) const;
 
   bool hasFP(const MachineFunction &MF) const;
@@ -85,7 +82,8 @@ public:
   void eliminateFrameIndex(MachineBasicBlock::iterator II,
                            RegScavenger *RS = NULL) const;
 
-  void processFunctionBeforeCalleeSavedScan(MachineFunction &MF) const;
+  void processFunctionBeforeCalleeSavedScan(MachineFunction &MF,
+                                            RegScavenger *RS = NULL) const;
 
   void emitPrologue(MachineFunction &MF) const;
   void emitEpilogue(MachineFunction &MF, MachineBasicBlock &MBB) const;