diff options
author | Sebastian Graf <sebastian.graf@kit.edu> | 2019-02-19 13:52:11 +0100 |
---|---|---|
committer | Marge Bot <ben+marge-bot@smart-cactus.org> | 2019-03-07 20:44:08 -0500 |
commit | 1675d40afe07b9c414eaa37d85819f37f8420118 (patch) | |
tree | 0e0fe32fdf1a70a90e2c531a89b0a16b07fbad20 /compiler/stranal | |
parent | 068b7e983f4a0b35f453aa5e609998efd0c3f334 (diff) | |
download | haskell-1675d40afe07b9c414eaa37d85819f37f8420118.tar.gz |
Always do the worker/wrapper split for NOINLINEs
Trac #10069 revealed that small NOINLINE functions didn't get split
into worker and wrapper. This was due to `certainlyWillInline`
saying that any unfoldings with a guidance of `UnfWhen` inline
unconditionally. That isn't the case for NOINLINE functions, so we
catch this case earlier now.
Nofib results:
--------------------------------------------------------------------------------
Program Allocs Instrs
--------------------------------------------------------------------------------
fannkuch-redux -0.3% 0.0%
gg +0.0% +0.1%
maillist -0.2% -0.2%
minimax 0.0% -0.8%
--------------------------------------------------------------------------------
Min -0.3% -0.8%
Max +0.0% +0.1%
Geometric Mean -0.0% -0.0%
Fixes #10069.
-------------------------
Metric Increase:
T9233
-------------------------
Diffstat (limited to 'compiler/stranal')
-rw-r--r-- | compiler/stranal/WorkWrap.hs | 31 |
1 files changed, 31 insertions, 0 deletions
diff --git a/compiler/stranal/WorkWrap.hs b/compiler/stranal/WorkWrap.hs index 34cfd64ecd..8f34b3b2ec 100644 --- a/compiler/stranal/WorkWrap.hs +++ b/compiler/stranal/WorkWrap.hs @@ -242,6 +242,37 @@ NOINLINE pragma to the worker. (See Trac #13143 for a real-world example.) +It is crucial that we do this for *all* NOINLINE functions. Trac #10069 +demonstrates what happens when we promise to w/w a (NOINLINE) leaf function, but +fail to deliver: + + data C = C Int# Int# + + {-# NOINLINE c1 #-} + c1 :: C -> Int# + c1 (C _ n) = n + + {-# NOINLINE fc #-} + fc :: C -> Int# + fc c = 2 *# c1 c + +Failing to w/w `c1`, but still w/wing `fc` leads to the following code: + + c1 :: C -> Int# + c1 (C _ n) = n + + $wfc :: Int# -> Int# + $wfc n = let c = C 0# n in 2 #* c1 c + + fc :: C -> Int# + fc (C _ n) = $wfc n + +Yikes! The reboxed `C` in `$wfc` can't cancel out, so we are in a bad place. +This generalises to any function that derives its strictness signature from +its callees, so we have to make sure that when a function announces particular +strictness properties, we have to w/w them accordingly, even if it means +splitting a NOINLINE function. + Note [Worker activation] ~~~~~~~~~~~~~~~~~~~~~~~~ Follows on from Note [Worker-wrapper for INLINABLE functions] |