diff options
| author | simonpj@microsoft.com <unknown> | 2008-11-26 14:34:48 +0000 |
|---|---|---|
| committer | simonpj@microsoft.com <unknown> | 2008-11-26 14:34:48 +0000 |
| commit | c3712c026c7b6561d67ce2947cffae209646d4dc (patch) | |
| tree | ce5b9769148d4f6a036c70600386ef7312919c62 | |
| parent | 403ffff4279671d32e645888b8d9743f73cb4acd (diff) | |
| download | haskell-c3712c026c7b6561d67ce2947cffae209646d4dc.tar.gz | |
Fix Trac #2756: CorePrep strictness bug
| -rw-r--r-- | compiler/coreSyn/CorePrep.lhs | 25 |
1 files changed, 21 insertions, 4 deletions
diff --git a/compiler/coreSyn/CorePrep.lhs b/compiler/coreSyn/CorePrep.lhs index e90a12a505..5fa5002bfe 100644 --- a/compiler/coreSyn/CorePrep.lhs +++ b/compiler/coreSyn/CorePrep.lhs @@ -178,7 +178,7 @@ addFloat :: Floats -> FloatingBind -> Floats addFloat (Floats ok_to_spec floats) new_float = Floats (combine ok_to_spec (check new_float)) (floats `snocOL` new_float) where - check (FloatLet _) = OkToSpec + check (FloatLet _) = OkToSpec check (FloatCase _ _ ok_for_spec) | ok_for_spec = IfUnboxedOk | otherwise = NotOkToSpec @@ -324,7 +324,8 @@ corePrepArg :: CorePrepEnv -> CoreArg -> RhsDemand -> UniqSM (Floats, CoreArg) corePrepArg env arg dem = do (floats, arg') <- corePrepExprFloat env arg - if exprIsTrivial arg' + if exprIsTrivial arg' && allLazy NotTopLevel NonRecursive floats + -- Note [Floating unlifted arguments] then return (floats, arg') else do v <- newVar (exprType arg') (floats', v') <- mkLocalNonRec v dem floats arg' @@ -341,7 +342,23 @@ exprIsTrivial (Note _ e) = exprIsTrivial e exprIsTrivial (Cast e _) = exprIsTrivial e exprIsTrivial (Lam b body) | isTyVar b = exprIsTrivial body exprIsTrivial _ = False +\end{code} + +Note [Floating unlifted arguments] +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +Consider C (let v* = expensive in v) + +where the "*" indicates "will be demanded". Usually v will have been +inlined by now, but let's suppose it hasn't (see Trac #2756). Then we +do *not* want to get + + let v* = expensive in C v +because that has different strictness. Hence the use of 'allLazy'. +(NB: the let v* turns into a FloatCase, in mkLocalNonRec.) + + +\begin{code} -- --------------------------------------------------------------------------- -- Dealing with expressions -- --------------------------------------------------------------------------- @@ -603,11 +620,11 @@ mkLocalNonRec bndr dem floats rhs | isStrict dem -- It's a strict let so we definitely float all the bindings - = let -- Don't make a case for a value binding, + = let -- Don't make a case for a value binding, -- even if it's strict. Otherwise we get -- case (\x -> e) of ...! float | exprIsHNF rhs = FloatLet (NonRec bndr rhs) - | otherwise = FloatCase bndr rhs (exprOkForSpeculation rhs) + | otherwise = FloatCase bndr rhs (exprOkForSpeculation rhs) in return (addFloat floats float, evald_bndr) |
