diff options
author | Eric Seidel <eric@seidel.io> | 2017-02-05 21:29:37 -0500 |
---|---|---|
committer | Ben Gamari <ben@smart-cactus.org> | 2017-02-05 22:54:17 -0500 |
commit | b572aadb20c2e41e2f6d7b48401bd0b4239ce9f8 (patch) | |
tree | a6c361cf7e66128ecc0e248652f9e7dff11e186a /testsuite/timeout | |
parent | a9754e3cfa71f5d346b5d6e88fbb2324b57a7421 (diff) | |
download | haskell-b572aadb20c2e41e2f6d7b48401bd0b4239ce9f8.tar.gz |
Do Worker/Wrapper for NOINLINE things
Disabling worker/wrapper for NOINLINE things can cause unnecessary
reboxing of values. Consider
{-# NOINLINE f #-}
f :: Int -> a
f x = error (show x)
g :: Bool -> Bool -> Int -> Int
g True True p = f p
g False True p = p + 1
g b False p = g b True p
the strictness analysis will discover f and g are strict, but because f
has no wrapper, the worker for g will rebox p. So we get
$wg x y p# =
let p = I# p# in -- Yikes! Reboxing!
case x of
False ->
case y of
False -> $wg False True p#
True -> +# p# 1#
True ->
case y of
False -> $wg True True p#
True -> case f p of { }
g x y p = case p of (I# p#) -> $wg x y p#
Now, in this case the reboxing will float into the True branch, an so
the allocation will only happen on the error path. But it won't float
inwards if there are multiple branches that call (f p), so the reboxing
will happen on every call of g. Disaster.
Solution: do worker/wrapper even on NOINLINE things; but move the
NOINLINE pragma to the worker.
Test Plan: make test TEST="13143"
Reviewers: simonpj, bgamari, dfeuer, austin
Reviewed By: simonpj, bgamari
Subscribers: dfeuer, thomie
Differential Revision: https://phabricator.haskell.org/D3046
Diffstat (limited to 'testsuite/timeout')
0 files changed, 0 insertions, 0 deletions