ARMFrameLowering: Only set ExtraCSSpill for actually unused registers.
authorMatthias Braun <matze@braunis.de>
Fri, 28 Jul 2017 01:36:32 +0000 (01:36 +0000)
committerMatthias Braun <matze@braunis.de>
Fri, 28 Jul 2017 01:36:32 +0000 (01:36 +0000)
The code assumed that unclobbered/unspilled callee saved registers are
unused in the function. This is not true for callee saved registers that are
also used to pass parameters such as swiftself.

rdar://33401922

llvm-svn: 309350

llvm/lib/Target/ARM/ARMFrameLowering.cpp
llvm/test/CodeGen/ARM/pei-swiftself.mir [new file with mode: 0644]

index b204faa..12e6e32 100644 (file)
@@ -1743,7 +1743,6 @@ void ARMFrameLowering::determineCalleeSaves(MachineFunction &MF,
     (MFI.adjustsStack() && !canSimplifyCallFramePseudos(MF)) ||
     // For large argument stacks fp relative addressed may overflow.
     (HasFP && (MaxFixedOffset - MaxFPOffset) >= (int)EstimatedRSStackSizeLimit);
-  bool ExtraCSSpill = false;
   if (BigFrameOffsets ||
       !CanEliminateFrame || RegInfo->cannotEliminateFrame(MF)) {
     AFI->setHasStackFrame(true);
@@ -1768,6 +1767,10 @@ void ARMFrameLowering::determineCalleeSaves(MachineFunction &MF,
         CS1Spilled = true;
     }
 
+    // This is true when we inserted a spill for an unused register that can now
+    // be used for register scavenging.
+    bool ExtraCSSpill = false;
+
     if (AFI->isThumb1OnlyFunction()) {
       // For Thumb1-only targets, we need some low registers when we save and
       // restore the high registers (which aren't allocatable, but could be
@@ -1870,7 +1873,9 @@ void ARMFrameLowering::determineCalleeSaves(MachineFunction &MF,
         SavedRegs.set(Reg);
         NumGPRSpills++;
         CS1Spilled = true;
-        ExtraCSSpill = true;
+        assert(!MRI.isReserved(Reg) && "Should not be reserved");
+        if (!MRI.isPhysRegUsed(Reg))
+          ExtraCSSpill = true;
         UnspilledCS1GPRs.erase(llvm::find(UnspilledCS1GPRs, Reg));
         if (Reg == ARM::LR)
           LRSpilled = true;
@@ -1889,7 +1894,8 @@ void ARMFrameLowering::determineCalleeSaves(MachineFunction &MF,
         UnspilledCS1GPRs.erase(LRPos);
 
       ForceLRSpill = false;
-      ExtraCSSpill = true;
+      if (!MRI.isReserved(ARM::LR) && !MRI.isPhysRegUsed(ARM::LR))
+        ExtraCSSpill = true;
     }
 
     // If stack and double are 8-byte aligned and we are spilling an odd number
@@ -1909,7 +1915,7 @@ void ARMFrameLowering::determineCalleeSaves(MachineFunction &MF,
             SavedRegs.set(Reg);
             DEBUG(dbgs() << "Spilling " << PrintReg(Reg, TRI)
                          << " to make up alignment\n");
-            if (!MRI.isReserved(Reg))
+            if (!MRI.isReserved(Reg) && !MRI.isPhysRegUsed(Reg))
               ExtraCSSpill = true;
             break;
           }
@@ -1919,7 +1925,7 @@ void ARMFrameLowering::determineCalleeSaves(MachineFunction &MF,
         SavedRegs.set(Reg);
         DEBUG(dbgs() << "Spilling " << PrintReg(Reg, TRI)
                      << " to make up alignment\n");
-        if (!MRI.isReserved(Reg))
+        if (!MRI.isReserved(Reg) && !MRI.isPhysRegUsed(Reg))
           ExtraCSSpill = true;
       }
     }
@@ -1955,11 +1961,14 @@ void ARMFrameLowering::determineCalleeSaves(MachineFunction &MF,
           }
         }
       }
-      if (Extras.size() && NumExtras == 0) {
-        for (unsigned i = 0, e = Extras.size(); i != e; ++i) {
-          SavedRegs.set(Extras[i]);
+      if (NumExtras == 0) {
+        for (unsigned Reg : Extras) {
+          SavedRegs.set(Reg);
+          if (!MRI.isPhysRegUsed(Reg))
+            ExtraCSSpill = true;
         }
-      } else if (!AFI->isThumb1OnlyFunction()) {
+      }
+      if (!ExtraCSSpill && !AFI->isThumb1OnlyFunction()) {
         // note: Thumb1 functions spill to R12, not the stack.  Reserve a slot
         // closest to SP or frame pointer.
         assert(RS && "Register scavenging not provided");
diff --git a/llvm/test/CodeGen/ARM/pei-swiftself.mir b/llvm/test/CodeGen/ARM/pei-swiftself.mir
new file mode 100644 (file)
index 0000000..055efee
--- /dev/null
@@ -0,0 +1,60 @@
+# RUN: llc -o - %s -mtriple=arm-- -run-pass prologepilog | FileCheck %s
+--- |
+  define swiftcc i8* @need_emergency_slot(i8 *swiftself %v) {
+    ; Just a dummy to add a swiftself bit. The real code is in the MI below.
+    unreachable
+  }
+...
+---
+# CHECK-LABEL: name: need_emergency_slot
+# Make sure we do not just assume an unsaved/restored callee saved register
+# is free to use. Callee saved parameters may still be used if they were used
+# to pass arguments (as in swiftself).
+name: need_emergency_slot
+tracksRegLiveness: true
+stack:
+  - { id: 0, type: default, size: 8, alignment: 8 }
+  - { id: 1, type: default, size: 4096, alignment: 8 }
+body: |
+  bb.0:
+    liveins: %r10   ; swiftself parameter comes in as %r10
+
+    ; Bring up register pressure to force emergency spilling, coax scavenging
+    ; to use %r10 as that one is not spilled/restored.
+    %r0 = IMPLICIT_DEF
+    %r1 = IMPLICIT_DEF
+    %r2 = IMPLICIT_DEF
+    %r3 = IMPLICIT_DEF
+    %r4 = IMPLICIT_DEF
+    %r5 = IMPLICIT_DEF
+    %r6 = IMPLICIT_DEF
+    %r7 = IMPLICIT_DEF
+    %r8 = IMPLICIT_DEF
+    %r9 = IMPLICIT_DEF
+    %r11 = IMPLICIT_DEF
+    %r12 = IMPLICIT_DEF
+    %lr = IMPLICIT_DEF
+
+    ; Computing the large stack offset requires an extra register. We should
+    ; not just use %r10 for that.
+    ; CHECK-NOT: STRi12 %1,{{.*}}%r10
+
+    STRi12 %r1, %stack.0, 0, 14, _ :: (store 4)
+
+    ; use the swiftself parameter value.
+    KILL %r10
+
+    KILL %r0
+    KILL %r1
+    KILL %r2
+    KILL %r3
+    KILL %r4
+    KILL %r5
+    KILL %r6
+    KILL %r7
+    KILL %r8
+    KILL %r9
+    KILL %r11
+    KILL %r12
+    KILL %lr
+...