{-# LANGUAGE CPP #-}
module DmdAnal ( dmdAnalProgram ) where
#include "HsVersions.h"
import GhcPrelude
import DynFlags
import WwLib ( findTypeShape, deepSplitProductType_maybe )
import Demand
import CoreSyn
import CoreSeq ( seqBinds )
import Outputable
import VarEnv
import BasicTypes
import Data.List
import DataCon
import Id
import CoreUtils ( exprIsHNF, exprType, exprIsTrivial, exprOkForSpeculation )
import TyCon
import Type
import Coercion ( Coercion, coVarsOfCo )
import FamInstEnv
import Util
import Maybes ( isJust )
import TysWiredIn
import TysPrim ( realWorldStatePrimTy )
import ErrUtils ( dumpIfSet_dyn )
import Name ( getName, stableNameCmp )
import Data.Function ( on )
import UniqSet
dmdAnalProgram :: DynFlags -> FamInstEnvs -> CoreProgram -> IO CoreProgram
dmdAnalProgram :: DynFlags -> FamInstEnvs -> CoreProgram -> IO CoreProgram
dmdAnalProgram dflags :: DynFlags
dflags fam_envs :: FamInstEnvs
fam_envs binds :: CoreProgram
binds
= do {
let { binds_plus_dmds :: CoreProgram
binds_plus_dmds = CoreProgram -> CoreProgram
do_prog CoreProgram
binds } ;
DynFlags -> DumpFlag -> String -> SDoc -> IO ()
dumpIfSet_dyn DynFlags
dflags DumpFlag
Opt_D_dump_str_signatures
"Strictness signatures" (SDoc -> IO ()) -> SDoc -> IO ()
forall a b. (a -> b) -> a -> b
$
CoreProgram -> SDoc
dumpStrSig CoreProgram
binds_plus_dmds ;
CoreProgram -> ()
seqBinds CoreProgram
binds_plus_dmds () -> IO CoreProgram -> IO CoreProgram
forall a b. a -> b -> b
`seq` CoreProgram -> IO CoreProgram
forall (m :: * -> *) a. Monad m => a -> m a
return CoreProgram
binds_plus_dmds
}
where
do_prog :: CoreProgram -> CoreProgram
do_prog :: CoreProgram -> CoreProgram
do_prog binds :: CoreProgram
binds = (AnalEnv, CoreProgram) -> CoreProgram
forall a b. (a, b) -> b
snd ((AnalEnv, CoreProgram) -> CoreProgram)
-> (AnalEnv, CoreProgram) -> CoreProgram
forall a b. (a -> b) -> a -> b
$ (AnalEnv -> CoreBind -> (AnalEnv, CoreBind))
-> AnalEnv -> CoreProgram -> (AnalEnv, CoreProgram)
forall (t :: * -> *) a b c.
Traversable t =>
(a -> b -> (a, c)) -> a -> t b -> (a, t c)
mapAccumL AnalEnv -> CoreBind -> (AnalEnv, CoreBind)
dmdAnalTopBind (DynFlags -> FamInstEnvs -> AnalEnv
emptyAnalEnv DynFlags
dflags FamInstEnvs
fam_envs) CoreProgram
binds
dmdAnalTopBind :: AnalEnv
-> CoreBind
-> (AnalEnv, CoreBind)
dmdAnalTopBind :: AnalEnv -> CoreBind -> (AnalEnv, CoreBind)
dmdAnalTopBind env :: AnalEnv
env (NonRec id :: CoreBndr
id rhs :: Expr CoreBndr
rhs)
= (TopLevelFlag -> AnalEnv -> CoreBndr -> StrictSig -> AnalEnv
extendAnalEnv TopLevelFlag
TopLevel AnalEnv
env CoreBndr
id2 (CoreBndr -> StrictSig
idStrictness CoreBndr
id2), CoreBndr -> Expr CoreBndr -> CoreBind
forall b. b -> Expr b -> Bind b
NonRec CoreBndr
id2 Expr CoreBndr
rhs2)
where
( _, _, rhs1 :: Expr CoreBndr
rhs1) = TopLevelFlag
-> Maybe [CoreBndr]
-> AnalEnv
-> CleanDemand
-> CoreBndr
-> Expr CoreBndr
-> (DmdEnv, CoreBndr, Expr CoreBndr)
dmdAnalRhsLetDown TopLevelFlag
TopLevel Maybe [CoreBndr]
forall a. Maybe a
Nothing AnalEnv
env CleanDemand
cleanEvalDmd CoreBndr
id Expr CoreBndr
rhs
( _, id2 :: CoreBndr
id2, rhs2 :: Expr CoreBndr
rhs2) = TopLevelFlag
-> Maybe [CoreBndr]
-> AnalEnv
-> CleanDemand
-> CoreBndr
-> Expr CoreBndr
-> (DmdEnv, CoreBndr, Expr CoreBndr)
dmdAnalRhsLetDown TopLevelFlag
TopLevel Maybe [CoreBndr]
forall a. Maybe a
Nothing (AnalEnv -> AnalEnv
nonVirgin AnalEnv
env) CleanDemand
cleanEvalDmd CoreBndr
id Expr CoreBndr
rhs1
dmdAnalTopBind env :: AnalEnv
env (Rec pairs :: [(CoreBndr, Expr CoreBndr)]
pairs)
= (AnalEnv
env', [(CoreBndr, Expr CoreBndr)] -> CoreBind
forall b. [(b, Expr b)] -> Bind b
Rec [(CoreBndr, Expr CoreBndr)]
pairs')
where
(env' :: AnalEnv
env', _, pairs' :: [(CoreBndr, Expr CoreBndr)]
pairs') = TopLevelFlag
-> AnalEnv
-> CleanDemand
-> [(CoreBndr, Expr CoreBndr)]
-> (AnalEnv, DmdEnv, [(CoreBndr, Expr CoreBndr)])
dmdFix TopLevelFlag
TopLevel AnalEnv
env CleanDemand
cleanEvalDmd [(CoreBndr, Expr CoreBndr)]
pairs
dmdTransformThunkDmd :: CoreExpr -> Demand -> Demand
dmdTransformThunkDmd :: Expr CoreBndr -> Demand -> Demand
dmdTransformThunkDmd e :: Expr CoreBndr
e
| Expr CoreBndr -> Bool
exprIsTrivial Expr CoreBndr
e = Demand -> Demand
forall a. a -> a
id
| Bool
otherwise = Demand -> Demand
forall s u. JointDmd s (Use u) -> JointDmd s (Use u)
oneifyDmd
dmdAnalStar :: AnalEnv
-> Demand
-> CoreExpr
-> (BothDmdArg, CoreExpr)
dmdAnalStar :: AnalEnv -> Demand -> Expr CoreBndr -> (BothDmdArg, Expr CoreBndr)
dmdAnalStar env :: AnalEnv
env dmd :: Demand
dmd e :: Expr CoreBndr
e
| (dmd_shell :: DmdShell
dmd_shell, cd :: CleanDemand
cd) <- Demand -> (DmdShell, CleanDemand)
toCleanDmd Demand
dmd
, (dmd_ty :: DmdType
dmd_ty, e' :: Expr CoreBndr
e') <- AnalEnv -> CleanDemand -> Expr CoreBndr -> (DmdType, Expr CoreBndr)
dmdAnal AnalEnv
env CleanDemand
cd Expr CoreBndr
e
= ASSERT2( not (isUnliftedType (exprType e)) || exprOkForSpeculation e, ppr e )
(DmdShell -> DmdType -> BothDmdArg
postProcessDmdType DmdShell
dmd_shell DmdType
dmd_ty, Expr CoreBndr
e')
dmdAnal, dmdAnal' :: AnalEnv
-> CleanDemand
-> CoreExpr -> (DmdType, CoreExpr)
dmdAnal :: AnalEnv -> CleanDemand -> Expr CoreBndr -> (DmdType, Expr CoreBndr)
dmdAnal env :: AnalEnv
env d :: CleanDemand
d e :: Expr CoreBndr
e =
AnalEnv -> CleanDemand -> Expr CoreBndr -> (DmdType, Expr CoreBndr)
dmdAnal' AnalEnv
env CleanDemand
d Expr CoreBndr
e
dmdAnal' :: AnalEnv -> CleanDemand -> Expr CoreBndr -> (DmdType, Expr CoreBndr)
dmdAnal' _ _ (Lit lit :: Literal
lit) = (DmdType
nopDmdType, Literal -> Expr CoreBndr
forall b. Literal -> Expr b
Lit Literal
lit)
dmdAnal' _ _ (Type ty :: Type
ty) = (DmdType
nopDmdType, Type -> Expr CoreBndr
forall b. Type -> Expr b
Type Type
ty)
dmdAnal' _ _ (Coercion co :: Coercion
co)
= (DmdEnv -> DmdType
unitDmdType (Coercion -> DmdEnv
coercionDmdEnv Coercion
co), Coercion -> Expr CoreBndr
forall b. Coercion -> Expr b
Coercion Coercion
co)
dmdAnal' env :: AnalEnv
env dmd :: CleanDemand
dmd (Var var :: CoreBndr
var)
= (AnalEnv -> CoreBndr -> CleanDemand -> DmdType
dmdTransform AnalEnv
env CoreBndr
var CleanDemand
dmd, CoreBndr -> Expr CoreBndr
forall b. CoreBndr -> Expr b
Var CoreBndr
var)
dmdAnal' env :: AnalEnv
env dmd :: CleanDemand
dmd (Cast e :: Expr CoreBndr
e co :: Coercion
co)
= (DmdType
dmd_ty DmdType -> BothDmdArg -> DmdType
`bothDmdType` DmdEnv -> BothDmdArg
mkBothDmdArg (Coercion -> DmdEnv
coercionDmdEnv Coercion
co), Expr CoreBndr -> Coercion -> Expr CoreBndr
forall b. Expr b -> Coercion -> Expr b
Cast Expr CoreBndr
e' Coercion
co)
where
(dmd_ty :: DmdType
dmd_ty, e' :: Expr CoreBndr
e') = AnalEnv -> CleanDemand -> Expr CoreBndr -> (DmdType, Expr CoreBndr)
dmdAnal AnalEnv
env CleanDemand
dmd Expr CoreBndr
e
dmdAnal' env :: AnalEnv
env dmd :: CleanDemand
dmd (Tick t :: Tickish CoreBndr
t e :: Expr CoreBndr
e)
= (DmdType
dmd_ty, Tickish CoreBndr -> Expr CoreBndr -> Expr CoreBndr
forall b. Tickish CoreBndr -> Expr b -> Expr b
Tick Tickish CoreBndr
t Expr CoreBndr
e')
where
(dmd_ty :: DmdType
dmd_ty, e' :: Expr CoreBndr
e') = AnalEnv -> CleanDemand -> Expr CoreBndr -> (DmdType, Expr CoreBndr)
dmdAnal AnalEnv
env CleanDemand
dmd Expr CoreBndr
e
dmdAnal' env :: AnalEnv
env dmd :: CleanDemand
dmd (App fun :: Expr CoreBndr
fun (Type ty :: Type
ty))
= (DmdType
fun_ty, Expr CoreBndr -> Expr CoreBndr -> Expr CoreBndr
forall b. Expr b -> Expr b -> Expr b
App Expr CoreBndr
fun' (Type -> Expr CoreBndr
forall b. Type -> Expr b
Type Type
ty))
where
(fun_ty :: DmdType
fun_ty, fun' :: Expr CoreBndr
fun') = AnalEnv -> CleanDemand -> Expr CoreBndr -> (DmdType, Expr CoreBndr)
dmdAnal AnalEnv
env CleanDemand
dmd Expr CoreBndr
fun
dmdAnal' env :: AnalEnv
env dmd :: CleanDemand
dmd (App fun :: Expr CoreBndr
fun arg :: Expr CoreBndr
arg)
=
let
call_dmd :: CleanDemand
call_dmd = CleanDemand -> CleanDemand
mkCallDmd CleanDemand
dmd
(fun_ty :: DmdType
fun_ty, fun' :: Expr CoreBndr
fun') = AnalEnv -> CleanDemand -> Expr CoreBndr -> (DmdType, Expr CoreBndr)
dmdAnal AnalEnv
env CleanDemand
call_dmd Expr CoreBndr
fun
(arg_dmd :: Demand
arg_dmd, res_ty :: DmdType
res_ty) = DmdType -> (Demand, DmdType)
splitDmdTy DmdType
fun_ty
(arg_ty :: BothDmdArg
arg_ty, arg' :: Expr CoreBndr
arg') = AnalEnv -> Demand -> Expr CoreBndr -> (BothDmdArg, Expr CoreBndr)
dmdAnalStar AnalEnv
env (Expr CoreBndr -> Demand -> Demand
dmdTransformThunkDmd Expr CoreBndr
arg Demand
arg_dmd) Expr CoreBndr
arg
in
(DmdType
res_ty DmdType -> BothDmdArg -> DmdType
`bothDmdType` BothDmdArg
arg_ty, Expr CoreBndr -> Expr CoreBndr -> Expr CoreBndr
forall b. Expr b -> Expr b -> Expr b
App Expr CoreBndr
fun' Expr CoreBndr
arg')
dmdAnal' env :: AnalEnv
env dmd :: CleanDemand
dmd (Lam var :: CoreBndr
var body :: Expr CoreBndr
body)
| CoreBndr -> Bool
isTyVar CoreBndr
var
= let
(body_ty :: DmdType
body_ty, body' :: Expr CoreBndr
body') = AnalEnv -> CleanDemand -> Expr CoreBndr -> (DmdType, Expr CoreBndr)
dmdAnal AnalEnv
env CleanDemand
dmd Expr CoreBndr
body
in
(DmdType
body_ty, CoreBndr -> Expr CoreBndr -> Expr CoreBndr
forall b. b -> Expr b -> Expr b
Lam CoreBndr
var Expr CoreBndr
body')
| Bool
otherwise
= let (body_dmd :: CleanDemand
body_dmd, defer_and_use :: DmdShell
defer_and_use) = CleanDemand -> (CleanDemand, DmdShell)
peelCallDmd CleanDemand
dmd
env' :: AnalEnv
env' = AnalEnv -> CoreBndr -> AnalEnv
extendSigsWithLam AnalEnv
env CoreBndr
var
(body_ty :: DmdType
body_ty, body' :: Expr CoreBndr
body') = AnalEnv -> CleanDemand -> Expr CoreBndr -> (DmdType, Expr CoreBndr)
dmdAnal AnalEnv
env' CleanDemand
body_dmd Expr CoreBndr
body
(lam_ty :: DmdType
lam_ty, var' :: CoreBndr
var') = AnalEnv -> Bool -> DmdType -> CoreBndr -> (DmdType, CoreBndr)
annotateLamIdBndr AnalEnv
env Bool
notArgOfDfun DmdType
body_ty CoreBndr
var
in
(DmdShell -> DmdType -> DmdType
postProcessUnsat DmdShell
defer_and_use DmdType
lam_ty, CoreBndr -> Expr CoreBndr -> Expr CoreBndr
forall b. b -> Expr b -> Expr b
Lam CoreBndr
var' Expr CoreBndr
body')
dmdAnal' env :: AnalEnv
env dmd :: CleanDemand
dmd (Case scrut :: Expr CoreBndr
scrut case_bndr :: CoreBndr
case_bndr ty :: Type
ty [(DataAlt dc :: DataCon
dc, bndrs :: [CoreBndr]
bndrs, rhs :: Expr CoreBndr
rhs)])
| let tycon :: TyCon
tycon = DataCon -> TyCon
dataConTyCon DataCon
dc
, Maybe DataCon -> Bool
forall a. Maybe a -> Bool
isJust (TyCon -> Maybe DataCon
isDataProductTyCon_maybe TyCon
tycon)
, Just rec_tc' :: RecTcChecker
rec_tc' <- RecTcChecker -> TyCon -> Maybe RecTcChecker
checkRecTc (AnalEnv -> RecTcChecker
ae_rec_tc AnalEnv
env) TyCon
tycon
= let
env_w_tc :: AnalEnv
env_w_tc = AnalEnv
env { ae_rec_tc :: RecTcChecker
ae_rec_tc = RecTcChecker
rec_tc' }
env_alt :: AnalEnv
env_alt = AnalEnv
-> Expr CoreBndr -> CoreBndr -> DataCon -> [CoreBndr] -> AnalEnv
extendEnvForProdAlt AnalEnv
env_w_tc Expr CoreBndr
scrut CoreBndr
case_bndr DataCon
dc [CoreBndr]
bndrs
(rhs_ty :: DmdType
rhs_ty, rhs' :: Expr CoreBndr
rhs') = AnalEnv -> CleanDemand -> Expr CoreBndr -> (DmdType, Expr CoreBndr)
dmdAnal AnalEnv
env_alt CleanDemand
dmd Expr CoreBndr
rhs
(alt_ty1 :: DmdType
alt_ty1, dmds :: [Demand]
dmds) = AnalEnv -> DmdType -> [CoreBndr] -> (DmdType, [Demand])
findBndrsDmds AnalEnv
env DmdType
rhs_ty [CoreBndr]
bndrs
(alt_ty2 :: DmdType
alt_ty2, case_bndr_dmd :: Demand
case_bndr_dmd) = AnalEnv -> Bool -> DmdType -> CoreBndr -> (DmdType, Demand)
findBndrDmd AnalEnv
env Bool
False DmdType
alt_ty1 CoreBndr
case_bndr
id_dmds :: [Demand]
id_dmds = Demand -> [Demand] -> [Demand]
addCaseBndrDmd Demand
case_bndr_dmd [Demand]
dmds
alt_ty3 :: DmdType
alt_ty3 | Expr CoreBndr -> DataCon -> [CoreBndr] -> Bool
io_hack_reqd Expr CoreBndr
scrut DataCon
dc [CoreBndr]
bndrs = DmdType -> DmdType
deferAfterIO DmdType
alt_ty2
| Bool
otherwise = DmdType
alt_ty2
scrut_dmd :: CleanDemand
scrut_dmd = [Demand] -> CleanDemand
mkProdDmd [Demand]
id_dmds
(scrut_ty :: DmdType
scrut_ty, scrut' :: Expr CoreBndr
scrut') = AnalEnv -> CleanDemand -> Expr CoreBndr -> (DmdType, Expr CoreBndr)
dmdAnal AnalEnv
env CleanDemand
scrut_dmd Expr CoreBndr
scrut
res_ty :: DmdType
res_ty = DmdType
alt_ty3 DmdType -> BothDmdArg -> DmdType
`bothDmdType` DmdType -> BothDmdArg
toBothDmdArg DmdType
scrut_ty
case_bndr' :: CoreBndr
case_bndr' = CoreBndr -> Demand -> CoreBndr
setIdDemandInfo CoreBndr
case_bndr Demand
case_bndr_dmd
bndrs' :: [CoreBndr]
bndrs' = [CoreBndr] -> [Demand] -> [CoreBndr]
setBndrsDemandInfo [CoreBndr]
bndrs [Demand]
id_dmds
in
(DmdType
res_ty, Expr CoreBndr
-> CoreBndr -> Type -> [Alt CoreBndr] -> Expr CoreBndr
forall b. Expr b -> b -> Type -> [Alt b] -> Expr b
Case Expr CoreBndr
scrut' CoreBndr
case_bndr' Type
ty [(DataCon -> AltCon
DataAlt DataCon
dc, [CoreBndr]
bndrs', Expr CoreBndr
rhs')])
dmdAnal' env :: AnalEnv
env dmd :: CleanDemand
dmd (Case scrut :: Expr CoreBndr
scrut case_bndr :: CoreBndr
case_bndr ty :: Type
ty alts :: [Alt CoreBndr]
alts)
= let
(alt_tys :: [DmdType]
alt_tys, alts' :: [Alt CoreBndr]
alts') = (Alt CoreBndr -> (DmdType, Alt CoreBndr))
-> [Alt CoreBndr] -> ([DmdType], [Alt CoreBndr])
forall a b c. (a -> (b, c)) -> [a] -> ([b], [c])
mapAndUnzip (AnalEnv
-> CleanDemand
-> CoreBndr
-> Alt CoreBndr
-> (DmdType, Alt CoreBndr)
dmdAnalAlt AnalEnv
env CleanDemand
dmd CoreBndr
case_bndr) [Alt CoreBndr]
alts
(scrut_ty :: DmdType
scrut_ty, scrut' :: Expr CoreBndr
scrut') = AnalEnv -> CleanDemand -> Expr CoreBndr -> (DmdType, Expr CoreBndr)
dmdAnal AnalEnv
env CleanDemand
cleanEvalDmd Expr CoreBndr
scrut
(alt_ty :: DmdType
alt_ty, case_bndr' :: CoreBndr
case_bndr') = AnalEnv -> DmdType -> CoreBndr -> (DmdType, CoreBndr)
annotateBndr AnalEnv
env ((DmdType -> DmdType -> DmdType) -> DmdType -> [DmdType] -> DmdType
forall (t :: * -> *) a b.
Foldable t =>
(a -> b -> b) -> b -> t a -> b
foldr DmdType -> DmdType -> DmdType
lubDmdType DmdType
botDmdType [DmdType]
alt_tys) CoreBndr
case_bndr
res_ty :: DmdType
res_ty = DmdType
alt_ty DmdType -> BothDmdArg -> DmdType
`bothDmdType` DmdType -> BothDmdArg
toBothDmdArg DmdType
scrut_ty
in
(DmdType
res_ty, Expr CoreBndr
-> CoreBndr -> Type -> [Alt CoreBndr] -> Expr CoreBndr
forall b. Expr b -> b -> Type -> [Alt b] -> Expr b
Case Expr CoreBndr
scrut' CoreBndr
case_bndr' Type
ty [Alt CoreBndr]
alts')
dmdAnal' env :: AnalEnv
env dmd :: CleanDemand
dmd (Let (NonRec id :: CoreBndr
id rhs :: Expr CoreBndr
rhs) body :: Expr CoreBndr
body)
| CoreBndr -> Expr CoreBndr -> Bool
useLetUp CoreBndr
id Expr CoreBndr
rhs
, Maybe CoreBndr
Nothing <- Expr CoreBndr -> Maybe CoreBndr
unpackTrivial Expr CoreBndr
rhs
= (DmdType
final_ty, CoreBind -> Expr CoreBndr -> Expr CoreBndr
forall b. Bind b -> Expr b -> Expr b
Let (CoreBndr -> Expr CoreBndr -> CoreBind
forall b. b -> Expr b -> Bind b
NonRec CoreBndr
id' Expr CoreBndr
rhs') Expr CoreBndr
body')
where
(body_ty :: DmdType
body_ty, body' :: Expr CoreBndr
body') = AnalEnv -> CleanDemand -> Expr CoreBndr -> (DmdType, Expr CoreBndr)
dmdAnal AnalEnv
env CleanDemand
dmd Expr CoreBndr
body
(body_ty' :: DmdType
body_ty', id_dmd :: Demand
id_dmd) = AnalEnv -> Bool -> DmdType -> CoreBndr -> (DmdType, Demand)
findBndrDmd AnalEnv
env Bool
notArgOfDfun DmdType
body_ty CoreBndr
id
id' :: CoreBndr
id' = CoreBndr -> Demand -> CoreBndr
setIdDemandInfo CoreBndr
id Demand
id_dmd
(rhs_ty :: BothDmdArg
rhs_ty, rhs' :: Expr CoreBndr
rhs') = AnalEnv -> Demand -> Expr CoreBndr -> (BothDmdArg, Expr CoreBndr)
dmdAnalStar AnalEnv
env (Expr CoreBndr -> Demand -> Demand
dmdTransformThunkDmd Expr CoreBndr
rhs Demand
id_dmd) Expr CoreBndr
rhs
final_ty :: DmdType
final_ty = DmdType
body_ty' DmdType -> BothDmdArg -> DmdType
`bothDmdType` BothDmdArg
rhs_ty
dmdAnal' env :: AnalEnv
env dmd :: CleanDemand
dmd (Let (NonRec id :: CoreBndr
id rhs :: Expr CoreBndr
rhs) body :: Expr CoreBndr
body)
= (DmdType
body_ty2, CoreBind -> Expr CoreBndr -> Expr CoreBndr
forall b. Bind b -> Expr b -> Expr b
Let (CoreBndr -> Expr CoreBndr -> CoreBind
forall b. b -> Expr b -> Bind b
NonRec CoreBndr
id2 Expr CoreBndr
rhs') Expr CoreBndr
body')
where
(lazy_fv :: DmdEnv
lazy_fv, id1 :: CoreBndr
id1, rhs' :: Expr CoreBndr
rhs') = TopLevelFlag
-> Maybe [CoreBndr]
-> AnalEnv
-> CleanDemand
-> CoreBndr
-> Expr CoreBndr
-> (DmdEnv, CoreBndr, Expr CoreBndr)
dmdAnalRhsLetDown TopLevelFlag
NotTopLevel Maybe [CoreBndr]
forall a. Maybe a
Nothing AnalEnv
env CleanDemand
dmd CoreBndr
id Expr CoreBndr
rhs
env1 :: AnalEnv
env1 = TopLevelFlag -> AnalEnv -> CoreBndr -> StrictSig -> AnalEnv
extendAnalEnv TopLevelFlag
NotTopLevel AnalEnv
env CoreBndr
id1 (CoreBndr -> StrictSig
idStrictness CoreBndr
id1)
(body_ty :: DmdType
body_ty, body' :: Expr CoreBndr
body') = AnalEnv -> CleanDemand -> Expr CoreBndr -> (DmdType, Expr CoreBndr)
dmdAnal AnalEnv
env1 CleanDemand
dmd Expr CoreBndr
body
(body_ty1 :: DmdType
body_ty1, id2 :: CoreBndr
id2) = AnalEnv -> DmdType -> CoreBndr -> (DmdType, CoreBndr)
annotateBndr AnalEnv
env DmdType
body_ty CoreBndr
id1
body_ty2 :: DmdType
body_ty2 = DmdType -> DmdEnv -> DmdType
addLazyFVs DmdType
body_ty1 DmdEnv
lazy_fv
dmdAnal' env :: AnalEnv
env dmd :: CleanDemand
dmd (Let (Rec pairs :: [(CoreBndr, Expr CoreBndr)]
pairs) body :: Expr CoreBndr
body)
= let
(env' :: AnalEnv
env', lazy_fv :: DmdEnv
lazy_fv, pairs' :: [(CoreBndr, Expr CoreBndr)]
pairs') = TopLevelFlag
-> AnalEnv
-> CleanDemand
-> [(CoreBndr, Expr CoreBndr)]
-> (AnalEnv, DmdEnv, [(CoreBndr, Expr CoreBndr)])
dmdFix TopLevelFlag
NotTopLevel AnalEnv
env CleanDemand
dmd [(CoreBndr, Expr CoreBndr)]
pairs
(body_ty :: DmdType
body_ty, body' :: Expr CoreBndr
body') = AnalEnv -> CleanDemand -> Expr CoreBndr -> (DmdType, Expr CoreBndr)
dmdAnal AnalEnv
env' CleanDemand
dmd Expr CoreBndr
body
body_ty1 :: DmdType
body_ty1 = DmdType -> [CoreBndr] -> DmdType
deleteFVs DmdType
body_ty (((CoreBndr, Expr CoreBndr) -> CoreBndr)
-> [(CoreBndr, Expr CoreBndr)] -> [CoreBndr]
forall a b. (a -> b) -> [a] -> [b]
map (CoreBndr, Expr CoreBndr) -> CoreBndr
forall a b. (a, b) -> a
fst [(CoreBndr, Expr CoreBndr)]
pairs)
body_ty2 :: DmdType
body_ty2 = DmdType -> DmdEnv -> DmdType
addLazyFVs DmdType
body_ty1 DmdEnv
lazy_fv
in
DmdType
body_ty2 DmdType -> (DmdType, Expr CoreBndr) -> (DmdType, Expr CoreBndr)
forall a b. a -> b -> b
`seq`
(DmdType
body_ty2, CoreBind -> Expr CoreBndr -> Expr CoreBndr
forall b. Bind b -> Expr b -> Expr b
Let ([(CoreBndr, Expr CoreBndr)] -> CoreBind
forall b. [(b, Expr b)] -> Bind b
Rec [(CoreBndr, Expr CoreBndr)]
pairs') Expr CoreBndr
body')
io_hack_reqd :: CoreExpr -> DataCon -> [Var] -> Bool
io_hack_reqd :: Expr CoreBndr -> DataCon -> [CoreBndr] -> Bool
io_hack_reqd scrut :: Expr CoreBndr
scrut con :: DataCon
con bndrs :: [CoreBndr]
bndrs
| (bndr :: CoreBndr
bndr:_) <- [CoreBndr]
bndrs
, DataCon
con DataCon -> DataCon -> Bool
forall a. Eq a => a -> a -> Bool
== Boxity -> Int -> DataCon
tupleDataCon Boxity
Unboxed 2
, CoreBndr -> Type
idType CoreBndr
bndr Type -> Type -> Bool
`eqType` Type
realWorldStatePrimTy
, (fun :: Expr CoreBndr
fun, _) <- Expr CoreBndr -> (Expr CoreBndr, [Expr CoreBndr])
forall b. Expr b -> (Expr b, [Expr b])
collectArgs Expr CoreBndr
scrut
= case Expr CoreBndr
fun of
Var f :: CoreBndr
f -> Bool -> Bool
not (CoreBndr -> Bool
isPrimOpId CoreBndr
f)
_ -> Bool
True
| Bool
otherwise
= Bool
False
dmdAnalAlt :: AnalEnv -> CleanDemand -> Id -> Alt Var -> (DmdType, Alt Var)
dmdAnalAlt :: AnalEnv
-> CleanDemand
-> CoreBndr
-> Alt CoreBndr
-> (DmdType, Alt CoreBndr)
dmdAnalAlt env :: AnalEnv
env dmd :: CleanDemand
dmd case_bndr :: CoreBndr
case_bndr (con :: AltCon
con,bndrs :: [CoreBndr]
bndrs,rhs :: Expr CoreBndr
rhs)
| [CoreBndr] -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null [CoreBndr]
bndrs
, (rhs_ty :: DmdType
rhs_ty, rhs' :: Expr CoreBndr
rhs') <- AnalEnv -> CleanDemand -> Expr CoreBndr -> (DmdType, Expr CoreBndr)
dmdAnal AnalEnv
env CleanDemand
dmd Expr CoreBndr
rhs
= (DmdType
rhs_ty, (AltCon
con, [], Expr CoreBndr
rhs'))
| Bool
otherwise
, (rhs_ty :: DmdType
rhs_ty, rhs' :: Expr CoreBndr
rhs') <- AnalEnv -> CleanDemand -> Expr CoreBndr -> (DmdType, Expr CoreBndr)
dmdAnal AnalEnv
env CleanDemand
dmd Expr CoreBndr
rhs
, (alt_ty :: DmdType
alt_ty, dmds :: [Demand]
dmds) <- AnalEnv -> DmdType -> [CoreBndr] -> (DmdType, [Demand])
findBndrsDmds AnalEnv
env DmdType
rhs_ty [CoreBndr]
bndrs
, let case_bndr_dmd :: Demand
case_bndr_dmd = DmdType -> CoreBndr -> Demand
findIdDemand DmdType
alt_ty CoreBndr
case_bndr
id_dmds :: [Demand]
id_dmds = Demand -> [Demand] -> [Demand]
addCaseBndrDmd Demand
case_bndr_dmd [Demand]
dmds
= (DmdType
alt_ty, (AltCon
con, [CoreBndr] -> [Demand] -> [CoreBndr]
setBndrsDemandInfo [CoreBndr]
bndrs [Demand]
id_dmds, Expr CoreBndr
rhs'))
dmdTransform :: AnalEnv
-> Id
-> CleanDemand
-> DmdType
dmdTransform :: AnalEnv -> CoreBndr -> CleanDemand -> DmdType
dmdTransform env :: AnalEnv
env var :: CoreBndr
var dmd :: CleanDemand
dmd
| CoreBndr -> Bool
isDataConWorkId CoreBndr
var
= Int -> StrictSig -> CleanDemand -> DmdType
dmdTransformDataConSig (CoreBndr -> Int
idArity CoreBndr
var) (CoreBndr -> StrictSig
idStrictness CoreBndr
var) CleanDemand
dmd
| GeneralFlag -> DynFlags -> Bool
gopt GeneralFlag
Opt_DmdTxDictSel (AnalEnv -> DynFlags
ae_dflags AnalEnv
env),
Just _ <- CoreBndr -> Maybe Class
isClassOpId_maybe CoreBndr
var
= StrictSig -> CleanDemand -> DmdType
dmdTransformDictSelSig (CoreBndr -> StrictSig
idStrictness CoreBndr
var) CleanDemand
dmd
| CoreBndr -> Bool
isGlobalId CoreBndr
var
= let res :: DmdType
res = StrictSig -> CleanDemand -> DmdType
dmdTransformSig (CoreBndr -> StrictSig
idStrictness CoreBndr
var) CleanDemand
dmd in
DmdType
res
| Just (sig :: StrictSig
sig, top_lvl :: TopLevelFlag
top_lvl) <- AnalEnv -> CoreBndr -> Maybe (StrictSig, TopLevelFlag)
lookupSigEnv AnalEnv
env CoreBndr
var
, let fn_ty :: DmdType
fn_ty = StrictSig -> CleanDemand -> DmdType
dmdTransformSig StrictSig
sig CleanDemand
dmd
=
if TopLevelFlag -> Bool
isTopLevel TopLevelFlag
top_lvl
then DmdType
fn_ty
else DmdType -> CoreBndr -> Demand -> DmdType
addVarDmd DmdType
fn_ty CoreBndr
var (CleanDemand -> Demand
mkOnceUsedDmd CleanDemand
dmd)
| Bool
otherwise
= DmdEnv -> DmdType
unitDmdType (CoreBndr -> Demand -> DmdEnv
forall a. CoreBndr -> a -> VarEnv a
unitVarEnv CoreBndr
var (CleanDemand -> Demand
mkOnceUsedDmd CleanDemand
dmd))
dmdFix :: TopLevelFlag
-> AnalEnv
-> CleanDemand
-> [(Id,CoreExpr)]
-> (AnalEnv, DmdEnv, [(Id,CoreExpr)])
dmdFix :: TopLevelFlag
-> AnalEnv
-> CleanDemand
-> [(CoreBndr, Expr CoreBndr)]
-> (AnalEnv, DmdEnv, [(CoreBndr, Expr CoreBndr)])
dmdFix top_lvl :: TopLevelFlag
top_lvl env :: AnalEnv
env let_dmd :: CleanDemand
let_dmd orig_pairs :: [(CoreBndr, Expr CoreBndr)]
orig_pairs
= Int
-> [(CoreBndr, Expr CoreBndr)]
-> (AnalEnv, DmdEnv, [(CoreBndr, Expr CoreBndr)])
loop 1 [(CoreBndr, Expr CoreBndr)]
initial_pairs
where
bndrs :: [CoreBndr]
bndrs = ((CoreBndr, Expr CoreBndr) -> CoreBndr)
-> [(CoreBndr, Expr CoreBndr)] -> [CoreBndr]
forall a b. (a -> b) -> [a] -> [b]
map (CoreBndr, Expr CoreBndr) -> CoreBndr
forall a b. (a, b) -> a
fst [(CoreBndr, Expr CoreBndr)]
orig_pairs
initial_pairs :: [(CoreBndr, Expr CoreBndr)]
initial_pairs | AnalEnv -> Bool
ae_virgin AnalEnv
env = [(CoreBndr -> StrictSig -> CoreBndr
setIdStrictness CoreBndr
id StrictSig
botSig, Expr CoreBndr
rhs) | (id :: CoreBndr
id, rhs :: Expr CoreBndr
rhs) <- [(CoreBndr, Expr CoreBndr)]
orig_pairs ]
| Bool
otherwise = [(CoreBndr, Expr CoreBndr)]
orig_pairs
abort :: (AnalEnv, DmdEnv, [(Id,CoreExpr)])
abort :: (AnalEnv, DmdEnv, [(CoreBndr, Expr CoreBndr)])
abort = (AnalEnv
env, DmdEnv
lazy_fv', [(CoreBndr, Expr CoreBndr)]
zapped_pairs)
where (lazy_fv :: DmdEnv
lazy_fv, pairs' :: [(CoreBndr, Expr CoreBndr)]
pairs') = Bool
-> [(CoreBndr, Expr CoreBndr)]
-> (DmdEnv, [(CoreBndr, Expr CoreBndr)])
step Bool
True ([(CoreBndr, Expr CoreBndr)] -> [(CoreBndr, Expr CoreBndr)]
zapIdStrictness [(CoreBndr, Expr CoreBndr)]
orig_pairs)
non_lazy_fvs :: DmdEnv
non_lazy_fvs = [DmdEnv] -> DmdEnv
forall a. [VarEnv a] -> VarEnv a
plusVarEnvList ([DmdEnv] -> DmdEnv) -> [DmdEnv] -> DmdEnv
forall a b. (a -> b) -> a -> b
$ ((CoreBndr, Expr CoreBndr) -> DmdEnv)
-> [(CoreBndr, Expr CoreBndr)] -> [DmdEnv]
forall a b. (a -> b) -> [a] -> [b]
map (StrictSig -> DmdEnv
strictSigDmdEnv (StrictSig -> DmdEnv)
-> ((CoreBndr, Expr CoreBndr) -> StrictSig)
-> (CoreBndr, Expr CoreBndr)
-> DmdEnv
forall b c a. (b -> c) -> (a -> b) -> a -> c
. CoreBndr -> StrictSig
idStrictness (CoreBndr -> StrictSig)
-> ((CoreBndr, Expr CoreBndr) -> CoreBndr)
-> (CoreBndr, Expr CoreBndr)
-> StrictSig
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (CoreBndr, Expr CoreBndr) -> CoreBndr
forall a b. (a, b) -> a
fst) [(CoreBndr, Expr CoreBndr)]
pairs'
lazy_fv' :: DmdEnv
lazy_fv' = DmdEnv
lazy_fv DmdEnv -> DmdEnv -> DmdEnv
forall a. VarEnv a -> VarEnv a -> VarEnv a
`plusVarEnv` (Demand -> Demand) -> DmdEnv -> DmdEnv
forall a b. (a -> b) -> VarEnv a -> VarEnv b
mapVarEnv (Demand -> Demand -> Demand
forall a b. a -> b -> a
const Demand
topDmd) DmdEnv
non_lazy_fvs
zapped_pairs :: [(CoreBndr, Expr CoreBndr)]
zapped_pairs = [(CoreBndr, Expr CoreBndr)] -> [(CoreBndr, Expr CoreBndr)]
zapIdStrictness [(CoreBndr, Expr CoreBndr)]
pairs'
loop :: Int -> [(Id,CoreExpr)] -> (AnalEnv, DmdEnv, [(Id,CoreExpr)])
loop :: Int
-> [(CoreBndr, Expr CoreBndr)]
-> (AnalEnv, DmdEnv, [(CoreBndr, Expr CoreBndr)])
loop n :: Int
n pairs :: [(CoreBndr, Expr CoreBndr)]
pairs
| Bool
found_fixpoint = (AnalEnv
final_anal_env, DmdEnv
lazy_fv, [(CoreBndr, Expr CoreBndr)]
pairs')
| Int
n Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== 10 = (AnalEnv, DmdEnv, [(CoreBndr, Expr CoreBndr)])
abort
| Bool
otherwise = Int
-> [(CoreBndr, Expr CoreBndr)]
-> (AnalEnv, DmdEnv, [(CoreBndr, Expr CoreBndr)])
loop (Int
nInt -> Int -> Int
forall a. Num a => a -> a -> a
+1) [(CoreBndr, Expr CoreBndr)]
pairs'
where
found_fixpoint :: Bool
found_fixpoint = ((CoreBndr, Expr CoreBndr) -> StrictSig)
-> [(CoreBndr, Expr CoreBndr)] -> [StrictSig]
forall a b. (a -> b) -> [a] -> [b]
map (CoreBndr -> StrictSig
idStrictness (CoreBndr -> StrictSig)
-> ((CoreBndr, Expr CoreBndr) -> CoreBndr)
-> (CoreBndr, Expr CoreBndr)
-> StrictSig
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (CoreBndr, Expr CoreBndr) -> CoreBndr
forall a b. (a, b) -> a
fst) [(CoreBndr, Expr CoreBndr)]
pairs' [StrictSig] -> [StrictSig] -> Bool
forall a. Eq a => a -> a -> Bool
== ((CoreBndr, Expr CoreBndr) -> StrictSig)
-> [(CoreBndr, Expr CoreBndr)] -> [StrictSig]
forall a b. (a -> b) -> [a] -> [b]
map (CoreBndr -> StrictSig
idStrictness (CoreBndr -> StrictSig)
-> ((CoreBndr, Expr CoreBndr) -> CoreBndr)
-> (CoreBndr, Expr CoreBndr)
-> StrictSig
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (CoreBndr, Expr CoreBndr) -> CoreBndr
forall a b. (a, b) -> a
fst) [(CoreBndr, Expr CoreBndr)]
pairs
first_round :: Bool
first_round = Int
n Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== 1
(lazy_fv :: DmdEnv
lazy_fv, pairs' :: [(CoreBndr, Expr CoreBndr)]
pairs') = Bool
-> [(CoreBndr, Expr CoreBndr)]
-> (DmdEnv, [(CoreBndr, Expr CoreBndr)])
step Bool
first_round [(CoreBndr, Expr CoreBndr)]
pairs
final_anal_env :: AnalEnv
final_anal_env = TopLevelFlag -> AnalEnv -> [CoreBndr] -> AnalEnv
extendAnalEnvs TopLevelFlag
top_lvl AnalEnv
env (((CoreBndr, Expr CoreBndr) -> CoreBndr)
-> [(CoreBndr, Expr CoreBndr)] -> [CoreBndr]
forall a b. (a -> b) -> [a] -> [b]
map (CoreBndr, Expr CoreBndr) -> CoreBndr
forall a b. (a, b) -> a
fst [(CoreBndr, Expr CoreBndr)]
pairs')
step :: Bool -> [(Id, CoreExpr)] -> (DmdEnv, [(Id, CoreExpr)])
step :: Bool
-> [(CoreBndr, Expr CoreBndr)]
-> (DmdEnv, [(CoreBndr, Expr CoreBndr)])
step first_round :: Bool
first_round pairs :: [(CoreBndr, Expr CoreBndr)]
pairs = (DmdEnv
lazy_fv, [(CoreBndr, Expr CoreBndr)]
pairs')
where
start_env :: AnalEnv
start_env | Bool
first_round = AnalEnv
env
| Bool
otherwise = AnalEnv -> AnalEnv
nonVirgin AnalEnv
env
start :: (AnalEnv, DmdEnv)
start = (TopLevelFlag -> AnalEnv -> [CoreBndr] -> AnalEnv
extendAnalEnvs TopLevelFlag
top_lvl AnalEnv
start_env (((CoreBndr, Expr CoreBndr) -> CoreBndr)
-> [(CoreBndr, Expr CoreBndr)] -> [CoreBndr]
forall a b. (a -> b) -> [a] -> [b]
map (CoreBndr, Expr CoreBndr) -> CoreBndr
forall a b. (a, b) -> a
fst [(CoreBndr, Expr CoreBndr)]
pairs), DmdEnv
emptyDmdEnv)
((_,lazy_fv :: DmdEnv
lazy_fv), pairs' :: [(CoreBndr, Expr CoreBndr)]
pairs') = ((AnalEnv, DmdEnv)
-> (CoreBndr, Expr CoreBndr)
-> ((AnalEnv, DmdEnv), (CoreBndr, Expr CoreBndr)))
-> (AnalEnv, DmdEnv)
-> [(CoreBndr, Expr CoreBndr)]
-> ((AnalEnv, DmdEnv), [(CoreBndr, Expr CoreBndr)])
forall (t :: * -> *) a b c.
Traversable t =>
(a -> b -> (a, c)) -> a -> t b -> (a, t c)
mapAccumL (AnalEnv, DmdEnv)
-> (CoreBndr, Expr CoreBndr)
-> ((AnalEnv, DmdEnv), (CoreBndr, Expr CoreBndr))
my_downRhs (AnalEnv, DmdEnv)
start [(CoreBndr, Expr CoreBndr)]
pairs
my_downRhs :: (AnalEnv, DmdEnv)
-> (CoreBndr, Expr CoreBndr)
-> ((AnalEnv, DmdEnv), (CoreBndr, Expr CoreBndr))
my_downRhs (env :: AnalEnv
env, lazy_fv :: DmdEnv
lazy_fv) (id :: CoreBndr
id,rhs :: Expr CoreBndr
rhs)
= ((AnalEnv
env', DmdEnv
lazy_fv'), (CoreBndr
id', Expr CoreBndr
rhs'))
where
(lazy_fv1 :: DmdEnv
lazy_fv1, id' :: CoreBndr
id', rhs' :: Expr CoreBndr
rhs') = TopLevelFlag
-> Maybe [CoreBndr]
-> AnalEnv
-> CleanDemand
-> CoreBndr
-> Expr CoreBndr
-> (DmdEnv, CoreBndr, Expr CoreBndr)
dmdAnalRhsLetDown TopLevelFlag
top_lvl ([CoreBndr] -> Maybe [CoreBndr]
forall a. a -> Maybe a
Just [CoreBndr]
bndrs) AnalEnv
env CleanDemand
let_dmd CoreBndr
id Expr CoreBndr
rhs
lazy_fv' :: DmdEnv
lazy_fv' = (Demand -> Demand -> Demand) -> DmdEnv -> DmdEnv -> DmdEnv
forall a. (a -> a -> a) -> VarEnv a -> VarEnv a -> VarEnv a
plusVarEnv_C Demand -> Demand -> Demand
bothDmd DmdEnv
lazy_fv DmdEnv
lazy_fv1
env' :: AnalEnv
env' = TopLevelFlag -> AnalEnv -> CoreBndr -> StrictSig -> AnalEnv
extendAnalEnv TopLevelFlag
top_lvl AnalEnv
env CoreBndr
id (CoreBndr -> StrictSig
idStrictness CoreBndr
id')
zapIdStrictness :: [(Id, CoreExpr)] -> [(Id, CoreExpr)]
zapIdStrictness :: [(CoreBndr, Expr CoreBndr)] -> [(CoreBndr, Expr CoreBndr)]
zapIdStrictness pairs :: [(CoreBndr, Expr CoreBndr)]
pairs = [(CoreBndr -> StrictSig -> CoreBndr
setIdStrictness CoreBndr
id StrictSig
nopSig, Expr CoreBndr
rhs) | (id :: CoreBndr
id, rhs :: Expr CoreBndr
rhs) <- [(CoreBndr, Expr CoreBndr)]
pairs ]
dmdAnalTrivialRhs ::
AnalEnv -> Id -> CoreExpr -> Var ->
(DmdEnv, Id, CoreExpr)
dmdAnalTrivialRhs :: AnalEnv
-> CoreBndr
-> Expr CoreBndr
-> CoreBndr
-> (DmdEnv, CoreBndr, Expr CoreBndr)
dmdAnalTrivialRhs env :: AnalEnv
env id :: CoreBndr
id rhs :: Expr CoreBndr
rhs fn :: CoreBndr
fn
= (DmdEnv
fn_fv, AnalEnv -> CoreBndr -> StrictSig -> CoreBndr
set_idStrictness AnalEnv
env CoreBndr
id StrictSig
fn_str, Expr CoreBndr
rhs)
where
fn_str :: StrictSig
fn_str = AnalEnv -> CoreBndr -> StrictSig
getStrictness AnalEnv
env CoreBndr
fn
fn_fv :: DmdEnv
fn_fv | CoreBndr -> Bool
isLocalId CoreBndr
fn = CoreBndr -> Demand -> DmdEnv
forall a. CoreBndr -> a -> VarEnv a
unitVarEnv CoreBndr
fn Demand
topDmd
| Bool
otherwise = DmdEnv
emptyDmdEnv
dmdAnalRhsLetDown :: TopLevelFlag
-> Maybe [Id]
-> AnalEnv -> CleanDemand
-> Id -> CoreExpr
-> (DmdEnv, Id, CoreExpr)
dmdAnalRhsLetDown :: TopLevelFlag
-> Maybe [CoreBndr]
-> AnalEnv
-> CleanDemand
-> CoreBndr
-> Expr CoreBndr
-> (DmdEnv, CoreBndr, Expr CoreBndr)
dmdAnalRhsLetDown top_lvl :: TopLevelFlag
top_lvl rec_flag :: Maybe [CoreBndr]
rec_flag env :: AnalEnv
env let_dmd :: CleanDemand
let_dmd id :: CoreBndr
id rhs :: Expr CoreBndr
rhs
| Just fn :: CoreBndr
fn <- Expr CoreBndr -> Maybe CoreBndr
unpackTrivial Expr CoreBndr
rhs
= AnalEnv
-> CoreBndr
-> Expr CoreBndr
-> CoreBndr
-> (DmdEnv, CoreBndr, Expr CoreBndr)
dmdAnalTrivialRhs AnalEnv
env CoreBndr
id Expr CoreBndr
rhs CoreBndr
fn
| Bool
otherwise
= (DmdEnv
lazy_fv, CoreBndr
id', [CoreBndr] -> Expr CoreBndr -> Expr CoreBndr
forall b. [b] -> Expr b -> Expr b
mkLams [CoreBndr]
bndrs' Expr CoreBndr
body')
where
(bndrs :: [CoreBndr]
bndrs, body :: Expr CoreBndr
body, body_dmd :: CleanDemand
body_dmd)
= case CoreBndr -> Maybe Int
isJoinId_maybe CoreBndr
id of
Just join_arity :: Int
join_arity
| (bndrs :: [CoreBndr]
bndrs, body :: Expr CoreBndr
body) <- Int -> Expr CoreBndr -> ([CoreBndr], Expr CoreBndr)
forall b. Int -> Expr b -> ([b], Expr b)
collectNBinders Int
join_arity Expr CoreBndr
rhs
-> ([CoreBndr]
bndrs, Expr CoreBndr
body, CleanDemand
let_dmd)
Nothing | (bndrs :: [CoreBndr]
bndrs, body :: Expr CoreBndr
body) <- Expr CoreBndr -> ([CoreBndr], Expr CoreBndr)
forall b. Expr b -> ([b], Expr b)
collectBinders Expr CoreBndr
rhs
-> ([CoreBndr]
bndrs, Expr CoreBndr
body, AnalEnv -> Expr CoreBndr -> CleanDemand
mkBodyDmd AnalEnv
env Expr CoreBndr
body)
env_body :: AnalEnv
env_body = (AnalEnv -> CoreBndr -> AnalEnv)
-> AnalEnv -> [CoreBndr] -> AnalEnv
forall (t :: * -> *) b a.
Foldable t =>
(b -> a -> b) -> b -> t a -> b
foldl' AnalEnv -> CoreBndr -> AnalEnv
extendSigsWithLam AnalEnv
env [CoreBndr]
bndrs
(body_ty :: DmdType
body_ty, body' :: Expr CoreBndr
body') = AnalEnv -> CleanDemand -> Expr CoreBndr -> (DmdType, Expr CoreBndr)
dmdAnal AnalEnv
env_body CleanDemand
body_dmd Expr CoreBndr
body
body_ty' :: DmdType
body_ty' = DmdType -> DmdType
removeDmdTyArgs DmdType
body_ty
(DmdType rhs_fv :: DmdEnv
rhs_fv rhs_dmds :: [Demand]
rhs_dmds rhs_res :: DmdResult
rhs_res, bndrs' :: [CoreBndr]
bndrs')
= AnalEnv -> Bool -> DmdType -> [CoreBndr] -> (DmdType, [CoreBndr])
annotateLamBndrs AnalEnv
env (CoreBndr -> Bool
isDFunId CoreBndr
id) DmdType
body_ty' [CoreBndr]
bndrs
sig_ty :: StrictSig
sig_ty = DmdType -> StrictSig
mkStrictSig (DmdEnv -> [Demand] -> DmdResult -> DmdType
mkDmdType DmdEnv
sig_fv [Demand]
rhs_dmds DmdResult
rhs_res')
id' :: CoreBndr
id' = AnalEnv -> CoreBndr -> StrictSig -> CoreBndr
set_idStrictness AnalEnv
env CoreBndr
id StrictSig
sig_ty
rhs_fv1 :: DmdEnv
rhs_fv1 = case Maybe [CoreBndr]
rec_flag of
Just bs :: [CoreBndr]
bs -> DmdEnv -> DmdEnv
reuseEnv (DmdEnv -> [CoreBndr] -> DmdEnv
forall a. VarEnv a -> [CoreBndr] -> VarEnv a
delVarEnvList DmdEnv
rhs_fv [CoreBndr]
bs)
Nothing -> DmdEnv
rhs_fv
(lazy_fv :: DmdEnv
lazy_fv, sig_fv :: DmdEnv
sig_fv) = Bool -> DmdEnv -> (DmdEnv, DmdEnv)
splitFVs Bool
is_thunk DmdEnv
rhs_fv1
rhs_res' :: DmdResult
rhs_res' = Bool -> Bool -> DmdResult -> DmdResult
trimCPRInfo Bool
trim_all Bool
trim_sums DmdResult
rhs_res
trim_all :: Bool
trim_all = Bool
is_thunk Bool -> Bool -> Bool
&& Bool
not_strict
trim_sums :: Bool
trim_sums = Bool -> Bool
not (TopLevelFlag -> Bool
isTopLevel TopLevelFlag
top_lvl)
is_thunk :: Bool
is_thunk = Bool -> Bool
not (Expr CoreBndr -> Bool
exprIsHNF Expr CoreBndr
rhs) Bool -> Bool -> Bool
&& Bool -> Bool
not (CoreBndr -> Bool
isJoinId CoreBndr
id)
not_strict :: Bool
not_strict
= TopLevelFlag -> Bool
isTopLevel TopLevelFlag
top_lvl
Bool -> Bool -> Bool
|| Maybe [CoreBndr] -> Bool
forall a. Maybe a -> Bool
isJust Maybe [CoreBndr]
rec_flag
Bool -> Bool -> Bool
|| Bool -> Bool
not (Demand -> Bool
forall s u. JointDmd (Str s) (Use u) -> Bool
isStrictDmd (CoreBndr -> Demand
idDemandInfo CoreBndr
id) Bool -> Bool -> Bool
|| AnalEnv -> Bool
ae_virgin AnalEnv
env)
mkBodyDmd :: AnalEnv -> CoreExpr -> CleanDemand
mkBodyDmd :: AnalEnv -> Expr CoreBndr -> CleanDemand
mkBodyDmd env :: AnalEnv
env body :: Expr CoreBndr
body
= case FamInstEnvs
-> Type
-> Maybe (DataCon, [Type], [(Type, StrictnessMark)], Coercion)
deepSplitProductType_maybe (AnalEnv -> FamInstEnvs
ae_fam_envs AnalEnv
env) (Expr CoreBndr -> Type
exprType Expr CoreBndr
body) of
Nothing -> CleanDemand
cleanEvalDmd
Just (dc :: DataCon
dc, _, _, _) -> Int -> CleanDemand
cleanEvalProdDmd (DataCon -> Int
dataConRepArity DataCon
dc)
unpackTrivial :: CoreExpr -> Maybe Id
unpackTrivial :: Expr CoreBndr -> Maybe CoreBndr
unpackTrivial (Var v :: CoreBndr
v) = CoreBndr -> Maybe CoreBndr
forall a. a -> Maybe a
Just CoreBndr
v
unpackTrivial (Cast e :: Expr CoreBndr
e _) = Expr CoreBndr -> Maybe CoreBndr
unpackTrivial Expr CoreBndr
e
unpackTrivial (Lam v :: CoreBndr
v e :: Expr CoreBndr
e) | CoreBndr -> Bool
isTyVar CoreBndr
v = Expr CoreBndr -> Maybe CoreBndr
unpackTrivial Expr CoreBndr
e
unpackTrivial (App e :: Expr CoreBndr
e a :: Expr CoreBndr
a) | Expr CoreBndr -> Bool
forall b. Expr b -> Bool
isTypeArg Expr CoreBndr
a = Expr CoreBndr -> Maybe CoreBndr
unpackTrivial Expr CoreBndr
e
unpackTrivial _ = Maybe CoreBndr
forall a. Maybe a
Nothing
useLetUp :: Var -> CoreExpr -> Bool
useLetUp :: CoreBndr -> Expr CoreBndr -> Bool
useLetUp f :: CoreBndr
f _ | CoreBndr -> Bool
isJoinId CoreBndr
f = Bool
False
useLetUp f :: CoreBndr
f (Lam v :: CoreBndr
v e :: Expr CoreBndr
e) | CoreBndr -> Bool
isTyVar CoreBndr
v = CoreBndr -> Expr CoreBndr -> Bool
useLetUp CoreBndr
f Expr CoreBndr
e
useLetUp _ (Lam _ _) = Bool
False
useLetUp _ _ = Bool
True
unitDmdType :: DmdEnv -> DmdType
unitDmdType :: DmdEnv -> DmdType
unitDmdType dmd_env :: DmdEnv
dmd_env = DmdEnv -> [Demand] -> DmdResult -> DmdType
DmdType DmdEnv
dmd_env [] DmdResult
topRes
coercionDmdEnv :: Coercion -> DmdEnv
coercionDmdEnv :: Coercion -> DmdEnv
coercionDmdEnv co :: Coercion
co = (CoreBndr -> Demand) -> VarEnv CoreBndr -> DmdEnv
forall a b. (a -> b) -> VarEnv a -> VarEnv b
mapVarEnv (Demand -> CoreBndr -> Demand
forall a b. a -> b -> a
const Demand
topDmd) (UniqSet CoreBndr -> VarEnv CoreBndr
forall a. UniqSet a -> UniqFM a
getUniqSet (UniqSet CoreBndr -> VarEnv CoreBndr)
-> UniqSet CoreBndr -> VarEnv CoreBndr
forall a b. (a -> b) -> a -> b
$ Coercion -> UniqSet CoreBndr
coVarsOfCo Coercion
co)
addVarDmd :: DmdType -> Var -> Demand -> DmdType
addVarDmd :: DmdType -> CoreBndr -> Demand -> DmdType
addVarDmd (DmdType fv :: DmdEnv
fv ds :: [Demand]
ds res :: DmdResult
res) var :: CoreBndr
var dmd :: Demand
dmd
= DmdEnv -> [Demand] -> DmdResult -> DmdType
DmdType ((Demand -> Demand -> Demand)
-> DmdEnv -> CoreBndr -> Demand -> DmdEnv
forall a. (a -> a -> a) -> VarEnv a -> CoreBndr -> a -> VarEnv a
extendVarEnv_C Demand -> Demand -> Demand
bothDmd DmdEnv
fv CoreBndr
var Demand
dmd) [Demand]
ds DmdResult
res
addLazyFVs :: DmdType -> DmdEnv -> DmdType
addLazyFVs :: DmdType -> DmdEnv -> DmdType
addLazyFVs dmd_ty :: DmdType
dmd_ty lazy_fvs :: DmdEnv
lazy_fvs
= DmdType
dmd_ty DmdType -> BothDmdArg -> DmdType
`bothDmdType` DmdEnv -> BothDmdArg
mkBothDmdArg DmdEnv
lazy_fvs
setBndrsDemandInfo :: [Var] -> [Demand] -> [Var]
setBndrsDemandInfo :: [CoreBndr] -> [Demand] -> [CoreBndr]
setBndrsDemandInfo (b :: CoreBndr
b:bs :: [CoreBndr]
bs) (d :: Demand
d:ds :: [Demand]
ds)
| CoreBndr -> Bool
isTyVar CoreBndr
b = CoreBndr
b CoreBndr -> [CoreBndr] -> [CoreBndr]
forall a. a -> [a] -> [a]
: [CoreBndr] -> [Demand] -> [CoreBndr]
setBndrsDemandInfo [CoreBndr]
bs (Demand
dDemand -> [Demand] -> [Demand]
forall a. a -> [a] -> [a]
:[Demand]
ds)
| Bool
otherwise = CoreBndr -> Demand -> CoreBndr
setIdDemandInfo CoreBndr
b Demand
d CoreBndr -> [CoreBndr] -> [CoreBndr]
forall a. a -> [a] -> [a]
: [CoreBndr] -> [Demand] -> [CoreBndr]
setBndrsDemandInfo [CoreBndr]
bs [Demand]
ds
setBndrsDemandInfo [] ds :: [Demand]
ds = ASSERT( null ds ) []
setBndrsDemandInfo bs :: [CoreBndr]
bs _ = String -> SDoc -> [CoreBndr]
forall a. HasCallStack => String -> SDoc -> a
pprPanic "setBndrsDemandInfo" ([CoreBndr] -> SDoc
forall a. Outputable a => a -> SDoc
ppr [CoreBndr]
bs)
annotateBndr :: AnalEnv -> DmdType -> Var -> (DmdType, Var)
annotateBndr :: AnalEnv -> DmdType -> CoreBndr -> (DmdType, CoreBndr)
annotateBndr env :: AnalEnv
env dmd_ty :: DmdType
dmd_ty var :: CoreBndr
var
| CoreBndr -> Bool
isId CoreBndr
var = (DmdType
dmd_ty', CoreBndr -> Demand -> CoreBndr
setIdDemandInfo CoreBndr
var Demand
dmd)
| Bool
otherwise = (DmdType
dmd_ty, CoreBndr
var)
where
(dmd_ty' :: DmdType
dmd_ty', dmd :: Demand
dmd) = AnalEnv -> Bool -> DmdType -> CoreBndr -> (DmdType, Demand)
findBndrDmd AnalEnv
env Bool
False DmdType
dmd_ty CoreBndr
var
annotateLamBndrs :: AnalEnv -> DFunFlag -> DmdType -> [Var] -> (DmdType, [Var])
annotateLamBndrs :: AnalEnv -> Bool -> DmdType -> [CoreBndr] -> (DmdType, [CoreBndr])
annotateLamBndrs env :: AnalEnv
env args_of_dfun :: Bool
args_of_dfun ty :: DmdType
ty bndrs :: [CoreBndr]
bndrs = (DmdType -> CoreBndr -> (DmdType, CoreBndr))
-> DmdType -> [CoreBndr] -> (DmdType, [CoreBndr])
forall (t :: * -> *) a b c.
Traversable t =>
(a -> b -> (a, c)) -> a -> t b -> (a, t c)
mapAccumR DmdType -> CoreBndr -> (DmdType, CoreBndr)
annotate DmdType
ty [CoreBndr]
bndrs
where
annotate :: DmdType -> CoreBndr -> (DmdType, CoreBndr)
annotate dmd_ty :: DmdType
dmd_ty bndr :: CoreBndr
bndr
| CoreBndr -> Bool
isId CoreBndr
bndr = AnalEnv -> Bool -> DmdType -> CoreBndr -> (DmdType, CoreBndr)
annotateLamIdBndr AnalEnv
env Bool
args_of_dfun DmdType
dmd_ty CoreBndr
bndr
| Bool
otherwise = (DmdType
dmd_ty, CoreBndr
bndr)
annotateLamIdBndr :: AnalEnv
-> DFunFlag
-> DmdType
-> Id
-> (DmdType,
Id)
annotateLamIdBndr :: AnalEnv -> Bool -> DmdType -> CoreBndr -> (DmdType, CoreBndr)
annotateLamIdBndr env :: AnalEnv
env arg_of_dfun :: Bool
arg_of_dfun dmd_ty :: DmdType
dmd_ty id :: CoreBndr
id
= ASSERT( isId id )
(DmdType
final_ty, CoreBndr -> Demand -> CoreBndr
setIdDemandInfo CoreBndr
id Demand
dmd)
where
final_ty :: DmdType
final_ty = case Unfolding -> Maybe (Expr CoreBndr)
maybeUnfoldingTemplate (CoreBndr -> Unfolding
idUnfolding CoreBndr
id) of
Nothing -> DmdType
main_ty
Just unf :: Expr CoreBndr
unf -> DmdType
main_ty DmdType -> BothDmdArg -> DmdType
`bothDmdType` BothDmdArg
unf_ty
where
(unf_ty :: BothDmdArg
unf_ty, _) = AnalEnv -> Demand -> Expr CoreBndr -> (BothDmdArg, Expr CoreBndr)
dmdAnalStar AnalEnv
env Demand
dmd Expr CoreBndr
unf
main_ty :: DmdType
main_ty = Demand -> DmdType -> DmdType
addDemand Demand
dmd DmdType
dmd_ty'
(dmd_ty' :: DmdType
dmd_ty', dmd :: Demand
dmd) = AnalEnv -> Bool -> DmdType -> CoreBndr -> (DmdType, Demand)
findBndrDmd AnalEnv
env Bool
arg_of_dfun DmdType
dmd_ty CoreBndr
id
deleteFVs :: DmdType -> [Var] -> DmdType
deleteFVs :: DmdType -> [CoreBndr] -> DmdType
deleteFVs (DmdType fvs :: DmdEnv
fvs dmds :: [Demand]
dmds res :: DmdResult
res) bndrs :: [CoreBndr]
bndrs
= DmdEnv -> [Demand] -> DmdResult -> DmdType
DmdType (DmdEnv -> [CoreBndr] -> DmdEnv
forall a. VarEnv a -> [CoreBndr] -> VarEnv a
delVarEnvList DmdEnv
fvs [CoreBndr]
bndrs) [Demand]
dmds DmdResult
res
type DFunFlag = Bool
notArgOfDfun :: DFunFlag
notArgOfDfun :: Bool
notArgOfDfun = Bool
False
data AnalEnv
= AE { AnalEnv -> DynFlags
ae_dflags :: DynFlags
, AnalEnv -> SigEnv
ae_sigs :: SigEnv
, AnalEnv -> Bool
ae_virgin :: Bool
, AnalEnv -> RecTcChecker
ae_rec_tc :: RecTcChecker
, AnalEnv -> FamInstEnvs
ae_fam_envs :: FamInstEnvs
}
type SigEnv = VarEnv (StrictSig, TopLevelFlag)
instance Outputable AnalEnv where
ppr :: AnalEnv -> SDoc
ppr (AE { ae_sigs :: AnalEnv -> SigEnv
ae_sigs = SigEnv
env, ae_virgin :: AnalEnv -> Bool
ae_virgin = Bool
virgin })
= String -> SDoc
text "AE" SDoc -> SDoc -> SDoc
<+> SDoc -> SDoc
braces ([SDoc] -> SDoc
vcat
[ String -> SDoc
text "ae_virgin =" SDoc -> SDoc -> SDoc
<+> Bool -> SDoc
forall a. Outputable a => a -> SDoc
ppr Bool
virgin
, String -> SDoc
text "ae_sigs =" SDoc -> SDoc -> SDoc
<+> SigEnv -> SDoc
forall a. Outputable a => a -> SDoc
ppr SigEnv
env ])
emptyAnalEnv :: DynFlags -> FamInstEnvs -> AnalEnv
emptyAnalEnv :: DynFlags -> FamInstEnvs -> AnalEnv
emptyAnalEnv dflags :: DynFlags
dflags fam_envs :: FamInstEnvs
fam_envs
= AE :: DynFlags
-> SigEnv -> Bool -> RecTcChecker -> FamInstEnvs -> AnalEnv
AE { ae_dflags :: DynFlags
ae_dflags = DynFlags
dflags
, ae_sigs :: SigEnv
ae_sigs = SigEnv
emptySigEnv
, ae_virgin :: Bool
ae_virgin = Bool
True
, ae_rec_tc :: RecTcChecker
ae_rec_tc = RecTcChecker
initRecTc
, ae_fam_envs :: FamInstEnvs
ae_fam_envs = FamInstEnvs
fam_envs
}
emptySigEnv :: SigEnv
emptySigEnv :: SigEnv
emptySigEnv = SigEnv
forall a. VarEnv a
emptyVarEnv
extendAnalEnvs :: TopLevelFlag -> AnalEnv -> [Id] -> AnalEnv
extendAnalEnvs :: TopLevelFlag -> AnalEnv -> [CoreBndr] -> AnalEnv
extendAnalEnvs top_lvl :: TopLevelFlag
top_lvl env :: AnalEnv
env vars :: [CoreBndr]
vars
= AnalEnv
env { ae_sigs :: SigEnv
ae_sigs = TopLevelFlag -> SigEnv -> [CoreBndr] -> SigEnv
extendSigEnvs TopLevelFlag
top_lvl (AnalEnv -> SigEnv
ae_sigs AnalEnv
env) [CoreBndr]
vars }
extendSigEnvs :: TopLevelFlag -> SigEnv -> [Id] -> SigEnv
extendSigEnvs :: TopLevelFlag -> SigEnv -> [CoreBndr] -> SigEnv
extendSigEnvs top_lvl :: TopLevelFlag
top_lvl sigs :: SigEnv
sigs vars :: [CoreBndr]
vars
= SigEnv -> [(CoreBndr, (StrictSig, TopLevelFlag))] -> SigEnv
forall a. VarEnv a -> [(CoreBndr, a)] -> VarEnv a
extendVarEnvList SigEnv
sigs [ (CoreBndr
var, (CoreBndr -> StrictSig
idStrictness CoreBndr
var, TopLevelFlag
top_lvl)) | CoreBndr
var <- [CoreBndr]
vars]
extendAnalEnv :: TopLevelFlag -> AnalEnv -> Id -> StrictSig -> AnalEnv
extendAnalEnv :: TopLevelFlag -> AnalEnv -> CoreBndr -> StrictSig -> AnalEnv
extendAnalEnv top_lvl :: TopLevelFlag
top_lvl env :: AnalEnv
env var :: CoreBndr
var sig :: StrictSig
sig
= AnalEnv
env { ae_sigs :: SigEnv
ae_sigs = TopLevelFlag -> SigEnv -> CoreBndr -> StrictSig -> SigEnv
extendSigEnv TopLevelFlag
top_lvl (AnalEnv -> SigEnv
ae_sigs AnalEnv
env) CoreBndr
var StrictSig
sig }
extendSigEnv :: TopLevelFlag -> SigEnv -> Id -> StrictSig -> SigEnv
extendSigEnv :: TopLevelFlag -> SigEnv -> CoreBndr -> StrictSig -> SigEnv
extendSigEnv top_lvl :: TopLevelFlag
top_lvl sigs :: SigEnv
sigs var :: CoreBndr
var sig :: StrictSig
sig = SigEnv -> CoreBndr -> (StrictSig, TopLevelFlag) -> SigEnv
forall a. VarEnv a -> CoreBndr -> a -> VarEnv a
extendVarEnv SigEnv
sigs CoreBndr
var (StrictSig
sig, TopLevelFlag
top_lvl)
lookupSigEnv :: AnalEnv -> Id -> Maybe (StrictSig, TopLevelFlag)
lookupSigEnv :: AnalEnv -> CoreBndr -> Maybe (StrictSig, TopLevelFlag)
lookupSigEnv env :: AnalEnv
env id :: CoreBndr
id = SigEnv -> CoreBndr -> Maybe (StrictSig, TopLevelFlag)
forall a. VarEnv a -> CoreBndr -> Maybe a
lookupVarEnv (AnalEnv -> SigEnv
ae_sigs AnalEnv
env) CoreBndr
id
getStrictness :: AnalEnv -> Id -> StrictSig
getStrictness :: AnalEnv -> CoreBndr -> StrictSig
getStrictness env :: AnalEnv
env fn :: CoreBndr
fn
| CoreBndr -> Bool
isGlobalId CoreBndr
fn = CoreBndr -> StrictSig
idStrictness CoreBndr
fn
| Just (sig :: StrictSig
sig, _) <- AnalEnv -> CoreBndr -> Maybe (StrictSig, TopLevelFlag)
lookupSigEnv AnalEnv
env CoreBndr
fn = StrictSig
sig
| Bool
otherwise = StrictSig
nopSig
nonVirgin :: AnalEnv -> AnalEnv
nonVirgin :: AnalEnv -> AnalEnv
nonVirgin env :: AnalEnv
env = AnalEnv
env { ae_virgin :: Bool
ae_virgin = Bool
False }
extendSigsWithLam :: AnalEnv -> Id -> AnalEnv
extendSigsWithLam :: AnalEnv -> CoreBndr -> AnalEnv
extendSigsWithLam env :: AnalEnv
env id :: CoreBndr
id
| CoreBndr -> Bool
isId CoreBndr
id
, Demand -> Bool
forall s u. JointDmd (Str s) (Use u) -> Bool
isStrictDmd (CoreBndr -> Demand
idDemandInfo CoreBndr
id) Bool -> Bool -> Bool
|| AnalEnv -> Bool
ae_virgin AnalEnv
env
, Just (dc :: DataCon
dc,_,_,_) <- FamInstEnvs
-> Type
-> Maybe (DataCon, [Type], [(Type, StrictnessMark)], Coercion)
deepSplitProductType_maybe (AnalEnv -> FamInstEnvs
ae_fam_envs AnalEnv
env) (Type
-> Maybe (DataCon, [Type], [(Type, StrictnessMark)], Coercion))
-> Type
-> Maybe (DataCon, [Type], [(Type, StrictnessMark)], Coercion)
forall a b. (a -> b) -> a -> b
$ CoreBndr -> Type
idType CoreBndr
id
= TopLevelFlag -> AnalEnv -> CoreBndr -> StrictSig -> AnalEnv
extendAnalEnv TopLevelFlag
NotTopLevel AnalEnv
env CoreBndr
id (Int -> StrictSig
cprProdSig (DataCon -> Int
dataConRepArity DataCon
dc))
| Bool
otherwise
= AnalEnv
env
extendEnvForProdAlt :: AnalEnv -> CoreExpr -> Id -> DataCon -> [Var] -> AnalEnv
extendEnvForProdAlt :: AnalEnv
-> Expr CoreBndr -> CoreBndr -> DataCon -> [CoreBndr] -> AnalEnv
extendEnvForProdAlt env :: AnalEnv
env scrut :: Expr CoreBndr
scrut case_bndr :: CoreBndr
case_bndr dc :: DataCon
dc bndrs :: [CoreBndr]
bndrs
= (AnalEnv -> (CoreBndr, StrictnessMark) -> AnalEnv)
-> AnalEnv -> [(CoreBndr, StrictnessMark)] -> AnalEnv
forall (t :: * -> *) b a.
Foldable t =>
(b -> a -> b) -> b -> t a -> b
foldl' AnalEnv -> (CoreBndr, StrictnessMark) -> AnalEnv
do_con_arg AnalEnv
env1 [(CoreBndr, StrictnessMark)]
ids_w_strs
where
env1 :: AnalEnv
env1 = TopLevelFlag -> AnalEnv -> CoreBndr -> StrictSig -> AnalEnv
extendAnalEnv TopLevelFlag
NotTopLevel AnalEnv
env CoreBndr
case_bndr StrictSig
case_bndr_sig
ids_w_strs :: [(CoreBndr, StrictnessMark)]
ids_w_strs = (CoreBndr -> Bool) -> [CoreBndr] -> [CoreBndr]
forall a. (a -> Bool) -> [a] -> [a]
filter CoreBndr -> Bool
isId [CoreBndr]
bndrs [CoreBndr] -> [StrictnessMark] -> [(CoreBndr, StrictnessMark)]
forall a b. [a] -> [b] -> [(a, b)]
`zip` DataCon -> [StrictnessMark]
dataConRepStrictness DataCon
dc
case_bndr_sig :: StrictSig
case_bndr_sig = Int -> StrictSig
cprProdSig (DataCon -> Int
dataConRepArity DataCon
dc)
fam_envs :: FamInstEnvs
fam_envs = AnalEnv -> FamInstEnvs
ae_fam_envs AnalEnv
env
do_con_arg :: AnalEnv -> (CoreBndr, StrictnessMark) -> AnalEnv
do_con_arg env :: AnalEnv
env (id :: CoreBndr
id, str :: StrictnessMark
str)
| let is_strict :: Bool
is_strict = Demand -> Bool
forall s u. JointDmd (Str s) (Use u) -> Bool
isStrictDmd (CoreBndr -> Demand
idDemandInfo CoreBndr
id) Bool -> Bool -> Bool
|| StrictnessMark -> Bool
isMarkedStrict StrictnessMark
str
, AnalEnv -> Bool
ae_virgin AnalEnv
env Bool -> Bool -> Bool
|| (Bool
is_var_scrut Bool -> Bool -> Bool
&& Bool
is_strict)
, Just (dc :: DataCon
dc,_,_,_) <- FamInstEnvs
-> Type
-> Maybe (DataCon, [Type], [(Type, StrictnessMark)], Coercion)
deepSplitProductType_maybe FamInstEnvs
fam_envs (Type
-> Maybe (DataCon, [Type], [(Type, StrictnessMark)], Coercion))
-> Type
-> Maybe (DataCon, [Type], [(Type, StrictnessMark)], Coercion)
forall a b. (a -> b) -> a -> b
$ CoreBndr -> Type
idType CoreBndr
id
= TopLevelFlag -> AnalEnv -> CoreBndr -> StrictSig -> AnalEnv
extendAnalEnv TopLevelFlag
NotTopLevel AnalEnv
env CoreBndr
id (Int -> StrictSig
cprProdSig (DataCon -> Int
dataConRepArity DataCon
dc))
| Bool
otherwise
= AnalEnv
env
is_var_scrut :: Bool
is_var_scrut = Expr CoreBndr -> Bool
forall b. Expr b -> Bool
is_var Expr CoreBndr
scrut
is_var :: Expr b -> Bool
is_var (Cast e :: Expr b
e _) = Expr b -> Bool
is_var Expr b
e
is_var (Var v :: CoreBndr
v) = CoreBndr -> Bool
isLocalId CoreBndr
v
is_var _ = Bool
False
findBndrsDmds :: AnalEnv -> DmdType -> [Var] -> (DmdType, [Demand])
findBndrsDmds :: AnalEnv -> DmdType -> [CoreBndr] -> (DmdType, [Demand])
findBndrsDmds env :: AnalEnv
env dmd_ty :: DmdType
dmd_ty bndrs :: [CoreBndr]
bndrs
= DmdType -> [CoreBndr] -> (DmdType, [Demand])
go DmdType
dmd_ty [CoreBndr]
bndrs
where
go :: DmdType -> [CoreBndr] -> (DmdType, [Demand])
go dmd_ty :: DmdType
dmd_ty [] = (DmdType
dmd_ty, [])
go dmd_ty :: DmdType
dmd_ty (b :: CoreBndr
b:bs :: [CoreBndr]
bs)
| CoreBndr -> Bool
isId CoreBndr
b = let (dmd_ty1 :: DmdType
dmd_ty1, dmds :: [Demand]
dmds) = DmdType -> [CoreBndr] -> (DmdType, [Demand])
go DmdType
dmd_ty [CoreBndr]
bs
(dmd_ty2 :: DmdType
dmd_ty2, dmd :: Demand
dmd) = AnalEnv -> Bool -> DmdType -> CoreBndr -> (DmdType, Demand)
findBndrDmd AnalEnv
env Bool
False DmdType
dmd_ty1 CoreBndr
b
in (DmdType
dmd_ty2, Demand
dmd Demand -> [Demand] -> [Demand]
forall a. a -> [a] -> [a]
: [Demand]
dmds)
| Bool
otherwise = DmdType -> [CoreBndr] -> (DmdType, [Demand])
go DmdType
dmd_ty [CoreBndr]
bs
findBndrDmd :: AnalEnv -> Bool -> DmdType -> Id -> (DmdType, Demand)
findBndrDmd :: AnalEnv -> Bool -> DmdType -> CoreBndr -> (DmdType, Demand)
findBndrDmd env :: AnalEnv
env arg_of_dfun :: Bool
arg_of_dfun dmd_ty :: DmdType
dmd_ty id :: CoreBndr
id
= (DmdType
dmd_ty', Demand
dmd')
where
dmd' :: Demand
dmd' = DynFlags -> Demand -> Demand
killUsageDemand (AnalEnv -> DynFlags
ae_dflags AnalEnv
env) (Demand -> Demand) -> Demand -> Demand
forall a b. (a -> b) -> a -> b
$
Demand -> Demand
strictify (Demand -> Demand) -> Demand -> Demand
forall a b. (a -> b) -> a -> b
$
Demand -> TypeShape -> Demand
trimToType Demand
starting_dmd (FamInstEnvs -> Type -> TypeShape
findTypeShape FamInstEnvs
fam_envs Type
id_ty)
(dmd_ty' :: DmdType
dmd_ty', starting_dmd :: Demand
starting_dmd) = DmdType -> CoreBndr -> (DmdType, Demand)
peelFV DmdType
dmd_ty CoreBndr
id
id_ty :: Type
id_ty = CoreBndr -> Type
idType CoreBndr
id
strictify :: Demand -> Demand
strictify dmd :: Demand
dmd
| GeneralFlag -> DynFlags -> Bool
gopt GeneralFlag
Opt_DictsStrict (AnalEnv -> DynFlags
ae_dflags AnalEnv
env)
, Bool -> Bool
not Bool
arg_of_dfun
= Type -> Demand -> Demand
strictifyDictDmd Type
id_ty Demand
dmd
| Bool
otherwise
= Demand
dmd
fam_envs :: FamInstEnvs
fam_envs = AnalEnv -> FamInstEnvs
ae_fam_envs AnalEnv
env
set_idStrictness :: AnalEnv -> Id -> StrictSig -> Id
set_idStrictness :: AnalEnv -> CoreBndr -> StrictSig -> CoreBndr
set_idStrictness env :: AnalEnv
env id :: CoreBndr
id sig :: StrictSig
sig
= CoreBndr -> StrictSig -> CoreBndr
setIdStrictness CoreBndr
id (DynFlags -> StrictSig -> StrictSig
killUsageSig (AnalEnv -> DynFlags
ae_dflags AnalEnv
env) StrictSig
sig)
dumpStrSig :: CoreProgram -> SDoc
dumpStrSig :: CoreProgram -> SDoc
dumpStrSig binds :: CoreProgram
binds = [SDoc] -> SDoc
vcat ((CoreBndr -> SDoc) -> [CoreBndr] -> [SDoc]
forall a b. (a -> b) -> [a] -> [b]
map CoreBndr -> SDoc
printId [CoreBndr]
ids)
where
ids :: [CoreBndr]
ids = (CoreBndr -> CoreBndr -> Ordering) -> [CoreBndr] -> [CoreBndr]
forall a. (a -> a -> Ordering) -> [a] -> [a]
sortBy (Name -> Name -> Ordering
stableNameCmp (Name -> Name -> Ordering)
-> (CoreBndr -> Name) -> CoreBndr -> CoreBndr -> Ordering
forall b c a. (b -> b -> c) -> (a -> b) -> a -> a -> c
`on` CoreBndr -> Name
forall a. NamedThing a => a -> Name
getName) ((CoreBind -> [CoreBndr]) -> CoreProgram -> [CoreBndr]
forall (t :: * -> *) a b. Foldable t => (a -> [b]) -> t a -> [b]
concatMap CoreBind -> [CoreBndr]
forall b. Bind b -> [b]
getIds CoreProgram
binds)
getIds :: Bind b -> [b]
getIds (NonRec i :: b
i _) = [ b
i ]
getIds (Rec bs :: [(b, Expr b)]
bs) = ((b, Expr b) -> b) -> [(b, Expr b)] -> [b]
forall a b. (a -> b) -> [a] -> [b]
map (b, Expr b) -> b
forall a b. (a, b) -> a
fst [(b, Expr b)]
bs
printId :: CoreBndr -> SDoc
printId id :: CoreBndr
id | CoreBndr -> Bool
isExportedId CoreBndr
id = CoreBndr -> SDoc
forall a. Outputable a => a -> SDoc
ppr CoreBndr
id SDoc -> SDoc -> SDoc
<> SDoc
colon SDoc -> SDoc -> SDoc
<+> StrictSig -> SDoc
pprIfaceStrictSig (CoreBndr -> StrictSig
idStrictness CoreBndr
id)
| Bool
otherwise = SDoc
empty