{-# LANGUAGE CPP #-}
module CoreUnfold (
Unfolding, UnfoldingGuidance,
noUnfolding, mkImplicitUnfolding,
mkUnfolding, mkCoreUnfolding,
mkTopUnfolding, 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 GhcPrelude
import DynFlags
import CoreSyn
import OccurAnal ( occurAnalyseExpr_NoBinderSwap )
import CoreOpt
import CoreArity ( manifestArity )
import CoreUtils
import Id
import Demand ( isBottomingSig )
import DataCon
import Literal
import PrimOp
import IdInfo
import BasicTypes ( Arity, InlineSpec(..), inlinePragmaSpec )
import Type
import PrelNames
import TysPrim ( realWorldStatePrimTy )
import Bag
import Util
import Outputable
import ForeignCall
import Name
import qualified Data.ByteString as BS
import Data.List
mkTopUnfolding :: DynFlags -> Bool -> CoreExpr -> Unfolding
mkTopUnfolding :: DynFlags -> Bool -> CoreExpr -> Unfolding
mkTopUnfolding DynFlags
dflags Bool
is_bottoming CoreExpr
rhs
= DynFlags
-> UnfoldingSource -> Bool -> Bool -> CoreExpr -> Unfolding
mkUnfolding DynFlags
dflags UnfoldingSource
InlineRhs Bool
True Bool
is_bottoming CoreExpr
rhs
mkImplicitUnfolding :: DynFlags -> CoreExpr -> Unfolding
mkImplicitUnfolding :: DynFlags -> CoreExpr -> Unfolding
mkImplicitUnfolding DynFlags
dflags CoreExpr
expr
= DynFlags -> Bool -> CoreExpr -> Unfolding
mkTopUnfolding DynFlags
dflags Bool
False (DynFlags -> CoreExpr -> CoreExpr
simpleOptExpr DynFlags
dflags CoreExpr
expr)
mkSimpleUnfolding :: DynFlags -> CoreExpr -> Unfolding
mkSimpleUnfolding :: DynFlags -> CoreExpr -> Unfolding
mkSimpleUnfolding DynFlags
dflags CoreExpr
rhs
= DynFlags
-> UnfoldingSource -> Bool -> Bool -> CoreExpr -> Unfolding
mkUnfolding DynFlags
dflags UnfoldingSource
InlineRhs Bool
False Bool
False CoreExpr
rhs
mkDFunUnfolding :: [Var] -> DataCon -> [CoreExpr] -> Unfolding
mkDFunUnfolding :: [Var] -> DataCon -> [CoreExpr] -> Unfolding
mkDFunUnfolding [Var]
bndrs DataCon
con [CoreExpr]
ops
= DFunUnfolding :: [Var] -> DataCon -> [CoreExpr] -> Unfolding
DFunUnfolding { df_bndrs :: [Var]
df_bndrs = [Var]
bndrs
, df_con :: DataCon
df_con = DataCon
con
, df_args :: [CoreExpr]
df_args = (CoreExpr -> CoreExpr) -> [CoreExpr] -> [CoreExpr]
forall a b. (a -> b) -> [a] -> [b]
map CoreExpr -> CoreExpr
occurAnalyseExpr_NoBinderSwap [CoreExpr]
ops }
mkWwInlineRule :: DynFlags -> CoreExpr -> Arity -> Unfolding
mkWwInlineRule :: DynFlags -> CoreExpr -> Arity -> Unfolding
mkWwInlineRule DynFlags
dflags CoreExpr
expr Arity
arity
= UnfoldingSource
-> Bool -> CoreExpr -> UnfoldingGuidance -> Unfolding
mkCoreUnfolding UnfoldingSource
InlineStable Bool
True
(DynFlags -> CoreExpr -> CoreExpr
simpleOptExpr DynFlags
dflags CoreExpr
expr)
(UnfWhen :: Arity -> Bool -> Bool -> UnfoldingGuidance
UnfWhen { ug_arity :: Arity
ug_arity = Arity
arity, ug_unsat_ok :: Bool
ug_unsat_ok = Bool
unSaturatedOk
, ug_boring_ok :: Bool
ug_boring_ok = Bool
boringCxtNotOk })
mkCompulsoryUnfolding :: CoreExpr -> Unfolding
mkCompulsoryUnfolding :: CoreExpr -> Unfolding
mkCompulsoryUnfolding CoreExpr
expr
= UnfoldingSource
-> Bool -> CoreExpr -> UnfoldingGuidance -> Unfolding
mkCoreUnfolding UnfoldingSource
InlineCompulsory Bool
True
(DynFlags -> CoreExpr -> CoreExpr
simpleOptExpr DynFlags
unsafeGlobalDynFlags CoreExpr
expr)
(UnfWhen :: Arity -> Bool -> Bool -> UnfoldingGuidance
UnfWhen { ug_arity :: Arity
ug_arity = Arity
0
, ug_unsat_ok :: Bool
ug_unsat_ok = Bool
unSaturatedOk, ug_boring_ok :: Bool
ug_boring_ok = Bool
boringCxtOk })
mkWorkerUnfolding :: DynFlags -> (CoreExpr -> CoreExpr) -> Unfolding -> Unfolding
mkWorkerUnfolding :: DynFlags -> (CoreExpr -> CoreExpr) -> Unfolding -> Unfolding
mkWorkerUnfolding DynFlags
dflags CoreExpr -> CoreExpr
work_fn
(CoreUnfolding { uf_src :: Unfolding -> UnfoldingSource
uf_src = UnfoldingSource
src, uf_tmpl :: Unfolding -> CoreExpr
uf_tmpl = CoreExpr
tmpl
, uf_is_top :: Unfolding -> Bool
uf_is_top = Bool
top_lvl })
| UnfoldingSource -> Bool
isStableSource UnfoldingSource
src
= UnfoldingSource
-> Bool -> CoreExpr -> UnfoldingGuidance -> Unfolding
mkCoreUnfolding UnfoldingSource
src Bool
top_lvl CoreExpr
new_tmpl UnfoldingGuidance
guidance
where
new_tmpl :: CoreExpr
new_tmpl = DynFlags -> CoreExpr -> CoreExpr
simpleOptExpr DynFlags
dflags (CoreExpr -> CoreExpr
work_fn CoreExpr
tmpl)
guidance :: UnfoldingGuidance
guidance = DynFlags -> Bool -> CoreExpr -> UnfoldingGuidance
calcUnfoldingGuidance DynFlags
dflags Bool
False CoreExpr
new_tmpl
mkWorkerUnfolding DynFlags
_ CoreExpr -> CoreExpr
_ Unfolding
_ = Unfolding
noUnfolding
mkInlineUnfolding :: CoreExpr -> Unfolding
mkInlineUnfolding :: CoreExpr -> Unfolding
mkInlineUnfolding CoreExpr
expr
= UnfoldingSource
-> Bool -> CoreExpr -> UnfoldingGuidance -> Unfolding
mkCoreUnfolding UnfoldingSource
InlineStable
Bool
True
CoreExpr
expr' UnfoldingGuidance
guide
where
expr' :: CoreExpr
expr' = DynFlags -> CoreExpr -> CoreExpr
simpleOptExpr DynFlags
unsafeGlobalDynFlags CoreExpr
expr
guide :: UnfoldingGuidance
guide = UnfWhen :: Arity -> Bool -> Bool -> UnfoldingGuidance
UnfWhen { ug_arity :: Arity
ug_arity = CoreExpr -> Arity
manifestArity CoreExpr
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 = CoreExpr -> Bool
inlineBoringOk CoreExpr
expr'
mkInlineUnfoldingWithArity :: Arity -> CoreExpr -> Unfolding
mkInlineUnfoldingWithArity :: Arity -> CoreExpr -> Unfolding
mkInlineUnfoldingWithArity Arity
arity CoreExpr
expr
= UnfoldingSource
-> Bool -> CoreExpr -> UnfoldingGuidance -> Unfolding
mkCoreUnfolding UnfoldingSource
InlineStable
Bool
True
CoreExpr
expr' UnfoldingGuidance
guide
where
expr' :: CoreExpr
expr' = DynFlags -> CoreExpr -> CoreExpr
simpleOptExpr DynFlags
unsafeGlobalDynFlags CoreExpr
expr
guide :: UnfoldingGuidance
guide = UnfWhen :: Arity -> Bool -> Bool -> UnfoldingGuidance
UnfWhen { ug_arity :: Arity
ug_arity = Arity
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 | Arity
arity Arity -> Arity -> Bool
forall a. Eq a => a -> a -> Bool
== Arity
0 = Bool
True
| Bool
otherwise = CoreExpr -> Bool
inlineBoringOk CoreExpr
expr'
mkInlinableUnfolding :: DynFlags -> CoreExpr -> Unfolding
mkInlinableUnfolding :: DynFlags -> CoreExpr -> Unfolding
mkInlinableUnfolding DynFlags
dflags CoreExpr
expr
= DynFlags
-> UnfoldingSource -> Bool -> Bool -> CoreExpr -> Unfolding
mkUnfolding DynFlags
dflags UnfoldingSource
InlineStable Bool
False Bool
False CoreExpr
expr'
where
expr' :: CoreExpr
expr' = DynFlags -> CoreExpr -> CoreExpr
simpleOptExpr DynFlags
dflags CoreExpr
expr
specUnfolding :: DynFlags -> [Var] -> (CoreExpr -> CoreExpr) -> Arity
-> Unfolding -> Unfolding
specUnfolding :: DynFlags
-> [Var]
-> (CoreExpr -> CoreExpr)
-> Arity
-> Unfolding
-> Unfolding
specUnfolding DynFlags
dflags [Var]
spec_bndrs CoreExpr -> CoreExpr
spec_app Arity
arity_decrease
df :: Unfolding
df@(DFunUnfolding { df_bndrs :: Unfolding -> [Var]
df_bndrs = [Var]
old_bndrs, df_con :: Unfolding -> DataCon
df_con = DataCon
con, df_args :: Unfolding -> [CoreExpr]
df_args = [CoreExpr]
args })
= ASSERT2( arity_decrease == count isId old_bndrs - count isId spec_bndrs, ppr df )
[Var] -> DataCon -> [CoreExpr] -> Unfolding
mkDFunUnfolding [Var]
spec_bndrs DataCon
con ((CoreExpr -> CoreExpr) -> [CoreExpr] -> [CoreExpr]
forall a b. (a -> b) -> [a] -> [b]
map CoreExpr -> CoreExpr
spec_arg [CoreExpr]
args)
where
spec_arg :: CoreExpr -> CoreExpr
spec_arg CoreExpr
arg = DynFlags -> CoreExpr -> CoreExpr
simpleOptExpr DynFlags
dflags (CoreExpr -> CoreExpr
spec_app ([Var] -> CoreExpr -> CoreExpr
forall b. [b] -> Expr b -> Expr b
mkLams [Var]
old_bndrs CoreExpr
arg))
specUnfolding DynFlags
dflags [Var]
spec_bndrs CoreExpr -> CoreExpr
spec_app Arity
arity_decrease
(CoreUnfolding { uf_src :: Unfolding -> UnfoldingSource
uf_src = UnfoldingSource
src, uf_tmpl :: Unfolding -> CoreExpr
uf_tmpl = CoreExpr
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 -> Arity
ug_arity = Arity
old_arity
, ug_unsat_ok :: UnfoldingGuidance -> Bool
ug_unsat_ok = Bool
unsat_ok
, ug_boring_ok :: UnfoldingGuidance -> Bool
ug_boring_ok = Bool
boring_ok } <- UnfoldingGuidance
old_guidance
= let guidance :: UnfoldingGuidance
guidance = UnfWhen :: Arity -> Bool -> Bool -> UnfoldingGuidance
UnfWhen { ug_arity :: Arity
ug_arity = Arity
old_arity Arity -> Arity -> Arity
forall a. Num a => a -> a -> a
- Arity
arity_decrease
, ug_unsat_ok :: Bool
ug_unsat_ok = Bool
unsat_ok
, ug_boring_ok :: Bool
ug_boring_ok = Bool
boring_ok }
new_tmpl :: CoreExpr
new_tmpl = DynFlags -> CoreExpr -> CoreExpr
simpleOptExpr DynFlags
dflags ([Var] -> CoreExpr -> CoreExpr
forall b. [b] -> Expr b -> Expr b
mkLams [Var]
spec_bndrs (CoreExpr -> CoreExpr
spec_app CoreExpr
tmpl))
in UnfoldingSource
-> Bool -> CoreExpr -> UnfoldingGuidance -> Unfolding
mkCoreUnfolding UnfoldingSource
src Bool
top_lvl CoreExpr
new_tmpl UnfoldingGuidance
guidance
specUnfolding DynFlags
_ [Var]
_ CoreExpr -> CoreExpr
_ Arity
_ Unfolding
_ = Unfolding
noUnfolding
mkCoreUnfolding :: UnfoldingSource -> Bool -> CoreExpr
-> UnfoldingGuidance -> Unfolding
mkCoreUnfolding :: UnfoldingSource
-> Bool -> CoreExpr -> UnfoldingGuidance -> Unfolding
mkCoreUnfolding UnfoldingSource
src Bool
top_lvl CoreExpr
expr UnfoldingGuidance
guidance
= CoreUnfolding :: CoreExpr
-> UnfoldingSource
-> Bool
-> Bool
-> Bool
-> Bool
-> Bool
-> UnfoldingGuidance
-> Unfolding
CoreUnfolding { uf_tmpl :: CoreExpr
uf_tmpl = CoreExpr -> CoreExpr
occurAnalyseExpr_NoBinderSwap CoreExpr
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 = CoreExpr -> Bool
exprIsHNF CoreExpr
expr,
uf_is_conlike :: Bool
uf_is_conlike = CoreExpr -> Bool
exprIsConLike CoreExpr
expr,
uf_is_work_free :: Bool
uf_is_work_free = CoreExpr -> Bool
exprIsWorkFree CoreExpr
expr,
uf_expandable :: Bool
uf_expandable = CoreExpr -> Bool
exprIsExpandable CoreExpr
expr,
uf_guidance :: UnfoldingGuidance
uf_guidance = UnfoldingGuidance
guidance }
mkUnfolding :: DynFlags -> UnfoldingSource
-> Bool
-> Bool
-> CoreExpr
-> Unfolding
mkUnfolding :: DynFlags
-> UnfoldingSource -> Bool -> Bool -> CoreExpr -> Unfolding
mkUnfolding DynFlags
dflags UnfoldingSource
src Bool
is_top_lvl Bool
is_bottoming CoreExpr
expr
= CoreUnfolding :: CoreExpr
-> UnfoldingSource
-> Bool
-> Bool
-> Bool
-> Bool
-> Bool
-> UnfoldingGuidance
-> Unfolding
CoreUnfolding { uf_tmpl :: CoreExpr
uf_tmpl = CoreExpr -> CoreExpr
occurAnalyseExpr_NoBinderSwap CoreExpr
expr,
uf_src :: UnfoldingSource
uf_src = UnfoldingSource
src,
uf_is_top :: Bool
uf_is_top = Bool
is_top_lvl,
uf_is_value :: Bool
uf_is_value = CoreExpr -> Bool
exprIsHNF CoreExpr
expr,
uf_is_conlike :: Bool
uf_is_conlike = CoreExpr -> Bool
exprIsConLike CoreExpr
expr,
uf_expandable :: Bool
uf_expandable = CoreExpr -> Bool
exprIsExpandable CoreExpr
expr,
uf_is_work_free :: Bool
uf_is_work_free = CoreExpr -> Bool
exprIsWorkFree CoreExpr
expr,
uf_guidance :: UnfoldingGuidance
uf_guidance = UnfoldingGuidance
guidance }
where
is_top_bottoming :: Bool
is_top_bottoming = Bool
is_top_lvl Bool -> Bool -> Bool
&& Bool
is_bottoming
guidance :: UnfoldingGuidance
guidance = DynFlags -> Bool -> CoreExpr -> UnfoldingGuidance
calcUnfoldingGuidance DynFlags
dflags Bool
is_top_bottoming CoreExpr
expr
inlineBoringOk :: CoreExpr -> Bool
inlineBoringOk :: CoreExpr -> Bool
inlineBoringOk CoreExpr
e
= Arity -> CoreExpr -> Bool
go Arity
0 CoreExpr
e
where
go :: Int -> CoreExpr -> Bool
go :: Arity -> CoreExpr -> Bool
go Arity
credit (Lam Var
x CoreExpr
e) | Var -> Bool
isId Var
x = Arity -> CoreExpr -> Bool
go (Arity
creditArity -> Arity -> Arity
forall a. Num a => a -> a -> a
+Arity
1) CoreExpr
e
| Bool
otherwise = Arity -> CoreExpr -> Bool
go Arity
credit CoreExpr
e
go Arity
credit (App CoreExpr
f (Type {})) = Arity -> CoreExpr -> Bool
go Arity
credit CoreExpr
f
go Arity
credit (App CoreExpr
f CoreExpr
a) | Arity
credit Arity -> Arity -> Bool
forall a. Ord a => a -> a -> Bool
> Arity
0
, CoreExpr -> Bool
exprIsTrivial CoreExpr
a = Arity -> CoreExpr -> Bool
go (Arity
creditArity -> Arity -> Arity
forall a. Num a => a -> a -> a
-Arity
1) CoreExpr
f
go Arity
credit (Tick Tickish Var
_ CoreExpr
e) = Arity -> CoreExpr -> Bool
go Arity
credit CoreExpr
e
go Arity
credit (Cast CoreExpr
e Coercion
_) = Arity -> CoreExpr -> Bool
go Arity
credit CoreExpr
e
go Arity
_ (Var {}) = Bool
boringCxtOk
go Arity
_ CoreExpr
_ = Bool
boringCxtNotOk
calcUnfoldingGuidance
:: DynFlags
-> Bool
-> CoreExpr
-> UnfoldingGuidance
calcUnfoldingGuidance :: DynFlags -> Bool -> CoreExpr -> UnfoldingGuidance
calcUnfoldingGuidance DynFlags
dflags Bool
is_top_bottoming (Tick Tickish Var
t CoreExpr
expr)
| Bool -> Bool
not (Tickish Var -> Bool
forall id. Tickish id -> Bool
tickishIsCode Tickish Var
t)
= DynFlags -> Bool -> CoreExpr -> UnfoldingGuidance
calcUnfoldingGuidance DynFlags
dflags Bool
is_top_bottoming CoreExpr
expr
calcUnfoldingGuidance DynFlags
dflags Bool
is_top_bottoming CoreExpr
expr
= case DynFlags -> Arity -> [Var] -> CoreExpr -> ExprSize
sizeExpr DynFlags
dflags Arity
bOMB_OUT_SIZE [Var]
val_bndrs CoreExpr
body of
ExprSize
TooBig -> UnfoldingGuidance
UnfNever
SizeIs Arity
size Bag (Var, Arity)
cased_bndrs Arity
scrut_discount
| CoreExpr -> Arity -> Arity -> Bool
uncondInline CoreExpr
expr Arity
n_val_bndrs Arity
size
-> UnfWhen :: Arity -> Bool -> Bool -> UnfoldingGuidance
UnfWhen { ug_unsat_ok :: Bool
ug_unsat_ok = Bool
unSaturatedOk
, ug_boring_ok :: Bool
ug_boring_ok = Bool
boringCxtOk
, ug_arity :: Arity
ug_arity = Arity
n_val_bndrs }
| Bool
is_top_bottoming
-> UnfoldingGuidance
UnfNever
| Bool
otherwise
-> UnfIfGoodArgs :: [Arity] -> Arity -> Arity -> UnfoldingGuidance
UnfIfGoodArgs { ug_args :: [Arity]
ug_args = (Var -> Arity) -> [Var] -> [Arity]
forall a b. (a -> b) -> [a] -> [b]
map (Bag (Var, Arity) -> Var -> Arity
mk_discount Bag (Var, Arity)
cased_bndrs) [Var]
val_bndrs
, ug_size :: Arity
ug_size = Arity
size
, ug_res :: Arity
ug_res = Arity
scrut_discount }
where
([Var]
bndrs, CoreExpr
body) = CoreExpr -> ([Var], CoreExpr)
forall b. Expr b -> ([b], Expr b)
collectBinders CoreExpr
expr
bOMB_OUT_SIZE :: Arity
bOMB_OUT_SIZE = DynFlags -> Arity
ufCreationThreshold DynFlags
dflags
val_bndrs :: [Var]
val_bndrs = (Var -> Bool) -> [Var] -> [Var]
forall a. (a -> Bool) -> [a] -> [a]
filter Var -> Bool
isId [Var]
bndrs
n_val_bndrs :: Arity
n_val_bndrs = [Var] -> Arity
forall (t :: * -> *) a. Foldable t => t a -> Arity
length [Var]
val_bndrs
mk_discount :: Bag (Id,Int) -> Id -> Int
mk_discount :: Bag (Var, Arity) -> Var -> Arity
mk_discount Bag (Var, Arity)
cbs Var
bndr = (Arity -> (Var, Arity) -> Arity)
-> Arity -> Bag (Var, Arity) -> Arity
forall (t :: * -> *) b a.
Foldable t =>
(b -> a -> b) -> b -> t a -> b
foldl' Arity -> (Var, Arity) -> Arity
combine Arity
0 Bag (Var, Arity)
cbs
where
combine :: Arity -> (Var, Arity) -> Arity
combine Arity
acc (Var
bndr', Arity
disc)
| Var
bndr Var -> Var -> Bool
forall a. Eq a => a -> a -> Bool
== Var
bndr' = Arity
acc Arity -> Arity -> Arity
`plus_disc` Arity
disc
| Bool
otherwise = Arity
acc
plus_disc :: Int -> Int -> Int
plus_disc :: Arity -> Arity -> Arity
plus_disc | Type -> Bool
isFunTy (Var -> Type
idType Var
bndr) = Arity -> Arity -> Arity
forall a. Ord a => a -> a -> a
max
| Bool
otherwise = Arity -> Arity -> Arity
forall a. Num a => a -> a -> a
(+)
uncondInline :: CoreExpr -> Arity -> Int -> Bool
uncondInline :: CoreExpr -> Arity -> Arity -> Bool
uncondInline CoreExpr
rhs Arity
arity Arity
size
| Arity
arity Arity -> Arity -> Bool
forall a. Ord a => a -> a -> Bool
> Arity
0 = Arity
size Arity -> Arity -> Bool
forall a. Ord a => a -> a -> Bool
<= Arity
10 Arity -> Arity -> Arity
forall a. Num a => a -> a -> a
* (Arity
arity Arity -> Arity -> Arity
forall a. Num a => a -> a -> a
+ Arity
1)
| Bool
otherwise = CoreExpr -> Bool
exprIsTrivial CoreExpr
rhs
sizeExpr :: DynFlags
-> Int
-> [Id]
-> CoreExpr
-> ExprSize
sizeExpr :: DynFlags -> Arity -> [Var] -> CoreExpr -> ExprSize
sizeExpr DynFlags
dflags Arity
bOMB_OUT_SIZE [Var]
top_args CoreExpr
expr
= CoreExpr -> ExprSize
size_up CoreExpr
expr
where
size_up :: CoreExpr -> ExprSize
size_up (Cast CoreExpr
e Coercion
_) = CoreExpr -> ExprSize
size_up CoreExpr
e
size_up (Tick Tickish Var
_ CoreExpr
e) = CoreExpr -> ExprSize
size_up CoreExpr
e
size_up (Type Type
_) = ExprSize
sizeZero
size_up (Coercion Coercion
_) = ExprSize
sizeZero
size_up (Lit Literal
lit) = Arity -> ExprSize
sizeN (Literal -> Arity
litSize Literal
lit)
size_up (Var Var
f) | Var -> Bool
isRealWorldId Var
f = ExprSize
sizeZero
| Bool
otherwise = Var -> [CoreExpr] -> Arity -> ExprSize
size_up_call Var
f [] Arity
0
size_up (App CoreExpr
fun CoreExpr
arg)
| CoreExpr -> Bool
forall b. Expr b -> Bool
isTyCoArg CoreExpr
arg = CoreExpr -> ExprSize
size_up CoreExpr
fun
| Bool
otherwise = CoreExpr -> ExprSize
size_up CoreExpr
arg ExprSize -> ExprSize -> ExprSize
`addSizeNSD`
CoreExpr -> [CoreExpr] -> Arity -> ExprSize
size_up_app CoreExpr
fun [CoreExpr
arg] (if CoreExpr -> Bool
forall b. Expr b -> Bool
isRealWorldExpr CoreExpr
arg then Arity
1 else Arity
0)
size_up (Lam Var
b CoreExpr
e)
| Var -> Bool
isId Var
b Bool -> Bool -> Bool
&& Bool -> Bool
not (Var -> Bool
isRealWorldId Var
b) = DynFlags -> ExprSize -> ExprSize
lamScrutDiscount DynFlags
dflags (CoreExpr -> ExprSize
size_up CoreExpr
e ExprSize -> Arity -> ExprSize
`addSizeN` Arity
10)
| Bool
otherwise = CoreExpr -> ExprSize
size_up CoreExpr
e
size_up (Let (NonRec Var
binder CoreExpr
rhs) CoreExpr
body)
= (Var, CoreExpr) -> ExprSize
size_up_rhs (Var
binder, CoreExpr
rhs) ExprSize -> ExprSize -> ExprSize
`addSizeNSD`
CoreExpr -> ExprSize
size_up CoreExpr
body ExprSize -> Arity -> ExprSize
`addSizeN`
Var -> Arity
forall p. Num p => Var -> p
size_up_alloc Var
binder
size_up (Let (Rec [(Var, CoreExpr)]
pairs) CoreExpr
body)
= ((Var, CoreExpr) -> ExprSize -> ExprSize)
-> ExprSize -> [(Var, CoreExpr)] -> ExprSize
forall (t :: * -> *) a b.
Foldable t =>
(a -> b -> b) -> b -> t a -> b
foldr (ExprSize -> ExprSize -> ExprSize
addSizeNSD (ExprSize -> ExprSize -> ExprSize)
-> ((Var, CoreExpr) -> ExprSize)
-> (Var, CoreExpr)
-> ExprSize
-> ExprSize
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Var, CoreExpr) -> ExprSize
size_up_rhs)
(CoreExpr -> ExprSize
size_up CoreExpr
body ExprSize -> Arity -> ExprSize
`addSizeN` [Arity] -> Arity
forall (t :: * -> *) a. (Foldable t, Num a) => t a -> a
sum (((Var, CoreExpr) -> Arity) -> [(Var, CoreExpr)] -> [Arity]
forall a b. (a -> b) -> [a] -> [b]
map (Var -> Arity
forall p. Num p => Var -> p
size_up_alloc (Var -> Arity)
-> ((Var, CoreExpr) -> Var) -> (Var, CoreExpr) -> Arity
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Var, CoreExpr) -> Var
forall a b. (a, b) -> a
fst) [(Var, CoreExpr)]
pairs))
[(Var, CoreExpr)]
pairs
size_up (Case CoreExpr
e Var
_ Type
_ [Alt Var]
alts)
| [Alt Var] -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null [Alt Var]
alts
= CoreExpr -> ExprSize
size_up CoreExpr
e
size_up (Case CoreExpr
e Var
_ Type
_ [Alt Var]
alts)
| Just Var
v <- CoreExpr -> Maybe Var
forall b. Expr b -> Maybe Var
is_top_arg CoreExpr
e
= let
alt_sizes :: [ExprSize]
alt_sizes = (Alt Var -> ExprSize) -> [Alt Var] -> [ExprSize]
forall a b. (a -> b) -> [a] -> [b]
map Alt Var -> ExprSize
size_up_alt [Alt Var]
alts
alts_size :: ExprSize -> ExprSize -> ExprSize
alts_size (SizeIs Arity
tot Bag (Var, Arity)
tot_disc Arity
tot_scrut)
(SizeIs Arity
max Bag (Var, Arity)
_ Arity
_)
= Arity -> Bag (Var, Arity) -> Arity -> ExprSize
SizeIs Arity
tot ((Var, Arity) -> Bag (Var, Arity)
forall a. a -> Bag a
unitBag (Var
v, Arity
20 Arity -> Arity -> Arity
forall a. Num a => a -> a -> a
+ Arity
tot Arity -> Arity -> Arity
forall a. Num a => a -> a -> a
- Arity
max)
Bag (Var, Arity) -> Bag (Var, Arity) -> Bag (Var, Arity)
forall a. Bag a -> Bag a -> Bag a
`unionBags` Bag (Var, Arity)
tot_disc) Arity
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 Var
is_top_arg (Var Var
v) | Var
v Var -> [Var] -> Bool
forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`elem` [Var]
top_args = Var -> Maybe Var
forall a. a -> Maybe a
Just Var
v
is_top_arg (Cast Expr b
e Coercion
_) = Expr b -> Maybe Var
is_top_arg Expr b
e
is_top_arg Expr b
_ = Maybe Var
forall a. Maybe a
Nothing
size_up (Case CoreExpr
e Var
_ Type
_ [Alt Var]
alts) = CoreExpr -> ExprSize
size_up CoreExpr
e ExprSize -> ExprSize -> ExprSize
`addSizeNSD`
(Alt Var -> ExprSize -> ExprSize)
-> ExprSize -> [Alt Var] -> ExprSize
forall (t :: * -> *) a b.
Foldable t =>
(a -> b -> b) -> b -> t a -> b
foldr (ExprSize -> ExprSize -> ExprSize
addAltSize (ExprSize -> ExprSize -> ExprSize)
-> (Alt Var -> ExprSize) -> Alt Var -> ExprSize -> ExprSize
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Alt Var -> ExprSize
size_up_alt) ExprSize
case_size [Alt Var]
alts
where
case_size :: ExprSize
case_size
| CoreExpr -> Bool
forall b. Expr b -> Bool
is_inline_scrut CoreExpr
e, [Alt Var] -> Arity -> Bool
forall a. [a] -> Arity -> Bool
lengthAtMost [Alt Var]
alts Arity
1 = Arity -> ExprSize
sizeN (-Arity
10)
| Bool
otherwise = ExprSize
sizeZero
is_inline_scrut :: Expr b -> Bool
is_inline_scrut (Var Var
v) = HasDebugCallStack => Type -> Bool
Type -> Bool
isUnliftedType (Var -> Type
idType Var
v)
is_inline_scrut Expr b
scrut
| (Var Var
f, [Expr b]
_) <- Expr b -> (Expr b, [Expr b])
forall b. Expr b -> (Expr b, [Expr b])
collectArgs Expr b
scrut
= case Var -> IdDetails
idDetails Var
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 :: (Var, CoreExpr) -> ExprSize
size_up_rhs (Var
bndr, CoreExpr
rhs)
| Just Arity
join_arity <- Var -> Maybe Arity
isJoinId_maybe Var
bndr
, ([Var]
_bndrs, CoreExpr
body) <- Arity -> CoreExpr -> ([Var], CoreExpr)
forall b. Arity -> Expr b -> ([b], Expr b)
collectNBinders Arity
join_arity CoreExpr
rhs
= CoreExpr -> ExprSize
size_up CoreExpr
body
| Bool
otherwise
= CoreExpr -> ExprSize
size_up CoreExpr
rhs
size_up_app :: CoreExpr -> [CoreExpr] -> Arity -> ExprSize
size_up_app (App CoreExpr
fun CoreExpr
arg) [CoreExpr]
args Arity
voids
| CoreExpr -> Bool
forall b. Expr b -> Bool
isTyCoArg CoreExpr
arg = CoreExpr -> [CoreExpr] -> Arity -> ExprSize
size_up_app CoreExpr
fun [CoreExpr]
args Arity
voids
| CoreExpr -> Bool
forall b. Expr b -> Bool
isRealWorldExpr CoreExpr
arg = CoreExpr -> [CoreExpr] -> Arity -> ExprSize
size_up_app CoreExpr
fun (CoreExpr
argCoreExpr -> [CoreExpr] -> [CoreExpr]
forall a. a -> [a] -> [a]
:[CoreExpr]
args) (Arity
voids Arity -> Arity -> Arity
forall a. Num a => a -> a -> a
+ Arity
1)
| Bool
otherwise = CoreExpr -> ExprSize
size_up CoreExpr
arg ExprSize -> ExprSize -> ExprSize
`addSizeNSD`
CoreExpr -> [CoreExpr] -> Arity -> ExprSize
size_up_app CoreExpr
fun (CoreExpr
argCoreExpr -> [CoreExpr] -> [CoreExpr]
forall a. a -> [a] -> [a]
:[CoreExpr]
args) Arity
voids
size_up_app (Var Var
fun) [CoreExpr]
args Arity
voids = Var -> [CoreExpr] -> Arity -> ExprSize
size_up_call Var
fun [CoreExpr]
args Arity
voids
size_up_app (Tick Tickish Var
_ CoreExpr
expr) [CoreExpr]
args Arity
voids = CoreExpr -> [CoreExpr] -> Arity -> ExprSize
size_up_app CoreExpr
expr [CoreExpr]
args Arity
voids
size_up_app (Cast CoreExpr
expr Coercion
_) [CoreExpr]
args Arity
voids = CoreExpr -> [CoreExpr] -> Arity -> ExprSize
size_up_app CoreExpr
expr [CoreExpr]
args Arity
voids
size_up_app CoreExpr
other [CoreExpr]
args Arity
voids = CoreExpr -> ExprSize
size_up CoreExpr
other ExprSize -> Arity -> ExprSize
`addSizeN`
Arity -> Arity -> Arity
callSize ([CoreExpr] -> Arity
forall (t :: * -> *) a. Foldable t => t a -> Arity
length [CoreExpr]
args) Arity
voids
size_up_call :: Id -> [CoreExpr] -> Int -> ExprSize
size_up_call :: Var -> [CoreExpr] -> Arity -> ExprSize
size_up_call Var
fun [CoreExpr]
val_args Arity
voids
= case Var -> IdDetails
idDetails Var
fun of
FCallId ForeignCall
_ -> Arity -> ExprSize
sizeN (Arity -> Arity -> Arity
callSize ([CoreExpr] -> Arity
forall (t :: * -> *) a. Foldable t => t a -> Arity
length [CoreExpr]
val_args) Arity
voids)
DataConWorkId DataCon
dc -> DataCon -> Arity -> ExprSize
conSize DataCon
dc ([CoreExpr] -> Arity
forall (t :: * -> *) a. Foldable t => t a -> Arity
length [CoreExpr]
val_args)
PrimOpId PrimOp
op -> PrimOp -> Arity -> ExprSize
primOpSize PrimOp
op ([CoreExpr] -> Arity
forall (t :: * -> *) a. Foldable t => t a -> Arity
length [CoreExpr]
val_args)
ClassOpId Class
_ -> DynFlags -> [Var] -> [CoreExpr] -> ExprSize
classOpSize DynFlags
dflags [Var]
top_args [CoreExpr]
val_args
IdDetails
_ -> DynFlags -> [Var] -> Var -> Arity -> Arity -> ExprSize
funSize DynFlags
dflags [Var]
top_args Var
fun ([CoreExpr] -> Arity
forall (t :: * -> *) a. Foldable t => t a -> Arity
length [CoreExpr]
val_args) Arity
voids
size_up_alt :: Alt Var -> ExprSize
size_up_alt (AltCon
_con, [Var]
_bndrs, CoreExpr
rhs) = CoreExpr -> ExprSize
size_up CoreExpr
rhs ExprSize -> Arity -> ExprSize
`addSizeN` Arity
10
size_up_alloc :: Var -> p
size_up_alloc Var
bndr
| Var -> Bool
isTyVar Var
bndr
Bool -> Bool -> Bool
|| Var -> Bool
isJoinId Var
bndr
Bool -> Bool -> Bool
|| HasDebugCallStack => Type -> Bool
Type -> Bool
isUnliftedType (Var -> Type
idType Var
bndr)
= p
0
| Bool
otherwise
= p
10
addSizeN :: ExprSize -> Arity -> ExprSize
addSizeN ExprSize
TooBig Arity
_ = ExprSize
TooBig
addSizeN (SizeIs Arity
n Bag (Var, Arity)
xs Arity
d) Arity
m = Arity -> Arity -> Bag (Var, Arity) -> Arity -> ExprSize
mkSizeIs Arity
bOMB_OUT_SIZE (Arity
n Arity -> Arity -> Arity
forall a. Num a => a -> a -> a
+ Arity
m) Bag (Var, Arity)
xs Arity
d
addAltSize :: ExprSize -> ExprSize -> ExprSize
addAltSize ExprSize
TooBig ExprSize
_ = ExprSize
TooBig
addAltSize ExprSize
_ ExprSize
TooBig = ExprSize
TooBig
addAltSize (SizeIs Arity
n1 Bag (Var, Arity)
xs Arity
d1) (SizeIs Arity
n2 Bag (Var, Arity)
ys Arity
d2)
= Arity -> Arity -> Bag (Var, Arity) -> Arity -> ExprSize
mkSizeIs Arity
bOMB_OUT_SIZE (Arity
n1 Arity -> Arity -> Arity
forall a. Num a => a -> a -> a
+ Arity
n2)
(Bag (Var, Arity)
xs Bag (Var, Arity) -> Bag (Var, Arity) -> Bag (Var, Arity)
forall a. Bag a -> Bag a -> Bag a
`unionBags` Bag (Var, Arity)
ys)
(Arity
d1 Arity -> Arity -> Arity
forall a. Num a => a -> a -> a
+ Arity
d2)
addSizeNSD :: ExprSize -> ExprSize -> ExprSize
addSizeNSD ExprSize
TooBig ExprSize
_ = ExprSize
TooBig
addSizeNSD ExprSize
_ ExprSize
TooBig = ExprSize
TooBig
addSizeNSD (SizeIs Arity
n1 Bag (Var, Arity)
xs Arity
_) (SizeIs Arity
n2 Bag (Var, Arity)
ys Arity
d2)
= Arity -> Arity -> Bag (Var, Arity) -> Arity -> ExprSize
mkSizeIs Arity
bOMB_OUT_SIZE (Arity
n1 Arity -> Arity -> Arity
forall a. Num a => a -> a -> a
+ Arity
n2)
(Bag (Var, Arity)
xs Bag (Var, Arity) -> Bag (Var, Arity) -> Bag (Var, Arity)
forall a. Bag a -> Bag a -> Bag a
`unionBags` Bag (Var, Arity)
ys)
Arity
d2
isRealWorldId :: Var -> Bool
isRealWorldId Var
id = Var -> Type
idType Var
id Type -> Type -> Bool
`eqType` Type
realWorldStatePrimTy
isRealWorldExpr :: Expr b -> Bool
isRealWorldExpr (Var Var
id) = Var -> Bool
isRealWorldId Var
id
isRealWorldExpr (Tick Tickish Var
_ Expr b
e) = Expr b -> Bool
isRealWorldExpr Expr b
e
isRealWorldExpr Expr b
_ = Bool
False
litSize :: Literal -> Int
litSize :: Literal -> Arity
litSize (LitNumber LitNumType
LitNumInteger Integer
_ Type
_) = Arity
100
litSize (LitNumber LitNumType
LitNumNatural Integer
_ Type
_) = Arity
100
litSize (LitString ByteString
str) = Arity
10 Arity -> Arity -> Arity
forall a. Num a => a -> a -> a
+ Arity
10 Arity -> Arity -> Arity
forall a. Num a => a -> a -> a
* ((ByteString -> Arity
BS.length ByteString
str Arity -> Arity -> Arity
forall a. Num a => a -> a -> a
+ Arity
3) Arity -> Arity -> Arity
forall a. Integral a => a -> a -> a
`div` Arity
4)
litSize Literal
_other = Arity
0
classOpSize :: DynFlags -> [Id] -> [CoreExpr] -> ExprSize
classOpSize :: DynFlags -> [Var] -> [CoreExpr] -> ExprSize
classOpSize DynFlags
_ [Var]
_ []
= ExprSize
sizeZero
classOpSize DynFlags
dflags [Var]
top_args (CoreExpr
arg1 : [CoreExpr]
other_args)
= Arity -> Bag (Var, Arity) -> Arity -> ExprSize
SizeIs Arity
size Bag (Var, Arity)
arg_discount Arity
0
where
size :: Arity
size = Arity
20 Arity -> Arity -> Arity
forall a. Num a => a -> a -> a
+ (Arity
10 Arity -> Arity -> Arity
forall a. Num a => a -> a -> a
* [CoreExpr] -> Arity
forall (t :: * -> *) a. Foldable t => t a -> Arity
length [CoreExpr]
other_args)
arg_discount :: Bag (Var, Arity)
arg_discount = case CoreExpr
arg1 of
Var Var
dict | Var
dict Var -> [Var] -> Bool
forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`elem` [Var]
top_args
-> (Var, Arity) -> Bag (Var, Arity)
forall a. a -> Bag a
unitBag (Var
dict, DynFlags -> Arity
ufDictDiscount DynFlags
dflags)
CoreExpr
_other -> Bag (Var, Arity)
forall a. Bag a
emptyBag
callSize
:: Int
-> Int
-> Int
callSize :: Arity -> Arity -> Arity
callSize Arity
n_val_args Arity
voids = Arity
10 Arity -> Arity -> Arity
forall a. Num a => a -> a -> a
* (Arity
1 Arity -> Arity -> Arity
forall a. Num a => a -> a -> a
+ Arity
n_val_args Arity -> Arity -> Arity
forall a. Num a => a -> a -> a
- Arity
voids)
jumpSize
:: Int
-> Int
-> Int
jumpSize :: Arity -> Arity -> Arity
jumpSize Arity
n_val_args Arity
voids = Arity
2 Arity -> Arity -> Arity
forall a. Num a => a -> a -> a
* (Arity
1 Arity -> Arity -> Arity
forall a. Num a => a -> a -> a
+ Arity
n_val_args Arity -> Arity -> Arity
forall a. Num a => a -> a -> a
- Arity
voids)
funSize :: DynFlags -> [Id] -> Id -> Int -> Int -> ExprSize
funSize :: DynFlags -> [Var] -> Var -> Arity -> Arity -> ExprSize
funSize DynFlags
dflags [Var]
top_args Var
fun Arity
n_val_args Arity
voids
| Var
fun Var -> Unique -> Bool
forall a. Uniquable a => a -> Unique -> Bool
`hasKey` Unique
buildIdKey = ExprSize
buildSize
| Var
fun Var -> Unique -> Bool
forall a. Uniquable a => a -> Unique -> Bool
`hasKey` Unique
augmentIdKey = ExprSize
augmentSize
| Bool
otherwise = Arity -> Bag (Var, Arity) -> Arity -> ExprSize
SizeIs Arity
size Bag (Var, Arity)
arg_discount Arity
res_discount
where
some_val_args :: Bool
some_val_args = Arity
n_val_args Arity -> Arity -> Bool
forall a. Ord a => a -> a -> Bool
> Arity
0
is_join :: Bool
is_join = Var -> Bool
isJoinId Var
fun
size :: Arity
size | Bool
is_join = Arity -> Arity -> Arity
jumpSize Arity
n_val_args Arity
voids
| Bool -> Bool
not Bool
some_val_args = Arity
0
| Bool
otherwise = Arity -> Arity -> Arity
callSize Arity
n_val_args Arity
voids
arg_discount :: Bag (Var, Arity)
arg_discount | Bool
some_val_args Bool -> Bool -> Bool
&& Var
fun Var -> [Var] -> Bool
forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`elem` [Var]
top_args
= (Var, Arity) -> Bag (Var, Arity)
forall a. a -> Bag a
unitBag (Var
fun, DynFlags -> Arity
ufFunAppDiscount DynFlags
dflags)
| Bool
otherwise = Bag (Var, Arity)
forall a. Bag a
emptyBag
res_discount :: Arity
res_discount | Var -> Arity
idArity Var
fun Arity -> Arity -> Bool
forall a. Ord a => a -> a -> Bool
> Arity
n_val_args = DynFlags -> Arity
ufFunAppDiscount DynFlags
dflags
| Bool
otherwise = Arity
0
conSize :: DataCon -> Int -> ExprSize
conSize :: DataCon -> Arity -> ExprSize
conSize DataCon
dc Arity
n_val_args
| Arity
n_val_args Arity -> Arity -> Bool
forall a. Eq a => a -> a -> Bool
== Arity
0 = Arity -> Bag (Var, Arity) -> Arity -> ExprSize
SizeIs Arity
0 Bag (Var, Arity)
forall a. Bag a
emptyBag Arity
10
| DataCon -> Bool
isUnboxedTupleCon DataCon
dc = Arity -> Bag (Var, Arity) -> Arity -> ExprSize
SizeIs Arity
0 Bag (Var, Arity)
forall a. Bag a
emptyBag (Arity
10 Arity -> Arity -> Arity
forall a. Num a => a -> a -> a
* (Arity
1 Arity -> Arity -> Arity
forall a. Num a => a -> a -> a
+ Arity
n_val_args))
| Bool
otherwise = Arity -> Bag (Var, Arity) -> Arity -> ExprSize
SizeIs Arity
10 Bag (Var, Arity)
forall a. Bag a
emptyBag (Arity
10 Arity -> Arity -> Arity
forall a. Num a => a -> a -> a
* (Arity
1 Arity -> Arity -> Arity
forall a. Num a => a -> a -> a
+ Arity
n_val_args))
primOpSize :: PrimOp -> Int -> ExprSize
primOpSize :: PrimOp -> Arity -> ExprSize
primOpSize PrimOp
op Arity
n_val_args
= if PrimOp -> Bool
primOpOutOfLine PrimOp
op
then Arity -> ExprSize
sizeN (Arity
op_size Arity -> Arity -> Arity
forall a. Num a => a -> a -> a
+ Arity
n_val_args)
else Arity -> ExprSize
sizeN Arity
op_size
where
op_size :: Arity
op_size = PrimOp -> Arity
primOpCodeSize PrimOp
op
buildSize :: ExprSize
buildSize :: ExprSize
buildSize = Arity -> Bag (Var, Arity) -> Arity -> ExprSize
SizeIs Arity
0 Bag (Var, Arity)
forall a. Bag a
emptyBag Arity
40
augmentSize :: ExprSize
augmentSize :: ExprSize
augmentSize = Arity -> Bag (Var, Arity) -> Arity -> ExprSize
SizeIs Arity
0 Bag (Var, Arity)
forall a. Bag a
emptyBag Arity
40
lamScrutDiscount :: DynFlags -> ExprSize -> ExprSize
lamScrutDiscount :: DynFlags -> ExprSize -> ExprSize
lamScrutDiscount DynFlags
dflags (SizeIs Arity
n Bag (Var, Arity)
vs Arity
_) = Arity -> Bag (Var, Arity) -> Arity -> ExprSize
SizeIs Arity
n Bag (Var, Arity)
vs (DynFlags -> Arity
ufFunAppDiscount DynFlags
dflags)
lamScrutDiscount DynFlags
_ ExprSize
TooBig = ExprSize
TooBig
data ExprSize
= TooBig
| SizeIs { ExprSize -> Arity
_es_size_is :: {-# UNPACK #-} !Int
, ExprSize -> Bag (Var, Arity)
_es_args :: !(Bag (Id,Int))
, ExprSize -> Arity
_es_discount :: {-# UNPACK #-} !Int
}
instance Outputable ExprSize where
ppr :: ExprSize -> SDoc
ppr ExprSize
TooBig = String -> SDoc
text String
"TooBig"
ppr (SizeIs Arity
a Bag (Var, Arity)
_ Arity
c) = SDoc -> SDoc
brackets (Arity -> SDoc
int Arity
a SDoc -> SDoc -> SDoc
<+> Arity -> SDoc
int Arity
c)
mkSizeIs :: Int -> Int -> Bag (Id, Int) -> Int -> ExprSize
mkSizeIs :: Arity -> Arity -> Bag (Var, Arity) -> Arity -> ExprSize
mkSizeIs Arity
max Arity
n Bag (Var, Arity)
xs Arity
d | (Arity
n Arity -> Arity -> Arity
forall a. Num a => a -> a -> a
- Arity
d) Arity -> Arity -> Bool
forall a. Ord a => a -> a -> Bool
> Arity
max = ExprSize
TooBig
| Bool
otherwise = Arity -> Bag (Var, Arity) -> Arity -> ExprSize
SizeIs Arity
n Bag (Var, Arity)
xs Arity
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 Arity
n1 Bag (Var, Arity)
_ Arity
_) s2 :: ExprSize
s2@(SizeIs Arity
n2 Bag (Var, Arity)
_ Arity
_) | Arity
n1 Arity -> Arity -> Bool
forall a. Ord a => a -> a -> Bool
> Arity
n2 = ExprSize
s1
| Bool
otherwise = ExprSize
s2
sizeZero :: ExprSize
sizeN :: Int -> ExprSize
sizeZero :: ExprSize
sizeZero = Arity -> Bag (Var, Arity) -> Arity -> ExprSize
SizeIs Arity
0 Bag (Var, Arity)
forall a. Bag a
emptyBag Arity
0
sizeN :: Arity -> ExprSize
sizeN Arity
n = Arity -> Bag (Var, Arity) -> Arity -> ExprSize
SizeIs Arity
n Bag (Var, Arity)
forall a. Bag a
emptyBag Arity
0
couldBeSmallEnoughToInline :: DynFlags -> Int -> CoreExpr -> Bool
couldBeSmallEnoughToInline :: DynFlags -> Arity -> CoreExpr -> Bool
couldBeSmallEnoughToInline DynFlags
dflags Arity
threshold CoreExpr
rhs
= case DynFlags -> Arity -> [Var] -> CoreExpr -> ExprSize
sizeExpr DynFlags
dflags Arity
threshold [] CoreExpr
body of
ExprSize
TooBig -> Bool
False
ExprSize
_ -> Bool
True
where
([Var]
_, CoreExpr
body) = CoreExpr -> ([Var], CoreExpr)
forall b. Expr b -> ([b], Expr b)
collectBinders CoreExpr
rhs
smallEnoughToInline :: DynFlags -> Unfolding -> Bool
smallEnoughToInline :: DynFlags -> Unfolding -> Bool
smallEnoughToInline DynFlags
dflags (CoreUnfolding {uf_guidance :: Unfolding -> UnfoldingGuidance
uf_guidance = UnfIfGoodArgs {ug_size :: UnfoldingGuidance -> Arity
ug_size = Arity
size}})
= Arity
size Arity -> Arity -> Bool
forall a. Ord a => a -> a -> Bool
<= DynFlags -> Arity
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 -> CoreExpr
uf_tmpl = CoreExpr
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 -> CoreExpr -> UnfoldingGuidance -> Maybe Unfolding
do_cunf CoreExpr
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 :: CoreExpr -> UnfoldingGuidance -> Maybe Unfolding
do_cunf CoreExpr
_ UnfoldingGuidance
UnfNever = Maybe Unfolding
forall a. Maybe a
Nothing
do_cunf CoreExpr
_ (UnfWhen {}) = Unfolding -> Maybe Unfolding
forall a. a -> Maybe a
Just (Unfolding
fn_unf { uf_src :: UnfoldingSource
uf_src = UnfoldingSource
InlineStable })
do_cunf CoreExpr
expr (UnfIfGoodArgs { ug_size :: UnfoldingGuidance -> Arity
ug_size = Arity
size, ug_args :: UnfoldingGuidance -> [Arity]
ug_args = [Arity]
args })
| IdInfo -> Arity
arityInfo IdInfo
fn_info Arity -> Arity -> Bool
forall a. Ord a => a -> a -> Bool
> Arity
0
, Bool -> Bool
not (StrictSig -> Bool
isBottomingSig (IdInfo -> StrictSig
strictnessInfo IdInfo
fn_info))
, let unf_arity :: Arity
unf_arity = [Arity] -> Arity
forall (t :: * -> *) a. Foldable t => t a -> Arity
length [Arity]
args
, Arity
size Arity -> Arity -> Arity
forall a. Num a => a -> a -> a
- (Arity
10 Arity -> Arity -> Arity
forall a. Num a => a -> a -> a
* (Arity
unf_arity Arity -> Arity -> Arity
forall a. Num a => a -> a -> a
+ Arity
1)) Arity -> Arity -> Bool
forall a. Ord a => a -> a -> Bool
<= DynFlags -> Arity
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 :: Arity -> Bool -> Bool -> UnfoldingGuidance
UnfWhen { ug_arity :: Arity
ug_arity = Arity
unf_arity
, ug_unsat_ok :: Bool
ug_unsat_ok = Bool
unSaturatedOk
, ug_boring_ok :: Bool
ug_boring_ok = CoreExpr -> Bool
inlineBoringOk CoreExpr
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
-> Var
-> Bool
-> Bool
-> [ArgSummary]
-> CallCtxt
-> Maybe CoreExpr
callSiteInline DynFlags
dflags Var
id Bool
active_unfolding Bool
lone_variable [ArgSummary]
arg_infos CallCtxt
cont_info
= case Var -> Unfolding
idUnfolding Var
id of
CoreUnfolding { uf_tmpl :: Unfolding -> CoreExpr
uf_tmpl = CoreExpr
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
-> Var
-> Bool
-> [ArgSummary]
-> CallCtxt
-> CoreExpr
-> Bool
-> Bool
-> UnfoldingGuidance
-> Maybe CoreExpr
tryUnfolding DynFlags
dflags Var
id Bool
lone_variable
[ArgSummary]
arg_infos CallCtxt
cont_info CoreExpr
unf_template
Bool
is_wf Bool
is_exp UnfoldingGuidance
guidance
| Bool
otherwise -> DynFlags
-> Var -> String -> SDoc -> Maybe CoreExpr -> Maybe CoreExpr
forall a. DynFlags -> Var -> String -> SDoc -> a -> a
traceInline DynFlags
dflags Var
id String
"Inactive unfolding:" (Var -> SDoc
forall a. Outputable a => a -> SDoc
ppr Var
id) Maybe CoreExpr
forall a. Maybe a
Nothing
Unfolding
NoUnfolding -> Maybe CoreExpr
forall a. Maybe a
Nothing
Unfolding
BootUnfolding -> Maybe CoreExpr
forall a. Maybe a
Nothing
OtherCon {} -> Maybe CoreExpr
forall a. Maybe a
Nothing
DFunUnfolding {} -> Maybe CoreExpr
forall a. Maybe a
Nothing
traceInline :: DynFlags -> Id -> String -> SDoc -> a -> a
traceInline :: DynFlags -> Var -> String -> SDoc -> a -> a
traceInline DynFlags
dflags Var
inline_id String
str SDoc
doc a
result
| Just String
prefix <- DynFlags -> Maybe String
inlineCheck DynFlags
dflags
= if String
prefix String -> String -> Bool
forall a. Eq a => [a] -> [a] -> Bool
`isPrefixOf` OccName -> String
occNameString (Var -> OccName
forall a. NamedThing a => a -> OccName
getOccName Var
inline_id)
then String -> SDoc -> a -> a
forall a. String -> SDoc -> a -> a
pprTrace String
str SDoc
doc a
result
else a
result
| DumpFlag -> DynFlags -> Bool
dopt DumpFlag
Opt_D_dump_inlinings DynFlags
dflags Bool -> Bool -> Bool
&& DumpFlag -> DynFlags -> Bool
dopt DumpFlag
Opt_D_verbose_core2core DynFlags
dflags
= String -> SDoc -> a -> a
forall a. String -> SDoc -> a -> a
pprTrace String
str SDoc
doc a
result
| Bool
otherwise
= a
result
very_aggressive :: DynFlags -> Bool
very_aggressive :: DynFlags -> Bool
very_aggressive = DynFlags -> Bool
ufVeryAggressive
{-# NOINLINE very_aggressive #-}
tryUnfolding :: DynFlags -> Id -> Bool -> [ArgSummary] -> CallCtxt
-> CoreExpr -> Bool -> Bool -> UnfoldingGuidance
-> Maybe CoreExpr
tryUnfolding :: DynFlags
-> Var
-> Bool
-> [ArgSummary]
-> CallCtxt
-> CoreExpr
-> Bool
-> Bool
-> UnfoldingGuidance
-> Maybe CoreExpr
tryUnfolding DynFlags
dflags Var
id Bool
lone_variable
[ArgSummary]
arg_infos CallCtxt
cont_info CoreExpr
unf_template
Bool
is_wf Bool
is_exp UnfoldingGuidance
guidance
= case UnfoldingGuidance
guidance of
UnfoldingGuidance
UnfNever -> DynFlags
-> Var -> String -> SDoc -> Maybe CoreExpr -> Maybe CoreExpr
forall a. DynFlags -> Var -> String -> SDoc -> a -> a
traceInline DynFlags
dflags Var
id String
str (String -> SDoc
text String
"UnfNever") Maybe CoreExpr
forall a. Maybe a
Nothing
UnfWhen { ug_arity :: UnfoldingGuidance -> Arity
ug_arity = Arity
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
very_aggressive DynFlags
dflags)
-> DynFlags
-> Var -> String -> SDoc -> Maybe CoreExpr -> Maybe CoreExpr
forall a. DynFlags -> Var -> String -> SDoc -> a -> a
traceInline DynFlags
dflags Var
id String
str (Bool -> SDoc -> Bool -> SDoc
forall a. Outputable a => a -> SDoc -> Bool -> SDoc
mk_doc Bool
some_benefit SDoc
empty Bool
True) (CoreExpr -> Maybe CoreExpr
forall a. a -> Maybe a
Just CoreExpr
unf_template)
| Bool
otherwise
-> DynFlags
-> Var -> String -> SDoc -> Maybe CoreExpr -> Maybe CoreExpr
forall a. DynFlags -> Var -> String -> SDoc -> a -> a
traceInline DynFlags
dflags Var
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 CoreExpr
forall a. Maybe a
Nothing
where
some_benefit :: Bool
some_benefit = Arity -> Bool
calc_some_benefit Arity
uf_arity
enough_args :: Bool
enough_args = (Arity
n_val_args Arity -> Arity -> Bool
forall a. Ord a => a -> a -> Bool
>= Arity
uf_arity) Bool -> Bool -> Bool
|| (Bool
unsat_ok Bool -> Bool -> Bool
&& Arity
n_val_args Arity -> Arity -> Bool
forall a. Ord a => a -> a -> Bool
> Arity
0)
UnfIfGoodArgs { ug_args :: UnfoldingGuidance -> [Arity]
ug_args = [Arity]
arg_discounts, ug_res :: UnfoldingGuidance -> Arity
ug_res = Arity
res_discount, ug_size :: UnfoldingGuidance -> Arity
ug_size = Arity
size }
| DynFlags -> Bool
very_aggressive DynFlags
dflags
-> DynFlags
-> Var -> String -> SDoc -> Maybe CoreExpr -> Maybe CoreExpr
forall a. DynFlags -> Var -> String -> SDoc -> a -> a
traceInline DynFlags
dflags Var
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) (CoreExpr -> Maybe CoreExpr
forall a. a -> Maybe a
Just CoreExpr
unf_template)
| Bool
is_wf Bool -> Bool -> Bool
&& Bool
some_benefit Bool -> Bool -> Bool
&& Bool
small_enough
-> DynFlags
-> Var -> String -> SDoc -> Maybe CoreExpr -> Maybe CoreExpr
forall a. DynFlags -> Var -> String -> SDoc -> a -> a
traceInline DynFlags
dflags Var
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) (CoreExpr -> Maybe CoreExpr
forall a. a -> Maybe a
Just CoreExpr
unf_template)
| Bool
otherwise
-> DynFlags
-> Var -> String -> SDoc -> Maybe CoreExpr -> Maybe CoreExpr
forall a. DynFlags -> Var -> String -> SDoc -> a -> a
traceInline DynFlags
dflags Var
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 CoreExpr
forall a. Maybe a
Nothing
where
some_benefit :: Bool
some_benefit = Arity -> Bool
calc_some_benefit ([Arity] -> Arity
forall (t :: * -> *) a. Foldable t => t a -> Arity
length [Arity]
arg_discounts)
extra_doc :: SDoc
extra_doc = String -> SDoc
text String
"discounted size =" SDoc -> SDoc -> SDoc
<+> Arity -> SDoc
int Arity
discounted_size
discounted_size :: Arity
discounted_size = Arity
size Arity -> Arity -> Arity
forall a. Num a => a -> a -> a
- Arity
discount
small_enough :: Bool
small_enough = Arity
discounted_size Arity -> Arity -> Bool
forall a. Ord a => a -> a -> Bool
<= DynFlags -> Arity
ufUseThreshold DynFlags
dflags
discount :: Arity
discount = DynFlags -> [Arity] -> Arity -> [ArgSummary] -> CallCtxt -> Arity
computeDiscount DynFlags
dflags [Arity]
arg_discounts
Arity
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 (Var -> SDoc
forall a. Outputable a => a -> SDoc
ppr Var
id)
n_val_args :: Arity
n_val_args = [ArgSummary] -> Arity
forall (t :: * -> *) a. Foldable t => t a -> Arity
length [ArgSummary]
arg_infos
calc_some_benefit :: Arity -> Bool
calc_some_benefit :: Arity -> Bool
calc_some_benefit Arity
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 = Arity
n_val_args Arity -> Arity -> Bool
forall a. Ord a => a -> a -> Bool
>= Arity
uf_arity
over_saturated :: Bool
over_saturated = Arity
n_val_args Arity -> Arity -> Bool
forall a. Ord a => a -> a -> Bool
> Arity
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 -> Arity
uf_arity Arity -> Arity -> Bool
forall a. Ord a => a -> a -> Bool
> Arity
0
CallCtxt
DiscArgCtxt -> Arity
uf_arity Arity -> Arity -> Bool
forall a. Ord a => a -> a -> Bool
> Arity
0
CallCtxt
RhsCtxt -> Arity
uf_arity Arity -> Arity -> Bool
forall a. Ord a => a -> a -> Bool
> Arity
0
CallCtxt
_other -> Bool
False
computeDiscount :: DynFlags -> [Int] -> Int -> [ArgSummary] -> CallCtxt
-> Int
computeDiscount :: DynFlags -> [Arity] -> Arity -> [ArgSummary] -> CallCtxt -> Arity
computeDiscount DynFlags
dflags [Arity]
arg_discounts Arity
res_discount [ArgSummary]
arg_infos CallCtxt
cont_info
= Arity
10
Arity -> Arity -> Arity
forall a. Num a => a -> a -> a
+ Arity
10 Arity -> Arity -> Arity
forall a. Num a => a -> a -> a
* [Arity] -> Arity
forall (t :: * -> *) a. Foldable t => t a -> Arity
length [Arity]
actual_arg_discounts
Arity -> Arity -> Arity
forall a. Num a => a -> a -> a
+ Float -> Arity
forall a b. (RealFrac a, Integral b) => a -> b
round (DynFlags -> Float
ufKeenessFactor DynFlags
dflags Float -> Float -> Float
forall a. Num a => a -> a -> a
*
Arity -> Float
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Arity
total_arg_discount Arity -> Arity -> Arity
forall a. Num a => a -> a -> a
+ Arity
res_discount'))
where
actual_arg_discounts :: [Arity]
actual_arg_discounts = (Arity -> ArgSummary -> Arity)
-> [Arity] -> [ArgSummary] -> [Arity]
forall a b c. (a -> b -> c) -> [a] -> [b] -> [c]
zipWith Arity -> ArgSummary -> Arity
forall p. Num p => p -> ArgSummary -> p
mk_arg_discount [Arity]
arg_discounts [ArgSummary]
arg_infos
total_arg_discount :: Arity
total_arg_discount = [Arity] -> Arity
forall (t :: * -> *) a. (Foldable t, Num a) => t a -> a
sum [Arity]
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' :: Arity
res_discount'
| Ordering
LT <- [Arity]
arg_discounts [Arity] -> [ArgSummary] -> Ordering
forall a b. [a] -> [b] -> Ordering
`compareLength` [ArgSummary]
arg_infos
= Arity
res_discount
| Bool
otherwise
= case CallCtxt
cont_info of
CallCtxt
BoringCtxt -> Arity
0
CallCtxt
CaseCtxt -> Arity
res_discount
CallCtxt
ValAppCtxt -> Arity
res_discount
CallCtxt
_ -> Arity
40 Arity -> Arity -> Arity
forall a. Ord a => a -> a -> a
`min` Arity
res_discount