diff options
author | simonpj@microsoft.com <unknown> | 2006-05-08 14:28:34 +0000 |
---|---|---|
committer | simonpj@microsoft.com <unknown> | 2006-05-08 14:28:34 +0000 |
commit | 302265d525004c7870864549f7a07a5759d32912 (patch) | |
tree | b649752f104b35710b370603db16fe43862a5acd /compiler/stranal | |
parent | 36b27193c994b4a267c8dfdbf833d73b455130aa (diff) | |
download | haskell-302265d525004c7870864549f7a07a5759d32912.tar.gz |
Remove NOINLINE strictness hack
The stricteness analyser used to have a HACK which ensured that NOINLNE things
were not strictness-analysed. The reason was unsafePerformIO. Left to itself,
the strictness analyser would discover this strictness for unsafePerformIO:
unsafePerformIO: C(U(AV))
But then consider this sub-expression
unsafePerformIO (\s -> let r = f x in
case writeIORef v r s of (# s1, _ #) ->
(# s1, r #)
The strictness analyser will now find that r is sure to be eval'd,
and may then hoist it out. This makes tests/lib/should_run/memo002
deadlock.
Solving this by making all NOINLINE things have no strictness info is overkill.
In particular, it's overkill for runST, which is perfectly respectable.
Consider
f x = runST (return x)
This should be strict in x.
So the new plan is to define unsafePerformIO using the 'lazy' combinator:
unsafePerformIO (IO m) = lazy (case m realWorld# of (# _, r #) -> r)
Remember, 'lazy' is a wired-in identity-function Id, of type a->a, which is
magically NON-STRICT, and is inlined after strictness analysis. So
unsafePerformIO will look non-strict, and that's what we want.
Now we don't need the hack in the strictness analyser.
Diffstat (limited to 'compiler/stranal')
-rw-r--r-- | compiler/stranal/DmdAnal.lhs | 28 | ||||
-rw-r--r-- | compiler/stranal/WorkWrap.lhs | 2 |
2 files changed, 1 insertions, 29 deletions
diff --git a/compiler/stranal/DmdAnal.lhs b/compiler/stranal/DmdAnal.lhs index c5cfb7b4bd..127fa7800f 100644 --- a/compiler/stranal/DmdAnal.lhs +++ b/compiler/stranal/DmdAnal.lhs @@ -530,34 +530,6 @@ by dmdAnalTopBind. \begin{code} mk_sig_ty never_inline thunk_cpr_ok rhs (DmdType fv dmds res) - | never_inline && not (isBotRes res) - -- HACK ALERT - -- Don't strictness-analyse NOINLINE things. Why not? Because - -- the NOINLINE says "don't expose any of the inner workings at the call - -- site" and the strictness is certainly an inner working. - -- - -- More concretely, the demand analyser discovers the following strictness - -- for unsafePerformIO: C(U(AV)) - -- But then consider - -- unsafePerformIO (\s -> let r = f x in - -- case writeIORef v r s of (# s1, _ #) -> - -- (# s1, r #) - -- The strictness analyser will find that the binding for r is strict, - -- (becuase of uPIO's strictness sig), and so it'll evaluate it before - -- doing the writeIORef. This actually makes tests/lib/should_run/memo002 - -- get a deadlock! - -- - -- Solution: don't expose the strictness of unsafePerformIO. - -- - -- But we do want to expose the strictness of error functions, - -- which are also often marked NOINLINE - -- {-# NOINLINE foo #-} - -- foo x = error ("wubble buggle" ++ x) - -- So (hack, hack) we only drop the strictness for non-bottom things - -- This is all very unsatisfactory. - = (deferEnv fv, topSig) - - | otherwise = (lazy_fv, mkStrictSig dmd_ty) where dmd_ty = DmdType strict_fv final_dmds res' diff --git a/compiler/stranal/WorkWrap.lhs b/compiler/stranal/WorkWrap.lhs index 64eba89273..d964026756 100644 --- a/compiler/stranal/WorkWrap.lhs +++ b/compiler/stranal/WorkWrap.lhs @@ -137,7 +137,7 @@ wwExpr e@(Note InlineMe expr) = returnUs e wwExpr e@(Var v) | v `hasKey` lazyIdKey = returnUs lazyIdUnfolding | otherwise = returnUs e - -- Inline 'lazy' after strictness analysis + -- HACK alert: Inline 'lazy' after strictness analysis -- (but not inside InlineMe's) wwExpr (Lam binder expr) |