diff options
author | Nicolas Frisby <nicolas.frisby@gmail.com> | 2013-07-17 10:39:25 -0500 |
---|---|---|
committer | Nicolas Frisby <nicolas.frisby@gmail.com> | 2013-09-08 01:34:28 -0500 |
commit | c73d372bfebb5acee45e196d4e8694b656c7fd82 (patch) | |
tree | fe1b5664a29944a5344204627cc7b3ace3d68b8b /compiler/stranal | |
parent | 275725892cc14fea32091b80d17b14c8cbf50e84 (diff) | |
download | haskell-c73d372bfebb5acee45e196d4e8694b656c7fd82.tar.gz |
resurrected -fdicts-strict, off by default
also added -fdmd-tx-dict-sel, on by default
Diffstat (limited to 'compiler/stranal')
-rw-r--r-- | compiler/stranal/DmdAnal.lhs | 49 |
1 files changed, 40 insertions, 9 deletions
diff --git a/compiler/stranal/DmdAnal.lhs b/compiler/stranal/DmdAnal.lhs index 0aff8ffd93..98c4083ddf 100644 --- a/compiler/stranal/DmdAnal.lhs +++ b/compiler/stranal/DmdAnal.lhs @@ -180,6 +180,7 @@ dmdAnal env dmd (App fun arg) -- Non-type arguments -- , text "overall res dmd_ty =" <+> ppr (res_ty `bothDmdType` arg_ty) ]) (res_ty `bothDmdType` arg_ty, App fun' arg') +-- this is an anonymous lambda, since @dmdAnalRhs@ uses @collectBinders@ dmdAnal env dmd (Lam var body) | isTyVar var = let @@ -195,7 +196,7 @@ dmdAnal env dmd (Lam var body) env' = extendSigsWithLam env var (body_ty, body') = dmdAnal env' body_dmd body - (lam_ty, var') = annotateLamIdBndr env body_ty one_shot var + (lam_ty, var') = annotateLamIdBndr env notArgOfDfun body_ty one_shot var in (deferAndUse defer_me one_shot lam_ty, Lam var' body') @@ -480,6 +481,10 @@ dmdTransform env var dmd = dmdTransformDataConSig (idArity var) (idStrictness var) dmd + | gopt Opt_DmdTxDictSel (ae_dflags env), + Just _ <- isClassOpId_maybe var -- Dictionary component selector + = dmdTransformDictSelSig (idStrictness var) dmd + | isGlobalId var -- Imported function = let res = dmdTransformSig (idStrictness var) dmd in -- pprTrace "dmdTransform" (vcat [ppr var, ppr (idStrictness var), ppr dmd, ppr res]) @@ -589,7 +594,7 @@ dmdAnalRhs top_lvl rec_flag env id rhs (bndrs, body) = collectBinders rhs env_body = foldl extendSigsWithLam env bndrs (body_dmd_ty, body') = dmdAnal env_body body_dmd body - (rhs_dmd_ty, bndrs') = annotateLamBndrs env body_dmd_ty bndrs + (rhs_dmd_ty, bndrs') = annotateLamBndrs env (isDFunId id) body_dmd_ty bndrs id' = set_idStrictness env id sig_ty sig_ty = mkStrictSig (mkDmdType sig_fv rhs_dmds rhs_res') -- See Note [NOINLINE and strictness] @@ -733,6 +738,13 @@ the safe result we also have absent demand set to Abs, which makes it possible to safely ignore non-mentioned variables (their joint demand is <L,A>). +Note [do not strictify the argument dictionaries of a dfun] +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +The typechecker can tie recursive knots involving dfuns, so we do the +conservative thing and refrain from strictifying a dfun's argument +dictionaries. + \begin{code} annotateBndr :: AnalEnv -> DmdType -> Var -> (DmdType, Var) -- The returned env has the var deleted @@ -741,33 +753,41 @@ annotateBndr :: AnalEnv -> DmdType -> Var -> (DmdType, Var) -- No effect on the argument demands annotateBndr env dmd_ty@(DmdType fv ds res) var | isTyVar var = (dmd_ty, var) - | otherwise = (DmdType fv' ds res, set_idDemandInfo env var dmd) + | otherwise = (DmdType fv' ds res, set_idDemandInfo env var dmd') where (fv', dmd) = peelFV fv var res + dmd' | gopt Opt_DictsStrict (ae_dflags env) + -- We never want to strictify a recursive let. At the moment + -- annotateBndr is only call for non-recursive lets; if that + -- changes, we need a RecFlag parameter and another guard here. + = strictifyDictDmd (idType var) dmd + | otherwise = dmd + annotateBndrs :: AnalEnv -> DmdType -> [Var] -> (DmdType, [Var]) annotateBndrs env = mapAccumR (annotateBndr env) -annotateLamBndrs :: AnalEnv -> DmdType -> [Var] -> (DmdType, [Var]) -annotateLamBndrs env ty bndrs = mapAccumR annotate ty bndrs +annotateLamBndrs :: AnalEnv -> DFunFlag -> DmdType -> [Var] -> (DmdType, [Var]) +annotateLamBndrs env args_of_dfun ty bndrs = mapAccumR annotate ty bndrs where annotate dmd_ty bndr - | isId bndr = annotateLamIdBndr env dmd_ty Many bndr + | isId bndr = annotateLamIdBndr env args_of_dfun dmd_ty Many bndr | otherwise = (dmd_ty, bndr) annotateLamIdBndr :: AnalEnv + -> DFunFlag -- is this lambda at the top of the RHS of a dfun? -> DmdType -- Demand type of body -> Count -- One-shot-ness of the lambda -> Id -- Lambda binder -> (DmdType, -- Demand type of lambda Id) -- and binder annotated with demand -annotateLamIdBndr env _dmd_ty@(DmdType fv ds res) one_shot id +annotateLamIdBndr env arg_of_dfun _dmd_ty@(DmdType fv ds res) one_shot id -- For lambdas we add the demand to the argument demands -- Only called for Ids = ASSERT( isId id ) -- pprTrace "annLamBndr" (vcat [ppr id, ppr _dmd_ty]) $ - (final_ty, setOneShotness one_shot (set_idDemandInfo env id dmd)) + (final_ty, setOneShotness one_shot (set_idDemandInfo env id dmd')) where -- Watch out! See note [Lambda-bound unfoldings] final_ty = case maybeUnfoldingTemplate (idUnfolding id) of @@ -780,6 +800,12 @@ annotateLamIdBndr env _dmd_ty@(DmdType fv ds res) one_shot id (fv', dmd) = peelFV fv id res + dmd' | gopt Opt_DictsStrict (ae_dflags env), + -- see Note [do not strictify the argument dictionaries of a dfun] + not arg_of_dfun + = strictifyDictDmd (idType id) dmd + | otherwise = dmd + deleteFVs :: DmdType -> [Var] -> DmdType deleteFVs (DmdType fvs dmds res) bndrs = DmdType (delVarEnvList fvs bndrs) dmds res @@ -985,13 +1011,18 @@ forget that fact, otherwise we might make 'x' absent when it isn't. %************************************************************************ \begin{code} +type DFunFlag = Bool -- indicates if the lambda being considered is in the + -- sequence of lambdas at the top of the RHS of a dfun +notArgOfDfun :: DFunFlag +notArgOfDfun = False + data AnalEnv = AE { ae_dflags :: DynFlags , ae_sigs :: SigEnv , ae_virgin :: Bool -- True on first iteration only -- See Note [Initialising strictness] , ae_rec_tc :: RecTcChecker - } + } -- We use the se_env to tell us whether to -- record info about a variable in the DmdEnv |