{-# LANGUAGE CPP #-}
module GHC.Core.Opt.DmdAnal
   ( DmdAnalOpts(..)
   , dmdAnalProgram
   )
where
#include "HsVersions.h"
import GHC.Prelude
import GHC.Core.Opt.WorkWrap.Utils
import GHC.Types.Demand   
import GHC.Core
import GHC.Core.Multiplicity ( scaledThing )
import GHC.Utils.Outputable
import GHC.Types.Var.Env
import GHC.Types.Var.Set
import GHC.Types.Basic
import Data.List        ( mapAccumL )
import GHC.Core.DataCon
import GHC.Types.ForeignCall ( isSafeForeignCall )
import GHC.Types.Id
import GHC.Core.Utils
import GHC.Core.TyCon
import GHC.Core.Type
import GHC.Core.FVs      ( rulesRhsFreeIds, bndrRuleAndUnfoldingIds )
import GHC.Core.Coercion ( Coercion, coVarsOfCo )
import GHC.Core.FamInstEnv
import GHC.Core.Opt.Arity ( typeArity )
import GHC.Utils.Misc
import GHC.Utils.Panic
import GHC.Data.Maybe         ( isJust )
import GHC.Builtin.PrimOps
import GHC.Builtin.Types.Prim ( realWorldStatePrimTy )
import GHC.Types.Unique.Set
newtype DmdAnalOpts = DmdAnalOpts
   { DmdAnalOpts -> Bool
dmd_strict_dicts :: Bool 
   }
data WithDmdType a = WithDmdType !DmdType !a
getAnnotated :: WithDmdType a -> a
getAnnotated :: forall a. WithDmdType a -> a
getAnnotated (WithDmdType DmdType
_ a
a) = a
a
data DmdResult a b = R !a !b
dmdAnalProgram :: DmdAnalOpts -> FamInstEnvs -> [CoreRule] -> CoreProgram -> CoreProgram
dmdAnalProgram :: DmdAnalOpts
-> FamInstEnvs -> [CoreRule] -> CoreProgram -> CoreProgram
dmdAnalProgram DmdAnalOpts
opts FamInstEnvs
fam_envs [CoreRule]
rules CoreProgram
binds
  = WithDmdType CoreProgram -> CoreProgram
forall a. WithDmdType a -> a
getAnnotated (WithDmdType CoreProgram -> CoreProgram)
-> WithDmdType CoreProgram -> CoreProgram
forall a b. (a -> b) -> a -> b
$ AnalEnv -> CoreProgram -> WithDmdType CoreProgram
go (DmdAnalOpts -> FamInstEnvs -> AnalEnv
emptyAnalEnv DmdAnalOpts
opts FamInstEnvs
fam_envs) CoreProgram
binds
  where
    
    
    go :: AnalEnv -> CoreProgram -> WithDmdType CoreProgram
go AnalEnv
_   []     = DmdType -> CoreProgram -> WithDmdType CoreProgram
forall a. DmdType -> a -> WithDmdType a
WithDmdType DmdType
nopDmdType []
    go AnalEnv
env (Bind Var
b:CoreProgram
bs) = WithDmdType (DmdResult (Bind Var) CoreProgram)
-> WithDmdType CoreProgram
forall b. WithDmdType (DmdResult b [b]) -> WithDmdType [b]
cons_up (WithDmdType (DmdResult (Bind Var) CoreProgram)
 -> WithDmdType CoreProgram)
-> WithDmdType (DmdResult (Bind Var) CoreProgram)
-> WithDmdType CoreProgram
forall a b. (a -> b) -> a -> b
$ TopLevelFlag
-> AnalEnv
-> SubDemand
-> Bind Var
-> (AnalEnv -> WithDmdType CoreProgram)
-> WithDmdType (DmdResult (Bind Var) CoreProgram)
forall a.
TopLevelFlag
-> AnalEnv
-> SubDemand
-> Bind Var
-> (AnalEnv -> WithDmdType a)
-> WithDmdType (DmdResult (Bind Var) a)
dmdAnalBind TopLevelFlag
TopLevel AnalEnv
env SubDemand
topSubDmd Bind Var
b AnalEnv -> WithDmdType CoreProgram
anal_body
      where
        anal_body :: AnalEnv -> WithDmdType CoreProgram
anal_body AnalEnv
env'
          | WithDmdType DmdType
body_ty CoreProgram
bs' <- AnalEnv -> CoreProgram -> WithDmdType CoreProgram
go AnalEnv
env' CoreProgram
bs
          = DmdType -> CoreProgram -> WithDmdType CoreProgram
forall a. DmdType -> a -> WithDmdType a
WithDmdType (AnalEnv -> DmdType -> [Var] -> DmdType
add_exported_uses AnalEnv
env' DmdType
body_ty (Bind Var -> [Var]
forall b. Bind b -> [b]
bindersOf Bind Var
b)) CoreProgram
bs'
    cons_up :: WithDmdType (DmdResult b [b]) -> WithDmdType [b]
    cons_up :: forall b. WithDmdType (DmdResult b [b]) -> WithDmdType [b]
cons_up (WithDmdType DmdType
dmd_ty (R b
b' [b]
bs')) = DmdType -> [b] -> WithDmdType [b]
forall a. DmdType -> a -> WithDmdType a
WithDmdType DmdType
dmd_ty (b
b' b -> [b] -> [b]
forall a. a -> [a] -> [a]
: [b]
bs')
    add_exported_uses :: AnalEnv -> DmdType -> [Id] -> DmdType
    add_exported_uses :: AnalEnv -> DmdType -> [Var] -> DmdType
add_exported_uses AnalEnv
env = (DmdType -> Var -> DmdType) -> DmdType -> [Var] -> DmdType
forall (t :: * -> *) b a.
Foldable t =>
(b -> a -> b) -> b -> t a -> b
foldl' (AnalEnv -> DmdType -> Var -> DmdType
add_exported_use AnalEnv
env)
    
    
    
    add_exported_use :: AnalEnv -> DmdType -> Id -> DmdType
    add_exported_use :: AnalEnv -> DmdType -> Var -> DmdType
add_exported_use AnalEnv
env DmdType
dmd_ty Var
id
      | Var -> Bool
isExportedId Var
id Bool -> Bool -> Bool
|| Var -> VarSet -> Bool
elemVarSet Var
id VarSet
rule_fvs
      
      = DmdType
dmd_ty DmdType -> PlusDmdArg -> DmdType
`plusDmdType` (PlusDmdArg, CoreExpr) -> PlusDmdArg
forall a b. (a, b) -> a
fst (AnalEnv -> Demand -> CoreExpr -> (PlusDmdArg, CoreExpr)
dmdAnalStar AnalEnv
env Demand
topDmd (Var -> CoreExpr
forall b. Var -> Expr b
Var Var
id))
      | Bool
otherwise
      = DmdType
dmd_ty
    rule_fvs :: IdSet
    rule_fvs :: VarSet
rule_fvs = [CoreRule] -> VarSet
rulesRhsFreeIds [CoreRule]
rules
isInterestingTopLevelFn :: Id -> Bool
isInterestingTopLevelFn :: Var -> Bool
isInterestingTopLevelFn Var
id =
  Type -> [OneShotInfo]
typeArity (Var -> Type
idType Var
id) [OneShotInfo] -> Arity -> Bool
forall a. [a] -> Arity -> Bool
`lengthExceeds` Arity
0
dmdAnalBind
  :: TopLevelFlag
  -> AnalEnv
  -> SubDemand                 
                               
  -> CoreBind
  -> (AnalEnv -> WithDmdType a) 
                               
  -> WithDmdType (DmdResult CoreBind a)
dmdAnalBind :: forall a.
TopLevelFlag
-> AnalEnv
-> SubDemand
-> Bind Var
-> (AnalEnv -> WithDmdType a)
-> WithDmdType (DmdResult (Bind Var) a)
dmdAnalBind TopLevelFlag
top_lvl AnalEnv
env SubDemand
dmd Bind Var
bind AnalEnv -> WithDmdType a
anal_body = case Bind Var
bind of
  NonRec Var
id CoreExpr
rhs
    | TopLevelFlag -> Var -> Bool
useLetUp TopLevelFlag
top_lvl Var
id
    -> TopLevelFlag
-> AnalEnv
-> Var
-> CoreExpr
-> (AnalEnv -> WithDmdType a)
-> WithDmdType (DmdResult (Bind Var) a)
forall a.
TopLevelFlag
-> AnalEnv
-> Var
-> CoreExpr
-> (AnalEnv -> WithDmdType a)
-> WithDmdType (DmdResult (Bind Var) a)
dmdAnalBindLetUp   TopLevelFlag
top_lvl AnalEnv
env     Var
id CoreExpr
rhs AnalEnv -> WithDmdType a
anal_body
  Bind Var
_ -> TopLevelFlag
-> AnalEnv
-> SubDemand
-> Bind Var
-> (AnalEnv -> WithDmdType a)
-> WithDmdType (DmdResult (Bind Var) a)
forall a.
TopLevelFlag
-> AnalEnv
-> SubDemand
-> Bind Var
-> (AnalEnv -> WithDmdType a)
-> WithDmdType (DmdResult (Bind Var) a)
dmdAnalBindLetDown TopLevelFlag
top_lvl AnalEnv
env SubDemand
dmd Bind Var
bind   AnalEnv -> WithDmdType a
anal_body
setBindIdDemandInfo :: TopLevelFlag -> Id -> Demand -> Id
setBindIdDemandInfo :: TopLevelFlag -> Var -> Demand -> Var
setBindIdDemandInfo TopLevelFlag
top_lvl Var
id Demand
dmd = Var -> Demand -> Var
setIdDemandInfo Var
id (Demand -> Var) -> Demand -> Var
forall a b. (a -> b) -> a -> b
$ case TopLevelFlag
top_lvl of
  TopLevelFlag
TopLevel | Bool -> Bool
not (Var -> Bool
isInterestingTopLevelFn Var
id) -> Demand
topDmd
  TopLevelFlag
_                                           -> Demand
dmd
dmdAnalBindLetUp :: TopLevelFlag
                 -> AnalEnv
                 -> Id
                 -> CoreExpr
                 -> (AnalEnv -> WithDmdType a)
                 -> WithDmdType (DmdResult CoreBind a)
dmdAnalBindLetUp :: forall a.
TopLevelFlag
-> AnalEnv
-> Var
-> CoreExpr
-> (AnalEnv -> WithDmdType a)
-> WithDmdType (DmdResult (Bind Var) a)
dmdAnalBindLetUp TopLevelFlag
top_lvl AnalEnv
env Var
id CoreExpr
rhs AnalEnv -> WithDmdType a
anal_body = DmdType
-> DmdResult (Bind Var) a -> WithDmdType (DmdResult (Bind Var) a)
forall a. DmdType -> a -> WithDmdType a
WithDmdType DmdType
final_ty (Bind Var -> a -> DmdResult (Bind Var) a
forall a b. a -> b -> DmdResult a b
R (Var -> CoreExpr -> Bind Var
forall b. b -> Expr b -> Bind b
NonRec Var
id' CoreExpr
rhs') (a
body'))
  where
    WithDmdType DmdType
body_ty a
body'   = AnalEnv -> WithDmdType a
anal_body AnalEnv
env
    WithDmdType DmdType
body_ty' Demand
id_dmd = AnalEnv -> Bool -> DmdType -> Var -> WithDmdType Demand
findBndrDmd AnalEnv
env Bool
notArgOfDfun DmdType
body_ty Var
id
    !id' :: Var
id'                = TopLevelFlag -> Var -> Demand -> Var
setBindIdDemandInfo TopLevelFlag
top_lvl Var
id Demand
id_dmd
    (PlusDmdArg
rhs_ty, CoreExpr
rhs')     = AnalEnv -> Demand -> CoreExpr -> (PlusDmdArg, CoreExpr)
dmdAnalStar AnalEnv
env (CoreExpr -> Demand -> Demand
dmdTransformThunkDmd CoreExpr
rhs Demand
id_dmd) CoreExpr
rhs
    
    rule_fvs :: VarSet
rule_fvs           = Var -> VarSet
bndrRuleAndUnfoldingIds Var
id
    final_ty :: DmdType
final_ty           = DmdType
body_ty' DmdType -> PlusDmdArg -> DmdType
`plusDmdType` PlusDmdArg
rhs_ty DmdType -> VarSet -> DmdType
`keepAliveDmdType` VarSet
rule_fvs
dmdAnalBindLetDown :: TopLevelFlag -> AnalEnv -> SubDemand -> CoreBind -> (AnalEnv -> WithDmdType a) -> WithDmdType (DmdResult CoreBind a)
dmdAnalBindLetDown :: forall a.
TopLevelFlag
-> AnalEnv
-> SubDemand
-> Bind Var
-> (AnalEnv -> WithDmdType a)
-> WithDmdType (DmdResult (Bind Var) a)
dmdAnalBindLetDown TopLevelFlag
top_lvl AnalEnv
env SubDemand
dmd Bind Var
bind AnalEnv -> WithDmdType a
anal_body = case Bind Var
bind of
  NonRec Var
id CoreExpr
rhs
    | (AnalEnv
env', DmdEnv
lazy_fv, Var
id1, CoreExpr
rhs1) <-
        TopLevelFlag
-> RecFlag
-> AnalEnv
-> SubDemand
-> Var
-> CoreExpr
-> (AnalEnv, DmdEnv, Var, CoreExpr)
dmdAnalRhsSig TopLevelFlag
top_lvl RecFlag
NonRecursive AnalEnv
env SubDemand
dmd Var
id CoreExpr
rhs
    -> AnalEnv
-> DmdEnv
-> [(Var, CoreExpr)]
-> ([(Var, CoreExpr)] -> Bind Var)
-> WithDmdType (DmdResult (Bind Var) a)
do_rest AnalEnv
env' DmdEnv
lazy_fv [(Var
id1, CoreExpr
rhs1)] ((Var -> CoreExpr -> Bind Var) -> (Var, CoreExpr) -> Bind Var
forall a b c. (a -> b -> c) -> (a, b) -> c
uncurry Var -> CoreExpr -> Bind Var
forall b. b -> Expr b -> Bind b
NonRec ((Var, CoreExpr) -> Bind Var)
-> ([(Var, CoreExpr)] -> (Var, CoreExpr))
-> [(Var, CoreExpr)]
-> Bind Var
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [(Var, CoreExpr)] -> (Var, CoreExpr)
forall a. [a] -> a
only)
  Rec [(Var, CoreExpr)]
pairs
    | (AnalEnv
env', DmdEnv
lazy_fv, [(Var, CoreExpr)]
pairs') <- TopLevelFlag
-> AnalEnv
-> SubDemand
-> [(Var, CoreExpr)]
-> (AnalEnv, DmdEnv, [(Var, CoreExpr)])
dmdFix TopLevelFlag
top_lvl AnalEnv
env SubDemand
dmd [(Var, CoreExpr)]
pairs
    -> AnalEnv
-> DmdEnv
-> [(Var, CoreExpr)]
-> ([(Var, CoreExpr)] -> Bind Var)
-> WithDmdType (DmdResult (Bind Var) a)
do_rest AnalEnv
env' DmdEnv
lazy_fv [(Var, CoreExpr)]
pairs' [(Var, CoreExpr)] -> Bind Var
forall b. [(b, Expr b)] -> Bind b
Rec
  where
    do_rest :: AnalEnv
-> DmdEnv
-> [(Var, CoreExpr)]
-> ([(Var, CoreExpr)] -> Bind Var)
-> WithDmdType (DmdResult (Bind Var) a)
do_rest AnalEnv
env' DmdEnv
lazy_fv [(Var, CoreExpr)]
pairs1 [(Var, CoreExpr)] -> Bind Var
build_bind = DmdType
-> DmdResult (Bind Var) a -> WithDmdType (DmdResult (Bind Var) a)
forall a. DmdType -> a -> WithDmdType a
WithDmdType DmdType
final_ty (Bind Var -> a -> DmdResult (Bind Var) a
forall a b. a -> b -> DmdResult a b
R ([(Var, CoreExpr)] -> Bind Var
build_bind [(Var, CoreExpr)]
pairs2) a
body')
      where
        WithDmdType DmdType
body_ty a
body'        = AnalEnv -> WithDmdType a
anal_body AnalEnv
env'
        
        dmd_ty :: DmdType
dmd_ty                          = DmdType -> DmdEnv -> DmdType
addLazyFVs DmdType
body_ty DmdEnv
lazy_fv
        WithDmdType DmdType
final_ty [Demand]
id_dmds    = AnalEnv -> DmdType -> [Var] -> WithDmdType [Demand]
findBndrsDmds AnalEnv
env' DmdType
dmd_ty (((Var, CoreExpr) -> Var) -> [(Var, CoreExpr)] -> [Var]
forall a b. (a -> b) -> [a] -> [b]
strictMap (Var, CoreExpr) -> Var
forall a b. (a, b) -> a
fst [(Var, CoreExpr)]
pairs1)
        
        !pairs2 :: [(Var, CoreExpr)]
pairs2                         = ((Var, CoreExpr) -> Demand -> (Var, CoreExpr))
-> [(Var, CoreExpr)] -> [Demand] -> [(Var, CoreExpr)]
forall a b c. (a -> b -> c) -> [a] -> [b] -> [c]
strictZipWith (Var, CoreExpr) -> Demand -> (Var, CoreExpr)
do_one [(Var, CoreExpr)]
pairs1 [Demand]
id_dmds
        do_one :: (Var, CoreExpr) -> Demand -> (Var, CoreExpr)
do_one (Var
id', CoreExpr
rhs') Demand
dmd          = ((,) (Var -> CoreExpr -> (Var, CoreExpr))
-> Var -> CoreExpr -> (Var, CoreExpr)
forall a b. (a -> b) -> a -> b
$! TopLevelFlag -> Var -> Demand -> Var
setBindIdDemandInfo TopLevelFlag
top_lvl Var
id' Demand
dmd) (CoreExpr -> (Var, CoreExpr)) -> CoreExpr -> (Var, CoreExpr)
forall a b. (a -> b) -> a -> b
$! CoreExpr
rhs'
        
        
        
        
        
        
        
        
        
        
        
        
dmdTransformThunkDmd :: CoreExpr -> Demand -> Demand
dmdTransformThunkDmd :: CoreExpr -> Demand -> Demand
dmdTransformThunkDmd CoreExpr
e
  | CoreExpr -> Bool
exprIsTrivial CoreExpr
e = Demand -> Demand
forall a. a -> a
id
  | Bool
otherwise       = Demand -> Demand
oneifyDmd
dmdAnalStar :: AnalEnv
            -> Demand   
            -> CoreExpr 
            -> (PlusDmdArg, CoreExpr)
dmdAnalStar :: AnalEnv -> Demand -> CoreExpr -> (PlusDmdArg, CoreExpr)
dmdAnalStar AnalEnv
env (Card
n :* SubDemand
cd) CoreExpr
e
  | WithDmdType DmdType
dmd_ty CoreExpr
e'    <- AnalEnv -> SubDemand -> CoreExpr -> WithDmdType CoreExpr
dmdAnal AnalEnv
env SubDemand
cd CoreExpr
e
  = ASSERT2( not (isUnliftedType (exprType e)) || exprOkForSpeculation e, ppr e )
    
    
    (DmdType -> PlusDmdArg
toPlusDmdArg (DmdType -> PlusDmdArg) -> DmdType -> PlusDmdArg
forall a b. (a -> b) -> a -> b
$ Card -> DmdType -> DmdType
multDmdType Card
n DmdType
dmd_ty, CoreExpr
e')
dmdAnal, dmdAnal' :: AnalEnv
        -> SubDemand         
        -> CoreExpr -> WithDmdType CoreExpr
dmdAnal :: AnalEnv -> SubDemand -> CoreExpr -> WithDmdType CoreExpr
dmdAnal AnalEnv
env SubDemand
d CoreExpr
e = 
                  AnalEnv -> SubDemand -> CoreExpr -> WithDmdType CoreExpr
dmdAnal' AnalEnv
env SubDemand
d CoreExpr
e
dmdAnal' :: AnalEnv -> SubDemand -> CoreExpr -> WithDmdType CoreExpr
dmdAnal' AnalEnv
_ SubDemand
_ (Lit Literal
lit)     = DmdType -> CoreExpr -> WithDmdType CoreExpr
forall a. DmdType -> a -> WithDmdType a
WithDmdType DmdType
nopDmdType (Literal -> CoreExpr
forall b. Literal -> Expr b
Lit Literal
lit)
dmdAnal' AnalEnv
_ SubDemand
_ (Type Type
ty)     = DmdType -> CoreExpr -> WithDmdType CoreExpr
forall a. DmdType -> a -> WithDmdType a
WithDmdType DmdType
nopDmdType (Type -> CoreExpr
forall b. Type -> Expr b
Type Type
ty) 
dmdAnal' AnalEnv
_ SubDemand
_ (Coercion Coercion
co)
  = DmdType -> CoreExpr -> WithDmdType CoreExpr
forall a. DmdType -> a -> WithDmdType a
WithDmdType (DmdEnv -> DmdType
unitDmdType (Coercion -> DmdEnv
coercionDmdEnv Coercion
co)) (Coercion -> CoreExpr
forall b. Coercion -> Expr b
Coercion Coercion
co)
dmdAnal' AnalEnv
env SubDemand
dmd (Var Var
var)
  = DmdType -> CoreExpr -> WithDmdType CoreExpr
forall a. DmdType -> a -> WithDmdType a
WithDmdType (AnalEnv -> Var -> SubDemand -> DmdType
dmdTransform AnalEnv
env Var
var SubDemand
dmd) (Var -> CoreExpr
forall b. Var -> Expr b
Var Var
var)
dmdAnal' AnalEnv
env SubDemand
dmd (Cast CoreExpr
e Coercion
co)
  = DmdType -> CoreExpr -> WithDmdType CoreExpr
forall a. DmdType -> a -> WithDmdType a
WithDmdType (DmdType
dmd_ty DmdType -> PlusDmdArg -> DmdType
`plusDmdType` DmdEnv -> PlusDmdArg
mkPlusDmdArg (Coercion -> DmdEnv
coercionDmdEnv Coercion
co)) (CoreExpr -> Coercion -> CoreExpr
forall b. Expr b -> Coercion -> Expr b
Cast CoreExpr
e' Coercion
co)
  where
    WithDmdType DmdType
dmd_ty CoreExpr
e' = AnalEnv -> SubDemand -> CoreExpr -> WithDmdType CoreExpr
dmdAnal AnalEnv
env SubDemand
dmd CoreExpr
e
dmdAnal' AnalEnv
env SubDemand
dmd (Tick CoreTickish
t CoreExpr
e)
  = DmdType -> CoreExpr -> WithDmdType CoreExpr
forall a. DmdType -> a -> WithDmdType a
WithDmdType DmdType
dmd_ty (CoreTickish -> CoreExpr -> CoreExpr
forall b. CoreTickish -> Expr b -> Expr b
Tick CoreTickish
t CoreExpr
e')
  where
    WithDmdType DmdType
dmd_ty CoreExpr
e' = AnalEnv -> SubDemand -> CoreExpr -> WithDmdType CoreExpr
dmdAnal AnalEnv
env SubDemand
dmd CoreExpr
e
dmdAnal' AnalEnv
env SubDemand
dmd (App CoreExpr
fun (Type Type
ty))
  = DmdType -> CoreExpr -> WithDmdType CoreExpr
forall a. DmdType -> a -> WithDmdType a
WithDmdType DmdType
fun_ty (CoreExpr -> CoreExpr -> CoreExpr
forall b. Expr b -> Expr b -> Expr b
App CoreExpr
fun' (Type -> CoreExpr
forall b. Type -> Expr b
Type Type
ty))
  where
    WithDmdType DmdType
fun_ty CoreExpr
fun' = AnalEnv -> SubDemand -> CoreExpr -> WithDmdType CoreExpr
dmdAnal AnalEnv
env SubDemand
dmd CoreExpr
fun
dmdAnal' AnalEnv
env SubDemand
dmd (App CoreExpr
fun CoreExpr
arg)
  = 
    
    
    let
        call_dmd :: SubDemand
call_dmd          = SubDemand -> SubDemand
mkCalledOnceDmd SubDemand
dmd
        WithDmdType DmdType
fun_ty CoreExpr
fun' = AnalEnv -> SubDemand -> CoreExpr -> WithDmdType CoreExpr
dmdAnal AnalEnv
env SubDemand
call_dmd CoreExpr
fun
        (Demand
arg_dmd, DmdType
res_ty) = DmdType -> (Demand, DmdType)
splitDmdTy DmdType
fun_ty
        (PlusDmdArg
arg_ty, CoreExpr
arg')    = AnalEnv -> Demand -> CoreExpr -> (PlusDmdArg, CoreExpr)
dmdAnalStar AnalEnv
env (CoreExpr -> Demand -> Demand
dmdTransformThunkDmd CoreExpr
arg Demand
arg_dmd) CoreExpr
arg
    in
    DmdType -> CoreExpr -> WithDmdType CoreExpr
forall a. DmdType -> a -> WithDmdType a
WithDmdType (DmdType
res_ty DmdType -> PlusDmdArg -> DmdType
`plusDmdType` PlusDmdArg
arg_ty) (CoreExpr -> CoreExpr -> CoreExpr
forall b. Expr b -> Expr b -> Expr b
App CoreExpr
fun' CoreExpr
arg')
dmdAnal' AnalEnv
env SubDemand
dmd (Lam Var
var CoreExpr
body)
  | Var -> Bool
isTyVar Var
var
  = let
        WithDmdType DmdType
body_ty CoreExpr
body' = AnalEnv -> SubDemand -> CoreExpr -> WithDmdType CoreExpr
dmdAnal AnalEnv
env SubDemand
dmd CoreExpr
body
    in
    DmdType -> CoreExpr -> WithDmdType CoreExpr
forall a. DmdType -> a -> WithDmdType a
WithDmdType DmdType
body_ty (Var -> CoreExpr -> CoreExpr
forall b. b -> Expr b -> Expr b
Lam Var
var CoreExpr
body')
  | Bool
otherwise
  = let (Card
n, SubDemand
body_dmd)    = SubDemand -> (Card, SubDemand)
peelCallDmd SubDemand
dmd
          
        WithDmdType DmdType
body_ty CoreExpr
body' = AnalEnv -> SubDemand -> CoreExpr -> WithDmdType CoreExpr
dmdAnal AnalEnv
env SubDemand
body_dmd CoreExpr
body
        WithDmdType DmdType
lam_ty Var
var'   = AnalEnv -> Bool -> DmdType -> Var -> WithDmdType Var
annotateLamIdBndr AnalEnv
env Bool
notArgOfDfun DmdType
body_ty Var
var
        new_dmd_type :: DmdType
new_dmd_type = Card -> DmdType -> DmdType
multDmdType Card
n DmdType
lam_ty
    in
    DmdType -> CoreExpr -> WithDmdType CoreExpr
forall a. DmdType -> a -> WithDmdType a
WithDmdType DmdType
new_dmd_type (Var -> CoreExpr -> CoreExpr
forall b. b -> Expr b -> Expr b
Lam Var
var' CoreExpr
body')
dmdAnal' AnalEnv
env SubDemand
dmd (Case CoreExpr
scrut Var
case_bndr Type
ty [Alt AltCon
alt [Var]
bndrs CoreExpr
rhs])
  
  
  | AltCon -> Bool
is_single_data_alt AltCon
alt
  = let
        WithDmdType DmdType
rhs_ty CoreExpr
rhs'           = AnalEnv -> SubDemand -> CoreExpr -> WithDmdType CoreExpr
dmdAnal AnalEnv
env SubDemand
dmd CoreExpr
rhs
        WithDmdType DmdType
alt_ty1 [Demand]
dmds          = AnalEnv -> DmdType -> [Var] -> WithDmdType [Demand]
findBndrsDmds AnalEnv
env DmdType
rhs_ty [Var]
bndrs
        WithDmdType DmdType
alt_ty2 Demand
case_bndr_dmd = AnalEnv -> Bool -> DmdType -> Var -> WithDmdType Demand
findBndrDmd AnalEnv
env Bool
False DmdType
alt_ty1 Var
case_bndr
        
        
        (Card
_ :* SubDemand
case_bndr_sd)      = Demand
case_bndr_dmd
        
        
        
        !(![Var]
bndrs', !SubDemand
scrut_sd)
          | DataAlt DataCon
_ <- AltCon
alt
          , [Demand]
id_dmds <- SubDemand -> [Demand] -> [Demand]
addCaseBndrDmd SubDemand
case_bndr_sd [Demand]
dmds
          
          = let !new_info :: [Var]
new_info = [Var] -> [Demand] -> [Var]
setBndrsDemandInfo [Var]
bndrs [Demand]
id_dmds
                !new_prod :: SubDemand
new_prod = [Demand] -> SubDemand
mkProd [Demand]
id_dmds
            in ([Var]
new_info, SubDemand
new_prod)
          | Bool
otherwise
          
          
          = ASSERT( null bndrs ) (bndrs, case_bndr_sd)
        fam_envs :: FamInstEnvs
fam_envs                 = AnalEnv -> FamInstEnvs
ae_fam_envs AnalEnv
env
        alt_ty3 :: DmdType
alt_ty3
          
          | FamInstEnvs -> CoreExpr -> Bool
exprMayThrowPreciseException FamInstEnvs
fam_envs CoreExpr
scrut
          = DmdType -> DmdType
deferAfterPreciseException DmdType
alt_ty2
          | Bool
otherwise
          = DmdType
alt_ty2
        WithDmdType DmdType
scrut_ty CoreExpr
scrut' = AnalEnv -> SubDemand -> CoreExpr -> WithDmdType CoreExpr
dmdAnal AnalEnv
env SubDemand
scrut_sd CoreExpr
scrut
        res_ty :: DmdType
res_ty             = DmdType
alt_ty3 DmdType -> PlusDmdArg -> DmdType
`plusDmdType` DmdType -> PlusDmdArg
toPlusDmdArg DmdType
scrut_ty
        !case_bndr' :: Var
case_bndr'        = Var -> Demand -> Var
setIdDemandInfo Var
case_bndr Demand
case_bndr_dmd
    in
    DmdType -> CoreExpr -> WithDmdType CoreExpr
forall a. DmdType -> a -> WithDmdType a
WithDmdType DmdType
res_ty (CoreExpr -> Var -> Type -> [Alt Var] -> CoreExpr
forall b. Expr b -> b -> Type -> [Alt b] -> Expr b
Case CoreExpr
scrut' Var
case_bndr' Type
ty [AltCon -> [Var] -> CoreExpr -> Alt Var
forall b. AltCon -> [b] -> Expr b -> Alt b
Alt AltCon
alt [Var]
bndrs' CoreExpr
rhs'])
    where
      is_single_data_alt :: AltCon -> Bool
is_single_data_alt (DataAlt DataCon
dc) = Maybe DataCon -> Bool
forall a. Maybe a -> Bool
isJust (Maybe DataCon -> Bool) -> Maybe DataCon -> Bool
forall a b. (a -> b) -> a -> b
$ TyCon -> Maybe DataCon
tyConSingleAlgDataCon_maybe (TyCon -> Maybe DataCon) -> TyCon -> Maybe DataCon
forall a b. (a -> b) -> a -> b
$ DataCon -> TyCon
dataConTyCon DataCon
dc
      is_single_data_alt AltCon
_            = Bool
True
dmdAnal' AnalEnv
env SubDemand
dmd (Case CoreExpr
scrut Var
case_bndr Type
ty [Alt Var]
alts)
  = let      
        WithDmdType DmdType
alt_ty [Alt Var]
alts'     = [Alt Var] -> WithDmdType [Alt Var]
combineAltDmds [Alt Var]
alts
        combineAltDmds :: [Alt Var] -> WithDmdType [Alt Var]
combineAltDmds [] = DmdType -> [Alt Var] -> WithDmdType [Alt Var]
forall a. DmdType -> a -> WithDmdType a
WithDmdType DmdType
botDmdType []
        combineAltDmds (Alt Var
a:[Alt Var]
as) =
          let
            WithDmdType DmdType
cur_ty Alt Var
a' = AnalEnv -> SubDemand -> Var -> Alt Var -> WithDmdType (Alt Var)
dmdAnalSumAlt AnalEnv
env SubDemand
dmd Var
case_bndr Alt Var
a
            WithDmdType DmdType
rest_ty [Alt Var]
as' = [Alt Var] -> WithDmdType [Alt Var]
combineAltDmds [Alt Var]
as
          in DmdType -> [Alt Var] -> WithDmdType [Alt Var]
forall a. DmdType -> a -> WithDmdType a
WithDmdType (DmdType -> DmdType -> DmdType
lubDmdType DmdType
cur_ty DmdType
rest_ty) (Alt Var
a'Alt Var -> [Alt Var] -> [Alt Var]
forall a. a -> [a] -> [a]
:[Alt Var]
as')
        WithDmdType DmdType
scrut_ty CoreExpr
scrut'   = AnalEnv -> SubDemand -> CoreExpr -> WithDmdType CoreExpr
dmdAnal AnalEnv
env SubDemand
topSubDmd CoreExpr
scrut
        WithDmdType DmdType
alt_ty1 Var
case_bndr' = AnalEnv -> DmdType -> Var -> WithDmdType Var
annotateBndr AnalEnv
env DmdType
alt_ty Var
case_bndr
                               
                               
                               
        fam_envs :: FamInstEnvs
fam_envs             = AnalEnv -> FamInstEnvs
ae_fam_envs AnalEnv
env
        alt_ty2 :: DmdType
alt_ty2
          
          | FamInstEnvs -> CoreExpr -> Bool
exprMayThrowPreciseException FamInstEnvs
fam_envs CoreExpr
scrut
          = DmdType -> DmdType
deferAfterPreciseException DmdType
alt_ty1
          | Bool
otherwise
          = DmdType
alt_ty1
        res_ty :: DmdType
res_ty               = DmdType
alt_ty2 DmdType -> PlusDmdArg -> DmdType
`plusDmdType` DmdType -> PlusDmdArg
toPlusDmdArg DmdType
scrut_ty
    in
    DmdType -> CoreExpr -> WithDmdType CoreExpr
forall a. DmdType -> a -> WithDmdType a
WithDmdType DmdType
res_ty (CoreExpr -> Var -> Type -> [Alt Var] -> CoreExpr
forall b. Expr b -> b -> Type -> [Alt b] -> Expr b
Case CoreExpr
scrut' Var
case_bndr' Type
ty [Alt Var]
alts')
dmdAnal' AnalEnv
env SubDemand
dmd (Let Bind Var
bind CoreExpr
body)
  = DmdType -> CoreExpr -> WithDmdType CoreExpr
forall a. DmdType -> a -> WithDmdType a
WithDmdType DmdType
final_ty (Bind Var -> CoreExpr -> CoreExpr
forall b. Bind b -> Expr b -> Expr b
Let Bind Var
bind' CoreExpr
body')
  where
    !(WithDmdType DmdType
final_ty (R Bind Var
bind' CoreExpr
body')) = TopLevelFlag
-> AnalEnv
-> SubDemand
-> Bind Var
-> (AnalEnv -> WithDmdType CoreExpr)
-> WithDmdType (DmdResult (Bind Var) CoreExpr)
forall a.
TopLevelFlag
-> AnalEnv
-> SubDemand
-> Bind Var
-> (AnalEnv -> WithDmdType a)
-> WithDmdType (DmdResult (Bind Var) a)
dmdAnalBind TopLevelFlag
NotTopLevel AnalEnv
env SubDemand
dmd Bind Var
bind AnalEnv -> WithDmdType CoreExpr
go'
    go' :: AnalEnv -> WithDmdType CoreExpr
go' !AnalEnv
env'                 = AnalEnv -> SubDemand -> CoreExpr -> WithDmdType CoreExpr
dmdAnal AnalEnv
env' SubDemand
dmd CoreExpr
body
exprMayThrowPreciseException :: FamInstEnvs -> CoreExpr -> Bool
exprMayThrowPreciseException :: FamInstEnvs -> CoreExpr -> Bool
exprMayThrowPreciseException FamInstEnvs
envs CoreExpr
e
  | Bool -> Bool
not (FamInstEnvs -> Type -> Bool
forcesRealWorld FamInstEnvs
envs (CoreExpr -> Type
exprType CoreExpr
e))
  = Bool
False 
  | (Var Var
f, [CoreExpr]
_) <- CoreExpr -> (CoreExpr, [CoreExpr])
forall b. Expr b -> (Expr b, [Expr b])
collectArgs CoreExpr
e
  , Just PrimOp
op    <- Var -> Maybe PrimOp
isPrimOpId_maybe Var
f
  , PrimOp
op PrimOp -> PrimOp -> Bool
forall a. Eq a => a -> a -> Bool
/= PrimOp
RaiseIOOp
  = Bool
False 
  | (Var Var
f, [CoreExpr]
_) <- CoreExpr -> (CoreExpr, [CoreExpr])
forall b. Expr b -> (Expr b, [Expr b])
collectArgs CoreExpr
e
  , Just ForeignCall
fcall <- Var -> Maybe ForeignCall
isFCallId_maybe Var
f
  , Bool -> Bool
not (ForeignCall -> Bool
isSafeForeignCall ForeignCall
fcall)
  = Bool
False 
  | Bool
otherwise
  = Bool
True  
forcesRealWorld :: FamInstEnvs -> Type -> Bool
forcesRealWorld :: FamInstEnvs -> Type -> Bool
forcesRealWorld FamInstEnvs
fam_envs Type
ty
  | Type
ty Type -> Type -> Bool
`eqType` Type
realWorldStatePrimTy
  = Bool
True
  | Just DataConPatContext{ dcpc_dc :: DataConPatContext -> DataCon
dcpc_dc = DataCon
dc, dcpc_tc_args :: DataConPatContext -> [Type]
dcpc_tc_args = [Type]
tc_args }
      <- FamInstEnvs -> Type -> Maybe DataConPatContext
splitArgType_maybe FamInstEnvs
fam_envs Type
ty
  , DataCon -> Bool
isUnboxedTupleDataCon DataCon
dc
  , let field_tys :: [Scaled Type]
field_tys = DataCon -> [Type] -> [Scaled Type]
dataConInstArgTys DataCon
dc [Type]
tc_args
  = (Scaled Type -> Bool) -> [Scaled Type] -> Bool
forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
any (Type -> Type -> Bool
eqType Type
realWorldStatePrimTy (Type -> Bool) -> (Scaled Type -> Type) -> Scaled Type -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Scaled Type -> Type
forall a. Scaled a -> a
scaledThing) [Scaled Type]
field_tys
  | Bool
otherwise
  = Bool
False
dmdAnalSumAlt :: AnalEnv -> SubDemand -> Id -> Alt Var -> WithDmdType (Alt Var)
dmdAnalSumAlt :: AnalEnv -> SubDemand -> Var -> Alt Var -> WithDmdType (Alt Var)
dmdAnalSumAlt AnalEnv
env SubDemand
dmd Var
case_bndr (Alt AltCon
con [Var]
bndrs CoreExpr
rhs)
  | WithDmdType DmdType
rhs_ty CoreExpr
rhs' <- AnalEnv -> SubDemand -> CoreExpr -> WithDmdType CoreExpr
dmdAnal AnalEnv
env SubDemand
dmd CoreExpr
rhs
  , WithDmdType DmdType
alt_ty [Demand]
dmds <- AnalEnv -> DmdType -> [Var] -> WithDmdType [Demand]
findBndrsDmds AnalEnv
env DmdType
rhs_ty [Var]
bndrs
  , let (Card
_ :* SubDemand
case_bndr_sd) = DmdType -> Var -> Demand
findIdDemand DmdType
alt_ty Var
case_bndr
        
        id_dmds :: [Demand]
id_dmds             = SubDemand -> [Demand] -> [Demand]
addCaseBndrDmd SubDemand
case_bndr_sd [Demand]
dmds
        
        !new_ids :: [Var]
new_ids  = [Var] -> [Demand] -> [Var]
setBndrsDemandInfo [Var]
bndrs [Demand]
id_dmds
  = DmdType -> Alt Var -> WithDmdType (Alt Var)
forall a. DmdType -> a -> WithDmdType a
WithDmdType DmdType
alt_ty (AltCon -> [Var] -> CoreExpr -> Alt Var
forall b. AltCon -> [b] -> Expr b -> Alt b
Alt AltCon
con [Var]
new_ids CoreExpr
rhs')
dmdTransform :: AnalEnv         
             -> Id              
             -> SubDemand       
             -> DmdType         
                                
                                
dmdTransform :: AnalEnv -> Var -> SubDemand -> DmdType
dmdTransform AnalEnv
env Var
var SubDemand
dmd
  
  | Var -> Bool
isDataConWorkId Var
var
  = Arity -> SubDemand -> DmdType
dmdTransformDataConSig (Var -> Arity
idArity Var
var) SubDemand
dmd
  
  
  
  | Just Class
_ <- Var -> Maybe Class
isClassOpId_maybe Var
var
  = 
    StrictSig -> SubDemand -> DmdType
dmdTransformDictSelSig (Var -> StrictSig
idStrictness Var
var) SubDemand
dmd
  
  | Var -> Bool
isGlobalId Var
var
  , let res :: DmdType
res = StrictSig -> SubDemand -> DmdType
dmdTransformSig (Var -> StrictSig
idStrictness Var
var) SubDemand
dmd
  = 
    DmdType
res
  
  
  | Just (StrictSig
sig, TopLevelFlag
top_lvl) <- AnalEnv -> Var -> Maybe (StrictSig, TopLevelFlag)
lookupSigEnv AnalEnv
env Var
var
  , let fn_ty :: DmdType
fn_ty = StrictSig -> SubDemand -> DmdType
dmdTransformSig StrictSig
sig SubDemand
dmd
  = 
    case TopLevelFlag
top_lvl of
      TopLevelFlag
NotTopLevel -> DmdType -> Var -> Demand -> DmdType
addVarDmd DmdType
fn_ty Var
var (Card
C_11 Card -> SubDemand -> Demand
:* SubDemand
dmd)
      TopLevelFlag
TopLevel
        | Var -> Bool
isInterestingTopLevelFn Var
var
        
        
        
        
        -> DmdType -> Var -> Demand -> DmdType
addVarDmd DmdType
fn_ty Var
var (Card
C_0N Card -> Demand -> Demand
`multDmd` (Card
C_11 Card -> SubDemand -> Demand
:* SubDemand
dmd)) 
        | Bool
otherwise
        -> DmdType
fn_ty 
  
  
  
  
  | Bool
otherwise
  = 
    DmdEnv -> DmdType
unitDmdType (Var -> Demand -> DmdEnv
forall a. Var -> a -> VarEnv a
unitVarEnv Var
var (Card
C_11 Card -> SubDemand -> Demand
:* SubDemand
dmd))
dmdAnalRhsSig
  :: TopLevelFlag
  -> RecFlag
  -> AnalEnv -> SubDemand
  -> Id -> CoreExpr
  -> (AnalEnv, DmdEnv, Id, CoreExpr)
dmdAnalRhsSig :: TopLevelFlag
-> RecFlag
-> AnalEnv
-> SubDemand
-> Var
-> CoreExpr
-> (AnalEnv, DmdEnv, Var, CoreExpr)
dmdAnalRhsSig TopLevelFlag
top_lvl RecFlag
rec_flag AnalEnv
env SubDemand
let_dmd Var
id CoreExpr
rhs
  = 
    (AnalEnv
env', DmdEnv
lazy_fv, Var
id', CoreExpr
rhs')
  where
    rhs_arity :: Arity
rhs_arity = Var -> Arity
idArity Var
id
    
    rhs_dmd :: SubDemand
rhs_dmd 
            
            
            | Var -> Bool
isJoinId Var
id
            = Arity -> SubDemand -> SubDemand
mkCalledOnceDmds Arity
rhs_arity SubDemand
let_dmd
            | Bool
otherwise
            = Arity -> SubDemand -> SubDemand
mkCalledOnceDmds Arity
rhs_arity SubDemand
topSubDmd
    WithDmdType DmdType
rhs_dmd_ty CoreExpr
rhs' = AnalEnv -> SubDemand -> CoreExpr -> WithDmdType CoreExpr
dmdAnal AnalEnv
env SubDemand
rhs_dmd CoreExpr
rhs
    DmdType DmdEnv
rhs_fv [Demand]
rhs_dmds Divergence
rhs_div = DmdType
rhs_dmd_ty
    sig :: StrictSig
sig = Arity -> DmdType -> StrictSig
mkStrictSigForArity Arity
rhs_arity (DmdEnv -> [Demand] -> Divergence -> DmdType
DmdType DmdEnv
sig_fv [Demand]
rhs_dmds Divergence
rhs_div)
    id' :: Var
id' = Var
id Var -> StrictSig -> Var
`setIdStrictness` StrictSig
sig
    !env' :: AnalEnv
env' = TopLevelFlag -> AnalEnv -> Var -> StrictSig -> AnalEnv
extendAnalEnv TopLevelFlag
top_lvl AnalEnv
env Var
id' StrictSig
sig
    
    
    
    
    
    
    
    
    
    
    
    rhs_fv1 :: DmdEnv
rhs_fv1 = case RecFlag
rec_flag of
                RecFlag
Recursive    -> DmdEnv -> DmdEnv
reuseEnv DmdEnv
rhs_fv
                RecFlag
NonRecursive -> DmdEnv
rhs_fv
    
    rhs_fv2 :: DmdEnv
rhs_fv2 = DmdEnv
rhs_fv1 DmdEnv -> VarSet -> DmdEnv
`keepAliveDmdEnv` Var -> VarSet
bndrRuleAndUnfoldingIds Var
id
    
    !(!DmdEnv
lazy_fv, !DmdEnv
sig_fv) = (Demand -> Bool) -> DmdEnv -> (DmdEnv, DmdEnv)
forall a. (a -> Bool) -> VarEnv a -> (VarEnv a, VarEnv a)
partitionVarEnv Demand -> Bool
isWeakDmd DmdEnv
rhs_fv2
useLetUp :: TopLevelFlag -> Var -> Bool
useLetUp :: TopLevelFlag -> Var -> Bool
useLetUp TopLevelFlag
top_lvl Var
f = TopLevelFlag -> Bool
isNotTopLevel TopLevelFlag
top_lvl Bool -> Bool -> Bool
&& Var -> Arity
idArity Var
f Arity -> Arity -> Bool
forall a. Eq a => a -> a -> Bool
== Arity
0 Bool -> Bool -> Bool
&& Bool -> Bool
not (Var -> Bool
isJoinId Var
f)
dmdFix :: TopLevelFlag
       -> AnalEnv                            
       -> SubDemand
       -> [(Id,CoreExpr)]
       -> (AnalEnv, DmdEnv, [(Id,CoreExpr)]) 
dmdFix :: TopLevelFlag
-> AnalEnv
-> SubDemand
-> [(Var, CoreExpr)]
-> (AnalEnv, DmdEnv, [(Var, CoreExpr)])
dmdFix TopLevelFlag
top_lvl AnalEnv
env SubDemand
let_dmd [(Var, CoreExpr)]
orig_pairs
  = Arity -> [(Var, CoreExpr)] -> (AnalEnv, DmdEnv, [(Var, CoreExpr)])
loop Arity
1 [(Var, CoreExpr)]
initial_pairs
  where
    
    initial_pairs :: [(Var, CoreExpr)]
initial_pairs | AnalEnv -> Bool
ae_virgin AnalEnv
env = [(Var -> StrictSig -> Var
setIdStrictness Var
id StrictSig
botSig, CoreExpr
rhs) | (Var
id, CoreExpr
rhs) <- [(Var, CoreExpr)]
orig_pairs ]
                  | Bool
otherwise     = [(Var, CoreExpr)]
orig_pairs
    
    
    abort :: (AnalEnv, DmdEnv, [(Id,CoreExpr)])
    abort :: (AnalEnv, DmdEnv, [(Var, CoreExpr)])
abort = (AnalEnv
env, DmdEnv
lazy_fv', [(Var, CoreExpr)]
zapped_pairs)
      where (DmdEnv
lazy_fv, [(Var, CoreExpr)]
pairs') = Bool -> [(Var, CoreExpr)] -> (DmdEnv, [(Var, CoreExpr)])
step Bool
True ([(Var, CoreExpr)] -> [(Var, CoreExpr)]
zapIdStrictness [(Var, CoreExpr)]
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
$ ((Var, CoreExpr) -> DmdEnv) -> [(Var, CoreExpr)] -> [DmdEnv]
forall a b. (a -> b) -> [a] -> [b]
map (StrictSig -> DmdEnv
strictSigDmdEnv (StrictSig -> DmdEnv)
-> ((Var, CoreExpr) -> StrictSig) -> (Var, CoreExpr) -> DmdEnv
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Var -> StrictSig
idStrictness (Var -> StrictSig)
-> ((Var, CoreExpr) -> Var) -> (Var, CoreExpr) -> StrictSig
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Var, CoreExpr) -> Var
forall a b. (a, b) -> a
fst) [(Var, CoreExpr)]
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 :: [(Var, CoreExpr)]
zapped_pairs = [(Var, CoreExpr)] -> [(Var, CoreExpr)]
zapIdStrictness [(Var, CoreExpr)]
pairs'
    
    
    loop :: Int -> [(Id,CoreExpr)] -> (AnalEnv, DmdEnv, [(Id,CoreExpr)])
    loop :: Arity -> [(Var, CoreExpr)] -> (AnalEnv, DmdEnv, [(Var, CoreExpr)])
loop Arity
n [(Var, CoreExpr)]
pairs = 
                   
                   Arity -> [(Var, CoreExpr)] -> (AnalEnv, DmdEnv, [(Var, CoreExpr)])
loop' Arity
n [(Var, CoreExpr)]
pairs
    loop' :: Arity -> [(Var, CoreExpr)] -> (AnalEnv, DmdEnv, [(Var, CoreExpr)])
loop' Arity
n [(Var, CoreExpr)]
pairs
      | Bool
found_fixpoint = (AnalEnv
final_anal_env, DmdEnv
lazy_fv, [(Var, CoreExpr)]
pairs')
      | Arity
n Arity -> Arity -> Bool
forall a. Eq a => a -> a -> Bool
== Arity
10        = (AnalEnv, DmdEnv, [(Var, CoreExpr)])
abort
      | Bool
otherwise      = Arity -> [(Var, CoreExpr)] -> (AnalEnv, DmdEnv, [(Var, CoreExpr)])
loop (Arity
nArity -> Arity -> Arity
forall a. Num a => a -> a -> a
+Arity
1) [(Var, CoreExpr)]
pairs'
      where
        found_fixpoint :: Bool
found_fixpoint    = ((Var, CoreExpr) -> StrictSig) -> [(Var, CoreExpr)] -> [StrictSig]
forall a b. (a -> b) -> [a] -> [b]
map (Var -> StrictSig
idStrictness (Var -> StrictSig)
-> ((Var, CoreExpr) -> Var) -> (Var, CoreExpr) -> StrictSig
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Var, CoreExpr) -> Var
forall a b. (a, b) -> a
fst) [(Var, CoreExpr)]
pairs' [StrictSig] -> [StrictSig] -> Bool
forall a. Eq a => a -> a -> Bool
== ((Var, CoreExpr) -> StrictSig) -> [(Var, CoreExpr)] -> [StrictSig]
forall a b. (a -> b) -> [a] -> [b]
map (Var -> StrictSig
idStrictness (Var -> StrictSig)
-> ((Var, CoreExpr) -> Var) -> (Var, CoreExpr) -> StrictSig
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Var, CoreExpr) -> Var
forall a b. (a, b) -> a
fst) [(Var, CoreExpr)]
pairs
        first_round :: Bool
first_round       = Arity
n Arity -> Arity -> Bool
forall a. Eq a => a -> a -> Bool
== Arity
1
        (DmdEnv
lazy_fv, [(Var, CoreExpr)]
pairs') = Bool -> [(Var, CoreExpr)] -> (DmdEnv, [(Var, CoreExpr)])
step Bool
first_round [(Var, CoreExpr)]
pairs
        final_anal_env :: AnalEnv
final_anal_env    = TopLevelFlag -> AnalEnv -> [Var] -> AnalEnv
extendAnalEnvs TopLevelFlag
top_lvl AnalEnv
env (((Var, CoreExpr) -> Var) -> [(Var, CoreExpr)] -> [Var]
forall a b. (a -> b) -> [a] -> [b]
map (Var, CoreExpr) -> Var
forall a b. (a, b) -> a
fst [(Var, CoreExpr)]
pairs')
    step :: Bool -> [(Id, CoreExpr)] -> (DmdEnv, [(Id, CoreExpr)])
    step :: Bool -> [(Var, CoreExpr)] -> (DmdEnv, [(Var, CoreExpr)])
step Bool
first_round [(Var, CoreExpr)]
pairs = (DmdEnv
lazy_fv, [(Var, CoreExpr)]
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 -> [Var] -> AnalEnv
extendAnalEnvs TopLevelFlag
top_lvl AnalEnv
start_env (((Var, CoreExpr) -> Var) -> [(Var, CoreExpr)] -> [Var]
forall a b. (a -> b) -> [a] -> [b]
map (Var, CoreExpr) -> Var
forall a b. (a, b) -> a
fst [(Var, CoreExpr)]
pairs), DmdEnv
forall a. VarEnv a
emptyVarEnv)
        !((AnalEnv
_,!DmdEnv
lazy_fv), ![(Var, CoreExpr)]
pairs') = ((AnalEnv, DmdEnv)
 -> (Var, CoreExpr) -> ((AnalEnv, DmdEnv), (Var, CoreExpr)))
-> (AnalEnv, DmdEnv)
-> [(Var, CoreExpr)]
-> ((AnalEnv, DmdEnv), [(Var, CoreExpr)])
forall (t :: * -> *) s a b.
Traversable t =>
(s -> a -> (s, b)) -> s -> t a -> (s, t b)
mapAccumL (AnalEnv, DmdEnv)
-> (Var, CoreExpr) -> ((AnalEnv, DmdEnv), (Var, CoreExpr))
my_downRhs (AnalEnv, DmdEnv)
start [(Var, CoreExpr)]
pairs
                
                
                
        my_downRhs :: (AnalEnv, DmdEnv)
-> (Var, CoreExpr) -> ((AnalEnv, DmdEnv), (Var, CoreExpr))
my_downRhs (AnalEnv
env, DmdEnv
lazy_fv) (Var
id,CoreExpr
rhs)
          = 
            ((AnalEnv
env', DmdEnv
lazy_fv'), (Var
id', CoreExpr
rhs'))
          where
            !(!AnalEnv
env', !DmdEnv
lazy_fv1, !Var
id', !CoreExpr
rhs') = TopLevelFlag
-> RecFlag
-> AnalEnv
-> SubDemand
-> Var
-> CoreExpr
-> (AnalEnv, DmdEnv, Var, CoreExpr)
dmdAnalRhsSig TopLevelFlag
top_lvl RecFlag
Recursive AnalEnv
env SubDemand
let_dmd Var
id CoreExpr
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
plusDmd DmdEnv
lazy_fv DmdEnv
lazy_fv1
    zapIdStrictness :: [(Id, CoreExpr)] -> [(Id, CoreExpr)]
    zapIdStrictness :: [(Var, CoreExpr)] -> [(Var, CoreExpr)]
zapIdStrictness [(Var, CoreExpr)]
pairs = [(Var -> StrictSig -> Var
setIdStrictness Var
id StrictSig
nopSig, CoreExpr
rhs) | (Var
id, CoreExpr
rhs) <- [(Var, CoreExpr)]
pairs ]
unitDmdType :: DmdEnv -> DmdType
unitDmdType :: DmdEnv -> DmdType
unitDmdType DmdEnv
dmd_env = DmdEnv -> [Demand] -> Divergence -> DmdType
DmdType DmdEnv
dmd_env [] Divergence
topDiv
coercionDmdEnv :: Coercion -> DmdEnv
coercionDmdEnv :: Coercion -> DmdEnv
coercionDmdEnv Coercion
co = (Var -> Demand) -> VarEnv Var -> DmdEnv
forall a b. (a -> b) -> VarEnv a -> VarEnv b
mapVarEnv (Demand -> Var -> Demand
forall a b. a -> b -> a
const Demand
topDmd) (VarSet -> VarEnv Var
forall a. UniqSet a -> UniqFM a a
getUniqSet (VarSet -> VarEnv Var) -> VarSet -> VarEnv Var
forall a b. (a -> b) -> a -> b
$ Coercion -> VarSet
coVarsOfCo Coercion
co)
                    
addVarDmd :: DmdType -> Var -> Demand -> DmdType
addVarDmd :: DmdType -> Var -> Demand -> DmdType
addVarDmd (DmdType DmdEnv
fv [Demand]
ds Divergence
res) Var
var Demand
dmd
  = DmdEnv -> [Demand] -> Divergence -> DmdType
DmdType ((Demand -> Demand -> Demand) -> DmdEnv -> Var -> Demand -> DmdEnv
forall a. (a -> a -> a) -> VarEnv a -> Var -> a -> VarEnv a
extendVarEnv_C Demand -> Demand -> Demand
plusDmd DmdEnv
fv Var
var Demand
dmd) [Demand]
ds Divergence
res
addLazyFVs :: DmdType -> DmdEnv -> DmdType
addLazyFVs :: DmdType -> DmdEnv -> DmdType
addLazyFVs DmdType
dmd_ty DmdEnv
lazy_fvs
  = DmdType
dmd_ty DmdType -> PlusDmdArg -> DmdType
`plusDmdType` DmdEnv -> PlusDmdArg
mkPlusDmdArg DmdEnv
lazy_fvs
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
setBndrsDemandInfo :: [Var] -> [Demand] -> [Var]
setBndrsDemandInfo :: [Var] -> [Demand] -> [Var]
setBndrsDemandInfo (Var
b:[Var]
bs) [Demand]
ds
  | Var -> Bool
isTyVar Var
b = Var
b Var -> [Var] -> [Var]
forall a. a -> [a] -> [a]
: [Var] -> [Demand] -> [Var]
setBndrsDemandInfo [Var]
bs [Demand]
ds
setBndrsDemandInfo (Var
b:[Var]
bs) (Demand
d:[Demand]
ds) =
    let !new_info :: Var
new_info = Var -> Demand -> Var
setIdDemandInfo Var
b Demand
d
        !vars :: [Var]
vars = [Var] -> [Demand] -> [Var]
setBndrsDemandInfo [Var]
bs [Demand]
ds
    in Var
new_info Var -> [Var] -> [Var]
forall a. a -> [a] -> [a]
: [Var]
vars
setBndrsDemandInfo [] [Demand]
ds = ASSERT( null ds ) []
setBndrsDemandInfo [Var]
bs [Demand]
_  = String -> SDoc -> [Var]
forall a. HasCallStack => String -> SDoc -> a
pprPanic String
"setBndrsDemandInfo" ([Var] -> SDoc
forall a. Outputable a => a -> SDoc
ppr [Var]
bs)
annotateBndr :: AnalEnv -> DmdType -> Var -> WithDmdType Var
annotateBndr :: AnalEnv -> DmdType -> Var -> WithDmdType Var
annotateBndr AnalEnv
env DmdType
dmd_ty Var
var
  | Var -> Bool
isId Var
var  = DmdType -> Var -> WithDmdType Var
forall a. DmdType -> a -> WithDmdType a
WithDmdType DmdType
dmd_ty' Var
new_id
  | Bool
otherwise = DmdType -> Var -> WithDmdType Var
forall a. DmdType -> a -> WithDmdType a
WithDmdType DmdType
dmd_ty  Var
var
  where
    new_id :: Var
new_id = Var -> Demand -> Var
setIdDemandInfo Var
var Demand
dmd
    WithDmdType DmdType
dmd_ty' Demand
dmd = AnalEnv -> Bool -> DmdType -> Var -> WithDmdType Demand
findBndrDmd AnalEnv
env Bool
False DmdType
dmd_ty Var
var
annotateLamIdBndr :: AnalEnv
                  -> DFunFlag   
                  -> DmdType    
                  -> Id         
                  -> WithDmdType Id  
                                     
annotateLamIdBndr :: AnalEnv -> Bool -> DmdType -> Var -> WithDmdType Var
annotateLamIdBndr AnalEnv
env Bool
arg_of_dfun DmdType
dmd_ty Var
id
  = ASSERT( isId id )
    
    DmdType -> Var -> WithDmdType Var
forall a. DmdType -> a -> WithDmdType a
WithDmdType DmdType
final_ty Var
new_id
  where
    new_id :: Var
new_id = Var -> Demand -> Var
setIdDemandInfo Var
id Demand
dmd
      
    final_ty :: DmdType
final_ty = case Unfolding -> Maybe CoreExpr
maybeUnfoldingTemplate (Var -> Unfolding
idUnfolding Var
id) of
                 Maybe CoreExpr
Nothing  -> DmdType
main_ty
                 Just CoreExpr
unf -> DmdType
main_ty DmdType -> PlusDmdArg -> DmdType
`plusDmdType` PlusDmdArg
unf_ty
                          where
                             (PlusDmdArg
unf_ty, CoreExpr
_) = AnalEnv -> Demand -> CoreExpr -> (PlusDmdArg, CoreExpr)
dmdAnalStar AnalEnv
env Demand
dmd CoreExpr
unf
    main_ty :: DmdType
main_ty = Demand -> DmdType -> DmdType
addDemand Demand
dmd DmdType
dmd_ty'
    WithDmdType DmdType
dmd_ty' Demand
dmd = AnalEnv -> Bool -> DmdType -> Var -> WithDmdType Demand
findBndrDmd AnalEnv
env Bool
arg_of_dfun DmdType
dmd_ty Var
id
type DFunFlag = Bool  
                      
notArgOfDfun :: DFunFlag
notArgOfDfun :: Bool
notArgOfDfun = Bool
False
data AnalEnv = AE
   { AnalEnv -> Bool
ae_strict_dicts :: !Bool 
   , AnalEnv -> SigEnv
ae_sigs         :: !SigEnv
   , AnalEnv -> Bool
ae_virgin       :: !Bool 
                              
   , AnalEnv -> FamInstEnvs
ae_fam_envs     :: !FamInstEnvs
   }
        
        
        
        
        
        
type SigEnv = VarEnv (StrictSig, TopLevelFlag)
instance Outputable AnalEnv where
  ppr :: AnalEnv -> SDoc
ppr AnalEnv
env = String -> SDoc
text String
"AE" SDoc -> SDoc -> SDoc
<+> SDoc -> SDoc
braces ([SDoc] -> SDoc
vcat
         [ String -> SDoc
text String
"ae_virgin =" SDoc -> SDoc -> SDoc
<+> Bool -> SDoc
forall a. Outputable a => a -> SDoc
ppr (AnalEnv -> Bool
ae_virgin AnalEnv
env)
         , String -> SDoc
text String
"ae_strict_dicts =" SDoc -> SDoc -> SDoc
<+> Bool -> SDoc
forall a. Outputable a => a -> SDoc
ppr (AnalEnv -> Bool
ae_strict_dicts AnalEnv
env)
         , String -> SDoc
text String
"ae_sigs =" SDoc -> SDoc -> SDoc
<+> SigEnv -> SDoc
forall a. Outputable a => a -> SDoc
ppr (AnalEnv -> SigEnv
ae_sigs AnalEnv
env)
         ])
emptyAnalEnv :: DmdAnalOpts -> FamInstEnvs -> AnalEnv
emptyAnalEnv :: DmdAnalOpts -> FamInstEnvs -> AnalEnv
emptyAnalEnv DmdAnalOpts
opts FamInstEnvs
fam_envs
    = AE { ae_strict_dicts :: Bool
ae_strict_dicts = DmdAnalOpts -> Bool
dmd_strict_dicts DmdAnalOpts
opts
         , ae_sigs :: SigEnv
ae_sigs         = SigEnv
emptySigEnv
         , ae_virgin :: Bool
ae_virgin       = Bool
True
         , 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 -> [Var] -> AnalEnv
extendAnalEnvs TopLevelFlag
top_lvl AnalEnv
env [Var]
vars
  = AnalEnv
env { ae_sigs :: SigEnv
ae_sigs = TopLevelFlag -> SigEnv -> [Var] -> SigEnv
extendSigEnvs TopLevelFlag
top_lvl (AnalEnv -> SigEnv
ae_sigs AnalEnv
env) [Var]
vars }
extendSigEnvs :: TopLevelFlag -> SigEnv -> [Id] -> SigEnv
extendSigEnvs :: TopLevelFlag -> SigEnv -> [Var] -> SigEnv
extendSigEnvs TopLevelFlag
top_lvl SigEnv
sigs [Var]
vars
  = SigEnv -> [(Var, (StrictSig, TopLevelFlag))] -> SigEnv
forall a. VarEnv a -> [(Var, a)] -> VarEnv a
extendVarEnvList SigEnv
sigs [ (Var
var, (Var -> StrictSig
idStrictness Var
var, TopLevelFlag
top_lvl)) | Var
var <- [Var]
vars]
extendAnalEnv :: TopLevelFlag -> AnalEnv -> Id -> StrictSig -> AnalEnv
extendAnalEnv :: TopLevelFlag -> AnalEnv -> Var -> StrictSig -> AnalEnv
extendAnalEnv TopLevelFlag
top_lvl AnalEnv
env Var
var StrictSig
sig
  = AnalEnv
env { ae_sigs :: SigEnv
ae_sigs = TopLevelFlag -> SigEnv -> Var -> StrictSig -> SigEnv
extendSigEnv TopLevelFlag
top_lvl (AnalEnv -> SigEnv
ae_sigs AnalEnv
env) Var
var StrictSig
sig }
extendSigEnv :: TopLevelFlag -> SigEnv -> Id -> StrictSig -> SigEnv
extendSigEnv :: TopLevelFlag -> SigEnv -> Var -> StrictSig -> SigEnv
extendSigEnv TopLevelFlag
top_lvl SigEnv
sigs Var
var StrictSig
sig = SigEnv -> Var -> (StrictSig, TopLevelFlag) -> SigEnv
forall a. VarEnv a -> Var -> a -> VarEnv a
extendVarEnv SigEnv
sigs Var
var (StrictSig
sig, TopLevelFlag
top_lvl)
lookupSigEnv :: AnalEnv -> Id -> Maybe (StrictSig, TopLevelFlag)
lookupSigEnv :: AnalEnv -> Var -> Maybe (StrictSig, TopLevelFlag)
lookupSigEnv AnalEnv
env Var
id = SigEnv -> Var -> Maybe (StrictSig, TopLevelFlag)
forall a. VarEnv a -> Var -> Maybe a
lookupVarEnv (AnalEnv -> SigEnv
ae_sigs AnalEnv
env) Var
id
nonVirgin :: AnalEnv -> AnalEnv
nonVirgin :: AnalEnv -> AnalEnv
nonVirgin AnalEnv
env = AnalEnv
env { ae_virgin :: Bool
ae_virgin = Bool
False }
findBndrsDmds :: AnalEnv -> DmdType -> [Var] -> WithDmdType [Demand]
findBndrsDmds :: AnalEnv -> DmdType -> [Var] -> WithDmdType [Demand]
findBndrsDmds AnalEnv
env DmdType
dmd_ty [Var]
bndrs
  = DmdType -> [Var] -> WithDmdType [Demand]
go DmdType
dmd_ty [Var]
bndrs
  where
    go :: DmdType -> [Var] -> WithDmdType [Demand]
go DmdType
dmd_ty []  = DmdType -> [Demand] -> WithDmdType [Demand]
forall a. DmdType -> a -> WithDmdType a
WithDmdType DmdType
dmd_ty []
    go DmdType
dmd_ty (Var
b:[Var]
bs)
      | Var -> Bool
isId Var
b    = let WithDmdType DmdType
dmd_ty1 [Demand]
dmds = DmdType -> [Var] -> WithDmdType [Demand]
go DmdType
dmd_ty [Var]
bs
                        WithDmdType DmdType
dmd_ty2 Demand
dmd  = AnalEnv -> Bool -> DmdType -> Var -> WithDmdType Demand
findBndrDmd AnalEnv
env Bool
False DmdType
dmd_ty1 Var
b
                    in DmdType -> [Demand] -> WithDmdType [Demand]
forall a. DmdType -> a -> WithDmdType a
WithDmdType DmdType
dmd_ty2  (Demand
dmd Demand -> [Demand] -> [Demand]
forall a. a -> [a] -> [a]
: [Demand]
dmds)
      | Bool
otherwise = DmdType -> [Var] -> WithDmdType [Demand]
go DmdType
dmd_ty [Var]
bs
findBndrDmd :: AnalEnv -> Bool -> DmdType -> Id -> WithDmdType Demand
findBndrDmd :: AnalEnv -> Bool -> DmdType -> Var -> WithDmdType Demand
findBndrDmd AnalEnv
env Bool
arg_of_dfun DmdType
dmd_ty Var
id
  = 
    DmdType -> Demand -> WithDmdType Demand
forall a. DmdType -> a -> WithDmdType a
WithDmdType DmdType
dmd_ty' Demand
dmd'
  where
    dmd' :: Demand
dmd' = 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)
    (DmdType
dmd_ty', Demand
starting_dmd) = DmdType -> Var -> (DmdType, Demand)
peelFV DmdType
dmd_ty Var
id
    id_ty :: Type
id_ty = Var -> Type
idType Var
id
    strictify :: Demand -> Demand
strictify Demand
dmd
      | AnalEnv -> Bool
ae_strict_dicts 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