Spill / restore should avoid modifying the condition register.
authorEvan Cheng <evan.cheng@apple.com>
Wed, 7 Feb 2007 00:06:56 +0000 (00:06 +0000)
committerEvan Cheng <evan.cheng@apple.com>
Wed, 7 Feb 2007 00:06:56 +0000 (00:06 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@33971 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Target/ARM/ARMInstrInfo.cpp
lib/Target/ARM/ARMInstrThumb.td
lib/Target/ARM/ARMRegisterInfo.cpp
lib/Target/ARM/README-Thumb.txt

index 6adf645e493ff7e1b0ec0eeffd1d0859eb233554..36ed76d9616b357548178987ce55029c81cb55d9 100644 (file)
@@ -83,7 +83,7 @@ unsigned ARMInstrInfo::isLoadFromStackSlot(MachineInstr *MI, int &FrameIndex) co
       return MI->getOperand(0).getReg();
     }
     break;
-  case ARM::tLDRspi:
+  case ARM::tRestore:
     if (MI->getOperand(1).isFrameIndex() &&
         MI->getOperand(2).isImmediate() && 
         MI->getOperand(2).getImmedValue() == 0) {
@@ -117,7 +117,7 @@ unsigned ARMInstrInfo::isStoreToStackSlot(MachineInstr *MI, int &FrameIndex) con
       return MI->getOperand(0).getReg();
     }
     break;
-  case ARM::tSTRspi:
+  case ARM::tSpill:
     if (MI->getOperand(1).isFrameIndex() &&
         MI->getOperand(2).isImmediate() && 
         MI->getOperand(2).getImmedValue() == 0) {
index b0e531cdc84c4b8fc2e64fbbf7313e068c2ff4f9..59a0098f44d262c2896bdc2ac325066b6413d360 100644 (file)
@@ -239,6 +239,11 @@ def tLDRspi : TIs<(ops GPR:$dst, t_addrmode_sp:$addr),
                   "ldr $dst, $addr",
                   [(set GPR:$dst, (load t_addrmode_sp:$addr))]>;
 
+// Special instruction for restore. It cannot clobber condition register
+// when it's expanded by eliminateCallFramePseudoInstr().
+def tRestore : TIs<(ops GPR:$dst, t_addrmode_sp:$addr),
+                    "ldr $dst, $addr", []>;
+
 // Load tconstpool
 def tLDRpci : TIs<(ops GPR:$dst, i32imm:$addr),
                   "ldr $dst, $addr",
@@ -261,6 +266,11 @@ def tSTRH : TI2<(ops GPR:$src, t_addrmode_s2:$addr),
 def tSTRspi : TIs<(ops GPR:$src, t_addrmode_sp:$addr),
                    "str $src, $addr",
                    [(store GPR:$src, t_addrmode_sp:$addr)]>;
+
+// Special instruction for spill. It cannot clobber condition register
+// when it's expanded by eliminateCallFramePseudoInstr().
+def tSpill : TIs<(ops GPR:$src, t_addrmode_sp:$addr),
+                  "str $src, $addr", []>;
 }
 
 //===----------------------------------------------------------------------===//
