summaryrefslogtreecommitdiff
path: root/compiler/stranal
diff options
context:
space:
mode:
authorsimonpj@microsoft.com <unknown>2006-05-08 14:28:34 +0000
committersimonpj@microsoft.com <unknown>2006-05-08 14:28:34 +0000
commit302265d525004c7870864549f7a07a5759d32912 (patch)
treeb649752f104b35710b370603db16fe43862a5acd /compiler/stranal
parent36b27193c994b4a267c8dfdbf833d73b455130aa (diff)
downloadhaskell-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.lhs28
-rw-r--r--compiler/stranal/WorkWrap.lhs2
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)