summaryrefslogtreecommitdiff
path: root/compiler/stranal/DmdAnal.lhs
diff options
context:
space:
mode:
authorSimon PJ <simonpj@microsoft.com>2010-05-03 15:16:30 +0000
committerSimon PJ <simonpj@microsoft.com>2010-05-03 15:16:30 +0000
commit71c7067b7cc2b06265c97190e6a09c272ad7a175 (patch)
tree58afe6b53c94c17581e358b5ddd7aaf18521512b /compiler/stranal/DmdAnal.lhs
parent979c11345ee532a4fc56aab54f51d2924c0ea841 (diff)
downloadhaskell-71c7067b7cc2b06265c97190e6a09c272ad7a175.tar.gz
Make the demand analyser take account of lambda-bound unfoldings
This is a long-standing lurking bug. See Note [Lamba-bound unfoldings] in DmdAnal. I'm still not really happy with this lambda-bound-unfolding stuff.
Diffstat (limited to 'compiler/stranal/DmdAnal.lhs')
-rw-r--r--compiler/stranal/DmdAnal.lhs32
1 files changed, 26 insertions, 6 deletions
diff --git a/compiler/stranal/DmdAnal.lhs b/compiler/stranal/DmdAnal.lhs
index 4660aad56a..e8aa22c326 100644
--- a/compiler/stranal/DmdAnal.lhs
+++ b/compiler/stranal/DmdAnal.lhs
@@ -32,7 +32,7 @@ import TyCon ( isProductTyCon, isRecursiveTyCon )
import Id ( Id, idType, idInlineActivation,
isDataConWorkId, isGlobalId, idArity,
idStrictness, idStrictness_maybe,
- setIdStrictness, idDemandInfo,
+ setIdStrictness, idDemandInfo, idUnfolding,
idDemandInfo_maybe,
setIdDemandInfo
)
@@ -205,14 +205,14 @@ dmdAnal sigs dmd (Lam var body)
= let
sigs' = extendSigsWithLam sigs var
(body_ty, body') = dmdAnal sigs' body_dmd body
- (lam_ty, var') = annotateLamIdBndr body_ty var
+ (lam_ty, var') = annotateLamIdBndr sigs body_ty var
in
(lam_ty, Lam var' body')
| otherwise -- Not enough demand on the lambda; but do the body
= let -- anyway to annotate it and gather free var info
(body_ty, body') = dmdAnal sigs evalDmd body
- (lam_ty, var') = annotateLamIdBndr body_ty var
+ (lam_ty, var') = annotateLamIdBndr sigs body_ty var
in
(deferType lam_ty, Lam var' body')
@@ -728,17 +728,27 @@ annotateBndr dmd_ty@(DmdType fv ds res) var
annotateBndrs = mapAccumR annotateBndr
-annotateLamIdBndr :: DmdType -- Demand type of body
+annotateLamIdBndr :: SigEnv
+ -> DmdType -- Demand type of body
-> Id -- Lambda binder
-> (DmdType, -- Demand type of lambda
Id) -- and binder annotated with demand
-annotateLamIdBndr dmd_ty@(DmdType fv ds res) id
+annotateLamIdBndr sigs dmd_ty@(DmdType fv ds res) id
-- For lambdas we add the demand to the argument demands
-- Only called for Ids
= ASSERT( isId id )
- (DmdType fv' (hacked_dmd:ds) res, setIdDemandInfo id hacked_dmd)
+ (final_ty, setIdDemandInfo id hacked_dmd)
where
+ -- Watch out! See note [Lambda-bound unfoldings]
+ final_ty = case maybeUnfoldingTemplate (idUnfolding id) of
+ Nothing -> main_ty
+ Just unf -> main_ty `bothType` unf_ty
+ where
+ (unf_ty, _) = dmdAnal sigs dmd unf
+
+ main_ty = DmdType fv' (hacked_dmd:ds) res
+
(fv', dmd) = removeFV fv id res
hacked_dmd = argDemand dmd
-- This call to argDemand is vital, because otherwise we label
@@ -764,6 +774,16 @@ zapUnlifted id dmd | isUnLiftedType (idType id) = lazyDmd
| otherwise = dmd
\end{code}
+Note [Lamba-bound unfoldings]
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+We allow a lambda-bound variable to carry an unfolding, a facility that is used
+exclusively for join points; see Note [Case binders and join points]. If so,
+we must be careful to demand-analyse the RHS of the unfolding! Example
+ \x. \y{=Just x}. <body>
+Then if <body> uses 'y', then transitively it uses 'x', and we must not
+forget that fact, otherwise we might make 'x' absent when it isn't.
+
+
%************************************************************************
%* *
\subsection{Strictness signatures}