summaryrefslogtreecommitdiff
path: root/compiler/stranal/DmdAnal.lhs
diff options
context:
space:
mode:
authorSimon Peyton Jones <simonpj@microsoft.com>2013-05-28 09:02:16 +0100
committerSimon Peyton Jones <simonpj@microsoft.com>2013-06-06 14:29:55 +0100
commit667338607de99694946f55bc5656172f59f0ee15 (patch)
treeecfba393cdd2db0053c830f5498eae42af8d0924 /compiler/stranal/DmdAnal.lhs
parent3e7e5ba8333d318c38b4cfc538a97fdca0aed5b1 (diff)
downloadhaskell-667338607de99694946f55bc5656172f59f0ee15.tar.gz
Transfer strictness on trivial right-hand sides
See Note [Trivial right-hand sides]
Diffstat (limited to 'compiler/stranal/DmdAnal.lhs')
-rw-r--r--compiler/stranal/DmdAnal.lhs37
1 files changed, 35 insertions, 2 deletions
diff --git a/compiler/stranal/DmdAnal.lhs b/compiler/stranal/DmdAnal.lhs
index 62d898eef2..07c592be3f 100644
--- a/compiler/stranal/DmdAnal.lhs
+++ b/compiler/stranal/DmdAnal.lhs
@@ -243,8 +243,9 @@ dmdAnal env dmd (Case scrut case_bndr ty [alt@(DataAlt dc, _, _)])
scrut_dmd1 = mkProdDmd [idDemandInfo b | b <- bndrs', isId b]
scrut_dmd2 = strictenDmd (idDemandInfo case_bndr')
+ scrut_dmd = scrut_dmd1 `bothCleanDmd` scrut_dmd2
- (scrut_ty, scrut') = dmdAnal env (scrut_dmd1 `bothCleanDmd` scrut_dmd2) scrut
+ (scrut_ty, scrut') = dmdAnal env scrut_dmd scrut
res_ty = alt_ty1 `bothDmdType` scrut_ty
in
-- pprTrace "dmdAnal:Case1" (vcat [ text "scrut" <+> ppr scrut
@@ -486,7 +487,8 @@ dmdTransform env var dmd
| Just (sig, top_lvl) <- lookupSigEnv env var -- Local letrec bound thing
, let fn_ty = dmdTransformSig sig dmd
- = if isTopLevel top_lvl
+ = -- pprTrace "dmdTransform" (vcat [ppr var, ppr dmd, ppr fn_ty]) $
+ if isTopLevel top_lvl
then fn_ty -- Don't record top level things
else addVarDmd fn_ty var (mkOnceUsedDmd dmd)
@@ -577,6 +579,11 @@ dmdAnalRhs :: TopLevelFlag
-- Process the RHS of the binding, add the strictness signature
-- to the Id, and augment the environment with the signature as well.
dmdAnalRhs top_lvl rec_flag env id rhs
+ | Just fn <- unpackTrivial rhs -- See Note [Trivial right-hand sides]
+ , let fn_str = getStrictness env fn
+ = (fn_str, emptyDmdEnv, set_idStrictness env id fn_str, rhs)
+
+ | otherwise
= (sig_ty, lazy_fv, id', mkLams bndrs' body')
where
(bndrs, body) = collectBinders rhs
@@ -617,8 +624,28 @@ dmdAnalRhs top_lvl rec_flag env id rhs
|| isJust rec_flag -- get their demandInfo set at all
|| not (isStrictDmd (idDemandInfo id) || ae_virgin env)
-- See Note [Optimistic CPR in the "virgin" case]
+
+unpackTrivial :: CoreExpr -> Maybe Id
+-- Returns (Just v) if the arg is really equal to v, modulo
+-- casts, type applications etc
+-- See Note [Trivial right-hand sides]
+unpackTrivial (Var v) = Just v
+unpackTrivial (Cast e _) = unpackTrivial e
+unpackTrivial (Lam v e) | isTyVar v = unpackTrivial e
+unpackTrivial (App e a) | isTypeArg a = unpackTrivial e
+unpackTrivial _ = Nothing
\end{code}
+Note [Trivial right-hand sides]
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+Consider
+ foo = plusInt |> co
+where plusInt is an arity-2 function with known strictness. Clearly
+we want plusInt's strictness to propagate to foo! But because it has
+no manifest lambdas, it won't do so automatically. So we have a
+special case for right-hand sides that are "trivial", namely variables,
+casts, type applications, and the like.
+
Note [Product demands for function body]
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
This example comes from shootout/binary_trees:
@@ -1004,6 +1031,12 @@ extendSigEnv top_lvl sigs var sig = extendVarEnv sigs var (sig, top_lvl)
lookupSigEnv :: AnalEnv -> Id -> Maybe (StrictSig, TopLevelFlag)
lookupSigEnv env id = lookupVarEnv (ae_sigs env) id
+getStrictness :: AnalEnv -> Id -> StrictSig
+getStrictness env fn
+ | isGlobalId fn = idStrictness fn
+ | Just (sig, _) <- lookupSigEnv env fn = sig
+ | otherwise = topSig
+
addInitialSigs :: TopLevelFlag -> AnalEnv -> [Id] -> AnalEnv
-- See Note [Initialising strictness]
addInitialSigs top_lvl env@(AE { ae_sigs = sigs, ae_virgin = virgin }) ids