Index: lib/Target/PowerPC/PPCFrameLowering.cpp =================================================================== --- lib/Target/PowerPC/PPCFrameLowering.cpp +++ lib/Target/PowerPC/PPCFrameLowering.cpp @@ -672,8 +672,9 @@ 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 @@ // 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 @@ 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); 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 @@ .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 @@ .addReg(SPReg, RegState::Kill) .addReg(SPReg) .addReg(ScratchReg); + HasSTUX = true; + } + + if (!HasRedZone) { + assert(!isPPC64); + 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: test/CodeGen/PowerPC/crsave.ll =================================================================== --- test/CodeGen/PowerPC/crsave.ll +++ test/CodeGen/PowerPC/crsave.ll @@ -14,8 +14,9 @@ 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 @@ 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: test/CodeGen/PowerPC/empty-functions.ll =================================================================== --- test/CodeGen/PowerPC/empty-functions.ll +++ test/CodeGen/PowerPC/empty-functions.ll @@ -31,8 +31,8 @@ ; 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: test/CodeGen/PowerPC/ppc32-pic-large.ll =================================================================== --- test/CodeGen/PowerPC/ppc32-pic-large.ll +++ test/CodeGen/PowerPC/ppc32-pic-large.ll @@ -15,7 +15,8 @@ ; 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: test/CodeGen/PowerPC/ppc32-pic.ll =================================================================== --- test/CodeGen/PowerPC/ppc32-pic.ll +++ test/CodeGen/PowerPC/ppc32-pic.ll @@ -13,8 +13,8 @@ !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: test/CodeGen/PowerPC/stack-realign.ll =================================================================== --- test/CodeGen/PowerPC/stack-realign.ll +++ test/CodeGen/PowerPC/stack-realign.ll @@ -77,22 +77,24 @@ ; 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 @@ ; 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: subf 0, 0, 1 +; CHECK-32: stw 31, -4(0) +; CHECK-32: stw 30, -8(0) +; CHECK-32: mr 30, 0 ; CHECK-32: blr @@ -146,11 +150,12 @@ ; 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