index 90fc84ffe5b8de71cf4374ad5bcff45e1838f7af..2eb9eeac2bf75bf2bce4ab53234a068e2a55ffaa 100644 (file)
@@ -130,7 +130,7 @@ storeRegToStackSlot(MachineBasicBlock &MBB, MachineBasicBlock::iterator I,
     MachineFunction &MF = *MBB.getParent();
     ARMFunctionInfo *AFI = MF.getInfo<ARMFunctionInfo>();
     if (AFI->isThumbFunction())
-      BuildMI(MBB, I, TII.get(ARM::tSTRspi)).addReg(SrcReg)
+      BuildMI(MBB, I, TII.get(ARM::tSpill)).addReg(SrcReg)
         .addFrameIndex(FI).addImm(0);
     else
       BuildMI(MBB, I, TII.get(ARM::STR)).addReg(SrcReg)
@@ -153,7 +153,7 @@ loadRegFromStackSlot(MachineBasicBlock &MBB, MachineBasicBlock::iterator I,
     MachineFunction &MF = *MBB.getParent();
     ARMFunctionInfo *AFI = MF.getInfo<ARMFunctionInfo>();
     if (AFI->isThumbFunction())
-      BuildMI(MBB, I, TII.get(ARM::tLDRspi), DestReg)
+      BuildMI(MBB, I, TII.get(ARM::tRestore), DestReg)
         .addFrameIndex(FI).addImm(0);
     else
       BuildMI(MBB, I, TII.get(ARM::LDR), DestReg)
@@ -220,16 +220,16 @@ MachineInstr *ARMRegisterInfo::foldMemoryOperand(MachineInstr *MI,
     if (OpNum == 0) { // move -> store
       unsigned SrcReg = MI->getOperand(1).getReg();
       if (!isLowRegister(SrcReg))
-        // tSTRspi cannot take a high register operand.
+        // tSpill cannot take a high register operand.
         break;
-      NewMI = BuildMI(TII.get(ARM::tSTRspi)).addReg(SrcReg).addFrameIndex(FI)
+      NewMI = BuildMI(TII.get(ARM::tSpill)).addReg(SrcReg).addFrameIndex(FI)
         .addImm(0);
     } else {          // move -> load
       unsigned DstReg = MI->getOperand(0).getReg();
       if (!isLowRegister(DstReg))
-        // tLDRspi cannot target a high register operand.
+        // tRestore cannot target a high register operand.
         break;
-      NewMI = BuildMI(TII.get(ARM::tLDRspi), DstReg).addFrameIndex(FI)
+      NewMI = BuildMI(TII.get(ARM::tRestore), DstReg).addFrameIndex(FI)
         .addImm(0);
     }
     break;
@@ -412,7 +412,7 @@ void emitThumbRegPlusImmediate(MachineBasicBlock &MBB,
   if (isSub) Bytes = -NumBytes;
   bool isMul4 = (Bytes & 3) == 0;
   bool isTwoAddr = false;
-  bool DstNeBase = false;
+  bool DstNotEqBase = false;
   unsigned NumBits = 1;
   unsigned Scale = 1;
   int Opc = 0;
@@ -441,14 +441,14 @@ void emitThumbRegPlusImmediate(MachineBasicBlock &MBB,
     // r1 = sub sp, c
     // r8 = sub sp, c
     if (DestReg != BaseReg)
-      DstNeBase = true;
+      DstNotEqBase = true;
     NumBits = 8;
     Opc = isSub ? ARM::tSUBi8 : ARM::tADDi8;
     isTwoAddr = true;
   }
 
   unsigned NumMIs = calcNumMI(Opc, ExtraOpc, Bytes, NumBits, Scale);
-  unsigned Threshold = (DestReg == ARM::SP) ? 4 : 3;
+  unsigned Threshold = (DestReg == ARM::SP) ? 3 : 2;
   if (NumMIs > Threshold) {
     // This will expand into too many instructions. Load the immediate from a
     // constpool entry.
@@ -456,7 +456,7 @@ void emitThumbRegPlusImmediate(MachineBasicBlock &MBB,
     return;
   }
 
-  if (DstNeBase) {
+  if (DstNotEqBase) {
     if (isLowRegister(DestReg) && isLowRegister(BaseReg)) {
       // If both are low registers, emit DestReg = add BaseReg, max(Imm, 7)
       unsigned Chunk = (1 << 3) - 1;
@@ -730,27 +730,20 @@ void ARMRegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II) const{
       isSub = true;
     }
 
-    if (!isSub || !isThumb) {
-      MachineOperand &ImmOp = MI.getOperand(ImmIdx);
-      int ImmedOffset = Offset / Scale;
-      unsigned Mask = (1 << NumBits) - 1;
-      if ((unsigned)Offset <= Mask * Scale) {
-        // Replace the FrameIndex with sp
-        MI.getOperand(i).ChangeToRegister(FrameReg, false);
-        if (isSub)
-          ImmedOffset |= 1 << NumBits;
-        ImmOp.ChangeToImmediate(ImmedOffset);
-        return;
-      }
+    MachineOperand &ImmOp = MI.getOperand(ImmIdx);
+    int ImmedOffset = Offset / Scale;
+    unsigned Mask = (1 << NumBits) - 1;
+    if ((unsigned)Offset <= Mask * Scale) {
+      // Replace the FrameIndex with sp
+      MI.getOperand(i).ChangeToRegister(FrameReg, false);
+      if (isSub)
+        ImmedOffset |= 1 << NumBits;
+      ImmOp.ChangeToImmediate(ImmedOffset);
+      return;
+    }
 
+    if (!isThumb) {
       // Otherwise, it didn't fit. Pull in what we can to simplify the immed.
-      if (AddrMode == ARMII::AddrModeTs) {
-        // Thumb tLDRspi, tSTRspi. These will change to instructions that use
-        // a different base register.
-        NumBits = 5;
-        Mask = (1 << NumBits) - 1;
-      }
-
       ImmedOffset = ImmedOffset & Mask;
       if (isSub)
         ImmedOffset |= 1 << NumBits;
@@ -768,8 +761,12 @@ void ARMRegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II) const{
     if (TII.isLoad(Opcode)) {
       // Use the destination register to materialize sp + offset.
       unsigned TmpReg = MI.getOperand(0).getReg();
-      emitThumbRegPlusImmediate(MBB, II, TmpReg, FrameReg,
-                                isSub ? -Offset : Offset, TII);
+      if (Opcode == ARM::tRestore)
+        emitThumbRegPlusConstPool(MBB, II, TmpReg, FrameReg,
+                                  isSub ? -Offset : Offset, TII);
+      else
+        emitThumbRegPlusImmediate(MBB, II, TmpReg, FrameReg,
+                                  isSub ? -Offset : Offset, TII);
       MI.setInstrDescriptor(TII.get(ARM::tLDR));
       MI.getOperand(i).ChangeToRegister(TmpReg, false);
       MI.addRegOperand(0, false); // tLDR has an extra register operand.
@@ -788,8 +785,12 @@ void ARMRegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II) const{
         BuildMI(MBB, II, TII.get(ARM::tMOVrr), ARM::R12).addReg(ARM::R2);
         TmpReg = ARM::R2;
       }
-      emitThumbRegPlusImmediate(MBB, II, TmpReg, FrameReg,
-                                isSub ? -Offset : Offset, TII);
+      if (Opcode == ARM::tSpill)
+        emitThumbRegPlusConstPool(MBB, II, TmpReg, FrameReg,
+                                  isSub ? -Offset : Offset, TII);
+      else
+        emitThumbRegPlusImmediate(MBB, II, TmpReg, FrameReg,
+                                  isSub ? -Offset : Offset, TII);
       MI.setInstrDescriptor(TII.get(ARM::tSTR));
       MI.getOperand(i).ChangeToRegister(TmpReg, false);
       MI.addRegOperand(0, false); // tSTR has an extra register operand.
@@ -1098,7 +1099,7 @@ static bool isCalleeSavedRegister(unsigned Reg, const unsigned *CSRegs) {
 static bool isCSRestore(MachineInstr *MI, const unsigned *CSRegs) {
   return ((MI->getOpcode() == ARM::FLDD ||
            MI->getOpcode() == ARM::LDR  ||
-           MI->getOpcode() == ARM::tLDRspi) &&
+           MI->getOpcode() == ARM::tRestore) &&
           MI->getOperand(1).isFrameIndex() &&
           isCalleeSavedRegister(MI->getOperand(0).getReg(), CSRegs));
 }
index 3bb8695b3a387ff37254f496dc16dbc1bd06680b..6c2cb710ab30a4af204207ad4ca4760e28946800 100644 (file)
@@ -124,3 +124,20 @@ L12:
        .align 2
 L11:
        .long   642
+
+//===---------------------------------------------------------------------===//
+
+When spilling in thumb mode and the sp offset is too large to fit in the ldr /
+str offset field, we load the offset from a constpool entry and add it to sp:
+
+ldr r2, LCPI
+add r2, sp
+ldr r2, [r2]
+
+These instructions preserve the condition code which is important if the spill
+is between a cmp and a bcc instruction. However, we can use the (potentially)
+cheaper sequnce if we know it's ok to clobber the condition register.
+
+add r2, sp, #255 * 4
+add r2, #132
+ldr r2, [r2, #7 * 4]