{-# LANGUAGE CPP #-}
{-# OPTIONS_GHC -Wno-incomplete-record-updates #-}
module GHC.Core.Unfold (
Unfolding, UnfoldingGuidance,
noUnfolding,
mkUnfolding, mkCoreUnfolding,
mkFinalUnfolding, mkSimpleUnfolding, mkWorkerUnfolding,
mkInlineUnfolding, mkInlineUnfoldingWithArity,
mkInlinableUnfolding, mkWwInlineRule,
mkCompulsoryUnfolding, mkDFunUnfolding,
specUnfolding,
ArgSummary(..),
couldBeSmallEnoughToInline, inlineBoringOk,
certainlyWillInline, smallEnoughToInline,
callSiteInline, CallCtxt(..),
exprIsConApp_maybe, exprIsLiteral_maybe
) where
#include "HsVersions.h"
import GHC.Prelude
import GHC.Driver.Session
import GHC.Core
import GHC.Core.Opt.OccurAnal ( occurAnalyseExpr )
import GHC.Core.SimpleOpt
import GHC.Core.Opt.Arity ( manifestArity )
import GHC.Core.Utils
import GHC.Types.Id
import GHC.Types.Demand ( StrictSig, isDeadEndSig )
import GHC.Core.DataCon
import GHC.Types.Literal
import GHC.Builtin.PrimOps
import GHC.Types.Id.Info
import GHC.Types.Basic ( Arity, InlineSpec(..), inlinePragmaSpec )
import GHC.Core.Type
import GHC.Builtin.Names
import GHC.Builtin.Types.Prim ( realWorldStatePrimTy )
import GHC.Data.Bag
import GHC.Utils.Misc
import GHC.Utils.Outputable
import GHC.Types.ForeignCall
import GHC.Types.Name
import GHC.Utils.Error
import qualified Data.ByteString as BS
import Data.List
mkFinalUnfolding :: DynFlags -> UnfoldingSource -> StrictSig -> CoreExpr -> Unfolding
mkFinalUnfolding :: DynFlags -> UnfoldingSource -> StrictSig -> CoreArg -> Unfolding
mkFinalUnfolding DynFlags
dflags UnfoldingSource
src StrictSig
strict_sig CoreArg
expr
= DynFlags -> UnfoldingSource -> Bool -> Bool -> CoreArg -> Unfolding
mkUnfolding DynFlags
dflags UnfoldingSource
src
Bool
True
(StrictSig -> Bool
isDeadEndSig StrictSig
strict_sig)
CoreArg
expr
mkCompulsoryUnfolding :: CoreExpr -> Unfolding
mkCompulsoryUnfolding :: CoreArg -> Unfolding
mkCompulsoryUnfolding CoreArg
expr
= UnfoldingSource
-> Bool -> CoreArg -> UnfoldingGuidance -> Unfolding
mkCoreUnfolding UnfoldingSource
InlineCompulsory Bool
True
(HasDebugCallStack => DynFlags -> CoreArg -> CoreArg
DynFlags -> CoreArg -> CoreArg
simpleOptExpr DynFlags
unsafeGlobalDynFlags CoreArg
expr)
(UnfWhen :: Int -> Bool -> Bool -> UnfoldingGuidance
UnfWhen { ug_arity :: Int
ug_arity = Int
0
, ug_unsat_ok :: Bool
ug_unsat_ok = Bool
unSaturatedOk, ug_boring_ok :: Bool
ug_boring_ok = Bool
boringCxtOk })
mkSimpleUnfolding :: DynFlags -> CoreExpr -> Unfolding
mkSimpleUnfolding :: DynFlags -> CoreArg -> Unfolding
mkSimpleUnfolding DynFlags
dflags CoreArg
rhs
= DynFlags -> UnfoldingSource -> Bool -> Bool -> CoreArg -> Unfolding
mkUnfolding DynFlags
dflags UnfoldingSource
InlineRhs Bool
False Bool
False CoreArg
rhs
mkDFunUnfolding :: [Var] -> DataCon -> [CoreExpr] -> Unfolding
mkDFunUnfolding :: [Id] -> DataCon -> [CoreArg] -> Unfolding
mkDFunUnfolding [Id]
bndrs DataCon
con [CoreArg]
ops
= DFunUnfolding :: [Id] -> DataCon -> [CoreArg] -> Unfolding
DFunUnfolding { df_bndrs :: [Id]
df_bndrs = [Id]
bndrs
, df_con :: DataCon
df_con = DataCon
con
, df_args :: [CoreArg]
df_args = (CoreArg -> CoreArg) -> [CoreArg] -> [CoreArg]
forall a b. (a -> b) -> [a] -> [b]
map CoreArg -> CoreArg
occurAnalyseExpr [CoreArg]
ops }
mkWwInlineRule :: DynFlags -> CoreExpr -> Arity -> Unfolding
mkWwInlineRule :: DynFlags -> CoreArg -> Int -> Unfolding
mkWwInlineRule DynFlags
dflags CoreArg
expr Int
arity
= UnfoldingSource
-> Bool -> CoreArg -> UnfoldingGuidance -> Unfolding
mkCoreUnfolding UnfoldingSource
InlineStable Bool
True
(HasDebugCallStack => DynFlags -> CoreArg -> CoreArg
DynFlags -> CoreArg -> CoreArg
simpleOptExpr DynFlags
dflags CoreArg
expr)
(UnfWhen :: Int -> Bool -> Bool -> UnfoldingGuidance
UnfWhen { ug_arity :: Int
ug_arity = Int
arity, ug_unsat_ok :: Bool
ug_unsat_ok = Bool
unSaturatedOk
, ug_boring_ok :: Bool
ug_boring_ok = Bool
boringCxtNotOk })
mkWorkerUnfolding :: DynFlags -> (CoreExpr -> CoreExpr) -> Unfolding -> Unfolding
mkWorkerUnfolding :: DynFlags -> (CoreArg -> CoreArg) -> Unfolding -> Unfolding
mkWorkerUnfolding DynFlags
dflags 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 -> UnfoldingGuidance -> Unfolding
mkCoreUnfolding UnfoldingSource
src Bool
top_lvl CoreArg
new_tmpl UnfoldingGuidance
guidance
where
new_tmpl :: CoreArg
new_tmpl = HasDebugCallStack => DynFlags -> CoreArg -> CoreArg
DynFlags -> CoreArg -> CoreArg
simpleOptExpr DynFlags
dflags (CoreArg -> CoreArg
work_fn CoreArg
tmpl)
guidance :: UnfoldingGuidance
guidance = DynFlags -> Bool -> CoreArg -> UnfoldingGuidance
calcUnfoldingGuidance DynFlags
dflags Bool
False CoreArg
new_tmpl
mkWorkerUnfolding DynFlags
_ CoreArg -> CoreArg
_ Unfolding
_ = Unfolding
noUnfolding
mkInlineUnfolding :: CoreExpr -> Unfolding
mkInlineUnfolding :: CoreArg -> Unfolding
mkInlineUnfolding CoreArg
expr
= UnfoldingSource
-> Bool -> CoreArg -> UnfoldingGuidance -> Unfolding
mkCoreUnfolding UnfoldingSource
InlineStable
Bool
True
CoreArg
expr' UnfoldingGuidance
guide
where
expr' :: CoreArg
expr' = HasDebugCallStack => DynFlags -> CoreArg -> CoreArg
DynFlags -> CoreArg -> CoreArg
simpleOptExpr DynFlags
unsafeGlobalDynFlags CoreArg
expr
guide :: UnfoldingGuidance
guide = UnfWhen :: Int -> Bool -> Bool -> UnfoldingGuidance
UnfWhen { ug_arity :: Int
ug_arity = CoreArg -> Int
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 :: Arity -> CoreExpr -> Unfolding
mkInlineUnfoldingWithArity :: Int -> CoreArg -> Unfolding
mkInlineUnfoldingWithArity Int
arity CoreArg
expr
= UnfoldingSource
-> Bool -> CoreArg -> UnfoldingGuidance -> Unfolding
mkCoreUnfolding UnfoldingSource
InlineStable
Bool
True
CoreArg
expr' UnfoldingGuidance
guide
where
expr' :: CoreArg
expr' = HasDebugCallStack => DynFlags -> CoreArg -> CoreArg
DynFlags -> CoreArg -> CoreArg
simpleOptExpr DynFlags
unsafeGlobalDynFlags CoreArg
expr
guide :: UnfoldingGuidance
guide = UnfWhen :: Int -> Bool -> Bool -> UnfoldingGuidance
UnfWhen { ug_arity :: Int
ug_arity = Int
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 | Int
arity Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
0 = Bool
True
| Bool
otherwise = CoreArg -> Bool
inlineBoringOk CoreArg
expr'
mkInlinableUnfolding :: DynFlags -> CoreExpr -> Unfolding
mkInlinableUnfolding :: DynFlags -> CoreArg -> Unfolding
mkInlinableUnfolding DynFlags
dflags CoreArg
expr
= DynFlags -> UnfoldingSource -> Bool -> Bool -> CoreArg -> Unfolding
mkUnfolding DynFlags
dflags UnfoldingSource
InlineStable Bool
False Bool
False CoreArg
expr'
where
expr' :: CoreArg
expr' = HasDebugCallStack => DynFlags -> CoreArg -> CoreArg
DynFlags -> CoreArg -> CoreArg
simpleOptExpr DynFlags
dflags CoreArg
expr
specUnfolding :: DynFlags
-> [Var] -> (CoreExpr -> CoreExpr)
-> [CoreArg]
-> Unfolding -> Unfolding
specUnfolding :: DynFlags
-> [Id]
-> (CoreArg -> CoreArg)
-> [CoreArg]
-> Unfolding
-> Unfolding
specUnfolding DynFlags
dflags [Id]
spec_bndrs CoreArg -> CoreArg
spec_app [CoreArg]
rule_lhs_args
df :: Unfolding
df@(DFunUnfolding { df_bndrs :: Unfolding -> [Id]
df_bndrs = [Id]
old_bndrs, df_con :: Unfolding -> DataCon
df_con = DataCon
con, df_args :: Unfolding -> [CoreArg]
df_args = [CoreArg]
args })
= ASSERT2( rule_lhs_args `equalLength` old_bndrs
, ppr df $$ ppr rule_lhs_args )
[Id] -> DataCon -> [CoreArg] -> Unfolding
mkDFunUnfolding [Id]
spec_bndrs DataCon
con ((CoreArg -> CoreArg) -> [CoreArg] -> [CoreArg]
forall a b. (a -> b) -> [a] -> [b]
map CoreArg -> CoreArg
spec_arg [CoreArg]
args)
where
spec_arg :: CoreArg -> CoreArg
spec_arg CoreArg
arg = HasDebugCallStack => DynFlags -> CoreArg -> CoreArg
DynFlags -> CoreArg -> CoreArg
simpleOptExpr DynFlags
dflags (CoreArg -> CoreArg) -> CoreArg -> CoreArg
forall a b. (a -> b) -> a -> b
$
CoreArg -> CoreArg
spec_app ([Id] -> CoreArg -> CoreArg
forall b. [b] -> Expr b -> Expr b
mkLams [Id]
old_bndrs CoreArg
arg)
specUnfolding DynFlags
dflags [Id]
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 -> Int
ug_arity = Int
old_arity } <- UnfoldingGuidance
old_guidance
= UnfoldingSource
-> Bool -> CoreArg -> UnfoldingGuidance -> Unfolding
mkCoreUnfolding UnfoldingSource
src Bool
top_lvl CoreArg
new_tmpl
(UnfoldingGuidance
old_guidance { ug_arity :: Int
ug_arity = Int
old_arity Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
arity_decrease })
where
new_tmpl :: CoreArg
new_tmpl = HasDebugCallStack => DynFlags -> CoreArg -> CoreArg
DynFlags -> CoreArg -> CoreArg
simpleOptExpr DynFlags
dflags (CoreArg -> CoreArg) -> CoreArg -> CoreArg
forall a b. (a -> b) -> a -> b
$
[Id] -> CoreArg -> CoreArg
forall b. [b] -> Expr b -> Expr b
mkLams [Id]
spec_bndrs (CoreArg -> CoreArg) -> CoreArg -> CoreArg
forall a b. (a -> b) -> a -> b
$
CoreArg -> CoreArg
spec_app CoreArg
tmpl
arity_decrease :: Int
arity_decrease = (CoreArg -> Bool) -> [CoreArg] -> Int
forall a. (a -> Bool) -> [a] -> Int
count CoreArg -> Bool
forall b. Expr b -> Bool
isValArg [CoreArg]
rule_lhs_args Int -> Int -> Int
forall a. Num a => a -> a -> a
- (Id -> Bool) -> [Id] -> Int
forall a. (a -> Bool) -> [a] -> Int
count Id -> Bool
isId [Id]
spec_bndrs
specUnfolding DynFlags
_ [Id]
_ CoreArg -> CoreArg
_ [CoreArg]
_ Unfolding
_ = Unfolding
noUnfolding
mkUnfolding :: DynFlags -> UnfoldingSource
-> Bool
-> Bool
-> CoreExpr
-> Unfolding
mkUnfolding :: DynFlags -> UnfoldingSource -> Bool -> Bool -> CoreArg -> Unfolding
mkUnfolding DynFlags
dflags UnfoldingSource
src Bool
top_lvl Bool
is_bottoming CoreArg
expr
= UnfoldingSource
-> Bool -> CoreArg -> UnfoldingGuidance -> Unfolding
mkCoreUnfolding UnfoldingSource
src Bool
top_lvl CoreArg
expr UnfoldingGuidance
guidance
where
is_top_bottoming :: Bool
is_top_bottoming = Bool
top_lvl Bool -> Bool -> Bool
&& Bool
is_bottoming
guidance :: UnfoldingGuidance
guidance = DynFlags -> Bool -> CoreArg -> UnfoldingGuidance
calcUnfoldingGuidance DynFlags
dflags Bool
is_top_bottoming CoreArg
expr
mkCoreUnfolding :: UnfoldingSource -> Bool -> CoreExpr
-> UnfoldingGuidance -> Unfolding
mkCoreUnfolding :: UnfoldingSource
-> Bool -> CoreArg -> UnfoldingGuidance -> Unfolding
mkCoreUnfolding UnfoldingSource
src Bool
top_lvl CoreArg
expr UnfoldingGuidance
guidance
= CoreUnfolding :: CoreArg
-> UnfoldingSource
-> Bool
-> Bool
-> Bool
-> Bool
-> Bool
-> UnfoldingGuidance
-> Unfolding
CoreUnfolding { uf_tmpl :: CoreArg
uf_tmpl = CoreArg -> CoreArg
occurAnalyseExpr CoreArg
expr,
uf_src :: UnfoldingSource
uf_src = UnfoldingSource
src,
uf_is_top :: Bool
uf_is_top = Bool
top_lvl,
uf_is_value :: Bool
uf_is_value = CoreArg -> Bool
exprIsHNF CoreArg
expr,
uf_is_conlike :: Bool
uf_is_conlike = CoreArg -> Bool
exprIsConLike CoreArg
expr,
uf_is_work_free :: Bool
uf_is_work_free = CoreArg -> Bool
exprIsWorkFree CoreArg
expr,
uf_expandable :: Bool
uf_expandable = CoreArg -> Bool
exprIsExpandable CoreArg
expr,
uf_guidance :: UnfoldingGuidance
uf_guidance = UnfoldingGuidance
guidance }
inlineBoringOk :: CoreExpr -> Bool
inlineBoringOk :: CoreArg -> Bool
inlineBoringOk CoreArg
e
= Int -> CoreArg -> Bool
go Int
0 CoreArg
e
where
go :: Int -> CoreExpr -> Bool
go :: Int -> CoreArg -> Bool
go Int
credit (Lam Id
x CoreArg
e) | Id -> Bool
isId Id
x = Int -> CoreArg -> Bool
go (Int
creditInt -> Int -> Int
forall a. Num a => a -> a -> a
+Int
1) CoreArg
e
| Bool
otherwise = Int -> CoreArg -> Bool
go Int
credit CoreArg
e
go Int
credit (App CoreArg
f (Type {})) = Int -> CoreArg -> Bool
go Int
credit CoreArg
f
go Int
credit (App CoreArg
f CoreArg
a) | Int
credit Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
> Int
0
, CoreArg -> Bool
exprIsTrivial CoreArg
a = Int -> CoreArg -> Bool
go (Int
creditInt -> Int -> Int
forall a. Num a => a -> a -> a
-Int
1) CoreArg
f
go Int
credit (Tick Tickish Id
_ CoreArg
e) = Int -> CoreArg -> Bool
go Int
credit CoreArg
e
go Int
credit (Cast CoreArg
e CoercionR
_) = Int -> CoreArg -> Bool
go Int
credit CoreArg
e
go Int
credit (Case CoreArg
scrut Id
_ Type
_ [(AltCon
_,[Id]
_,CoreArg
rhs)])
| CoreArg -> Bool
isUnsafeEqualityProof CoreArg
scrut = Int -> CoreArg -> Bool
go Int
credit CoreArg
rhs
go Int
_ (Var {}) = Bool
boringCxtOk
go Int
_ CoreArg
_ = Bool
boringCxtNotOk
calcUnfoldingGuidance
:: DynFlags
-> Bool
-> CoreExpr
-> UnfoldingGuidance
calcUnfoldingGuidance :: DynFlags -> Bool -> CoreArg -> UnfoldingGuidance
calcUnfoldingGuidance DynFlags
dflags Bool
is_top_bottoming (Tick Tickish Id
t CoreArg
expr)
| Bool -> Bool
not (Tickish Id -> Bool
forall id. Tickish id -> Bool
tickishIsCode Tickish Id
t)
= DynFlags -> Bool -> CoreArg -> UnfoldingGuidance
calcUnfoldingGuidance DynFlags
dflags Bool
is_top_bottoming CoreArg
expr
calcUnfoldingGuidance DynFlags
dflags Bool
is_top_bottoming CoreArg
expr
= case DynFlags -> Int -> [Id] -> CoreArg -> ExprSize
sizeExpr DynFlags
dflags Int
bOMB_OUT_SIZE [Id]
val_bndrs CoreArg
body of
ExprSize
TooBig -> UnfoldingGuidance
UnfNever
SizeIs Int
size Bag (Id, Int)
cased_bndrs Int
scrut_discount
| CoreArg -> Int -> Int -> Bool
uncondInline CoreArg
expr Int
n_val_bndrs Int
size
-> UnfWhen :: Int -> Bool -> Bool -> UnfoldingGuidance
UnfWhen { ug_unsat_ok :: Bool
ug_unsat_ok = Bool
unSaturatedOk
, ug_boring_ok :: Bool
ug_boring_ok = Bool
boringCxtOk
, ug_arity :: Int
ug_arity = Int
n_val_bndrs }
| Bool
is_top_bottoming
-> UnfoldingGuidance
UnfNever
| Bool
otherwise
-> UnfIfGoodArgs :: [Int] -> Int -> Int -> UnfoldingGuidance
UnfIfGoodArgs { ug_args :: [Int]
ug_args = (Id -> Int) -> [Id] -> [Int]
forall a b. (a -> b) -> [a] -> [b]
map (Bag (Id, Int) -> Id -> Int
mk_discount Bag (Id, Int)
cased_bndrs) [Id]
val_bndrs
, ug_size :: Int
ug_size = Int
size
, ug_res :: Int
ug_res = Int
scrut_discount }
where
([Id]
bndrs, CoreArg
body) = CoreArg -> ([Id], CoreArg)
forall b. Expr b -> ([b], Expr b)
collectBinders CoreArg
expr
bOMB_OUT_SIZE :: Int
bOMB_OUT_SIZE = DynFlags -> Int
ufCreationThreshold DynFlags
dflags
val_bndrs :: [Id]
val_bndrs = (Id -> Bool) -> [Id] -> [Id]
forall a. (a -> Bool) -> [a] -> [a]
filter Id -> Bool
isId [Id]
bndrs
n_val_bndrs :: Int
n_val_bndrs = [Id] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [Id]
val_bndrs
mk_discount :: Bag (Id,Int) -> Id -> Int
mk_discount :: Bag (Id, Int) -> Id -> Int
mk_discount Bag (Id, Int)
cbs Id
bndr = (Int -> (Id, Int) -> Int) -> Int -> Bag (Id, Int) -> Int
forall (t :: * -> *) b a.
Foldable t =>
(b -> a -> b) -> b -> t a -> b
foldl' Int -> (Id, Int) -> Int
combine Int
0 Bag (Id, Int)
cbs
where
combine :: Int -> (Id, Int) -> Int
combine Int
acc (Id
bndr', Int
disc)
| Id
bndr Id -> Id -> Bool
forall a. Eq a => a -> a -> Bool
== Id
bndr' = Int
acc Int -> Int -> Int
`plus_disc` Int
disc
| Bool
otherwise = Int
acc
plus_disc :: Int -> Int -> Int
plus_disc :: Int -> Int -> Int
plus_disc | Type -> Bool
isFunTy (Id -> Type
idType Id
bndr) = Int -> Int -> Int
forall a. Ord a => a -> a -> a
max
| Bool
otherwise = Int -> Int -> Int
forall a. Num a => a -> a -> a
(+)
uncondInline :: CoreExpr -> Arity -> Int -> Bool
uncondInline :: CoreArg -> Int -> Int -> Bool
uncondInline CoreArg
rhs Int
arity Int
size
| Int
arity Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
> Int
0 = Int
size Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
<= Int
10 Int -> Int -> Int
forall a. Num a => a -> a -> a
* (Int
arity Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
1)
| Bool
otherwise = CoreArg -> Bool
exprIsTrivial CoreArg
rhs
sizeExpr :: DynFlags
-> Int
-> [Id]
-> CoreExpr
-> ExprSize
sizeExpr :: DynFlags -> Int -> [Id] -> CoreArg -> ExprSize
sizeExpr DynFlags
dflags Int
bOMB_OUT_SIZE [Id]
top_args CoreArg
expr
= CoreArg -> ExprSize
size_up CoreArg
expr
where
size_up :: CoreArg -> ExprSize
size_up (Cast CoreArg
e CoercionR
_) = CoreArg -> ExprSize
size_up CoreArg
e
size_up (Tick Tickish Id
_ CoreArg
e) = CoreArg -> ExprSize
size_up CoreArg
e
size_up (Type Type
_) = ExprSize
sizeZero
size_up (Coercion CoercionR
_) = ExprSize
sizeZero
size_up (Lit Literal
lit) = Int -> ExprSize
sizeN (Literal -> Int
litSize Literal
lit)
size_up (Var Id
f) | Id -> Bool
isRealWorldId Id
f = ExprSize
sizeZero
| Bool
otherwise = Id -> [CoreArg] -> Int -> ExprSize
size_up_call Id
f [] Int
0
size_up (App CoreArg
fun CoreArg
arg)
| CoreArg -> Bool
forall b. Expr b -> Bool
isTyCoArg CoreArg
arg = CoreArg -> ExprSize
size_up CoreArg
fun
| Bool
otherwise = CoreArg -> ExprSize
size_up CoreArg
arg ExprSize -> ExprSize -> ExprSize
`addSizeNSD`
CoreArg -> [CoreArg] -> Int -> ExprSize
size_up_app CoreArg
fun [CoreArg
arg] (if CoreArg -> Bool
forall b. Expr b -> Bool
isRealWorldExpr CoreArg
arg then Int
1 else Int
0)
size_up (Lam Id
b CoreArg
e)
| Id -> Bool
isId Id
b Bool -> Bool -> Bool
&& Bool -> Bool
not (Id -> Bool
isRealWorldId Id
b) = DynFlags -> ExprSize -> ExprSize
lamScrutDiscount DynFlags
dflags (CoreArg -> ExprSize
size_up CoreArg
e ExprSize -> Int -> ExprSize
`addSizeN` Int
10)
| Bool
otherwise = CoreArg -> ExprSize
size_up CoreArg
e
size_up (Let (NonRec Id
binder CoreArg
rhs) CoreArg
body)
= (Id, CoreArg) -> ExprSize
size_up_rhs (Id
binder, CoreArg
rhs) ExprSize -> ExprSize -> ExprSize
`addSizeNSD`
CoreArg -> ExprSize
size_up CoreArg
body ExprSize -> Int -> ExprSize
`addSizeN`
Id -> Int
forall {p}. Num p => Id -> p
size_up_alloc Id
binder
size_up (Let (Rec [(Id, CoreArg)]
pairs) CoreArg
body)
= ((Id, CoreArg) -> ExprSize -> ExprSize)
-> ExprSize -> [(Id, CoreArg)] -> ExprSize
forall (t :: * -> *) a b.
Foldable t =>
(a -> b -> b) -> b -> t a -> b
foldr (ExprSize -> ExprSize -> ExprSize
addSizeNSD (ExprSize -> ExprSize -> ExprSize)
-> ((Id, CoreArg) -> ExprSize)
-> (Id, CoreArg)
-> ExprSize
-> ExprSize
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Id, CoreArg) -> ExprSize
size_up_rhs)
(CoreArg -> ExprSize
size_up CoreArg
body ExprSize -> Int -> ExprSize
`addSizeN` [Int] -> Int
forall (t :: * -> *) a. (Foldable t, Num a) => t a -> a
sum (((Id, CoreArg) -> Int) -> [(Id, CoreArg)] -> [Int]
forall a b. (a -> b) -> [a] -> [b]
map (Id -> Int
forall {p}. Num p => Id -> p
size_up_alloc (Id -> Int) -> ((Id, CoreArg) -> Id) -> (Id, CoreArg) -> Int
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Id, CoreArg) -> Id
forall a b. (a, b) -> a
fst) [(Id, CoreArg)]
pairs))
[(Id, CoreArg)]
pairs
size_up (Case CoreArg
e Id
_ Type
_ [Alt Id]
alts)
| [Alt Id] -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null [Alt Id]
alts
= CoreArg -> ExprSize
size_up CoreArg
e
size_up (Case CoreArg
e Id
_ Type
_ [Alt Id]
alts)
| Just Id
v <- CoreArg -> Maybe Id
forall {b}. Expr b -> Maybe Id
is_top_arg CoreArg
e
= let
alt_sizes :: [ExprSize]
alt_sizes = (Alt Id -> ExprSize) -> [Alt Id] -> [ExprSize]
forall a b. (a -> b) -> [a] -> [b]
map Alt Id -> ExprSize
size_up_alt [Alt Id]
alts
alts_size :: ExprSize -> ExprSize -> ExprSize
alts_size (SizeIs Int
tot Bag (Id, Int)
tot_disc Int
tot_scrut)
(SizeIs Int
max Bag (Id, Int)
_ Int
_)
= Int -> Bag (Id, Int) -> Int -> ExprSize
SizeIs Int
tot ((Id, Int) -> Bag (Id, Int)
forall a. a -> Bag a
unitBag (Id
v, Int
20 Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
tot Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
max)
Bag (Id, Int) -> Bag (Id, Int) -> Bag (Id, Int)
forall a. Bag a -> Bag a -> Bag a
`unionBags` Bag (Id, Int)
tot_disc) Int
tot_scrut
alts_size ExprSize
tot_size ExprSize
_ = ExprSize
tot_size
in
ExprSize -> ExprSize -> ExprSize
alts_size ((ExprSize -> ExprSize -> ExprSize) -> [ExprSize] -> ExprSize
forall (t :: * -> *) a. Foldable t => (a -> a -> a) -> t a -> a
foldr1 ExprSize -> ExprSize -> ExprSize
addAltSize [ExprSize]
alt_sizes)
((ExprSize -> ExprSize -> ExprSize) -> [ExprSize] -> ExprSize
forall (t :: * -> *) a. Foldable t => (a -> a -> a) -> t a -> a
foldr1 ExprSize -> ExprSize -> ExprSize
maxSize [ExprSize]
alt_sizes)
where
is_top_arg :: Expr b -> Maybe Id
is_top_arg (Var Id
v) | Id
v Id -> [Id] -> Bool
forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`elem` [Id]
top_args = Id -> Maybe Id
forall a. a -> Maybe a
Just Id
v
is_top_arg (Cast Expr b
e CoercionR
_) = Expr b -> Maybe Id
is_top_arg Expr b
e
is_top_arg Expr b
_ = Maybe Id
forall a. Maybe a
Nothing
size_up (Case CoreArg
e Id
_ Type
_ [Alt Id]
alts) = CoreArg -> ExprSize
size_up CoreArg
e ExprSize -> ExprSize -> ExprSize
`addSizeNSD`
(Alt Id -> ExprSize -> ExprSize)
-> ExprSize -> [Alt Id] -> ExprSize
forall (t :: * -> *) a b.
Foldable t =>
(a -> b -> b) -> b -> t a -> b
foldr (ExprSize -> ExprSize -> ExprSize
addAltSize (ExprSize -> ExprSize -> ExprSize)
-> (Alt Id -> ExprSize) -> Alt Id -> ExprSize -> ExprSize
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Alt Id -> ExprSize
size_up_alt) ExprSize
case_size [Alt Id]
alts
where
case_size :: ExprSize
case_size
| CoreArg -> Bool
forall b. Expr b -> Bool
is_inline_scrut CoreArg
e, [Alt Id] -> Int -> Bool
forall a. [a] -> Int -> Bool
lengthAtMost [Alt Id]
alts Int
1 = Int -> ExprSize
sizeN (-Int
10)
| Bool
otherwise = ExprSize
sizeZero
is_inline_scrut :: Expr b -> Bool
is_inline_scrut (Var Id
v) = HasDebugCallStack => Type -> Bool
Type -> Bool
isUnliftedType (Id -> Type
idType Id
v)
is_inline_scrut Expr b
scrut
| (Var Id
f, [Expr b]
_) <- Expr b -> (Expr b, [Expr b])
forall b. Expr b -> (Expr b, [Expr b])
collectArgs Expr b
scrut
= case Id -> IdDetails
idDetails Id
f of
FCallId ForeignCall
fc -> Bool -> Bool
not (ForeignCall -> Bool
isSafeForeignCall ForeignCall
fc)
PrimOpId PrimOp
op -> Bool -> Bool
not (PrimOp -> Bool
primOpOutOfLine PrimOp
op)
IdDetails
_other -> Bool
False
| Bool
otherwise
= Bool
False
size_up_rhs :: (Id, CoreArg) -> ExprSize
size_up_rhs (Id
bndr, CoreArg
rhs)
| Just Int
join_arity <- Id -> Maybe Int
isJoinId_maybe Id
bndr
, ([Id]
_bndrs, CoreArg
body) <- Int -> CoreArg -> ([Id], CoreArg)
forall b. Int -> Expr b -> ([b], Expr b)
collectNBinders Int
join_arity CoreArg
rhs
= CoreArg -> ExprSize
size_up CoreArg
body
| Bool
otherwise
= CoreArg -> ExprSize
size_up CoreArg
rhs
size_up_app :: CoreArg -> [CoreArg] -> Int -> ExprSize
size_up_app (App CoreArg
fun CoreArg
arg) [CoreArg]
args Int
voids
| CoreArg -> Bool
forall b. Expr b -> Bool
isTyCoArg CoreArg
arg = CoreArg -> [CoreArg] -> Int -> ExprSize
size_up_app CoreArg
fun [CoreArg]
args Int
voids
| CoreArg -> Bool
forall b. Expr b -> Bool
isRealWorldExpr CoreArg
arg = CoreArg -> [CoreArg] -> Int -> ExprSize
size_up_app CoreArg
fun (CoreArg
argCoreArg -> [CoreArg] -> [CoreArg]
forall a. a -> [a] -> [a]
:[CoreArg]
args) (Int
voids Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
1)
| Bool
otherwise = CoreArg -> ExprSize
size_up CoreArg
arg ExprSize -> ExprSize -> ExprSize
`addSizeNSD`
CoreArg -> [CoreArg] -> Int -> ExprSize
size_up_app CoreArg
fun (CoreArg
argCoreArg -> [CoreArg] -> [CoreArg]
forall a. a -> [a] -> [a]
:[CoreArg]
args) Int
voids
size_up_app (Var Id
fun) [CoreArg]
args Int
voids = Id -> [CoreArg] -> Int -> ExprSize
size_up_call Id
fun [CoreArg]
args Int
voids
size_up_app (Tick Tickish Id
_ CoreArg
expr) [CoreArg]
args Int
voids = CoreArg -> [CoreArg] -> Int -> ExprSize
size_up_app CoreArg
expr [CoreArg]
args Int
voids
size_up_app (Cast CoreArg
expr CoercionR
_) [CoreArg]
args Int
voids = CoreArg -> [CoreArg] -> Int -> ExprSize
size_up_app CoreArg
expr [CoreArg]
args Int
voids
size_up_app CoreArg
other [CoreArg]
args Int
voids = CoreArg -> ExprSize
size_up CoreArg
other ExprSize -> Int -> ExprSize
`addSizeN`
Int -> Int -> Int
callSize ([CoreArg] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [CoreArg]
args) Int
voids
size_up_call :: Id -> [CoreExpr] -> Int -> ExprSize
size_up_call :: Id -> [CoreArg] -> Int -> ExprSize
size_up_call Id
fun [CoreArg]
val_args Int
voids
= case Id -> IdDetails
idDetails Id
fun of
FCallId ForeignCall
_ -> Int -> ExprSize
sizeN (Int -> Int -> Int
callSize ([CoreArg] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [CoreArg]
val_args) Int
voids)
DataConWorkId DataCon
dc -> DataCon -> Int -> ExprSize
conSize DataCon
dc ([CoreArg] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [CoreArg]
val_args)
PrimOpId PrimOp
op -> PrimOp -> Int -> ExprSize
primOpSize PrimOp
op ([CoreArg] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [CoreArg]
val_args)
ClassOpId Class
_ -> DynFlags -> [Id] -> [CoreArg] -> ExprSize
classOpSize DynFlags
dflags [Id]
top_args [CoreArg]
val_args
IdDetails
_ -> DynFlags -> [Id] -> Id -> Int -> Int -> ExprSize
funSize DynFlags
dflags [Id]
top_args Id
fun ([CoreArg] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [CoreArg]
val_args) Int
voids
size_up_alt :: Alt Id -> ExprSize
size_up_alt (AltCon
_con, [Id]
_bndrs, CoreArg
rhs) = CoreArg -> ExprSize
size_up CoreArg
rhs ExprSize -> Int -> ExprSize
`addSizeN` Int
10
size_up_alloc :: Id -> p
size_up_alloc Id
bndr
| Id -> Bool
isTyVar Id
bndr
Bool -> Bool -> Bool
|| Id -> Bool
isJoinId Id
bndr
Bool -> Bool -> Bool
|| HasDebugCallStack => Type -> Bool
Type -> Bool
isUnliftedType (Id -> Type
idType Id
bndr)
= p
0
| Bool
otherwise
= p
10
addSizeN :: ExprSize -> Int -> ExprSize
addSizeN ExprSize
TooBig Int
_ = ExprSize
TooBig
addSizeN (SizeIs Int
n Bag (Id, Int)
xs Int
d) Int
m = Int -> Int -> Bag (Id, Int) -> Int -> ExprSize
mkSizeIs Int
bOMB_OUT_SIZE (Int
n Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
m) Bag (Id, Int)
xs Int
d
addAltSize :: ExprSize -> ExprSize -> ExprSize
addAltSize ExprSize
TooBig ExprSize
_ = ExprSize
TooBig
addAltSize ExprSize
_ ExprSize
TooBig = ExprSize
TooBig
addAltSize (SizeIs Int
n1 Bag (Id, Int)
xs Int
d1) (SizeIs Int
n2 Bag (Id, Int)
ys Int
d2)
= Int -> Int -> Bag (Id, Int) -> Int -> ExprSize
mkSizeIs Int
bOMB_OUT_SIZE (Int
n1 Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
n2)
(Bag (Id, Int)
xs Bag (Id, Int) -> Bag (Id, Int) -> Bag (Id, Int)
forall a. Bag a -> Bag a -> Bag a
`unionBags` Bag (Id, Int)
ys)
(Int
d1 Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
d2)
addSizeNSD :: ExprSize -> ExprSize -> ExprSize
addSizeNSD ExprSize
TooBig ExprSize
_ = ExprSize
TooBig
addSizeNSD ExprSize
_ ExprSize
TooBig = ExprSize
TooBig
addSizeNSD (SizeIs Int
n1 Bag (Id, Int)
xs Int
_) (SizeIs Int
n2 Bag (Id, Int)
ys Int
d2)
= Int -> Int -> Bag (Id, Int) -> Int -> ExprSize
mkSizeIs Int
bOMB_OUT_SIZE (Int
n1 Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
n2)
(Bag (Id, Int)
xs Bag (Id, Int) -> Bag (Id, Int) -> Bag (Id, Int)
forall a. Bag a -> Bag a -> Bag a
`unionBags` Bag (Id, Int)
ys)
Int
d2
isRealWorldId :: Id -> Bool
isRealWorldId Id
id = Id -> Type
idType Id
id Type -> Type -> Bool
`eqType` Type
realWorldStatePrimTy
isRealWorldExpr :: Expr b -> Bool
isRealWorldExpr (Var Id
id) = Id -> Bool
isRealWorldId Id
id
isRealWorldExpr (Tick Tickish Id
_ Expr b
e) = Expr b -> Bool
isRealWorldExpr Expr b
e
isRealWorldExpr Expr b
_ = Bool
False
litSize :: Literal -> Int
litSize :: Literal -> Int
litSize (LitNumber LitNumType
LitNumInteger Integer
_) = Int
100
litSize (LitNumber LitNumType
LitNumNatural Integer
_) = Int
100
litSize (LitString ByteString
str) = Int
10 Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
10 Int -> Int -> Int
forall a. Num a => a -> a -> a
* ((ByteString -> Int
BS.length ByteString
str Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
3) Int -> Int -> Int
forall a. Integral a => a -> a -> a
`div` Int
4)
litSize Literal
_other = Int
0
classOpSize :: DynFlags -> [Id] -> [CoreExpr] -> ExprSize
classOpSize :: DynFlags -> [Id] -> [CoreArg] -> ExprSize
classOpSize DynFlags
_ [Id]
_ []
= ExprSize
sizeZero
classOpSize DynFlags
dflags [Id]
top_args (CoreArg
arg1 : [CoreArg]
other_args)
= Int -> Bag (Id, Int) -> Int -> ExprSize
SizeIs Int
size Bag (Id, Int)
arg_discount Int
0
where
size :: Int
size = Int
20 Int -> Int -> Int
forall a. Num a => a -> a -> a
+ (Int
10 Int -> Int -> Int
forall a. Num a => a -> a -> a
* [CoreArg] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [CoreArg]
other_args)
arg_discount :: Bag (Id, Int)
arg_discount = case CoreArg
arg1 of
Var Id
dict | Id
dict Id -> [Id] -> Bool
forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`elem` [Id]
top_args
-> (Id, Int) -> Bag (Id, Int)
forall a. a -> Bag a
unitBag (Id
dict, DynFlags -> Int
ufDictDiscount DynFlags
dflags)
CoreArg
_other -> Bag (Id, Int)
forall a. Bag a
emptyBag
callSize
:: Int
-> Int
-> Int
callSize :: Int -> Int -> Int
callSize Int
n_val_args Int
voids = Int
10 Int -> Int -> Int
forall a. Num a => a -> a -> a
* (Int
1 Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
n_val_args Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
voids)
jumpSize
:: Int
-> Int
-> Int
jumpSize :: Int -> Int -> Int
jumpSize Int
n_val_args Int
voids = Int
2 Int -> Int -> Int
forall a. Num a => a -> a -> a
* (Int
1 Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
n_val_args Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
voids)
funSize :: DynFlags -> [Id] -> Id -> Int -> Int -> ExprSize
funSize :: DynFlags -> [Id] -> Id -> Int -> Int -> ExprSize
funSize DynFlags
dflags [Id]
top_args Id
fun Int
n_val_args Int
voids
| Id
fun Id -> Unique -> Bool
forall a. Uniquable a => a -> Unique -> Bool
`hasKey` Unique
buildIdKey = ExprSize
buildSize
| Id
fun Id -> Unique -> Bool
forall a. Uniquable a => a -> Unique -> Bool
`hasKey` Unique
augmentIdKey = ExprSize
augmentSize
| Bool
otherwise = Int -> Bag (Id, Int) -> Int -> ExprSize
SizeIs Int
size Bag (Id, Int)
arg_discount Int
res_discount
where
some_val_args :: Bool
some_val_args = Int
n_val_args Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
> Int
0
is_join :: Bool
is_join = Id -> Bool
isJoinId Id
fun
size :: Int
size | Bool
is_join = Int -> Int -> Int
jumpSize Int
n_val_args Int
voids
| Bool -> Bool
not Bool
some_val_args = Int
0
| Bool
otherwise = Int -> Int -> Int
callSize Int
n_val_args Int
voids
arg_discount :: Bag (Id, Int)
arg_discount | Bool
some_val_args Bool -> Bool -> Bool
&& Id
fun Id -> [Id] -> Bool
forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`elem` [Id]
top_args
= (Id, Int) -> Bag (Id, Int)
forall a. a -> Bag a
unitBag (Id
fun, DynFlags -> Int
ufFunAppDiscount DynFlags
dflags)
| Bool
otherwise = Bag (Id, Int)
forall a. Bag a
emptyBag
res_discount :: Int
res_discount | Id -> Int
idArity Id
fun Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
> Int
n_val_args = DynFlags -> Int
ufFunAppDiscount DynFlags
dflags
| Bool
otherwise = Int
0
conSize :: DataCon -> Int -> ExprSize
conSize :: DataCon -> Int -> ExprSize
conSize DataCon
dc Int
n_val_args
| Int
n_val_args Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
0 = Int -> Bag (Id, Int) -> Int -> ExprSize
SizeIs Int
0 Bag (Id, Int)
forall a. Bag a
emptyBag Int
10
| DataCon -> Bool
isUnboxedTupleCon DataCon
dc = Int -> Bag (Id, Int) -> Int -> ExprSize
SizeIs Int
0 Bag (Id, Int)
forall a. Bag a
emptyBag Int
10
| Bool
otherwise = Int -> Bag (Id, Int) -> Int -> ExprSize
SizeIs Int
10 Bag (Id, Int)
forall a. Bag a
emptyBag Int
10
primOpSize :: PrimOp -> Int -> ExprSize
primOpSize :: PrimOp -> Int -> ExprSize
primOpSize PrimOp
op Int
n_val_args
= if PrimOp -> Bool
primOpOutOfLine PrimOp
op
then Int -> ExprSize
sizeN (Int
op_size Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
n_val_args)
else Int -> ExprSize
sizeN Int
op_size
where
op_size :: Int
op_size = PrimOp -> Int
primOpCodeSize PrimOp
op
buildSize :: ExprSize
buildSize :: ExprSize
buildSize = Int -> Bag (Id, Int) -> Int -> ExprSize
SizeIs Int
0 Bag (Id, Int)
forall a. Bag a
emptyBag Int
40
augmentSize :: ExprSize
augmentSize :: ExprSize
augmentSize = Int -> Bag (Id, Int) -> Int -> ExprSize
SizeIs Int
0 Bag (Id, Int)
forall a. Bag a
emptyBag Int
40
lamScrutDiscount :: DynFlags -> ExprSize -> ExprSize
lamScrutDiscount :: DynFlags -> ExprSize -> ExprSize
lamScrutDiscount DynFlags
dflags (SizeIs Int
n Bag (Id, Int)
vs Int
_) = Int -> Bag (Id, Int) -> Int -> ExprSize
SizeIs Int
n Bag (Id, Int)
vs (DynFlags -> Int
ufFunAppDiscount DynFlags
dflags)
lamScrutDiscount DynFlags
_ ExprSize
TooBig = ExprSize
TooBig
data ExprSize
= TooBig
| SizeIs { ExprSize -> Int
_es_size_is :: {-# UNPACK #-} !Int
, ExprSize -> Bag (Id, Int)
_es_args :: !(Bag (Id,Int))
, ExprSize -> Int
_es_discount :: {-# UNPACK #-} !Int
}
instance Outputable ExprSize where
ppr :: ExprSize -> SDoc
ppr ExprSize
TooBig = String -> SDoc
text String
"TooBig"
ppr (SizeIs Int
a Bag (Id, Int)
_ Int
c) = SDoc -> SDoc
brackets (Int -> SDoc
int Int
a SDoc -> SDoc -> SDoc
<+> Int -> SDoc
int Int
c)
mkSizeIs :: Int -> Int -> Bag (Id, Int) -> Int -> ExprSize
mkSizeIs :: Int -> Int -> Bag (Id, Int) -> Int -> ExprSize
mkSizeIs Int
max Int
n Bag (Id, Int)
xs Int
d | (Int
n Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
d) Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
> Int
max = ExprSize
TooBig
| Bool
otherwise = Int -> Bag (Id, Int) -> Int -> ExprSize
SizeIs Int
n Bag (Id, Int)
xs Int
d
maxSize :: ExprSize -> ExprSize -> ExprSize
maxSize :: ExprSize -> ExprSize -> ExprSize
maxSize ExprSize
TooBig ExprSize
_ = ExprSize
TooBig
maxSize ExprSize
_ ExprSize
TooBig = ExprSize
TooBig
maxSize s1 :: ExprSize
s1@(SizeIs Int
n1 Bag (Id, Int)
_ Int
_) s2 :: ExprSize
s2@(SizeIs Int
n2 Bag (Id, Int)
_ Int
_) | Int
n1 Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
> Int
n2 = ExprSize
s1
| Bool
otherwise = ExprSize
s2
sizeZero :: ExprSize
sizeN :: Int -> ExprSize
sizeZero :: ExprSize
sizeZero = Int -> Bag (Id, Int) -> Int -> ExprSize
SizeIs Int
0 Bag (Id, Int)
forall a. Bag a
emptyBag Int
0
sizeN :: Int -> ExprSize
sizeN Int
n = Int -> Bag (Id, Int) -> Int -> ExprSize
SizeIs Int
n Bag (Id, Int)
forall a. Bag a
emptyBag Int
0
couldBeSmallEnoughToInline :: DynFlags -> Int -> CoreExpr -> Bool
couldBeSmallEnoughToInline :: DynFlags -> Int -> CoreArg -> Bool
couldBeSmallEnoughToInline DynFlags
dflags Int
threshold CoreArg
rhs
= case DynFlags -> Int -> [Id] -> CoreArg -> ExprSize
sizeExpr DynFlags
dflags Int
threshold [] CoreArg
body of
ExprSize
TooBig -> Bool
False
ExprSize
_ -> Bool
True
where
([Id]
_, CoreArg
body) = CoreArg -> ([Id], CoreArg)
forall b. Expr b -> ([b], Expr b)
collectBinders CoreArg
rhs
smallEnoughToInline :: DynFlags -> Unfolding -> Bool
smallEnoughToInline :: DynFlags -> Unfolding -> Bool
smallEnoughToInline DynFlags
dflags (CoreUnfolding {uf_guidance :: Unfolding -> UnfoldingGuidance
uf_guidance = UnfIfGoodArgs {ug_size :: UnfoldingGuidance -> Int
ug_size = Int
size}})
= Int
size Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
<= DynFlags -> Int
ufUseThreshold DynFlags
dflags
smallEnoughToInline DynFlags
_ Unfolding
_
= Bool
False
certainlyWillInline :: DynFlags -> IdInfo -> Maybe Unfolding
certainlyWillInline :: DynFlags -> IdInfo -> Maybe Unfolding
certainlyWillInline DynFlags
dflags IdInfo
fn_info
= case IdInfo -> Unfolding
unfoldingInfo IdInfo
fn_info of
CoreUnfolding { uf_tmpl :: Unfolding -> CoreArg
uf_tmpl = CoreArg
e, uf_guidance :: Unfolding -> UnfoldingGuidance
uf_guidance = UnfoldingGuidance
g }
| Bool
loop_breaker -> Maybe Unfolding
forall a. Maybe a
Nothing
| Bool
noinline -> Maybe Unfolding
forall a. Maybe a
Nothing
| Bool
otherwise -> CoreArg -> UnfoldingGuidance -> Maybe Unfolding
do_cunf CoreArg
e UnfoldingGuidance
g
DFunUnfolding {} -> Unfolding -> Maybe Unfolding
forall a. a -> Maybe a
Just Unfolding
fn_unf
Unfolding
_other_unf -> Maybe Unfolding
forall a. Maybe a
Nothing
where
loop_breaker :: Bool
loop_breaker = OccInfo -> Bool
isStrongLoopBreaker (IdInfo -> OccInfo
occInfo IdInfo
fn_info)
noinline :: Bool
noinline = InlinePragma -> InlineSpec
inlinePragmaSpec (IdInfo -> InlinePragma
inlinePragInfo IdInfo
fn_info) InlineSpec -> InlineSpec -> Bool
forall a. Eq a => a -> a -> Bool
== InlineSpec
NoInline
fn_unf :: Unfolding
fn_unf = IdInfo -> Unfolding
unfoldingInfo IdInfo
fn_info
do_cunf :: CoreExpr -> UnfoldingGuidance -> Maybe Unfolding
do_cunf :: CoreArg -> UnfoldingGuidance -> Maybe Unfolding
do_cunf CoreArg
_ UnfoldingGuidance
UnfNever = Maybe Unfolding
forall a. Maybe a
Nothing
do_cunf CoreArg
_ (UnfWhen {}) = Unfolding -> Maybe Unfolding
forall a. a -> Maybe a
Just (Unfolding
fn_unf { uf_src :: UnfoldingSource
uf_src = UnfoldingSource
InlineStable })
do_cunf CoreArg
expr (UnfIfGoodArgs { ug_size :: UnfoldingGuidance -> Int
ug_size = Int
size, ug_args :: UnfoldingGuidance -> [Int]
ug_args = [Int]
args })
| IdInfo -> Int
arityInfo IdInfo
fn_info Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
> Int
0
, Bool -> Bool
not (StrictSig -> Bool
isDeadEndSig (IdInfo -> StrictSig
strictnessInfo IdInfo
fn_info))
, let unf_arity :: Int
unf_arity = [Int] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [Int]
args
, Int
size Int -> Int -> Int
forall a. Num a => a -> a -> a
- (Int
10 Int -> Int -> Int
forall a. Num a => a -> a -> a
* (Int
unf_arity Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
1)) Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
<= DynFlags -> Int
ufUseThreshold DynFlags
dflags
= Unfolding -> Maybe Unfolding
forall a. a -> Maybe a
Just (Unfolding
fn_unf { uf_src :: UnfoldingSource
uf_src = UnfoldingSource
InlineStable
, uf_guidance :: UnfoldingGuidance
uf_guidance = UnfWhen :: Int -> Bool -> Bool -> UnfoldingGuidance
UnfWhen { ug_arity :: Int
ug_arity = Int
unf_arity
, ug_unsat_ok :: Bool
ug_unsat_ok = Bool
unSaturatedOk
, ug_boring_ok :: Bool
ug_boring_ok = CoreArg -> Bool
inlineBoringOk CoreArg
expr } })
| Bool
otherwise
= Maybe Unfolding
forall a. Maybe a
Nothing
callSiteInline :: DynFlags
-> Id
-> Bool
-> Bool
-> [ArgSummary]
-> CallCtxt
-> Maybe CoreExpr
data ArgSummary = TrivArg
| NonTrivArg
| ValueArg
instance Outputable ArgSummary where
ppr :: ArgSummary -> SDoc
ppr ArgSummary
TrivArg = String -> SDoc
text String
"TrivArg"
ppr ArgSummary
NonTrivArg = String -> SDoc
text String
"NonTrivArg"
ppr ArgSummary
ValueArg = String -> SDoc
text String
"ValueArg"
nonTriv :: ArgSummary -> Bool
nonTriv :: ArgSummary -> Bool
nonTriv ArgSummary
TrivArg = Bool
False
nonTriv ArgSummary
_ = Bool
True
data CallCtxt
= BoringCtxt
| RhsCtxt
| DiscArgCtxt
| RuleArgCtxt
| ValAppCtxt
| CaseCtxt
instance Outputable CallCtxt where
ppr :: CallCtxt -> SDoc
ppr CallCtxt
CaseCtxt = String -> SDoc
text String
"CaseCtxt"
ppr CallCtxt
ValAppCtxt = String -> SDoc
text String
"ValAppCtxt"
ppr CallCtxt
BoringCtxt = String -> SDoc
text String
"BoringCtxt"
ppr CallCtxt
RhsCtxt = String -> SDoc
text String
"RhsCtxt"
ppr CallCtxt
DiscArgCtxt = String -> SDoc
text String
"DiscArgCtxt"
ppr CallCtxt
RuleArgCtxt = String -> SDoc
text String
"RuleArgCtxt"
callSiteInline :: DynFlags
-> Id -> Bool -> Bool -> [ArgSummary] -> CallCtxt -> Maybe CoreArg
callSiteInline DynFlags
dflags Id
id Bool
active_unfolding Bool
lone_variable [ArgSummary]
arg_infos CallCtxt
cont_info
= case Id -> Unfolding
idUnfolding Id
id of
CoreUnfolding { uf_tmpl :: Unfolding -> CoreArg
uf_tmpl = CoreArg
unf_template
, uf_is_work_free :: Unfolding -> Bool
uf_is_work_free = Bool
is_wf
, uf_guidance :: Unfolding -> UnfoldingGuidance
uf_guidance = UnfoldingGuidance
guidance, uf_expandable :: Unfolding -> Bool
uf_expandable = Bool
is_exp }
| Bool
active_unfolding -> DynFlags
-> Id
-> Bool
-> [ArgSummary]
-> CallCtxt
-> CoreArg
-> Bool
-> Bool
-> UnfoldingGuidance
-> Maybe CoreArg
tryUnfolding DynFlags
dflags Id
id Bool
lone_variable
[ArgSummary]
arg_infos CallCtxt
cont_info CoreArg
unf_template
Bool
is_wf Bool
is_exp UnfoldingGuidance
guidance
| Bool
otherwise -> DynFlags -> Id -> String -> SDoc -> Maybe CoreArg -> Maybe CoreArg
forall a. DynFlags -> Id -> String -> SDoc -> a -> a
traceInline DynFlags
dflags Id
id String
"Inactive unfolding:" (Id -> SDoc
forall a. Outputable a => a -> SDoc
ppr Id
id) Maybe CoreArg
forall a. Maybe a
Nothing
Unfolding
NoUnfolding -> Maybe CoreArg
forall a. Maybe a
Nothing
Unfolding
BootUnfolding -> Maybe CoreArg
forall a. Maybe a
Nothing
OtherCon {} -> Maybe CoreArg
forall a. Maybe a
Nothing
DFunUnfolding {} -> Maybe CoreArg
forall a. Maybe a
Nothing
traceInline :: DynFlags -> Id -> String -> SDoc -> a -> a
traceInline :: forall a. DynFlags -> Id -> String -> SDoc -> a -> a
traceInline DynFlags
dflags Id
inline_id String
str SDoc
doc a
result
| Bool
enable = DynFlags -> String -> SDoc -> a -> a
TraceAction
traceAction DynFlags
dflags String
str SDoc
doc a
result
| Bool
otherwise = a
result
where
enable :: Bool
enable
| DumpFlag -> DynFlags -> Bool
dopt DumpFlag
Opt_D_dump_verbose_inlinings DynFlags
dflags
= Bool
True
| Just String
prefix <- DynFlags -> Maybe String
inlineCheck DynFlags
dflags
= String
prefix String -> String -> Bool
forall a. Eq a => [a] -> [a] -> Bool
`isPrefixOf` OccName -> String
occNameString (Id -> OccName
forall a. NamedThing a => a -> OccName
getOccName Id
inline_id)
| Bool
otherwise
= Bool
False
{-# INLINE traceInline #-}
tryUnfolding :: DynFlags -> Id -> Bool -> [ArgSummary] -> CallCtxt
-> CoreExpr -> Bool -> Bool -> UnfoldingGuidance
-> Maybe CoreExpr
tryUnfolding :: DynFlags
-> Id
-> Bool
-> [ArgSummary]
-> CallCtxt
-> CoreArg
-> Bool
-> Bool
-> UnfoldingGuidance
-> Maybe CoreArg
tryUnfolding DynFlags
dflags Id
id Bool
lone_variable
[ArgSummary]
arg_infos CallCtxt
cont_info CoreArg
unf_template
Bool
is_wf Bool
is_exp UnfoldingGuidance
guidance
= case UnfoldingGuidance
guidance of
UnfoldingGuidance
UnfNever -> DynFlags -> Id -> String -> SDoc -> Maybe CoreArg -> Maybe CoreArg
forall a. DynFlags -> Id -> String -> SDoc -> a -> a
traceInline DynFlags
dflags Id
id String
str (String -> SDoc
text String
"UnfNever") Maybe CoreArg
forall a. Maybe a
Nothing
UnfWhen { ug_arity :: UnfoldingGuidance -> Int
ug_arity = Int
uf_arity, ug_unsat_ok :: UnfoldingGuidance -> Bool
ug_unsat_ok = Bool
unsat_ok, ug_boring_ok :: UnfoldingGuidance -> Bool
ug_boring_ok = Bool
boring_ok }
| Bool
enough_args Bool -> Bool -> Bool
&& (Bool
boring_ok Bool -> Bool -> Bool
|| Bool
some_benefit Bool -> Bool -> Bool
|| DynFlags -> Bool
ufVeryAggressive DynFlags
dflags)
-> DynFlags -> Id -> String -> SDoc -> Maybe CoreArg -> Maybe CoreArg
forall a. DynFlags -> Id -> String -> SDoc -> a -> a
traceInline DynFlags
dflags Id
id String
str (Bool -> SDoc -> Bool -> SDoc
forall {a}. Outputable a => a -> SDoc -> Bool -> SDoc
mk_doc Bool
some_benefit SDoc
empty Bool
True) (CoreArg -> Maybe CoreArg
forall a. a -> Maybe a
Just CoreArg
unf_template)
| Bool
otherwise
-> DynFlags -> Id -> String -> SDoc -> Maybe CoreArg -> Maybe CoreArg
forall a. DynFlags -> Id -> String -> SDoc -> a -> a
traceInline DynFlags
dflags Id
id String
str (Bool -> SDoc -> Bool -> SDoc
forall {a}. Outputable a => a -> SDoc -> Bool -> SDoc
mk_doc Bool
some_benefit SDoc
empty Bool
False) Maybe CoreArg
forall a. Maybe a
Nothing
where
some_benefit :: Bool
some_benefit = Int -> Bool
calc_some_benefit Int
uf_arity
enough_args :: Bool
enough_args = (Int
n_val_args Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
>= Int
uf_arity) Bool -> Bool -> Bool
|| (Bool
unsat_ok Bool -> Bool -> Bool
&& Int
n_val_args Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
> Int
0)
UnfIfGoodArgs { ug_args :: UnfoldingGuidance -> [Int]
ug_args = [Int]
arg_discounts, ug_res :: UnfoldingGuidance -> Int
ug_res = Int
res_discount, ug_size :: UnfoldingGuidance -> Int
ug_size = Int
size }
| DynFlags -> Bool
ufVeryAggressive DynFlags
dflags
-> DynFlags -> Id -> String -> SDoc -> Maybe CoreArg -> Maybe CoreArg
forall a. DynFlags -> Id -> String -> SDoc -> a -> a
traceInline DynFlags
dflags Id
id String
str (Bool -> SDoc -> Bool -> SDoc
forall {a}. Outputable a => a -> SDoc -> Bool -> SDoc
mk_doc Bool
some_benefit SDoc
extra_doc Bool
True) (CoreArg -> Maybe CoreArg
forall a. a -> Maybe a
Just CoreArg
unf_template)
| Bool
is_wf Bool -> Bool -> Bool
&& Bool
some_benefit Bool -> Bool -> Bool
&& Bool
small_enough
-> DynFlags -> Id -> String -> SDoc -> Maybe CoreArg -> Maybe CoreArg
forall a. DynFlags -> Id -> String -> SDoc -> a -> a
traceInline DynFlags
dflags Id
id String
str (Bool -> SDoc -> Bool -> SDoc
forall {a}. Outputable a => a -> SDoc -> Bool -> SDoc
mk_doc Bool
some_benefit SDoc
extra_doc Bool
True) (CoreArg -> Maybe CoreArg
forall a. a -> Maybe a
Just CoreArg
unf_template)
| Bool
otherwise
-> DynFlags -> Id -> String -> SDoc -> Maybe CoreArg -> Maybe CoreArg
forall a. DynFlags -> Id -> String -> SDoc -> a -> a
traceInline DynFlags
dflags Id
id String
str (Bool -> SDoc -> Bool -> SDoc
forall {a}. Outputable a => a -> SDoc -> Bool -> SDoc
mk_doc Bool
some_benefit SDoc
extra_doc Bool
False) Maybe CoreArg
forall a. Maybe a
Nothing
where
some_benefit :: Bool
some_benefit = Int -> Bool
calc_some_benefit ([Int] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [Int]
arg_discounts)
extra_doc :: SDoc
extra_doc = String -> SDoc
text String
"discounted size =" SDoc -> SDoc -> SDoc
<+> Int -> SDoc
int Int
discounted_size
discounted_size :: Int
discounted_size = Int
size Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
discount
small_enough :: Bool
small_enough = Int
discounted_size Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
<= DynFlags -> Int
ufUseThreshold DynFlags
dflags
discount :: Int
discount = [Int] -> Int -> [ArgSummary] -> CallCtxt -> Int
computeDiscount [Int]
arg_discounts Int
res_discount [ArgSummary]
arg_infos CallCtxt
cont_info
where
mk_doc :: a -> SDoc -> Bool -> SDoc
mk_doc a
some_benefit SDoc
extra_doc Bool
yes_or_no
= [SDoc] -> SDoc
vcat [ String -> SDoc
text String
"arg infos" SDoc -> SDoc -> SDoc
<+> [ArgSummary] -> SDoc
forall a. Outputable a => a -> SDoc
ppr [ArgSummary]
arg_infos
, String -> SDoc
text String
"interesting continuation" SDoc -> SDoc -> SDoc
<+> CallCtxt -> SDoc
forall a. Outputable a => a -> SDoc
ppr CallCtxt
cont_info
, String -> SDoc
text String
"some_benefit" SDoc -> SDoc -> SDoc
<+> a -> SDoc
forall a. Outputable a => a -> SDoc
ppr a
some_benefit
, String -> SDoc
text String
"is exp:" SDoc -> SDoc -> SDoc
<+> Bool -> SDoc
forall a. Outputable a => a -> SDoc
ppr Bool
is_exp
, String -> SDoc
text String
"is work-free:" SDoc -> SDoc -> SDoc
<+> Bool -> SDoc
forall a. Outputable a => a -> SDoc
ppr Bool
is_wf
, String -> SDoc
text String
"guidance" SDoc -> SDoc -> SDoc
<+> UnfoldingGuidance -> SDoc
forall a. Outputable a => a -> SDoc
ppr UnfoldingGuidance
guidance
, SDoc
extra_doc
, String -> SDoc
text String
"ANSWER =" SDoc -> SDoc -> SDoc
<+> if Bool
yes_or_no then String -> SDoc
text String
"YES" else String -> SDoc
text String
"NO"]
str :: String
str = String
"Considering inlining: " String -> String -> String
forall a. [a] -> [a] -> [a]
++ DynFlags -> SDoc -> String
showSDocDump DynFlags
dflags (Id -> SDoc
forall a. Outputable a => a -> SDoc
ppr Id
id)
n_val_args :: Int
n_val_args = [ArgSummary] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [ArgSummary]
arg_infos
calc_some_benefit :: Arity -> Bool
calc_some_benefit :: Int -> Bool
calc_some_benefit Int
uf_arity
| Bool -> Bool
not Bool
saturated = Bool
interesting_args
| Bool
otherwise = Bool
interesting_args
Bool -> Bool -> Bool
|| Bool
interesting_call
where
saturated :: Bool
saturated = Int
n_val_args Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
>= Int
uf_arity
over_saturated :: Bool
over_saturated = Int
n_val_args Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
> Int
uf_arity
interesting_args :: Bool
interesting_args = (ArgSummary -> Bool) -> [ArgSummary] -> Bool
forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
any ArgSummary -> Bool
nonTriv [ArgSummary]
arg_infos
interesting_call :: Bool
interesting_call
| Bool
over_saturated
= Bool
True
| Bool
otherwise
= case CallCtxt
cont_info of
CallCtxt
CaseCtxt -> Bool -> Bool
not (Bool
lone_variable Bool -> Bool -> Bool
&& Bool
is_exp)
CallCtxt
ValAppCtxt -> Bool
True
CallCtxt
RuleArgCtxt -> Int
uf_arity Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
> Int
0
CallCtxt
DiscArgCtxt -> Int
uf_arity Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
> Int
0
CallCtxt
RhsCtxt -> Int
uf_arity Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
> Int
0
CallCtxt
_other -> Bool
False
computeDiscount :: [Int] -> Int -> [ArgSummary] -> CallCtxt
-> Int
computeDiscount :: [Int] -> Int -> [ArgSummary] -> CallCtxt -> Int
computeDiscount [Int]
arg_discounts Int
res_discount [ArgSummary]
arg_infos CallCtxt
cont_info
= Int
10
Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
10 Int -> Int -> Int
forall a. Num a => a -> a -> a
* [Int] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [Int]
actual_arg_discounts
Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
total_arg_discount Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
res_discount'
where
actual_arg_discounts :: [Int]
actual_arg_discounts = (Int -> ArgSummary -> Int) -> [Int] -> [ArgSummary] -> [Int]
forall a b c. (a -> b -> c) -> [a] -> [b] -> [c]
zipWith Int -> ArgSummary -> Int
forall {p}. Num p => p -> ArgSummary -> p
mk_arg_discount [Int]
arg_discounts [ArgSummary]
arg_infos
total_arg_discount :: Int
total_arg_discount = [Int] -> Int
forall (t :: * -> *) a. (Foldable t, Num a) => t a -> a
sum [Int]
actual_arg_discounts
mk_arg_discount :: p -> ArgSummary -> p
mk_arg_discount p
_ ArgSummary
TrivArg = p
0
mk_arg_discount p
_ ArgSummary
NonTrivArg = p
10
mk_arg_discount p
discount ArgSummary
ValueArg = p
discount
res_discount' :: Int
res_discount'
| Ordering
LT <- [Int]
arg_discounts [Int] -> [ArgSummary] -> Ordering
forall a b. [a] -> [b] -> Ordering
`compareLength` [ArgSummary]
arg_infos
= Int
res_discount
| Bool
otherwise
= case CallCtxt
cont_info of
CallCtxt
BoringCtxt -> Int
0
CallCtxt
CaseCtxt -> Int
res_discount
CallCtxt
ValAppCtxt -> Int
res_discount
CallCtxt
_ -> Int
40 Int -> Int -> Int
forall a. Ord a => a -> a -> a
`min` Int
res_discount