[PPC] Claim stack frame before storing into it, if no red zone is present
authorKrzysztof Parzyszek <kparzysz@codeaurora.org>
Tue, 6 Sep 2016 12:30:00 +0000 (12:30 +0000)
committerKrzysztof Parzyszek <kparzysz@codeaurora.org>
Tue, 6 Sep 2016 12:30:00 +0000 (12:30 +0000)
Unlike PPC64, PPC32/SVRV4 does not have red zone. In the absence of it
there is no guarantee that this part of the stack will not be modified
by any interrupt. To avoid this, make sure to claim the stack frame first
before storing into it.

This fixes https://llvm.org/bugs/show_bug.cgi?id=26519.

Differential Revision: https://reviews.llvm.org/D24093

llvm-svn: 280705

llvm/lib/Target/PowerPC/PPCFrameLowering.cpp
llvm/test/CodeGen/PowerPC/crsave.ll
llvm/test/CodeGen/PowerPC/empty-functions.ll
llvm/test/CodeGen/PowerPC/ppc32-pic-large.ll
llvm/test/CodeGen/PowerPC/ppc32-pic.ll
llvm/test/CodeGen/PowerPC/stack-realign.ll

index c59c619..614a7f8 100644 (file)
@@ -672,8 +672,9 @@ PPCFrameLowering::twoUniqueScratchRegsRequired(MachineBasicBlock *MBB) const {
   bool IsLargeFrame = !isInt<16>(NegFrameSize);
   MachineFrameInfo &MFI = MF.getFrameInfo();
   unsigned MaxAlign = MFI.getMaxAlignment();
+  bool HasRedZone = Subtarget.isPPC64() || !Subtarget.isSVR4ABI();
 
-  return IsLargeFrame && HasBP && MaxAlign > 1;
+  return (IsLargeFrame || !HasRedZone) && HasBP && MaxAlign > 1;
 }
 
 bool PPCFrameLowering::canUseAsPrologue(const MachineBasicBlock &MBB) const {
@@ -742,6 +743,7 @@ void PPCFrameLowering::emitPrologue(MachineFunction &MF,
   // Do we have a frame pointer and/or base pointer for this function?
   bool HasFP = hasFP(MF);
   bool HasBP = RegInfo->hasBasePointer(MF);
+  bool HasRedZone = isPPC64 || !isSVR4ABI;
 
   unsigned SPReg       = isPPC64 ? PPC::X1  : PPC::R1;
   unsigned BPReg       = RegInfo->getBaseRegister(MF);
@@ -876,54 +878,57 @@ void PPCFrameLowering::emitPrologue(MachineFunction &MF,
       MIB.addReg(MustSaveCRs[i], CrState);
   }
 
-  if (HasFP)
-    // FIXME: On PPC32 SVR4, we must not spill before claiming the stackframe.
-    BuildMI(MBB, MBBI, dl, StoreInst)
-      .addReg(FPReg)
-      .addImm(FPOffset)
-      .addReg(SPReg);
-
-  if (FI->usesPICBase())
-    // FIXME: On PPC32 SVR4, we must not spill before claiming the stackframe.
-    BuildMI(MBB, MBBI, dl, StoreInst)
-      .addReg(PPC::R30)
-      .addImm(PBPOffset)
-      .addReg(SPReg);
-
-  if (HasBP)
-    // FIXME: On PPC32 SVR4, we must not spill before claiming the stackframe.
-    BuildMI(MBB, MBBI, dl, StoreInst)
-      .addReg(BPReg)
-      .addImm(BPOffset)
-      .addReg(SPReg);
+  if (HasRedZone) {
+    if (HasFP)
+      BuildMI(MBB, MBBI, dl, StoreInst)
+        .addReg(FPReg)
+        .addImm(FPOffset)
+        .addReg(SPReg);
+    if (FI->usesPICBase())
+      BuildMI(MBB, MBBI, dl, StoreInst)
+        .addReg(PPC::R30)
+        .addImm(PBPOffset)
+        .addReg(SPReg);
+    if (HasBP)
+      BuildMI(MBB, MBBI, dl, StoreInst)
+        .addReg(BPReg)
+        .addImm(BPOffset)
+        .addReg(SPReg);
+  }
 
   if (MustSaveLR)
-    // FIXME: On PPC32 SVR4, we must not spill before claiming the stackframe.
     BuildMI(MBB, MBBI, dl, StoreInst)
       .addReg(ScratchReg, getKillRegState(true))
       .addImm(LROffset)
       .addReg(SPReg);
 
   if (MustSaveCR &&
-      !(SingleScratchReg && MustSaveLR)) // will only occur for PPC64
+      !(SingleScratchReg && MustSaveLR)) { // will only occur for PPC64
+    assert(HasRedZone && "A red zone is always available on PPC64");
     BuildMI(MBB, MBBI, dl, TII.get(PPC::STW8))
       .addReg(TempReg, getKillRegState(true))
       .addImm(8)
       .addReg(SPReg);
+  }
 
   // Skip the rest if this is a leaf function & all spills fit in the Red Zone.
-  if (!FrameSize) return;
+  if (!FrameSize)
+    return;
 
   // Adjust stack pointer: r1 += NegFrameSize.
   // If there is a preferred stack alignment, align R1 now
 
-  if (HasBP) {
+  if (HasBP && HasRedZone) {
     // Save a copy of r1 as the base pointer.
     BuildMI(MBB, MBBI, dl, OrInst, BPReg)
       .addReg(SPReg)
       .addReg(SPReg);
   }
 
+  // Have we generated a STUX instruction to claim stack frame? If so,
+  // the frame size will be placed in ScratchReg.
+  bool HasSTUX = false;
+
   // This condition must be kept in sync with canUseAsPrologue.
   if (HasBP && MaxAlign > 1) {
     if (isPPC64)
@@ -952,10 +957,12 @@ void PPCFrameLowering::emitPrologue(MachineFunction &MF,
         .addReg(ScratchReg, RegState::Kill)
         .addReg(TempReg, RegState::Kill);
     }
+
     BuildMI(MBB, MBBI, dl, StoreUpdtIdxInst, SPReg)
       .addReg(SPReg, RegState::Kill)
       .addReg(SPReg)
       .addReg(ScratchReg);
+    HasSTUX = true;
 
   } else if (!isLargeFrame) {
     BuildMI(MBB, MBBI, dl, StoreUpdtInst, SPReg)
@@ -973,6 +980,65 @@ void PPCFrameLowering::emitPrologue(MachineFunction &MF,
       .addReg(SPReg, RegState::Kill)
       .addReg(SPReg)
       .addReg(ScratchReg);
+    HasSTUX = true;
+  }
+
+  if (!HasRedZone) {
+    assert(!isPPC64 && "A red zone is always available on PPC64");
+    if (HasSTUX) {
+      // The frame size is in ScratchReg, and the SPReg has been advanced
+      // (downwards) by the frame size: SPReg = old SPReg + ScratchReg.
+      // Set ScratchReg to the original SPReg: ScratchReg = SPReg - ScratchReg.
+      BuildMI(MBB, MBBI, dl, TII.get(PPC::SUBF), ScratchReg)
+        .addReg(ScratchReg, RegState::Kill)
+        .addReg(SPReg);
+
+      // Now that the stack frame has been allocated, save all the necessary
+      // registers using ScratchReg as the base address.
+      if (HasFP)
+        BuildMI(MBB, MBBI, dl, StoreInst)
+          .addReg(FPReg)
+          .addImm(FPOffset)
+          .addReg(ScratchReg);
+      if (FI->usesPICBase())
+        BuildMI(MBB, MBBI, dl, StoreInst)
+          .addReg(PPC::R30)
+          .addImm(PBPOffset)
+          .addReg(ScratchReg);
+      if (HasBP) {
+        BuildMI(MBB, MBBI, dl, StoreInst)
+          .addReg(BPReg)
+          .addImm(BPOffset)
+          .addReg(ScratchReg);
+        BuildMI(MBB, MBBI, dl, OrInst, BPReg)
+          .addReg(ScratchReg, RegState::Kill)
+          .addReg(ScratchReg);
+      }
+    } else {
+      // The frame size is a known 16-bit constant (fitting in the immediate
+      // field of STWU). To be here we have to be compiling for PPC32.
+      // Since the SPReg has been decreased by FrameSize, add it back to each
+      // offset.
+      if (HasFP)
+        BuildMI(MBB, MBBI, dl, StoreInst)
+          .addReg(FPReg)
+          .addImm(FrameSize + FPOffset)
+          .addReg(SPReg);
+      if (FI->usesPICBase())
+        BuildMI(MBB, MBBI, dl, StoreInst)
+          .addReg(PPC::R30)
+          .addImm(FrameSize + PBPOffset)
+          .addReg(SPReg);
+      if (HasBP) {
+        BuildMI(MBB, MBBI, dl, StoreInst)
+          .addReg(BPReg)
+          .addImm(FrameSize + BPOffset)
+          .addReg(SPReg);
+        BuildMI(MBB, MBBI, dl, TII.get(PPC::ADDI), BPReg)
+          .addReg(SPReg)
+          .addImm(FrameSize);
+      }
+    }
   }
 
   // Add Call Frame Information for the instructions we generated above.
index a079e7f..d7be2fd 100644 (file)
@@ -14,8 +14,9 @@ entry:
   ret i32 %1
 }
 
-; PPC32: stw 31, -4(1)
+; PPC32-LABEL: test_cr2:
 ; PPC32: stwu 1, -32(1)
+; PPC32: stw 31, 28(1)
 ; PPC32: mfcr 12
 ; PPC32-NEXT: stw 12, 24(31)
 ; PPC32: lwz 12, 24(31)
@@ -43,8 +44,9 @@ entry:
   ret i32 %1
 }
 
-; PPC32: stw 31, -4(1)
+; PPC32-LABEL: test_cr234:
 ; PPC32: stwu 1, -32(1)
+; PPC32: stw 31, 28(1)
 ; PPC32: mfcr 12
 ; PPC32-NEXT: stw 12, 24(31)
 ; PPC32: lwz 12, 24(31)
index 5f7a151..56db8f3 100644 (file)
@@ -31,8 +31,8 @@ entry:
 ; LINUX-FP-NEXT: {{^}}.L[[BEGIN:.*]]:{{$}}
 ; LINUX-FP-NEXT: .cfi_startproc
 ; LINUX-FP-NEXT: {{^}}#
-; LINUX-FP-NEXT: stw 31, -4(1)
 ; LINUX-FP-NEXT: stwu 1, -16(1)
+; LINUX-FP-NEXT: stw 31, 12(1)
 ; LINUX-FP-NEXT: {{^}}.L{{.*}}:{{$}}
 ; LINUX-FP-NEXT:  .cfi_def_cfa_offset 16
 ; LINUX-FP-NEXT: {{^}}.L{{.*}}:{{$}}
index bc1d0a5..dbfbc1c 100644 (file)
@@ -15,7 +15,8 @@ entry:
 ; LARGE-BSS:       [[POFF:\.L[0-9]+\$poff]]:
 ; LARGE-BSS-NEXT:    .long .LTOC-[[PB:\.L[0-9]+\$pb]]
 ; LARGE-BSS-NEXT:  foo:
-; LARGE-BSS:         stw 30, -8(1)
+; LARGE-BSS:         stwu 1, -32(1)
+; LARGE-BSS:         stw 30, 24(1)
 ; LARGE-BSS:         bl [[PB]]
 ; LARGE-BSS-NEXT:  [[PB]]:
 ; LARGE-BSS:         mflr 30
index 63f521c..5c33233 100644 (file)
@@ -13,8 +13,8 @@ entry:
 !llvm.module.flags = !{!0}
 !0 = !{i32 1, !"PIC Level", i32 1}
 ; SMALL-BSS-LABEL:foo:
-; SMALL-BSS:         stw 30, -8(1)
 ; SMALL-BSS:         stwu 1, -32(1)
+; SMALL-BSS:         stw 30, 24(1)
 ; SMALL-BSS:         bl _GLOBAL_OFFSET_TABLE_@local-4
 ; SMALL-BSS:         mflr 30
 ; SMALL-BSS-DAG:     stw {{[0-9]+}}, 8(1)
index 1c93d66..00cd61d 100644 (file)
@@ -77,22 +77,24 @@ entry:
 ; CHECK-FP: blr
 
 ; CHECK-32-LABEL: @goo
-; CHECK-32-DAG: mflr {{[0-9]+}}
+; CHECK-32-DAG: mflr [[LR:[0-9]+]]
 ; CHECK-32-DAG: clrlwi [[REG:[0-9]+]], 1, 27
-; CHECK-32-DAG: stw 30, -8(1)
-; CHECK-32-DAG: mr 30, 1
-; CHECK-32-DAG: stw 0, 4(1)
+; CHECK-32-DAG: stw [[LR]], 4(1)
 ; CHECK-32-DAG: subfic 0, [[REG]], -64
 ; CHECK-32: stwux 1, 1, 0
+; CHECK-32: subf 0, 0, 1
+; CHECK-32: stw 30, -8(0)
+; CHECK-32: mr 30, 0
 
 ; CHECK-32-PIC-LABEL: @goo
-; CHECK-32-PIC-DAG: mflr {{[0-9]+}}
+; CHECK-32-PIC-DAG: mflr [[LR:[0-9]+]]
 ; CHECK-32-PIC-DAG: clrlwi [[REG:[0-9]+]], 1, 27
-; CHECK-32-PIC-DAG: stw 29, -12(1)
-; CHECK-32-PIC-DAG: mr 29, 1
-; CHECK-32-PIC-DAG: stw 0, 4(1)
+; CHECK-32-PIC-DAG: stw [[LR]], 4(1)
 ; CHECK-32-PIC-DAG: subfic 0, [[REG]], -64
 ; CHECK-32-PIC: stwux 1, 1, 0
+; CHECK-32-PIC: subf 0, 0, 1
+; CHECK-32-PIC: stw 29, -12(0)
+; CHECK-32-PIC-DAG: mr 29, 0
 
 ; The large-frame-size case.
 define void @hoo(%struct.s* byval nocapture readonly %a) {
@@ -130,13 +132,15 @@ entry:
 
 ; CHECK-32-DAG: lis [[REG1:[0-9]+]], -13
 ; CHECK-32-DAG: clrlwi [[REG3:[0-9]+]], 1, 27
-; CHECK-32-DAG: mflr {{[0-9]+}}
+; CHECK-32-DAG: mflr [[LR:[0-9]+]]
 ; CHECK-32-DAG: ori [[REG2:[0-9]+]], [[REG1]], 51904
-; CHECK-32-DAG: stw 30, -8(1)
-; CHECK-32-DAG: mr 30, 1
-; CHECK-32-DAG: stw 0, 4(1)
+; CHECK-32-DAG: stw [[LR]], 4(1)
 ; CHECK-32-DAG: subfc 0, [[REG3]], [[REG2]]
-; CHECK-32: stwux 1, 1, 0
+; CHECK-32:     stwux 1, 1, 0
+; CHECK-32:     subf 0, 0, 1
+; CHECK-32-DAG: stw 31, -4(0)
+; CHECK-32-DAG: stw 30, -8(0)
+; CHECK-32: mr 30, 0
 
 ; CHECK-32: blr
 
@@ -146,11 +150,12 @@ entry:
 ; CHECK-32-PIC-DAG: clrlwi [[REG3:[0-9]+]], 1, 27
 ; CHECK-32-PIC-DAG: mflr {{[0-9]+}}
 ; CHECK-32-PIC-DAG: ori [[REG2:[0-9]+]], [[REG1]], 51904
-; CHECK-32-PIC-DAG: stw 29, -12(1)
-; CHECK-32-PIC-DAG: mr 29, 1
 ; CHECK-32-PIC-DAG: stw 0, 4(1)
 ; CHECK-32-PIC-DAG: subfc 0, [[REG3]], [[REG2]]
-; CHECK-32: stwux 1, 1, 0
+; CHECK-32-PIC: stwux 1, 1, 0
+; CHECK-32-PIC: stw 29, -12(0)
+; CHECK-32-PIC: subf 0, 0, 1
+; CHECK-32-PIC: mr 29, 0
 
 ; CHECK-32: blr