[llvm] r306305 - [SystemZ] Fix missing emergency spill slot corner case

Ulrich Weigand via llvm-commits llvm-commits at lists.llvm.org
Mon Jun 26 09:50:33 PDT 2017


Author: uweigand
Date: Mon Jun 26 09:50:32 2017
New Revision: 306305

URL: http://llvm.org/viewvc/llvm-project?rev=306305&view=rev
Log:
[SystemZ] Fix missing emergency spill slot corner case

We sometimes need emergency spill slots for the register scavenger.
This may be the case when code needs to access a stack slot that
has an offset of 4096 or more relative to the stack pointer.

To make that determination, processFunctionBeforeFrameFinalized
currently simply checks the total stack frame size of the current
function.  But this is not enough, since code may need to access
stack slots in the caller's stack frame as well, in particular
incoming arguments stored on the stack.

This commit fixes the problem by taking argument slots into account.

Added:
    llvm/trunk/test/CodeGen/SystemZ/frame-21.ll
Modified:
    llvm/trunk/lib/Target/SystemZ/SystemZFrameLowering.cpp

Modified: llvm/trunk/lib/Target/SystemZ/SystemZFrameLowering.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/SystemZ/SystemZFrameLowering.cpp?rev=306305&r1=306304&r2=306305&view=diff
==============================================================================
--- llvm/trunk/lib/Target/SystemZ/SystemZFrameLowering.cpp (original)
+++ llvm/trunk/lib/Target/SystemZ/SystemZFrameLowering.cpp Mon Jun 26 09:50:32 2017
@@ -277,8 +277,21 @@ void SystemZFrameLowering::
 processFunctionBeforeFrameFinalized(MachineFunction &MF,
                                     RegScavenger *RS) const {
   MachineFrameInfo &MFFrame = MF.getFrameInfo();
-  uint64_t MaxReach = (MFFrame.estimateStackSize(MF) +
-                       SystemZMC::CallFrameSize * 2);
+  // Get the size of our stack frame to be allocated ...
+  uint64_t StackSize = (MFFrame.estimateStackSize(MF) +
+                        SystemZMC::CallFrameSize);
+  // ... and the maximum offset we may need to reach into the
+  // caller's frame to access the save area or stack arguments.
+  int64_t MaxArgOffset = SystemZMC::CallFrameSize;
+  for (int I = MFFrame.getObjectIndexBegin(); I != 0; ++I)
+    if (MFFrame.getObjectOffset(I) >= 0) {
+      int64_t ArgOffset = SystemZMC::CallFrameSize +
+                          MFFrame.getObjectOffset(I) +
+                          MFFrame.getObjectSize(I);
+      MaxArgOffset = std::max(MaxArgOffset, ArgOffset);
+    }
+
+  uint64_t MaxReach = StackSize + MaxArgOffset;
   if (!isUInt<12>(MaxReach)) {
     // We may need register scavenging slots if some parts of the frame
     // are outside the reach of an unsigned 12-bit displacement.

Added: llvm/trunk/test/CodeGen/SystemZ/frame-21.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/SystemZ/frame-21.ll?rev=306305&view=auto
==============================================================================
--- llvm/trunk/test/CodeGen/SystemZ/frame-21.ll (added)
+++ llvm/trunk/test/CodeGen/SystemZ/frame-21.ll Mon Jun 26 09:50:32 2017
@@ -0,0 +1,76 @@
+; Test the allocation of emergency spill slots.
+;
+; RUN: llc < %s -mtriple=s390x-linux-gnu | FileCheck %s
+
+; For frames of size less than 4096 - 2*160, no emercengy spill slot
+; is required.  Check the maximum such case.
+define void @f1(i64 %x) {
+; CHECK-LABEL: f1:
+; CHECK: stg %r2, 160(%r15)
+; CHECK: br %r14
+  %y = alloca [471 x i64], align 8
+  %ptr = getelementptr inbounds [471 x i64], [471 x i64]* %y, i64 0, i64 0
+  store volatile i64 %x, i64* %ptr
+  ret void
+}
+
+; If the frame size is at least 4096 - 2*160, we do need the emergency
+; spill slots.  Check the minimum such case.
+define void @f2(i64 %x) {
+; CHECK-LABEL: f2:
+; CHECK: stg %r2, 176(%r15)
+; CHECK: br %r14
+  %y = alloca [472 x i64], align 8
+  %ptr = getelementptr inbounds [472 x i64], [472 x i64]* %y, i64 0, i64 0
+  store volatile i64 %x, i64* %ptr
+  ret void
+}
+
+; However, if there are incoming stack arguments, those also need to be
+; in reach, so the maximum frame size without emergency spill slots is
+; 4096 - 2*160 - <size of incoming stack arguments>.  Check the maximum
+; case where we still need no emergency spill slots ...
+define void @f3(i64 %x, i64 %r3, i64 %r4, i64 %r5, i64 %r6, i64 %stack) {
+; CHECK-LABEL: f3:
+; CHECK: stg %r2, 160(%r15)
+; CHECK: br %r14
+  %y = alloca [470 x i64], align 8
+  %ptr = getelementptr inbounds [470 x i64], [470 x i64]* %y, i64 0, i64 0
+  store volatile i64 %x, i64* %ptr
+  ret void
+}
+
+; ... and the minimum case where we do.
+define void @f4(i64 %x, i64 %r3, i64 %r4, i64 %r5, i64 %r6, i64 %stack) {
+; CHECK-LABEL: f4:
+; CHECK: stg %r2, 176(%r15)
+; CHECK: br %r14
+  %y = alloca [471 x i64], align 8
+  %ptr = getelementptr inbounds [471 x i64], [471 x i64]* %y, i64 0, i64 0
+  store volatile i64 %x, i64* %ptr
+  ret void
+}
+
+; Try again for the case of two stack arguments.
+; Check the maximum case where we still need no emergency spill slots ...
+define void @f5(i64 %x, i64 %r3, i64 %r4, i64 %r5, i64 %r6, i64 %stack1, i64 %stack2) {
+; CHECK-LABEL: f5:
+; CHECK: stg %r2, 160(%r15)
+; CHECK: br %r14
+  %y = alloca [469 x i64], align 8
+  %ptr = getelementptr inbounds [469 x i64], [469 x i64]* %y, i64 0, i64 0
+  store volatile i64 %x, i64* %ptr
+  ret void
+}
+
+; ... and the minimum case where we do.
+define void @f6(i64 %x, i64 %r3, i64 %r4, i64 %r5, i64 %r6, i64 %stack1, i64 %stack2) {
+; CHECK-LABEL: f6:
+; CHECK: stg %r2, 176(%r15)
+; CHECK: br %r14
+  %y = alloca [470 x i64], align 8
+  %ptr = getelementptr inbounds [470 x i64], [470 x i64]* %y, i64 0, i64 0
+  store volatile i64 %x, i64* %ptr
+  ret void
+}
+




More information about the llvm-commits mailing list