aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJakob Stoklund Olesen <stoklund@2pi.dk>2013-04-09 04:37:47 +0000
committerJakob Stoklund Olesen <stoklund@2pi.dk>2013-04-09 04:37:47 +0000
commit6ed9284c2bcfb81fa0303409c6bd4366bc1e822a (patch)
treef1d8a9b711712b4b8c63f4c199e5ae892f7c52b8
parent8faf7df1447ca6ea4a3ff8f82789923d1839fb54 (diff)
downloadexternal_llvm-6ed9284c2bcfb81fa0303409c6bd4366bc1e822a.zip
external_llvm-6ed9284c2bcfb81fa0303409c6bd4366bc1e822a.tar.gz
external_llvm-6ed9284c2bcfb81fa0303409c6bd4366bc1e822a.tar.bz2
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
-rw-r--r--lib/Target/Sparc/SparcFrameLowering.cpp52
-rw-r--r--lib/Target/Sparc/SparcFrameLowering.h8
-rw-r--r--lib/Target/Sparc/SparcISelLowering.cpp5
-rw-r--r--test/CodeGen/SPARC/64abi.ll16
4 files changed, 56 insertions, 25 deletions
diff --git a/lib/Target/Sparc/SparcFrameLowering.cpp b/lib/Target/Sparc/SparcFrameLowering.cpp
index a0dae6e..7874240 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<const SparcInstrInfo*>(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<const SparcInstrInfo*>(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 464233e..c375662 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 eb01c5e..9dc5c1f 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 10d8ff7..ec97135 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