diff options
author | Peter Trommler <ptrommler@acm.org> | 2016-08-31 15:18:06 -0400 |
---|---|---|
committer | Ben Gamari <ben@smart-cactus.org> | 2016-08-31 15:18:39 -0400 |
commit | 010b07aae082cb6b1f2a5db3deecc5997f6d9a6d (patch) | |
tree | 4fc3bdf3e0a9516944a018913504d418eb208330 /compiler/nativeGen | |
parent | 1ad770f599a00e8f8919f7fcf4cf00800fd4d9ed (diff) | |
download | haskell-010b07aae082cb6b1f2a5db3deecc5997f6d9a6d.tar.gz |
PPC NCG: Implement minimal stack frame header.
According to the ABI specifications a minimal stack frame consists
of a header and a minimum size parameter save area. We reserve the
minimal size for each ABI.
On PowerPC 64-bil Linux and AIX the parameter save area can accomodate
up to eight parameters. So calls with eight parameters and fewer
can be done without allocating a new stack frame and deallocating
that stack frame after the call. On AIX one additional spill slot
is available on the stack.
Code size for all nofib benchmarks is 0.3 % smaller on powerpc64.
Test Plan: validate on AIX
Reviewers: hvr!, erikd, austin, simonmar, bgamari
Reviewed By: bgamari
Subscribers: thomie
Differential Revision: https://phabricator.haskell.org/D2445
Diffstat (limited to 'compiler/nativeGen')
-rw-r--r-- | compiler/nativeGen/PPC/CodeGen.hs | 5 | ||||
-rw-r--r-- | compiler/nativeGen/PPC/Instr.hs | 30 |
2 files changed, 27 insertions, 8 deletions
diff --git a/compiler/nativeGen/PPC/CodeGen.hs b/compiler/nativeGen/PPC/CodeGen.hs index 1b719fc0f9..d03a6e5c23 100644 --- a/compiler/nativeGen/PPC/CodeGen.hs +++ b/compiler/nativeGen/PPC/CodeGen.hs @@ -1286,14 +1286,15 @@ genCCall' dflags gcp target dest_regs args spFormat = if target32Bit platform then II32 else II64 + -- TODO: Do not create a new stack frame if delta is too large. move_sp_down finalStack - | delta > 64 = + | delta > stackFrameHeaderSize dflags = toOL [STU spFormat sp (AddrRegImm sp (ImmInt (-delta))), DELTA (-delta)] | otherwise = nilOL where delta = stackDelta finalStack move_sp_up finalStack - | delta > 64 = -- TODO: fix-up stack back-chain + | delta > stackFrameHeaderSize dflags = toOL [ADD sp sp (RIImm (ImmInt delta)), DELTA 0] | otherwise = nilOL diff --git a/compiler/nativeGen/PPC/Instr.hs b/compiler/nativeGen/PPC/Instr.hs index 23d8b6b2e6..5dc0325dff 100644 --- a/compiler/nativeGen/PPC/Instr.hs +++ b/compiler/nativeGen/PPC/Instr.hs @@ -15,6 +15,7 @@ module PPC.Instr ( archWordFormat, RI(..), Instr(..), + stackFrameHeaderSize, maxSpillSlots, allocMoreStack, makeFarBranches @@ -508,7 +509,7 @@ ppc_mkSpillInstr ppc_mkSpillInstr dflags reg delta slot = let platform = targetPlatform dflags - off = spillSlotToOffset slot + off = spillSlotToOffset dflags slot arch = platformArch platform in let fmt = case targetClassOfReg platform reg of @@ -533,7 +534,7 @@ ppc_mkLoadInstr ppc_mkLoadInstr dflags reg delta slot = let platform = targetPlatform dflags - off = spillSlotToOffset slot + off = spillSlotToOffset dflags slot arch = platformArch platform in let fmt = case targetClassOfReg platform reg of @@ -549,6 +550,22 @@ ppc_mkLoadInstr dflags reg delta slot in instr fmt reg (AddrRegImm sp (ImmInt (off-delta))) +-- | The size of a minimal stackframe header including minimal +-- parameter save area. +stackFrameHeaderSize :: DynFlags -> Int +stackFrameHeaderSize dflags + = case platformOS platform of + OSLinux -> case platformArch platform of + -- header + parameter save area + ArchPPC -> 64 -- TODO: check ABI spec + ArchPPC_64 ELF_V1 -> 48 + 8 * 8 + ArchPPC_64 ELF_V2 -> 32 + 8 * 8 + _ -> panic "PPC.stackFrameHeaderSize: Unknown Linux" + OSAIX -> 24 + 8 * 4 + OSDarwin -> 64 -- TODO: check ABI spec + _ -> panic "PPC.stackFrameHeaderSize: not defined for this OS" + where platform = targetPlatform dflags + -- | The maximum number of bytes required to spill a register. PPC32 -- has 32-bit GPRs and 64-bit FPRs, while PPC64 has 64-bit GPRs and -- 64-bit FPRs. So the maximum is 8 regardless of platforms unlike @@ -560,7 +577,8 @@ spillSlotSize = 8 -- | The number of spill slots available without allocating more. maxSpillSlots :: DynFlags -> Int maxSpillSlots dflags - = ((rESERVED_C_STACK_BYTES dflags - 64) `div` spillSlotSize) - 1 + = ((rESERVED_C_STACK_BYTES dflags - stackFrameHeaderSize dflags) + `div` spillSlotSize) - 1 -- = 0 -- useful for testing allocMoreStack -- | The number of bytes that the stack pointer should be aligned @@ -570,9 +588,9 @@ stackAlign :: Int stackAlign = 16 -- | Convert a spill slot number to a *byte* offset, with no sign. -spillSlotToOffset :: Int -> Int -spillSlotToOffset slot - = 64 + spillSlotSize * slot +spillSlotToOffset :: DynFlags -> Int -> Int +spillSlotToOffset dflags slot + = stackFrameHeaderSize dflags + spillSlotSize * slot -------------------------------------------------------------------------------- |