In thumb mode, R3 is reserved, but it can be live in to the function. If
authorEvan Cheng <evan.cheng@apple.com>
Wed, 7 Feb 2007 09:17:36 +0000 (09:17 +0000)
committerEvan Cheng <evan.cheng@apple.com>
Wed, 7 Feb 2007 09:17:36 +0000 (09:17 +0000)
that is the case, whenever we use it as a scratch register, save it to R12
first and then restore it after the use.
This is a temporary and truly horrible workaround!

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@33999 91177308-0d34-0410-b5e6-96231b3b80d8

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

index 6b3ac21d527c8fbe9b6586d025872c0a4aa15859..cf4c105fe1773f15c25069d6c521ccf02eb5f347 100644 (file)
@@ -40,6 +40,10 @@ class ARMFunctionInfo : public MachineFunctionInfo {
   /// far jump.
   bool LRForceSpilled;
 
+  /// R3IsLiveIn - True if R3 is live in to this function.
+  ///
+  bool R3IsLiveIn;
+
   /// FramePtrSpillOffset - If HasStackFrame, this records the frame pointer
   /// spill stack offset.
   unsigned FramePtrSpillOffset;
@@ -75,13 +79,15 @@ class ARMFunctionInfo : public MachineFunctionInfo {
 public:
   ARMFunctionInfo() :
     isThumb(false),
-    VarArgsRegSaveSize(0), HasStackFrame(false), LRForceSpilled(false),
+    VarArgsRegSaveSize(0), HasStackFrame(false),
+    LRForceSpilled(false), R3IsLiveIn(false),
     FramePtrSpillOffset(0), GPRCS1Offset(0), GPRCS2Offset(0), DPRCSOffset(0),
     GPRCS1Size(0), GPRCS2Size(0), DPRCSSize(0), JumpTableUId(0) {}
 
   ARMFunctionInfo(MachineFunction &MF) :
     isThumb(MF.getTarget().getSubtarget<ARMSubtarget>().isThumb()),
-    VarArgsRegSaveSize(0), HasStackFrame(false), LRForceSpilled(false),
+    VarArgsRegSaveSize(0), HasStackFrame(false),
+    LRForceSpilled(false), R3IsLiveIn(false),
     FramePtrSpillOffset(0), GPRCS1Offset(0), GPRCS2Offset(0), DPRCSOffset(0),
     GPRCS1Size(0), GPRCS2Size(0), DPRCSSize(0), JumpTableUId(0) {}
 
@@ -96,6 +102,9 @@ public:
   bool isLRForceSpilled() const { return LRForceSpilled; }
   void setLRIsForceSpilled(bool s) { LRForceSpilled = s; }
 
+  bool isR3IsLiveIn() const { return R3IsLiveIn; }
+  void setR3IsLiveIn(bool l) { R3IsLiveIn = l; }
+
   unsigned getFramePtrSpillOffset() const { return FramePtrSpillOffset; }
   void setFramePtrSpillOffset(unsigned o) { FramePtrSpillOffset = o; }
   
index 644fcec63c59cfdfda3d85c32722dc745179d3b8..ac2ed8ebab561ea3f1b23a835667925bc787e26f 100644 (file)
@@ -401,7 +401,10 @@ void emitThumbRegPlusConstPool(MachineBasicBlock &MBB,
 
     if (NumBytes <= 255 && NumBytes >= 0)
       BuildMI(MBB, MBBI, TII.get(ARM::tMOVri8), LdReg).addImm(NumBytes);
-    else
+    else if (NumBytes < 0 && NumBytes >= -255) {
+      BuildMI(MBB, MBBI, TII.get(ARM::tMOVri8), LdReg).addImm(NumBytes);
+      BuildMI(MBB, MBBI, TII.get(ARM::tNEG), LdReg).addReg(LdReg);
+    } else
       emitLoadConstPool(MBB, MBBI, LdReg, NumBytes, TII);
 
     // Emit add / sub.
@@ -811,7 +814,7 @@ void ARMRegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II) const{
       // being storing here. If that's the case, we do the following:
       // r12 = r2
       // Use r2 to materialize sp + offset
-      // str r12, r2
+      // str r3, r2
       // r2 = r12
       unsigned ValReg = MI.getOperand(0).getReg();
       unsigned TmpReg = ARM::R3;
@@ -820,6 +823,8 @@ void ARMRegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II) const{
         BuildMI(MBB, II, TII.get(ARM::tMOVrr), ARM::R12).addReg(ARM::R2);
         TmpReg = ARM::R2;
       }
+      if (TmpReg == ARM::R3 && AFI->isR3IsLiveIn())
+        BuildMI(MBB, II, TII.get(ARM::tMOVrr), ARM::R12).addReg(ARM::R3);
       if (Opcode == ARM::tSpill) {
         if (FrameReg == ARM::SP)
           emitThumbRegPlusConstPool(MBB, II, TmpReg, FrameReg,Offset,false,TII);
@@ -835,10 +840,12 @@ void ARMRegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II) const{
         MI.addRegOperand(FrameReg, false);  // Use [reg, reg] addrmode.
       else
         MI.addRegOperand(0, false); // tSTR has an extra register operand.
-      if (ValReg == ARM::R3) {
-        MachineBasicBlock::iterator NII = next(II);
+
+      MachineBasicBlock::iterator NII = next(II);
+      if (ValReg == ARM::R3)
         BuildMI(MBB, NII, TII.get(ARM::tMOVrr), ARM::R2).addReg(ARM::R12);
-      }
+      if (TmpReg == ARM::R3 && AFI->isR3IsLiveIn())
+        BuildMI(MBB, NII, TII.get(ARM::tMOVrr), ARM::R3).addReg(ARM::R12);
     } else
       assert(false && "Unexpected opcode!");
   } else {
@@ -1032,6 +1039,15 @@ void ARMRegisterInfo::emitPrologue(MachineFunction &MF) const {
   const std::vector<CalleeSavedInfo> &CSI = MFI->getCalleeSavedInfo();
 
   if (isThumb) {
+    // Check if R3 is live in. It might have to be used as a scratch register.
+    for (MachineFunction::livein_iterator I=MF.livein_begin(),E=MF.livein_end();
+         I != E; ++I) {
+      if ((*I).first == ARM::R3) {
+        AFI->setR3IsLiveIn(true);
+        break;
+      }
+    }
+
     // Thumb add/sub sp, imm8 instructions implicitly multiply the offset by 4.
     NumBytes = (NumBytes + 3) & ~3;
     MFI->setStackSize(NumBytes);