From 6ed9284c2bcfb81fa0303409c6bd4366bc1e822a Mon Sep 17 00:00:00 2001 From: Jakob Stoklund Olesen Date: Tue, 9 Apr 2013 04:37:47 +0000 Subject: [PATCH] Compute correct frame sizes for SPARC v9 64-bit frames. The save area is twice as big and there is no struct return slot. The stack pointer is always 16-byte aligned (after adding the bias). Also eliminate the stack adjustment instructions around calls when the function has a reserved stack frame. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@179083 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Target/Sparc/SparcFrameLowering.cpp | 52 ++++++++++++++++++++------------- lib/Target/Sparc/SparcFrameLowering.h | 8 +++-- lib/Target/Sparc/SparcISelLowering.cpp | 5 ++-- test/CodeGen/SPARC/64abi.ll | 16 ++++++++++ 4 files changed, 56 insertions(+), 25 deletions(-) diff --git a/lib/Target/Sparc/SparcFrameLowering.cpp b/lib/Target/Sparc/SparcFrameLowering.cpp index a0dae6e9480..7874240f598 100644 --- a/lib/Target/Sparc/SparcFrameLowering.cpp +++ b/lib/Target/Sparc/SparcFrameLowering.cpp @@ -37,18 +37,27 @@ void SparcFrameLowering::emitPrologue(MachineFunction &MF) const { // Get the number of bytes to allocate from the FrameInfo int NumBytes = (int) MFI->getStackSize(); - // Emit the correct save instruction based on the number of bytes in - // the frame. Minimum stack frame size according to V8 ABI is: - // 16 words for register window spill - // 1 word for address of returned aggregate-value - // + 6 words for passing parameters on the stack - // ---------- - // 23 words * 4 bytes per word = 92 bytes - NumBytes += 92; + if (SubTarget.is64Bit()) { + // All 64-bit stack frames must be 16-byte aligned, and must reserve space + // for spilling the 16 window registers at %sp+BIAS..%sp+BIAS+128. + NumBytes += 128; + // Frames with calls must also reserve space for 6 outgoing arguments + // whether they are used or not. LowerCall_64 takes care of that. + assert(NumBytes % 16 == 0 && "Stack size not 16-byte aligned"); + } else { + // Emit the correct save instruction based on the number of bytes in + // the frame. Minimum stack frame size according to V8 ABI is: + // 16 words for register window spill + // 1 word for address of returned aggregate-value + // + 6 words for passing parameters on the stack + // ---------- + // 23 words * 4 bytes per word = 92 bytes + NumBytes += 92; - // Round up to next doubleword boundary -- a double-word boundary - // is required by the ABI. - NumBytes = (NumBytes + 7) & ~7; + // Round up to next doubleword boundary -- a double-word boundary + // is required by the ABI. + NumBytes = RoundUpToAlignment(NumBytes, 8); + } NumBytes = -NumBytes; if (NumBytes >= -4096) { @@ -70,15 +79,18 @@ void SparcFrameLowering::emitPrologue(MachineFunction &MF) const { void SparcFrameLowering:: eliminateCallFramePseudoInstr(MachineFunction &MF, MachineBasicBlock &MBB, MachineBasicBlock::iterator I) const { - MachineInstr &MI = *I; - DebugLoc dl = MI.getDebugLoc(); - int Size = MI.getOperand(0).getImm(); - if (MI.getOpcode() == SP::ADJCALLSTACKDOWN) - Size = -Size; - const SparcInstrInfo &TII = - *static_cast(MF.getTarget().getInstrInfo()); - if (Size) - BuildMI(MBB, I, dl, TII.get(SP::ADDri), SP::O6).addReg(SP::O6).addImm(Size); + if (!hasReservedCallFrame(MF)) { + MachineInstr &MI = *I; + DebugLoc DL = MI.getDebugLoc(); + int Size = MI.getOperand(0).getImm(); + if (MI.getOpcode() == SP::ADJCALLSTACKDOWN) + Size = -Size; + const SparcInstrInfo &TII = + *static_cast(MF.getTarget().getInstrInfo()); + if (Size) + BuildMI(MBB, I, DL, TII.get(SP::ADDri), SP::O6).addReg(SP::O6) + .addImm(Size); + } MBB.erase(I); } diff --git a/lib/Target/Sparc/SparcFrameLowering.h b/lib/Target/Sparc/SparcFrameLowering.h index 464233e7da3..c3756620161 100644 --- a/lib/Target/Sparc/SparcFrameLowering.h +++ b/lib/Target/Sparc/SparcFrameLowering.h @@ -22,10 +22,12 @@ namespace llvm { class SparcSubtarget; class SparcFrameLowering : public TargetFrameLowering { + const SparcSubtarget &SubTarget; public: - explicit SparcFrameLowering(const SparcSubtarget &/*sti*/) - : TargetFrameLowering(TargetFrameLowering::StackGrowsDown, 8, 0) { - } + explicit SparcFrameLowering(const SparcSubtarget &ST) + : TargetFrameLowering(TargetFrameLowering::StackGrowsDown, + ST.is64Bit() ? 16 : 8, 0, ST.is64Bit() ? 16 : 8), + SubTarget(ST) {} /// emitProlog/emitEpilog - These methods insert prolog and epilog code into /// the function. diff --git a/lib/Target/Sparc/SparcISelLowering.cpp b/lib/Target/Sparc/SparcISelLowering.cpp index eb01c5ef318..9dc5c1ffffd 100644 --- a/lib/Target/Sparc/SparcISelLowering.cpp +++ b/lib/Target/Sparc/SparcISelLowering.cpp @@ -912,8 +912,9 @@ SparcTargetLowering::LowerCall_64(TargetLowering::CallLoweringInfo &CLI, // Get the size of the outgoing arguments stack space requirement. // The stack offset computed by CC_Sparc64 includes all arguments. - // We always allocate space for 6 arguments in the prolog. - unsigned ArgsSize = std::max(6*8u, CCInfo.getNextStackOffset()) - 6*8u; + // Called functions expect 6 argument words to exist in the stack frame, used + // or not. + unsigned ArgsSize = std::max(6*8u, CCInfo.getNextStackOffset()); // Keep stack frames 16-byte aligned. ArgsSize = RoundUpToAlignment(ArgsSize, 16); diff --git a/test/CodeGen/SPARC/64abi.ll b/test/CodeGen/SPARC/64abi.ll index 10d8ff7c9ae..ec971357214 100644 --- a/test/CodeGen/SPARC/64abi.ll +++ b/test/CodeGen/SPARC/64abi.ll @@ -1,6 +1,9 @@ ; RUN: llc < %s -march=sparcv9 -disable-sparc-delay-filler | FileCheck %s ; CHECK: intarg +; The save/restore frame is not strictly necessary here, but we would need to +; refer to %o registers instead. +; CHECK: save %sp, -128, %sp ; CHECK: stb %i0, [%i4] ; CHECK: stb %i1, [%i4] ; CHECK: sth %i2, [%i4] @@ -11,6 +14,7 @@ ; CHECK: st [[R]], [%i4] ; CHECK: ldx [%fp+2231], [[R:%[gilo][0-7]]] ; CHECK: stx [[R]], [%i4] +; CHECK: restore define void @intarg(i8 %a0, ; %i0 i8 %a1, ; %i1 i16 %a2, ; %i2 @@ -34,18 +38,23 @@ define void @intarg(i8 %a0, ; %i0 } ; CHECK: call_intarg +; 16 saved + 8 args. +; CHECK: save %sp, -192, %sp ; Sign-extend and store the full 64 bits. ; CHECK: sra %i0, 0, [[R:%[gilo][0-7]]] ; CHECK: stx [[R]], [%sp+2223] ; Use %o0-%o5 for outgoing arguments ; CHECK: or %g0, 5, %o5 ; CHECK: call intarg +; CHECK-NOT: add %sp +; CHECK: restore define void @call_intarg(i32 %i0, i8* %i1) { call void @intarg(i8 0, i8 1, i16 2, i32 3, i8* undef, i32 5, i32 %i0, i8* %i1) ret void } ; CHECK: floatarg +; CHECK: save %sp, -128, %sp ; CHECK: fstod %f1, ; CHECK: faddd %f2, ; CHECK: faddd %f4, @@ -81,12 +90,15 @@ define double @floatarg(float %a0, ; %f1 } ; CHECK: call_floatarg +; CHECK: save %sp, -272, %sp ; Store 4 bytes, right-aligned in slot. ; CHECK: st %f1, [%sp+2307] ; Store 8 bytes in full slot. ; CHECK: std %f2, [%sp+2311] ; CHECK: fmovd %f2, %f4 ; CHECK: call floatarg +; CHECK-NOT: add %sp +; CHECK: restore define void @call_floatarg(float %f1, double %d2, float %f5, double *%p) { %r = call double @floatarg(float %f5, double %d2, double %d2, double %d2, float %f5, float %f5, float %f5, float %f5, @@ -127,6 +139,8 @@ define void @mixedarg(i8 %a0, ; %i0 ; CHECK: fmovd %f2, %f6 ; CHECK: fmovd %f2, %f16 ; CHECK: call mixedarg +; CHECK-NOT: add %sp +; CHECK: restore define void @call_mixedarg(i64 %i0, double %f2, i16* %i2) { call void @mixedarg(i8 undef, float undef, @@ -155,6 +169,8 @@ define i32 @inreg_fi(i32 inreg %a0, ; high bits of %i0 } ; CHECK: call_inreg_fi +; Allocate space for 6 arguments, even when only 2 are used. +; CHECK: save %sp, -176, %sp ; CHECK: sllx %i1, 32, %o0 ; CHECK: fmovs %f5, %f1 ; CHECK: call inreg_fi -- 2.11.0