{-# LANGUAGE CPP #-}
module GHC.Core.Opt.CprAnal ( cprAnalProgram ) where
#include "HsVersions.h"
import GHC.Prelude
import GHC.Driver.Session
import GHC.Types.Demand
import GHC.Types.Cpr
import GHC.Core
import GHC.Core.Seq
import GHC.Utils.Outputable
import GHC.Builtin.Names ( runRWKey )
import GHC.Types.Var.Env
import GHC.Types.Basic
import GHC.Types.Id
import GHC.Types.Id.Info
import GHC.Core.DataCon
import GHC.Core.Multiplicity
import GHC.Core.Utils ( exprIsHNF, dumpIdInfoOfProgram )
import GHC.Core.Type
import GHC.Core.FamInstEnv
import GHC.Core.Opt.WorkWrap.Utils
import GHC.Utils.Misc
import GHC.Utils.Panic
import GHC.Utils.Logger ( Logger, dumpIfSet_dyn, DumpFormat (..) )
import GHC.Data.Graph.UnVar
import GHC.Data.Maybe ( isNothing )
import Control.Monad ( guard )
import Data.List ( mapAccumL )
import GHC.Driver.Ppr
String -> SDoc -> Any -> Any
_ = String -> SDoc -> Any -> Any
forall a. String -> SDoc -> a -> a
pprTrace
cprAnalProgram :: Logger -> DynFlags -> FamInstEnvs -> CoreProgram -> IO CoreProgram
cprAnalProgram :: Logger -> DynFlags -> FamInstEnvs -> CoreProgram -> IO CoreProgram
cprAnalProgram Logger
logger DynFlags
dflags FamInstEnvs
fam_envs CoreProgram
binds = do
let env :: AnalEnv
env = FamInstEnvs -> AnalEnv
emptyAnalEnv FamInstEnvs
fam_envs
let binds_plus_cpr :: CoreProgram
binds_plus_cpr = (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)
cprAnalTopBind AnalEnv
env CoreProgram
binds
Logger
-> DynFlags -> DumpFlag -> String -> DumpFormat -> SDoc -> IO ()
dumpIfSet_dyn Logger
logger DynFlags
dflags DumpFlag
Opt_D_dump_cpr_signatures String
"Cpr signatures" DumpFormat
FormatText (SDoc -> IO ()) -> SDoc -> IO ()
forall a b. (a -> b) -> a -> b
$
(IdInfo -> SDoc) -> CoreProgram -> SDoc
dumpIdInfoOfProgram (CprSig -> SDoc
forall a. Outputable a => a -> SDoc
ppr (CprSig -> SDoc) -> (IdInfo -> CprSig) -> IdInfo -> SDoc
forall b c a. (b -> c) -> (a -> b) -> a -> c
. IdInfo -> CprSig
cprInfo) CoreProgram
binds_plus_cpr
CoreProgram -> ()
seqBinds CoreProgram
binds_plus_cpr () -> IO CoreProgram -> IO CoreProgram
`seq` CoreProgram -> IO CoreProgram
forall (m :: * -> *) a. Monad m => a -> m a
return CoreProgram
binds_plus_cpr
cprAnalTopBind :: AnalEnv
-> CoreBind
-> (AnalEnv, CoreBind)
cprAnalTopBind :: AnalEnv -> CoreBind -> (AnalEnv, CoreBind)
cprAnalTopBind AnalEnv
env (NonRec CoreBndr
id Expr CoreBndr
rhs)
= (AnalEnv
env', CoreBndr -> Expr CoreBndr -> CoreBind
forall b. b -> Expr b -> Bind b
NonRec CoreBndr
id' Expr CoreBndr
rhs')
where
(CoreBndr
id', Expr CoreBndr
rhs', AnalEnv
env') = TopLevelFlag
-> AnalEnv
-> CoreBndr
-> Expr CoreBndr
-> (CoreBndr, Expr CoreBndr, AnalEnv)
cprAnalBind TopLevelFlag
TopLevel AnalEnv
env CoreBndr
id Expr CoreBndr
rhs
cprAnalTopBind AnalEnv
env (Rec [(CoreBndr, Expr CoreBndr)]
pairs)
= (AnalEnv
env', [(CoreBndr, Expr CoreBndr)] -> CoreBind
forall b. [(b, Expr b)] -> Bind b
Rec [(CoreBndr, Expr CoreBndr)]
pairs')
where
(AnalEnv
env', [(CoreBndr, Expr CoreBndr)]
pairs') = TopLevelFlag
-> AnalEnv
-> [(CoreBndr, Expr CoreBndr)]
-> (AnalEnv, [(CoreBndr, Expr CoreBndr)])
cprFix TopLevelFlag
TopLevel AnalEnv
env [(CoreBndr, Expr CoreBndr)]
pairs
cprAnal, cprAnal'
:: AnalEnv
-> CoreExpr
-> (CprType, CoreExpr)
cprAnal :: AnalEnv -> Expr CoreBndr -> (CprType, Expr CoreBndr)
cprAnal AnalEnv
env Expr CoreBndr
e =
AnalEnv -> Expr CoreBndr -> (CprType, Expr CoreBndr)
cprAnal' AnalEnv
env Expr CoreBndr
e
cprAnal' :: AnalEnv -> Expr CoreBndr -> (CprType, Expr CoreBndr)
cprAnal' AnalEnv
_ (Lit Literal
lit) = (CprType
topCprType, Literal -> Expr CoreBndr
forall b. Literal -> Expr b
Lit Literal
lit)
cprAnal' AnalEnv
_ (Type Type
ty) = (CprType
topCprType, Type -> Expr CoreBndr
forall b. Type -> Expr b
Type Type
ty)
cprAnal' AnalEnv
_ (Coercion Coercion
co) = (CprType
topCprType, Coercion -> Expr CoreBndr
forall b. Coercion -> Expr b
Coercion Coercion
co)
cprAnal' AnalEnv
env (Cast Expr CoreBndr
e Coercion
co)
= (CprType
cpr_ty, Expr CoreBndr -> Coercion -> Expr CoreBndr
forall b. Expr b -> Coercion -> Expr b
Cast Expr CoreBndr
e' Coercion
co)
where
(CprType
cpr_ty, Expr CoreBndr
e') = AnalEnv -> Expr CoreBndr -> (CprType, Expr CoreBndr)
cprAnal AnalEnv
env Expr CoreBndr
e
cprAnal' AnalEnv
env (Tick CoreTickish
t Expr CoreBndr
e)
= (CprType
cpr_ty, CoreTickish -> Expr CoreBndr -> Expr CoreBndr
forall b. CoreTickish -> Expr b -> Expr b
Tick CoreTickish
t Expr CoreBndr
e')
where
(CprType
cpr_ty, Expr CoreBndr
e') = AnalEnv -> Expr CoreBndr -> (CprType, Expr CoreBndr)
cprAnal AnalEnv
env Expr CoreBndr
e
cprAnal' AnalEnv
env e :: Expr CoreBndr
e@(Var{})
= AnalEnv
-> Expr CoreBndr
-> [Expr CoreBndr]
-> [CprType]
-> (CprType, Expr CoreBndr)
cprAnalApp AnalEnv
env Expr CoreBndr
e [] []
cprAnal' AnalEnv
env e :: Expr CoreBndr
e@(App{})
= AnalEnv
-> Expr CoreBndr
-> [Expr CoreBndr]
-> [CprType]
-> (CprType, Expr CoreBndr)
cprAnalApp AnalEnv
env Expr CoreBndr
e [] []
cprAnal' AnalEnv
env (Lam CoreBndr
var Expr CoreBndr
body)
| CoreBndr -> Bool
isTyVar CoreBndr
var
, (CprType
body_ty, Expr CoreBndr
body') <- AnalEnv -> Expr CoreBndr -> (CprType, Expr CoreBndr)
cprAnal AnalEnv
env Expr CoreBndr
body
= (CprType
body_ty, CoreBndr -> Expr CoreBndr -> Expr CoreBndr
forall b. b -> Expr b -> Expr b
Lam CoreBndr
var Expr CoreBndr
body')
| Bool
otherwise
= (CprType
lam_ty, CoreBndr -> Expr CoreBndr -> Expr CoreBndr
forall b. b -> Expr b -> Expr b
Lam CoreBndr
var Expr CoreBndr
body')
where
env' :: AnalEnv
env' = AnalEnv -> CoreBndr -> AnalEnv
extendSigEnvForArg AnalEnv
env CoreBndr
var
(CprType
body_ty, Expr CoreBndr
body') = AnalEnv -> Expr CoreBndr -> (CprType, Expr CoreBndr)
cprAnal AnalEnv
env' Expr CoreBndr
body
lam_ty :: CprType
lam_ty = CprType -> CprType
abstractCprTy CprType
body_ty
cprAnal' AnalEnv
env (Case Expr CoreBndr
scrut CoreBndr
case_bndr Type
ty [Alt CoreBndr]
alts)
= (CprType
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')
where
(CprType
scrut_ty, Expr CoreBndr
scrut') = AnalEnv -> Expr CoreBndr -> (CprType, Expr CoreBndr)
cprAnal AnalEnv
env Expr CoreBndr
scrut
env' :: AnalEnv
env' = AnalEnv -> CoreBndr -> CprSig -> AnalEnv
extendSigEnv AnalEnv
env CoreBndr
case_bndr (CprType -> CprSig
CprSig CprType
scrut_ty)
([CprType]
alt_tys, [Alt CoreBndr]
alts') = (Alt CoreBndr -> (CprType, Alt CoreBndr))
-> [Alt CoreBndr] -> ([CprType], [Alt CoreBndr])
forall a b c. (a -> (b, c)) -> [a] -> ([b], [c])
mapAndUnzip (AnalEnv -> CprType -> Alt CoreBndr -> (CprType, Alt CoreBndr)
cprAnalAlt AnalEnv
env' CprType
scrut_ty) [Alt CoreBndr]
alts
res_ty :: CprType
res_ty = (CprType -> CprType -> CprType) -> CprType -> [CprType] -> CprType
forall (t :: * -> *) b a.
Foldable t =>
(b -> a -> b) -> b -> t a -> b
foldl' CprType -> CprType -> CprType
lubCprType CprType
botCprType [CprType]
alt_tys
cprAnal' AnalEnv
env (Let (NonRec CoreBndr
id Expr CoreBndr
rhs) Expr CoreBndr
body)
= (CprType
body_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
(CoreBndr
id', Expr CoreBndr
rhs', AnalEnv
env') = TopLevelFlag
-> AnalEnv
-> CoreBndr
-> Expr CoreBndr
-> (CoreBndr, Expr CoreBndr, AnalEnv)
cprAnalBind TopLevelFlag
NotTopLevel AnalEnv
env CoreBndr
id Expr CoreBndr
rhs
(CprType
body_ty, Expr CoreBndr
body') = AnalEnv -> Expr CoreBndr -> (CprType, Expr CoreBndr)
cprAnal AnalEnv
env' Expr CoreBndr
body
cprAnal' AnalEnv
env (Let (Rec [(CoreBndr, Expr CoreBndr)]
pairs) Expr CoreBndr
body)
= CprType
body_ty CprType -> (CprType, Expr CoreBndr) -> (CprType, Expr CoreBndr)
`seq` (CprType
body_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
Rec [(CoreBndr, Expr CoreBndr)]
pairs') Expr CoreBndr
body')
where
(AnalEnv
env', [(CoreBndr, Expr CoreBndr)]
pairs') = TopLevelFlag
-> AnalEnv
-> [(CoreBndr, Expr CoreBndr)]
-> (AnalEnv, [(CoreBndr, Expr CoreBndr)])
cprFix TopLevelFlag
NotTopLevel AnalEnv
env [(CoreBndr, Expr CoreBndr)]
pairs
(CprType
body_ty, Expr CoreBndr
body') = AnalEnv -> Expr CoreBndr -> (CprType, Expr CoreBndr)
cprAnal AnalEnv
env' Expr CoreBndr
body
cprAnalAlt
:: AnalEnv
-> CprType
-> Alt Var
-> (CprType, Alt Var)
cprAnalAlt :: AnalEnv -> CprType -> Alt CoreBndr -> (CprType, Alt CoreBndr)
cprAnalAlt AnalEnv
env CprType
scrut_ty (Alt AltCon
con [CoreBndr]
bndrs Expr CoreBndr
rhs)
= (CprType
rhs_ty, AltCon -> [CoreBndr] -> Expr CoreBndr -> Alt CoreBndr
forall b. AltCon -> [b] -> Expr b -> Alt b
Alt AltCon
con [CoreBndr]
bndrs Expr CoreBndr
rhs')
where
env_alt :: AnalEnv
env_alt
| DataAlt DataCon
dc <- AltCon
con
, let ids :: [CoreBndr]
ids = (CoreBndr -> Bool) -> [CoreBndr] -> [CoreBndr]
forall a. (a -> Bool) -> [a] -> [a]
filter CoreBndr -> Bool
isId [CoreBndr]
bndrs
, CprType Arity
arity Cpr
cpr <- CprType
scrut_ty
, ASSERT( arity == 0 ) True
= case DataCon -> Cpr -> UnpackConFieldsResult
unpackConFieldsCpr DataCon
dc Cpr
cpr of
AllFieldsSame Cpr
field_cpr
| let sig :: CprSig
sig = Arity -> Cpr -> CprSig
mkCprSig Arity
0 Cpr
field_cpr
-> AnalEnv -> [CoreBndr] -> CprSig -> AnalEnv
extendSigEnvAllSame AnalEnv
env [CoreBndr]
ids CprSig
sig
ForeachField [Cpr]
field_cprs
| let sigs :: [CprSig]
sigs = (CoreBndr -> Cpr -> CprSig) -> [CoreBndr] -> [Cpr] -> [CprSig]
forall a b c. (a -> b -> c) -> [a] -> [b] -> [c]
zipWith (Arity -> Cpr -> CprSig
mkCprSig (Arity -> Cpr -> CprSig)
-> (CoreBndr -> Arity) -> CoreBndr -> Cpr -> CprSig
forall b c a. (b -> c) -> (a -> b) -> a -> c
. CoreBndr -> Arity
idArity) [CoreBndr]
ids [Cpr]
field_cprs
-> AnalEnv -> [(CoreBndr, CprSig)] -> AnalEnv
extendSigEnvList AnalEnv
env (String -> [CoreBndr] -> [CprSig] -> [(CoreBndr, CprSig)]
forall a b. String -> [a] -> [b] -> [(a, b)]
zipEqual String
"cprAnalAlt" [CoreBndr]
ids [CprSig]
sigs)
| Bool
otherwise
= AnalEnv
env
(CprType
rhs_ty, Expr CoreBndr
rhs') = AnalEnv -> Expr CoreBndr -> (CprType, Expr CoreBndr)
cprAnal AnalEnv
env_alt Expr CoreBndr
rhs
cprAnalApp :: AnalEnv -> CoreExpr -> [CoreArg] -> [CprType] -> (CprType, CoreExpr)
cprAnalApp :: AnalEnv
-> Expr CoreBndr
-> [Expr CoreBndr]
-> [CprType]
-> (CprType, Expr CoreBndr)
cprAnalApp AnalEnv
env Expr CoreBndr
e [Expr CoreBndr]
args' [CprType]
arg_tys
| App Expr CoreBndr
fn Expr CoreBndr
arg <- Expr CoreBndr
e, Expr CoreBndr -> Bool
forall b. Expr b -> Bool
isTypeArg Expr CoreBndr
arg
= AnalEnv
-> Expr CoreBndr
-> [Expr CoreBndr]
-> [CprType]
-> (CprType, Expr CoreBndr)
cprAnalApp AnalEnv
env Expr CoreBndr
fn (Expr CoreBndr
argExpr CoreBndr -> [Expr CoreBndr] -> [Expr CoreBndr]
forall a. a -> [a] -> [a]
:[Expr CoreBndr]
args') [CprType]
arg_tys
| App Expr CoreBndr
fn Expr CoreBndr
arg <- Expr CoreBndr
e
, (CprType
arg_ty, Expr CoreBndr
arg') <- AnalEnv -> Expr CoreBndr -> (CprType, Expr CoreBndr)
cprAnal AnalEnv
env Expr CoreBndr
arg
= AnalEnv
-> Expr CoreBndr
-> [Expr CoreBndr]
-> [CprType]
-> (CprType, Expr CoreBndr)
cprAnalApp AnalEnv
env Expr CoreBndr
fn (Expr CoreBndr
arg'Expr CoreBndr -> [Expr CoreBndr] -> [Expr CoreBndr]
forall a. a -> [a] -> [a]
:[Expr CoreBndr]
args') (CprType
arg_tyCprType -> [CprType] -> [CprType]
forall a. a -> [a] -> [a]
:[CprType]
arg_tys)
| Var CoreBndr
fn <- Expr CoreBndr
e
= (AnalEnv -> CoreBndr -> [CprType] -> CprType
cprTransform AnalEnv
env CoreBndr
fn [CprType]
arg_tys, Expr CoreBndr -> [Expr CoreBndr] -> Expr CoreBndr
forall b. Expr b -> [Expr b] -> Expr b
mkApps Expr CoreBndr
e [Expr CoreBndr]
args')
| Bool
otherwise
, (CprType
e_ty, Expr CoreBndr
e') <- AnalEnv -> Expr CoreBndr -> (CprType, Expr CoreBndr)
cprAnal AnalEnv
env Expr CoreBndr
e
= (CprType -> Arity -> CprType
applyCprTy CprType
e_ty ([CprType] -> Arity
forall (t :: * -> *) a. Foldable t => t a -> Arity
length [CprType]
arg_tys), Expr CoreBndr -> [Expr CoreBndr] -> Expr CoreBndr
forall b. Expr b -> [Expr b] -> Expr b
mkApps Expr CoreBndr
e' [Expr CoreBndr]
args')
cprTransform :: AnalEnv
-> Id
-> [CprType]
-> CprType
cprTransform :: AnalEnv -> CoreBndr -> [CprType] -> CprType
cprTransform AnalEnv
env CoreBndr
id [CprType]
args
=
CprType
sig
where
sig :: CprType
sig
| Just CprSig
sig <- AnalEnv -> CoreBndr -> Maybe CprSig
lookupSigEnv AnalEnv
env CoreBndr
id
= CprType -> Arity -> CprType
applyCprTy (CprSig -> CprType
getCprSig CprSig
sig) ([CprType] -> Arity
forall (t :: * -> *) a. Foldable t => t a -> Arity
length [CprType]
args)
| Just CprType
cpr_ty <- CoreBndr -> [CprType] -> Maybe CprType
cprTransformSpecial CoreBndr
id [CprType]
args
= CprType
cpr_ty
| Just Expr CoreBndr
rhs <- CoreBndr -> Maybe (Expr CoreBndr)
cprDataStructureUnfolding_maybe CoreBndr
id
= (CprType, Expr CoreBndr) -> CprType
forall a b. (a, b) -> a
fst ((CprType, Expr CoreBndr) -> CprType)
-> (CprType, Expr CoreBndr) -> CprType
forall a b. (a -> b) -> a -> b
$ AnalEnv -> Expr CoreBndr -> (CprType, Expr CoreBndr)
cprAnal AnalEnv
env Expr CoreBndr
rhs
| CoreBndr -> Bool
isGlobalId CoreBndr
id
= CprType -> Arity -> CprType
applyCprTy (CprSig -> CprType
getCprSig (CoreBndr -> CprSig
idCprInfo CoreBndr
id)) ([CprType] -> Arity
forall (t :: * -> *) a. Foldable t => t a -> Arity
length [CprType]
args)
| Bool
otherwise
= CprType
topCprType
cprTransformSpecial :: Id -> [CprType] -> Maybe CprType
cprTransformSpecial :: CoreBndr -> [CprType] -> Maybe CprType
cprTransformSpecial CoreBndr
id [CprType]
args
| CoreBndr -> Unique
idUnique CoreBndr
id Unique -> Unique -> Bool
forall a. Eq a => a -> a -> Bool
== Unique
runRWKey
, [CprType
arg] <- [CprType]
args
= CprType -> Maybe CprType
forall a. a -> Maybe a
Just (CprType -> Maybe CprType) -> CprType -> Maybe CprType
forall a b. (a -> b) -> a -> b
$ CprType -> Arity -> CprType
applyCprTy CprType
arg Arity
1
| Bool
otherwise
= Maybe CprType
forall a. Maybe a
Nothing
cprFix :: TopLevelFlag
-> AnalEnv
-> [(Id,CoreExpr)]
-> (AnalEnv, [(Id,CoreExpr)])
cprFix :: TopLevelFlag
-> AnalEnv
-> [(CoreBndr, Expr CoreBndr)]
-> (AnalEnv, [(CoreBndr, Expr CoreBndr)])
cprFix TopLevelFlag
top_lvl AnalEnv
orig_env [(CoreBndr, Expr CoreBndr)]
orig_pairs
= Arity
-> AnalEnv
-> [(CoreBndr, Expr CoreBndr)]
-> (AnalEnv, [(CoreBndr, Expr CoreBndr)])
loop Arity
1 AnalEnv
init_env [(CoreBndr, Expr CoreBndr)]
init_pairs
where
init_sig :: CoreBndr -> Expr CoreBndr -> CprSig
init_sig CoreBndr
id Expr CoreBndr
rhs
| CoreBndr -> Expr CoreBndr -> Bool
isDataStructure CoreBndr
id Expr CoreBndr
rhs = CprSig
topCprSig
| Bool
otherwise = Arity -> Cpr -> CprSig
mkCprSig Arity
0 Cpr
botCpr
orig_virgin :: Bool
orig_virgin = AnalEnv -> Bool
ae_virgin AnalEnv
orig_env
init_pairs :: [(CoreBndr, Expr CoreBndr)]
init_pairs | Bool
orig_virgin = [(CoreBndr -> CprSig -> CoreBndr
setIdCprInfo CoreBndr
id (CoreBndr -> Expr CoreBndr -> CprSig
init_sig CoreBndr
id Expr CoreBndr
rhs), Expr CoreBndr
rhs) | (CoreBndr
id, Expr CoreBndr
rhs) <- [(CoreBndr, Expr CoreBndr)]
orig_pairs ]
| Bool
otherwise = [(CoreBndr, Expr CoreBndr)]
orig_pairs
init_env :: AnalEnv
init_env = AnalEnv -> [CoreBndr] -> AnalEnv
extendSigEnvFromIds AnalEnv
orig_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)]
init_pairs)
loop :: Int -> AnalEnv -> [(Id,CoreExpr)] -> (AnalEnv, [(Id,CoreExpr)])
loop :: Arity
-> AnalEnv
-> [(CoreBndr, Expr CoreBndr)]
-> (AnalEnv, [(CoreBndr, Expr CoreBndr)])
loop Arity
n AnalEnv
env [(CoreBndr, Expr CoreBndr)]
pairs
| Bool
found_fixpoint = (AnalEnv
reset_env', [(CoreBndr, Expr CoreBndr)]
pairs')
| Bool
otherwise = Arity
-> AnalEnv
-> [(CoreBndr, Expr CoreBndr)]
-> (AnalEnv, [(CoreBndr, Expr CoreBndr)])
loop (Arity
nArity -> Arity -> Arity
forall a. Num a => a -> a -> a
+Arity
1) AnalEnv
env' [(CoreBndr, Expr CoreBndr)]
pairs'
where
(AnalEnv
env', [(CoreBndr, Expr CoreBndr)]
pairs') = AnalEnv
-> [(CoreBndr, Expr CoreBndr)]
-> (AnalEnv, [(CoreBndr, Expr CoreBndr)])
step (Bool -> (AnalEnv -> AnalEnv) -> AnalEnv -> AnalEnv
forall a. Bool -> (a -> a) -> a -> a
applyWhen (Arity
nArity -> Arity -> Bool
forall a. Eq a => a -> a -> Bool
/=Arity
1) AnalEnv -> AnalEnv
nonVirgin AnalEnv
env) [(CoreBndr, Expr CoreBndr)]
pairs
reset_env' :: AnalEnv
reset_env' = AnalEnv
env'{ ae_virgin :: Bool
ae_virgin = Bool
orig_virgin }
found_fixpoint :: Bool
found_fixpoint = ((CoreBndr, Expr CoreBndr) -> CprSig)
-> [(CoreBndr, Expr CoreBndr)] -> [CprSig]
forall a b. (a -> b) -> [a] -> [b]
map (CoreBndr -> CprSig
idCprInfo (CoreBndr -> CprSig)
-> ((CoreBndr, Expr CoreBndr) -> CoreBndr)
-> (CoreBndr, Expr CoreBndr)
-> CprSig
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' [CprSig] -> [CprSig] -> Bool
forall a. Eq a => a -> a -> Bool
== ((CoreBndr, Expr CoreBndr) -> CprSig)
-> [(CoreBndr, Expr CoreBndr)] -> [CprSig]
forall a b. (a -> b) -> [a] -> [b]
map (CoreBndr -> CprSig
idCprInfo (CoreBndr -> CprSig)
-> ((CoreBndr, Expr CoreBndr) -> CoreBndr)
-> (CoreBndr, Expr CoreBndr)
-> CprSig
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
step :: AnalEnv -> [(Id, CoreExpr)] -> (AnalEnv, [(Id, CoreExpr)])
step :: AnalEnv
-> [(CoreBndr, Expr CoreBndr)]
-> (AnalEnv, [(CoreBndr, Expr CoreBndr)])
step AnalEnv
env [(CoreBndr, Expr CoreBndr)]
pairs = (AnalEnv
-> (CoreBndr, Expr CoreBndr)
-> (AnalEnv, (CoreBndr, Expr CoreBndr)))
-> AnalEnv
-> [(CoreBndr, Expr CoreBndr)]
-> (AnalEnv, [(CoreBndr, Expr CoreBndr)])
forall (t :: * -> *) a b c.
Traversable t =>
(a -> b -> (a, c)) -> a -> t b -> (a, t c)
mapAccumL AnalEnv
-> (CoreBndr, Expr CoreBndr)
-> (AnalEnv, (CoreBndr, Expr CoreBndr))
go AnalEnv
env [(CoreBndr, Expr CoreBndr)]
pairs
where
go :: AnalEnv
-> (CoreBndr, Expr CoreBndr)
-> (AnalEnv, (CoreBndr, Expr CoreBndr))
go AnalEnv
env (CoreBndr
id, Expr CoreBndr
rhs) = (AnalEnv
env', (CoreBndr
id', Expr CoreBndr
rhs'))
where
(CoreBndr
id', Expr CoreBndr
rhs', AnalEnv
env') = TopLevelFlag
-> AnalEnv
-> CoreBndr
-> Expr CoreBndr
-> (CoreBndr, Expr CoreBndr, AnalEnv)
cprAnalBind TopLevelFlag
top_lvl AnalEnv
env CoreBndr
id Expr CoreBndr
rhs
cprAnalBind
:: TopLevelFlag
-> AnalEnv
-> Id
-> CoreExpr
-> (Id, CoreExpr, AnalEnv)
cprAnalBind :: TopLevelFlag
-> AnalEnv
-> CoreBndr
-> Expr CoreBndr
-> (CoreBndr, Expr CoreBndr, AnalEnv)
cprAnalBind TopLevelFlag
top_lvl AnalEnv
env CoreBndr
id Expr CoreBndr
rhs
| CoreBndr -> Expr CoreBndr -> Bool
isDataStructure CoreBndr
id Expr CoreBndr
rhs
= (CoreBndr
id, Expr CoreBndr
rhs, AnalEnv
env)
| Bool
otherwise
= (CoreBndr
id', Expr CoreBndr
rhs', AnalEnv
env')
where
(CprType
rhs_ty, Expr CoreBndr
rhs') = AnalEnv -> Expr CoreBndr -> (CprType, Expr CoreBndr)
cprAnal AnalEnv
env Expr CoreBndr
rhs
rhs_ty' :: CprType
rhs_ty'
| Bool
stays_thunk = CprType -> CprType
trimCprTy CprType
rhs_ty
| Bool
returns_sum = CprType -> CprType
trimCprTy CprType
rhs_ty
| Bool
otherwise = CprType
rhs_ty
sig :: CprSig
sig = Arity -> CprType -> CprSig
mkCprSigForArity (CoreBndr -> Arity
idArity CoreBndr
id) CprType
rhs_ty'
id' :: CoreBndr
id' = CoreBndr -> CprSig -> CoreBndr
setIdCprInfo CoreBndr
id CprSig
sig
env' :: AnalEnv
env' = AnalEnv -> CoreBndr -> CprSig -> AnalEnv
extendSigEnv AnalEnv
env CoreBndr
id CprSig
sig
stays_thunk :: Bool
stays_thunk = Bool
is_thunk Bool -> Bool -> Bool
&& Bool
not_strict
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 = Bool -> Bool
not (Demand -> Bool
isStrUsedDmd (CoreBndr -> Demand
idDemandInfo CoreBndr
id))
([TyCoBinder]
_, Type
ret_ty) = Type -> ([TyCoBinder], Type)
splitPiTys (CoreBndr -> Type
idType CoreBndr
id)
not_a_prod :: Bool
not_a_prod = Maybe DataConPatContext -> Bool
forall a. Maybe a -> Bool
isNothing (FamInstEnvs -> Type -> Maybe DataConPatContext
splitArgType_maybe (AnalEnv -> FamInstEnvs
ae_fam_envs AnalEnv
env) Type
ret_ty)
returns_sum :: Bool
returns_sum = Bool -> Bool
not (TopLevelFlag -> Bool
isTopLevel TopLevelFlag
top_lvl) Bool -> Bool -> Bool
&& Bool
not_a_prod
isDataStructure :: Id -> CoreExpr -> Bool
isDataStructure :: CoreBndr -> Expr CoreBndr -> Bool
isDataStructure CoreBndr
id Expr CoreBndr
rhs =
CoreBndr -> Arity
idArity CoreBndr
id Arity -> Arity -> Bool
forall a. Eq a => a -> a -> Bool
== Arity
0 Bool -> Bool -> Bool
&& Expr CoreBndr -> Bool
exprIsHNF Expr CoreBndr
rhs
cprDataStructureUnfolding_maybe :: Id -> Maybe CoreExpr
cprDataStructureUnfolding_maybe :: CoreBndr -> Maybe (Expr CoreBndr)
cprDataStructureUnfolding_maybe CoreBndr
id = do
Bool -> Maybe ()
forall (f :: * -> *). Alternative f => Bool -> f ()
guard (Activation -> Bool
activeInFinalPhase (CoreBndr -> Activation
idInlineActivation CoreBndr
id))
Expr CoreBndr
unf <- Unfolding -> Maybe (Expr CoreBndr)
expandUnfolding_maybe (CoreBndr -> Unfolding
idUnfolding CoreBndr
id)
Bool -> Maybe ()
forall (f :: * -> *). Alternative f => Bool -> f ()
guard (CoreBndr -> Expr CoreBndr -> Bool
isDataStructure CoreBndr
id Expr CoreBndr
unf)
Expr CoreBndr -> Maybe (Expr CoreBndr)
forall (m :: * -> *) a. Monad m => a -> m a
return Expr CoreBndr
unf
data AnalEnv
= AE
{ AnalEnv -> SigEnv
ae_sigs :: SigEnv
, AnalEnv -> Bool
ae_virgin :: Bool
, AnalEnv -> FamInstEnvs
ae_fam_envs :: FamInstEnvs
}
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 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 Bool
virgin
, String -> SDoc
text String
"ae_sigs =" SDoc -> SDoc -> SDoc
<+> SigEnv -> SDoc
forall a. Outputable a => a -> SDoc
ppr SigEnv
env ])
data SigEnv
= SE
{ SigEnv -> UnVarSet
se_tops :: !UnVarSet
, SigEnv -> VarEnv CprSig
se_sigs :: !(VarEnv CprSig)
}
instance Outputable SigEnv where
ppr :: SigEnv -> SDoc
ppr (SE { se_tops :: SigEnv -> UnVarSet
se_tops = UnVarSet
tops, se_sigs :: SigEnv -> VarEnv CprSig
se_sigs = VarEnv CprSig
sigs })
= String -> SDoc
text String
"SE" SDoc -> SDoc -> SDoc
<+> SDoc -> SDoc
braces ([SDoc] -> SDoc
vcat
[ String -> SDoc
text String
"se_tops =" SDoc -> SDoc -> SDoc
<+> UnVarSet -> SDoc
forall a. Outputable a => a -> SDoc
ppr UnVarSet
tops
, String -> SDoc
text String
"se_sigs =" SDoc -> SDoc -> SDoc
<+> VarEnv CprSig -> SDoc
forall a. Outputable a => a -> SDoc
ppr VarEnv CprSig
sigs ])
emptyAnalEnv :: FamInstEnvs -> AnalEnv
emptyAnalEnv :: FamInstEnvs -> AnalEnv
emptyAnalEnv FamInstEnvs
fam_envs
= AE
{ ae_sigs :: SigEnv
ae_sigs = UnVarSet -> VarEnv CprSig -> SigEnv
SE UnVarSet
emptyUnVarSet VarEnv CprSig
forall a. VarEnv a
emptyVarEnv
, ae_virgin :: Bool
ae_virgin = Bool
True
, ae_fam_envs :: FamInstEnvs
ae_fam_envs = FamInstEnvs
fam_envs
}
modifySigEnv :: (SigEnv -> SigEnv) -> AnalEnv -> AnalEnv
modifySigEnv :: (SigEnv -> SigEnv) -> AnalEnv -> AnalEnv
modifySigEnv SigEnv -> SigEnv
f AnalEnv
env = AnalEnv
env { ae_sigs :: SigEnv
ae_sigs = SigEnv -> SigEnv
f (AnalEnv -> SigEnv
ae_sigs AnalEnv
env) }
lookupSigEnv :: AnalEnv -> Id -> Maybe CprSig
lookupSigEnv :: AnalEnv -> CoreBndr -> Maybe CprSig
lookupSigEnv AE{ae_sigs :: AnalEnv -> SigEnv
ae_sigs = SE UnVarSet
tops VarEnv CprSig
sigs} CoreBndr
id
| CoreBndr
id CoreBndr -> UnVarSet -> Bool
`elemUnVarSet` UnVarSet
tops = CprSig -> Maybe CprSig
forall a. a -> Maybe a
Just CprSig
topCprSig
| Bool
otherwise = VarEnv CprSig -> CoreBndr -> Maybe CprSig
forall a. VarEnv a -> CoreBndr -> Maybe a
lookupVarEnv VarEnv CprSig
sigs CoreBndr
id
extendSigEnv :: AnalEnv -> Id -> CprSig -> AnalEnv
extendSigEnv :: AnalEnv -> CoreBndr -> CprSig -> AnalEnv
extendSigEnv AnalEnv
env CoreBndr
id CprSig
sig
| CprSig -> Bool
isTopCprSig CprSig
sig
= (SigEnv -> SigEnv) -> AnalEnv -> AnalEnv
modifySigEnv (\SigEnv
se -> SigEnv
se{se_tops :: UnVarSet
se_tops = CoreBndr -> UnVarSet -> UnVarSet
extendUnVarSet CoreBndr
id (SigEnv -> UnVarSet
se_tops SigEnv
se)}) AnalEnv
env
| Bool
otherwise
= (SigEnv -> SigEnv) -> AnalEnv -> AnalEnv
modifySigEnv (\SigEnv
se -> SigEnv
se{se_sigs :: VarEnv CprSig
se_sigs = VarEnv CprSig -> CoreBndr -> CprSig -> VarEnv CprSig
forall a. VarEnv a -> CoreBndr -> a -> VarEnv a
extendVarEnv (SigEnv -> VarEnv CprSig
se_sigs SigEnv
se) CoreBndr
id CprSig
sig}) AnalEnv
env
extendSigEnvList :: AnalEnv -> [(Id, CprSig)] -> AnalEnv
extendSigEnvList :: AnalEnv -> [(CoreBndr, CprSig)] -> AnalEnv
extendSigEnvList AnalEnv
env [(CoreBndr, CprSig)]
ids_cprs
= (AnalEnv -> (CoreBndr, CprSig) -> AnalEnv)
-> AnalEnv -> [(CoreBndr, CprSig)] -> AnalEnv
forall (t :: * -> *) b a.
Foldable t =>
(b -> a -> b) -> b -> t a -> b
foldl' (\AnalEnv
env (CoreBndr
id, CprSig
sig) -> AnalEnv -> CoreBndr -> CprSig -> AnalEnv
extendSigEnv AnalEnv
env CoreBndr
id CprSig
sig) AnalEnv
env [(CoreBndr, CprSig)]
ids_cprs
extendSigEnvFromIds :: AnalEnv -> [Id] -> AnalEnv
extendSigEnvFromIds :: AnalEnv -> [CoreBndr] -> AnalEnv
extendSigEnvFromIds AnalEnv
env [CoreBndr]
ids
= (AnalEnv -> CoreBndr -> AnalEnv)
-> AnalEnv -> [CoreBndr] -> AnalEnv
forall (t :: * -> *) b a.
Foldable t =>
(b -> a -> b) -> b -> t a -> b
foldl' (\AnalEnv
env CoreBndr
id -> AnalEnv -> CoreBndr -> CprSig -> AnalEnv
extendSigEnv AnalEnv
env CoreBndr
id (CoreBndr -> CprSig
idCprInfo CoreBndr
id)) AnalEnv
env [CoreBndr]
ids
extendSigEnvAllSame :: AnalEnv -> [Id] -> CprSig -> AnalEnv
extendSigEnvAllSame :: AnalEnv -> [CoreBndr] -> CprSig -> AnalEnv
extendSigEnvAllSame AnalEnv
env [CoreBndr]
ids CprSig
sig
= (AnalEnv -> CoreBndr -> AnalEnv)
-> AnalEnv -> [CoreBndr] -> AnalEnv
forall (t :: * -> *) b a.
Foldable t =>
(b -> a -> b) -> b -> t a -> b
foldl' (\AnalEnv
env CoreBndr
id -> AnalEnv -> CoreBndr -> CprSig -> AnalEnv
extendSigEnv AnalEnv
env CoreBndr
id CprSig
sig) AnalEnv
env [CoreBndr]
ids
nonVirgin :: AnalEnv -> AnalEnv
nonVirgin :: AnalEnv -> AnalEnv
nonVirgin AnalEnv
env = AnalEnv
env { ae_virgin :: Bool
ae_virgin = Bool
False }
extendSigEnvForArg :: AnalEnv -> Id -> AnalEnv
extendSigEnvForArg :: AnalEnv -> CoreBndr -> AnalEnv
extendSigEnvForArg AnalEnv
env CoreBndr
id
= AnalEnv -> CoreBndr -> CprSig -> AnalEnv
extendSigEnv AnalEnv
env CoreBndr
id (CprType -> CprSig
CprSig (AnalEnv -> Type -> Demand -> CprType
argCprType AnalEnv
env (CoreBndr -> Type
idType CoreBndr
id) (CoreBndr -> Demand
idDemandInfo CoreBndr
id)))
argCprType :: AnalEnv -> Type -> Demand -> CprType
argCprType :: AnalEnv -> Type -> Demand -> CprType
argCprType AnalEnv
env Type
arg_ty Demand
dmd = Arity -> Cpr -> CprType
CprType Arity
0 (Type -> Demand -> Cpr
go Type
arg_ty Demand
dmd)
where
go :: Type -> Demand -> Cpr
go Type
ty Demand
dmd
| Unbox (DataConPatContext { dcpc_dc :: DataConPatContext -> DataCon
dcpc_dc = DataCon
dc, dcpc_tc_args :: DataConPatContext -> [Type]
dcpc_tc_args = [Type]
tc_args }) [Demand]
ds
<- FamInstEnvs -> Bool -> Type -> Demand -> UnboxingDecision Demand
wantToUnbox (AnalEnv -> FamInstEnvs
ae_fam_envs AnalEnv
env) Bool
no_inlineable_prag Type
ty Demand
dmd
, [CoreBndr] -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null (DataCon -> [CoreBndr]
dataConExTyCoVars DataCon
dc)
, let arg_tys :: [Type]
arg_tys = (Scaled Type -> Type) -> [Scaled Type] -> [Type]
forall a b. (a -> b) -> [a] -> [b]
map Scaled Type -> Type
forall a. Scaled a -> a
scaledThing (DataCon -> [Type] -> [Scaled Type]
dataConInstArgTys DataCon
dc [Type]
tc_args)
= Arity -> [Cpr] -> Cpr
ConCpr (DataCon -> Arity
dataConTag DataCon
dc) ((Type -> Demand -> Cpr) -> [Type] -> [Demand] -> [Cpr]
forall a b c. (a -> b -> c) -> [a] -> [b] -> [c]
zipWith Type -> Demand -> Cpr
go [Type]
arg_tys [Demand]
ds)
| Bool
otherwise
= Cpr
topCpr
no_inlineable_prag :: Bool
no_inlineable_prag = Bool
False