{-# OPTIONS_GHC -Wno-incomplete-record-updates #-}
module GHC.Core.Unfold.Make
( noUnfolding
, mkUnfolding
, mkCoreUnfolding
, mkFinalUnfolding
, mkFinalUnfolding'
, mkSimpleUnfolding
, mkWorkerUnfolding
, mkInlineUnfoldingWithArity, mkInlineUnfoldingNoArity
, mkInlinableUnfolding
, mkWrapperUnfolding
, mkCompulsoryUnfolding, mkCompulsoryUnfolding'
, mkDFunUnfolding
, mkDataConUnfolding
, specUnfolding
, certainlyWillInline
)
where
import GHC.Prelude
import GHC.Core
import GHC.Core.Unfold
import GHC.Core.Opt.OccurAnal ( occurAnalyseExpr )
import GHC.Core.Opt.Arity ( manifestArity )
import GHC.Core.DataCon
import GHC.Core.Utils
import GHC.Types.Basic
import GHC.Types.Id
import GHC.Types.Id.Info
import GHC.Types.Demand ( DmdSig, isDeadEndSig )
import GHC.Utils.Outputable
import GHC.Utils.Misc
import GHC.Utils.Panic
import Data.Maybe ( fromMaybe )
import {-# SOURCE #-} GHC.Core.SimpleOpt
mkFinalUnfolding :: UnfoldingOpts -> UnfoldingSource -> DmdSig -> CoreExpr -> Unfolding
mkFinalUnfolding :: UnfoldingOpts -> UnfoldingSource -> DmdSig -> CoreArg -> Unfolding
mkFinalUnfolding UnfoldingOpts
opts UnfoldingSource
src DmdSig
strict_sig CoreArg
expr = UnfoldingOpts
-> UnfoldingSource
-> DmdSig
-> CoreArg
-> Maybe UnfoldingCache
-> Unfolding
mkFinalUnfolding' UnfoldingOpts
opts UnfoldingSource
src DmdSig
strict_sig CoreArg
expr forall a. Maybe a
Nothing
mkFinalUnfolding' :: UnfoldingOpts -> UnfoldingSource -> DmdSig -> CoreExpr -> Maybe UnfoldingCache -> Unfolding
mkFinalUnfolding' :: UnfoldingOpts
-> UnfoldingSource
-> DmdSig
-> CoreArg
-> Maybe UnfoldingCache
-> Unfolding
mkFinalUnfolding' UnfoldingOpts
opts UnfoldingSource
src DmdSig
strict_sig CoreArg
expr
= UnfoldingOpts
-> UnfoldingSource
-> Bool
-> Bool
-> CoreArg
-> Maybe UnfoldingCache
-> Unfolding
mkUnfolding UnfoldingOpts
opts UnfoldingSource
src
Bool
True
(DmdSig -> Bool
isDeadEndSig DmdSig
strict_sig)
CoreArg
expr
mkCompulsoryUnfolding' :: SimpleOpts -> CoreExpr -> Unfolding
mkCompulsoryUnfolding' :: SimpleOpts -> CoreArg -> Unfolding
mkCompulsoryUnfolding' SimpleOpts
opts CoreArg
expr = CoreArg -> Unfolding
mkCompulsoryUnfolding (HasDebugCallStack => SimpleOpts -> CoreArg -> CoreArg
simpleOptExpr SimpleOpts
opts CoreArg
expr)
mkCompulsoryUnfolding :: CoreExpr -> Unfolding
mkCompulsoryUnfolding :: CoreArg -> Unfolding
mkCompulsoryUnfolding CoreArg
expr
= UnfoldingSource
-> Bool
-> CoreArg
-> Maybe UnfoldingCache
-> UnfoldingGuidance
-> Unfolding
mkCoreUnfolding UnfoldingSource
CompulsorySrc Bool
True
CoreArg
expr forall a. Maybe a
Nothing
(UnfWhen { ug_arity :: ArityInfo
ug_arity = ArityInfo
0
, ug_unsat_ok :: Bool
ug_unsat_ok = Bool
unSaturatedOk, ug_boring_ok :: Bool
ug_boring_ok = Bool
boringCxtOk })
mkSimpleUnfolding :: UnfoldingOpts -> CoreExpr -> Unfolding
mkSimpleUnfolding :: UnfoldingOpts -> CoreArg -> Unfolding
mkSimpleUnfolding !UnfoldingOpts
opts CoreArg
rhs
= UnfoldingOpts
-> UnfoldingSource
-> Bool
-> Bool
-> CoreArg
-> Maybe UnfoldingCache
-> Unfolding
mkUnfolding UnfoldingOpts
opts UnfoldingSource
VanillaSrc Bool
False Bool
False CoreArg
rhs forall a. Maybe a
Nothing
mkDFunUnfolding :: [Var] -> DataCon -> [CoreExpr] -> Unfolding
mkDFunUnfolding :: [Var] -> DataCon -> [CoreArg] -> Unfolding
mkDFunUnfolding [Var]
bndrs DataCon
con [CoreArg]
ops
= DFunUnfolding { df_bndrs :: [Var]
df_bndrs = [Var]
bndrs
, df_con :: DataCon
df_con = DataCon
con
, df_args :: [CoreArg]
df_args = forall a b. (a -> b) -> [a] -> [b]
map CoreArg -> CoreArg
occurAnalyseExpr [CoreArg]
ops }
mkDataConUnfolding :: CoreExpr -> Unfolding
mkDataConUnfolding :: CoreArg -> Unfolding
mkDataConUnfolding CoreArg
expr
= UnfoldingSource
-> Bool
-> CoreArg
-> Maybe UnfoldingCache
-> UnfoldingGuidance
-> Unfolding
mkCoreUnfolding UnfoldingSource
StableSystemSrc Bool
True CoreArg
expr forall a. Maybe a
Nothing UnfoldingGuidance
guide
where
guide :: UnfoldingGuidance
guide = UnfWhen { ug_arity :: ArityInfo
ug_arity = CoreArg -> ArityInfo
manifestArity CoreArg
expr
, ug_unsat_ok :: Bool
ug_unsat_ok = Bool
unSaturatedOk
, ug_boring_ok :: Bool
ug_boring_ok = Bool
False }
mkWrapperUnfolding :: SimpleOpts -> CoreExpr -> Arity -> Unfolding
mkWrapperUnfolding :: SimpleOpts -> CoreArg -> ArityInfo -> Unfolding
mkWrapperUnfolding SimpleOpts
opts CoreArg
expr ArityInfo
arity
= UnfoldingSource
-> Bool
-> CoreArg
-> Maybe UnfoldingCache
-> UnfoldingGuidance
-> Unfolding
mkCoreUnfolding UnfoldingSource
StableSystemSrc Bool
True
(HasDebugCallStack => SimpleOpts -> CoreArg -> CoreArg
simpleOptExpr SimpleOpts
opts CoreArg
expr) forall a. Maybe a
Nothing
(UnfWhen { ug_arity :: ArityInfo
ug_arity = ArityInfo
arity
, ug_unsat_ok :: Bool
ug_unsat_ok = Bool
unSaturatedOk
, ug_boring_ok :: Bool
ug_boring_ok = Bool
boringCxtNotOk })
mkWorkerUnfolding :: SimpleOpts -> (CoreExpr -> CoreExpr) -> Unfolding -> Unfolding
mkWorkerUnfolding :: SimpleOpts -> (CoreArg -> CoreArg) -> Unfolding -> Unfolding
mkWorkerUnfolding SimpleOpts
opts CoreArg -> CoreArg
work_fn
(CoreUnfolding { uf_src :: Unfolding -> UnfoldingSource
uf_src = UnfoldingSource
src, uf_tmpl :: Unfolding -> CoreArg
uf_tmpl = CoreArg
tmpl
, uf_is_top :: Unfolding -> Bool
uf_is_top = Bool
top_lvl })
| UnfoldingSource -> Bool
isStableSource UnfoldingSource
src
= UnfoldingSource
-> Bool
-> CoreArg
-> Maybe UnfoldingCache
-> UnfoldingGuidance
-> Unfolding
mkCoreUnfolding UnfoldingSource
src Bool
top_lvl CoreArg
new_tmpl forall a. Maybe a
Nothing UnfoldingGuidance
guidance
where
new_tmpl :: CoreArg
new_tmpl = HasDebugCallStack => SimpleOpts -> CoreArg -> CoreArg
simpleOptExpr SimpleOpts
opts (CoreArg -> CoreArg
work_fn CoreArg
tmpl)
guidance :: UnfoldingGuidance
guidance = UnfoldingOpts -> Bool -> CoreArg -> UnfoldingGuidance
calcUnfoldingGuidance (SimpleOpts -> UnfoldingOpts
so_uf_opts SimpleOpts
opts) Bool
False CoreArg
new_tmpl
mkWorkerUnfolding SimpleOpts
_ CoreArg -> CoreArg
_ Unfolding
_ = Unfolding
noUnfolding
mkInlineUnfoldingNoArity :: SimpleOpts -> UnfoldingSource -> CoreExpr -> Unfolding
mkInlineUnfoldingNoArity :: SimpleOpts -> UnfoldingSource -> CoreArg -> Unfolding
mkInlineUnfoldingNoArity SimpleOpts
opts UnfoldingSource
src CoreArg
expr
= UnfoldingSource
-> Bool
-> CoreArg
-> Maybe UnfoldingCache
-> UnfoldingGuidance
-> Unfolding
mkCoreUnfolding UnfoldingSource
src
Bool
True
CoreArg
expr' forall a. Maybe a
Nothing UnfoldingGuidance
guide
where
expr' :: CoreArg
expr' = HasDebugCallStack => SimpleOpts -> CoreArg -> CoreArg
simpleOptExpr SimpleOpts
opts CoreArg
expr
guide :: UnfoldingGuidance
guide = UnfWhen { ug_arity :: ArityInfo
ug_arity = CoreArg -> ArityInfo
manifestArity CoreArg
expr'
, ug_unsat_ok :: Bool
ug_unsat_ok = Bool
unSaturatedOk
, ug_boring_ok :: Bool
ug_boring_ok = Bool
boring_ok }
boring_ok :: Bool
boring_ok = CoreArg -> Bool
inlineBoringOk CoreArg
expr'
mkInlineUnfoldingWithArity :: SimpleOpts -> UnfoldingSource -> Arity -> CoreExpr -> Unfolding
mkInlineUnfoldingWithArity :: SimpleOpts -> UnfoldingSource -> ArityInfo -> CoreArg -> Unfolding
mkInlineUnfoldingWithArity SimpleOpts
opts UnfoldingSource
src ArityInfo
arity CoreArg
expr
= UnfoldingSource
-> Bool
-> CoreArg
-> Maybe UnfoldingCache
-> UnfoldingGuidance
-> Unfolding
mkCoreUnfolding UnfoldingSource
src
Bool
True
CoreArg
expr' forall a. Maybe a
Nothing UnfoldingGuidance
guide
where
expr' :: CoreArg
expr' = HasDebugCallStack => SimpleOpts -> CoreArg -> CoreArg
simpleOptExpr SimpleOpts
opts CoreArg
expr
guide :: UnfoldingGuidance
guide = UnfWhen { ug_arity :: ArityInfo
ug_arity = ArityInfo
arity
, ug_unsat_ok :: Bool
ug_unsat_ok = Bool
needSaturated
, ug_boring_ok :: Bool
ug_boring_ok = Bool
boring_ok }
boring_ok :: Bool
boring_ok | ArityInfo
arity forall a. Eq a => a -> a -> Bool
== ArityInfo
0 = Bool
True
| Bool
otherwise = CoreArg -> Bool
inlineBoringOk CoreArg
expr'
mkInlinableUnfolding :: SimpleOpts -> UnfoldingSource -> CoreExpr -> Unfolding
mkInlinableUnfolding :: SimpleOpts -> UnfoldingSource -> CoreArg -> Unfolding
mkInlinableUnfolding SimpleOpts
opts UnfoldingSource
src CoreArg
expr
= UnfoldingOpts
-> UnfoldingSource
-> Bool
-> Bool
-> CoreArg
-> Maybe UnfoldingCache
-> Unfolding
mkUnfolding (SimpleOpts -> UnfoldingOpts
so_uf_opts SimpleOpts
opts) UnfoldingSource
src Bool
False Bool
False CoreArg
expr' forall a. Maybe a
Nothing
where
expr' :: CoreArg
expr' = HasDebugCallStack => SimpleOpts -> CoreArg -> CoreArg
simpleOptExpr SimpleOpts
opts CoreArg
expr
specUnfolding :: SimpleOpts
-> [Var] -> (CoreExpr -> CoreExpr)
-> [CoreArg]
-> Unfolding -> Unfolding
specUnfolding :: SimpleOpts
-> [Var]
-> (CoreArg -> CoreArg)
-> [CoreArg]
-> Unfolding
-> Unfolding
specUnfolding SimpleOpts
opts [Var]
spec_bndrs CoreArg -> CoreArg
spec_app [CoreArg]
rule_lhs_args
df :: Unfolding
df@(DFunUnfolding { df_bndrs :: Unfolding -> [Var]
df_bndrs = [Var]
old_bndrs, df_con :: Unfolding -> DataCon
df_con = DataCon
con, df_args :: Unfolding -> [CoreArg]
df_args = [CoreArg]
args })
= forall a. HasCallStack => Bool -> SDoc -> a -> a
assertPpr ([CoreArg]
rule_lhs_args forall a b. [a] -> [b] -> Bool
`equalLength` [Var]
old_bndrs)
(forall a. Outputable a => a -> SDoc
ppr Unfolding
df forall doc. IsDoc doc => doc -> doc -> doc
$$ forall a. Outputable a => a -> SDoc
ppr [CoreArg]
rule_lhs_args) forall a b. (a -> b) -> a -> b
$
[Var] -> DataCon -> [CoreArg] -> Unfolding
mkDFunUnfolding [Var]
spec_bndrs DataCon
con (forall a b. (a -> b) -> [a] -> [b]
map CoreArg -> CoreArg
spec_arg [CoreArg]
args)
where
spec_arg :: CoreArg -> CoreArg
spec_arg CoreArg
arg = HasDebugCallStack => SimpleOpts -> CoreArg -> CoreArg
simpleOptExpr SimpleOpts
opts forall a b. (a -> b) -> a -> b
$
CoreArg -> CoreArg
spec_app (forall b. [b] -> Expr b -> Expr b
mkLams [Var]
old_bndrs CoreArg
arg)
specUnfolding SimpleOpts
opts [Var]
spec_bndrs CoreArg -> CoreArg
spec_app [CoreArg]
rule_lhs_args
(CoreUnfolding { uf_src :: Unfolding -> UnfoldingSource
uf_src = UnfoldingSource
src, uf_tmpl :: Unfolding -> CoreArg
uf_tmpl = CoreArg
tmpl
, uf_is_top :: Unfolding -> Bool
uf_is_top = Bool
top_lvl
, uf_guidance :: Unfolding -> UnfoldingGuidance
uf_guidance = UnfoldingGuidance
old_guidance })
| UnfoldingSource -> Bool
isStableSource UnfoldingSource
src
, UnfWhen { ug_arity :: UnfoldingGuidance -> ArityInfo
ug_arity = ArityInfo
old_arity } <- UnfoldingGuidance
old_guidance
= UnfoldingSource
-> Bool
-> CoreArg
-> Maybe UnfoldingCache
-> UnfoldingGuidance
-> Unfolding
mkCoreUnfolding UnfoldingSource
src Bool
top_lvl CoreArg
new_tmpl forall a. Maybe a
Nothing
(UnfoldingGuidance
old_guidance { ug_arity :: ArityInfo
ug_arity = ArityInfo
old_arity forall a. Num a => a -> a -> a
- ArityInfo
arity_decrease })
where
new_tmpl :: CoreArg
new_tmpl = HasDebugCallStack => SimpleOpts -> CoreArg -> CoreArg
simpleOptExpr SimpleOpts
opts forall a b. (a -> b) -> a -> b
$
forall b. [b] -> Expr b -> Expr b
mkLams [Var]
spec_bndrs forall a b. (a -> b) -> a -> b
$
CoreArg -> CoreArg
spec_app CoreArg
tmpl
arity_decrease :: ArityInfo
arity_decrease = forall a. (a -> Bool) -> [a] -> ArityInfo
count forall b. Expr b -> Bool
isValArg [CoreArg]
rule_lhs_args forall a. Num a => a -> a -> a
- forall a. (a -> Bool) -> [a] -> ArityInfo
count Var -> Bool
isId [Var]
spec_bndrs
specUnfolding SimpleOpts
_ [Var]
_ CoreArg -> CoreArg
_ [CoreArg]
_ Unfolding
_ = Unfolding
noUnfolding
mkUnfolding :: UnfoldingOpts
-> UnfoldingSource
-> Bool
-> Bool
-> CoreExpr
-> Maybe UnfoldingCache
-> Unfolding
mkUnfolding :: UnfoldingOpts
-> UnfoldingSource
-> Bool
-> Bool
-> CoreArg
-> Maybe UnfoldingCache
-> Unfolding
mkUnfolding UnfoldingOpts
opts UnfoldingSource
src Bool
top_lvl Bool
is_bottoming CoreArg
expr Maybe UnfoldingCache
cache
= UnfoldingSource
-> Bool
-> CoreArg
-> Maybe UnfoldingCache
-> UnfoldingGuidance
-> Unfolding
mkCoreUnfolding UnfoldingSource
src Bool
top_lvl CoreArg
expr Maybe UnfoldingCache
cache UnfoldingGuidance
guidance
where
is_top_bottoming :: Bool
is_top_bottoming = Bool
top_lvl Bool -> Bool -> Bool
&& Bool
is_bottoming
guidance :: UnfoldingGuidance
guidance = UnfoldingOpts -> Bool -> CoreArg -> UnfoldingGuidance
calcUnfoldingGuidance UnfoldingOpts
opts Bool
is_top_bottoming CoreArg
expr
mkCoreUnfolding :: UnfoldingSource -> Bool -> CoreExpr
-> Maybe UnfoldingCache -> UnfoldingGuidance -> Unfolding
mkCoreUnfolding :: UnfoldingSource
-> Bool
-> CoreArg
-> Maybe UnfoldingCache
-> UnfoldingGuidance
-> Unfolding
mkCoreUnfolding UnfoldingSource
src Bool
top_lvl CoreArg
expr Maybe UnfoldingCache
precomputed_cache UnfoldingGuidance
guidance
= CoreUnfolding { uf_tmpl :: CoreArg
uf_tmpl = UnfoldingCache
cache seq :: forall a b. a -> b -> b
`seq`
CoreArg -> CoreArg
occurAnalyseExpr CoreArg
expr
, uf_src :: UnfoldingSource
uf_src = UnfoldingSource
src
, uf_is_top :: Bool
uf_is_top = Bool
top_lvl
, uf_cache :: UnfoldingCache
uf_cache = UnfoldingCache
cache
, uf_guidance :: UnfoldingGuidance
uf_guidance = UnfoldingGuidance
guidance }
where
is_value :: Bool
is_value = CoreArg -> Bool
exprIsHNF CoreArg
expr
is_conlike :: Bool
is_conlike = CoreArg -> Bool
exprIsConLike CoreArg
expr
is_work_free :: Bool
is_work_free = CoreArg -> Bool
exprIsWorkFree CoreArg
expr
is_expandable :: Bool
is_expandable = CoreArg -> Bool
exprIsExpandable CoreArg
expr
recomputed_cache :: UnfoldingCache
recomputed_cache = UnfoldingCache { uf_is_value :: Bool
uf_is_value = Bool
is_value
, uf_is_conlike :: Bool
uf_is_conlike = Bool
is_conlike
, uf_is_work_free :: Bool
uf_is_work_free = Bool
is_work_free
, uf_expandable :: Bool
uf_expandable = Bool
is_expandable }
cache :: UnfoldingCache
cache = forall a. a -> Maybe a -> a
fromMaybe UnfoldingCache
recomputed_cache Maybe UnfoldingCache
precomputed_cache
certainlyWillInline :: UnfoldingOpts -> IdInfo -> CoreExpr -> Maybe Unfolding
certainlyWillInline :: UnfoldingOpts -> IdInfo -> CoreArg -> Maybe Unfolding
certainlyWillInline UnfoldingOpts
opts IdInfo
fn_info CoreArg
rhs'
= case Unfolding
fn_unf of
CoreUnfolding { uf_guidance :: Unfolding -> UnfoldingGuidance
uf_guidance = UnfoldingGuidance
guidance, uf_src :: Unfolding -> UnfoldingSource
uf_src = UnfoldingSource
src }
| Bool
noinline -> forall a. Maybe a
Nothing
| Bool
otherwise
-> case UnfoldingGuidance
guidance of
UnfoldingGuidance
UnfNever -> forall a. Maybe a
Nothing
UnfWhen {} -> forall a. a -> Maybe a
Just (Unfolding
fn_unf { uf_src :: UnfoldingSource
uf_src = UnfoldingSource
src', uf_tmpl :: CoreArg
uf_tmpl = CoreArg
tmpl' })
UnfIfGoodArgs { ug_size :: UnfoldingGuidance -> ArityInfo
ug_size = ArityInfo
size, ug_args :: UnfoldingGuidance -> [ArityInfo]
ug_args = [ArityInfo]
args }
-> ArityInfo
-> [ArityInfo] -> UnfoldingSource -> CoreArg -> Maybe Unfolding
do_cunf ArityInfo
size [ArityInfo]
args UnfoldingSource
src' CoreArg
tmpl'
where
src' :: UnfoldingSource
src' | UnfoldingSource -> Bool
isCompulsorySource UnfoldingSource
src = UnfoldingSource
src
| Bool
otherwise = UnfoldingSource
StableSystemSrc
tmpl' :: CoreArg
tmpl' | UnfoldingSource -> Bool
isStableSource UnfoldingSource
src = Unfolding -> CoreArg
uf_tmpl Unfolding
fn_unf
| Bool
otherwise = CoreArg -> CoreArg
occurAnalyseExpr CoreArg
rhs'
DFunUnfolding {} -> forall a. a -> Maybe a
Just Unfolding
fn_unf
Unfolding
_other_unf -> forall a. Maybe a
Nothing
where
noinline :: Bool
noinline = InlinePragma -> Bool
isNoInlinePragma (IdInfo -> InlinePragma
inlinePragInfo IdInfo
fn_info)
fn_unf :: Unfolding
fn_unf = IdInfo -> Unfolding
unfoldingInfo IdInfo
fn_info
do_cunf :: ArityInfo
-> [ArityInfo] -> UnfoldingSource -> CoreArg -> Maybe Unfolding
do_cunf ArityInfo
size [ArityInfo]
args UnfoldingSource
src' CoreArg
tmpl'
| IdInfo -> ArityInfo
arityInfo IdInfo
fn_info forall a. Ord a => a -> a -> Bool
> ArityInfo
0
, Bool -> Bool
not (DmdSig -> Bool
isDeadEndSig (IdInfo -> DmdSig
dmdSigInfo IdInfo
fn_info))
, let unf_arity :: ArityInfo
unf_arity = forall (t :: * -> *) a. Foldable t => t a -> ArityInfo
length [ArityInfo]
args
, ArityInfo
size forall a. Num a => a -> a -> a
- (ArityInfo
10 forall a. Num a => a -> a -> a
* (ArityInfo
unf_arity forall a. Num a => a -> a -> a
+ ArityInfo
1)) forall a. Ord a => a -> a -> Bool
<= UnfoldingOpts -> ArityInfo
unfoldingUseThreshold UnfoldingOpts
opts
= forall a. a -> Maybe a
Just (Unfolding
fn_unf { uf_src :: UnfoldingSource
uf_src = UnfoldingSource
src'
, uf_tmpl :: CoreArg
uf_tmpl = CoreArg
tmpl'
, uf_guidance :: UnfoldingGuidance
uf_guidance = UnfWhen { ug_arity :: ArityInfo
ug_arity = ArityInfo
unf_arity
, ug_unsat_ok :: Bool
ug_unsat_ok = Bool
unSaturatedOk
, ug_boring_ok :: Bool
ug_boring_ok = CoreArg -> Bool
inlineBoringOk CoreArg
tmpl' } })
| Bool
otherwise
= forall a. Maybe a
Nothing