[commit: ghc] master: PPC NCG: Implement minimal stack frame header. (010b07a)
git at git.haskell.org
git at git.haskell.org
Wed Aug 31 19:56:23 UTC 2016
Repository : ssh://git@git.haskell.org/ghc
On branch : master
Link : http://ghc.haskell.org/trac/ghc/changeset/010b07aae082cb6b1f2a5db3deecc5997f6d9a6d/ghc
>---------------------------------------------------------------
commit 010b07aae082cb6b1f2a5db3deecc5997f6d9a6d
Author: Peter Trommler <ptrommler at acm.org>
Date: Wed Aug 31 15:18:06 2016 -0400
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
>---------------------------------------------------------------
010b07aae082cb6b1f2a5db3deecc5997f6d9a6d
compiler/nativeGen/PPC/CodeGen.hs | 5 +++--
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 1b719fc..d03a6e5 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 23d8b6b..5dc0325 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
--------------------------------------------------------------------------------
More information about the ghc-commits
mailing list