{-# LANGUAGE BangPatterns #-}
module GHC.Core.Unfold (
Unfolding, UnfoldingGuidance,
ExprSize(..), sizeExpr,
ArgSummary(..), nonTriv,
CallCtxt(..),
UnfoldingOpts (..), defaultUnfoldingOpts,
updateCreationThreshold, updateUseThreshold,
updateFunAppDiscount, updateDictDiscount,
updateVeryAggressive, updateCaseScaling,
updateCaseThreshold, updateReportPrefix,
inlineBoringOk, calcUnfoldingGuidance
) where
import GHC.Prelude
import GHC.Core
import GHC.Core.Utils
import GHC.Types.Id
import GHC.Core.DataCon
import GHC.Types.Literal
import GHC.Builtin.PrimOps
import GHC.Types.Id.Info
import GHC.Types.RepType ( isZeroBitTy )
import GHC.Types.Basic ( Arity, RecFlag )
import GHC.Core.Type
import GHC.Builtin.Names
import GHC.Data.Bag
import GHC.Utils.Misc
import GHC.Utils.Outputable
import GHC.Types.ForeignCall
import GHC.Types.Tickish
import qualified Data.ByteString as BS
data UnfoldingOpts = UnfoldingOpts
{ UnfoldingOpts -> Int
unfoldingCreationThreshold :: !Int
, UnfoldingOpts -> Int
unfoldingUseThreshold :: !Int
, UnfoldingOpts -> Int
unfoldingFunAppDiscount :: !Int
, UnfoldingOpts -> Int
unfoldingDictDiscount :: !Int
, UnfoldingOpts -> Bool
unfoldingVeryAggressive :: !Bool
, UnfoldingOpts -> Int
unfoldingCaseThreshold :: !Int
, UnfoldingOpts -> Int
unfoldingCaseScaling :: !Int
, UnfoldingOpts -> Maybe String
unfoldingReportPrefix :: !(Maybe String)
}
defaultUnfoldingOpts :: UnfoldingOpts
defaultUnfoldingOpts :: UnfoldingOpts
defaultUnfoldingOpts = UnfoldingOpts
{ unfoldingCreationThreshold :: Int
unfoldingCreationThreshold = Int
750
, unfoldingUseThreshold :: Int
unfoldingUseThreshold = Int
90
, unfoldingFunAppDiscount :: Int
unfoldingFunAppDiscount = Int
60
, unfoldingDictDiscount :: Int
unfoldingDictDiscount = Int
30
, unfoldingVeryAggressive :: Bool
unfoldingVeryAggressive = Bool
False
, unfoldingCaseThreshold :: Int
unfoldingCaseThreshold = Int
2
, unfoldingCaseScaling :: Int
unfoldingCaseScaling = Int
30
, unfoldingReportPrefix :: Maybe String
unfoldingReportPrefix = Maybe String
forall a. Maybe a
Nothing
}
updateCreationThreshold :: Int -> UnfoldingOpts -> UnfoldingOpts
updateCreationThreshold :: Int -> UnfoldingOpts -> UnfoldingOpts
updateCreationThreshold Int
n UnfoldingOpts
opts = UnfoldingOpts
opts { unfoldingCreationThreshold = n }
updateUseThreshold :: Int -> UnfoldingOpts -> UnfoldingOpts
updateUseThreshold :: Int -> UnfoldingOpts -> UnfoldingOpts
updateUseThreshold Int
n UnfoldingOpts
opts = UnfoldingOpts
opts { unfoldingUseThreshold = n }
updateFunAppDiscount :: Int -> UnfoldingOpts -> UnfoldingOpts
updateFunAppDiscount :: Int -> UnfoldingOpts -> UnfoldingOpts
updateFunAppDiscount Int
n UnfoldingOpts
opts = UnfoldingOpts
opts { unfoldingFunAppDiscount = n }
updateDictDiscount :: Int -> UnfoldingOpts -> UnfoldingOpts
updateDictDiscount :: Int -> UnfoldingOpts -> UnfoldingOpts
updateDictDiscount Int
n UnfoldingOpts
opts = UnfoldingOpts
opts { unfoldingDictDiscount = n }
updateVeryAggressive :: Bool -> UnfoldingOpts -> UnfoldingOpts
updateVeryAggressive :: Bool -> UnfoldingOpts -> UnfoldingOpts
updateVeryAggressive Bool
n UnfoldingOpts
opts = UnfoldingOpts
opts { unfoldingVeryAggressive = n }
updateCaseThreshold :: Int -> UnfoldingOpts -> UnfoldingOpts
updateCaseThreshold :: Int -> UnfoldingOpts -> UnfoldingOpts
updateCaseThreshold Int
n UnfoldingOpts
opts = UnfoldingOpts
opts { unfoldingCaseThreshold = n }
updateCaseScaling :: Int -> UnfoldingOpts -> UnfoldingOpts
updateCaseScaling :: Int -> UnfoldingOpts -> UnfoldingOpts
updateCaseScaling Int
n UnfoldingOpts
opts = UnfoldingOpts
opts { unfoldingCaseScaling = n }
updateReportPrefix :: Maybe String -> UnfoldingOpts -> UnfoldingOpts
updateReportPrefix :: Maybe String -> UnfoldingOpts -> UnfoldingOpts
updateReportPrefix Maybe String
n UnfoldingOpts
opts = UnfoldingOpts
opts { unfoldingReportPrefix = n }
data ArgSummary = TrivArg
| NonTrivArg
| ValueArg
instance Outputable ArgSummary where
ppr :: ArgSummary -> SDoc
ppr ArgSummary
TrivArg = String -> SDoc
forall doc. IsLine doc => String -> doc
text String
"TrivArg"
ppr ArgSummary
NonTrivArg = String -> SDoc
forall doc. IsLine doc => String -> doc
text String
"NonTrivArg"
ppr ArgSummary
ValueArg = String -> SDoc
forall doc. IsLine doc => String -> doc
text String
"ValueArg"
nonTriv :: ArgSummary -> Bool
nonTriv :: ArgSummary -> Bool
nonTriv ArgSummary
TrivArg = Bool
False
nonTriv ArgSummary
_ = Bool
True
data CallCtxt
= BoringCtxt
| RhsCtxt RecFlag
| DiscArgCtxt
| RuleArgCtxt
| ValAppCtxt
| CaseCtxt
instance Outputable CallCtxt where
ppr :: CallCtxt -> SDoc
ppr CallCtxt
CaseCtxt = String -> SDoc
forall doc. IsLine doc => String -> doc
text String
"CaseCtxt"
ppr CallCtxt
ValAppCtxt = String -> SDoc
forall doc. IsLine doc => String -> doc
text String
"ValAppCtxt"
ppr CallCtxt
BoringCtxt = String -> SDoc
forall doc. IsLine doc => String -> doc
text String
"BoringCtxt"
ppr (RhsCtxt RecFlag
ir)= String -> SDoc
forall doc. IsLine doc => String -> doc
text String
"RhsCtxt" SDoc -> SDoc -> SDoc
forall doc. IsLine doc => doc -> doc -> doc
<> SDoc -> SDoc
forall doc. IsLine doc => doc -> doc
parens (RecFlag -> SDoc
forall a. Outputable a => a -> SDoc
ppr RecFlag
ir)
ppr CallCtxt
DiscArgCtxt = String -> SDoc
forall doc. IsLine doc => String -> doc
text String
"DiscArgCtxt"
ppr CallCtxt
RuleArgCtxt = String -> SDoc
forall doc. IsLine doc => String -> doc
text String
"RuleArgCtxt"
inlineBoringOk :: CoreExpr -> Bool
inlineBoringOk :: CoreExpr -> Bool
inlineBoringOk CoreExpr
e
= Int -> CoreExpr -> Bool
go Int
0 CoreExpr
e
where
go :: Int -> CoreExpr -> Bool
go :: Int -> CoreExpr -> Bool
go Int
credit (Lam Id
x CoreExpr
e) | Id -> Bool
isId Id
x = Int -> CoreExpr -> Bool
go (Int
creditInt -> Int -> Int
forall a. Num a => a -> a -> a
+Int
1) CoreExpr
e
| Bool
otherwise = Int -> CoreExpr -> Bool
go Int
credit CoreExpr
e
go Int
credit (App CoreExpr
f (Type {})) = Int -> CoreExpr -> Bool
go Int
credit CoreExpr
f
go Int
credit (App CoreExpr
f CoreExpr
a) | Int
credit Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
> Int
0
, CoreExpr -> Bool
exprIsTrivial CoreExpr
a = Int -> CoreExpr -> Bool
go (Int
creditInt -> Int -> Int
forall a. Num a => a -> a -> a
-Int
1) CoreExpr
f
go Int
credit (Tick CoreTickish
_ CoreExpr
e) = Int -> CoreExpr -> Bool
go Int
credit CoreExpr
e
go Int
credit (Cast CoreExpr
e CoercionR
_) = Int -> CoreExpr -> Bool
go Int
credit CoreExpr
e
go Int
credit (Case CoreExpr
scrut Id
_ Type
_ [Alt AltCon
_ [Id]
_ CoreExpr
rhs])
| CoreExpr -> Bool
isUnsafeEqualityProof CoreExpr
scrut = Int -> CoreExpr -> Bool
go Int
credit CoreExpr
rhs
go Int
_ (Var {}) = Bool
boringCxtOk
go Int
_ CoreExpr
_ = Bool
boringCxtNotOk
calcUnfoldingGuidance
:: UnfoldingOpts
-> Bool
-> CoreExpr
-> UnfoldingGuidance
calcUnfoldingGuidance :: UnfoldingOpts -> Bool -> CoreExpr -> UnfoldingGuidance
calcUnfoldingGuidance UnfoldingOpts
opts Bool
is_top_bottoming (Tick CoreTickish
t CoreExpr
expr)
| Bool -> Bool
not (CoreTickish -> Bool
forall (pass :: TickishPass). GenTickish pass -> Bool
tickishIsCode CoreTickish
t)
= UnfoldingOpts -> Bool -> CoreExpr -> UnfoldingGuidance
calcUnfoldingGuidance UnfoldingOpts
opts Bool
is_top_bottoming CoreExpr
expr
calcUnfoldingGuidance UnfoldingOpts
opts Bool
is_top_bottoming CoreExpr
expr
= case UnfoldingOpts -> Int -> [Id] -> CoreExpr -> ExprSize
sizeExpr UnfoldingOpts
opts Int
bOMB_OUT_SIZE [Id]
val_bndrs CoreExpr
body of
ExprSize
TooBig -> UnfoldingGuidance
UnfNever
SizeIs Int
size Bag (Id, Int)
cased_bndrs Int
scrut_discount
| CoreExpr -> Int -> Int -> Bool
uncondInline CoreExpr
expr Int
n_val_bndrs Int
size
-> 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 { 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, CoreExpr
body) = CoreExpr -> ([Id], CoreExpr)
forall b. Expr b -> ([b], Expr b)
collectBinders CoreExpr
expr
bOMB_OUT_SIZE :: Int
bOMB_OUT_SIZE = UnfoldingOpts -> Int
unfoldingCreationThreshold UnfoldingOpts
opts
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 a. [a] -> 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 b a. (b -> a -> b) -> b -> Bag a -> b
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 :: CoreExpr -> Int -> Int -> Bool
uncondInline CoreExpr
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 = CoreExpr -> Bool
exprIsTrivial CoreExpr
rhs
sizeExpr :: UnfoldingOpts
-> Int
-> [Id]
-> CoreExpr
-> ExprSize
sizeExpr :: UnfoldingOpts -> Int -> [Id] -> CoreExpr -> ExprSize
sizeExpr UnfoldingOpts
opts !Int
bOMB_OUT_SIZE [Id]
top_args CoreExpr
expr
= CoreExpr -> ExprSize
size_up CoreExpr
expr
where
size_up :: CoreExpr -> ExprSize
size_up (Cast CoreExpr
e CoercionR
_) = CoreExpr -> ExprSize
size_up CoreExpr
e
size_up (Tick CoreTickish
_ CoreExpr
e) = CoreExpr -> ExprSize
size_up CoreExpr
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
isZeroBitId Id
f = ExprSize
sizeZero
| Bool
otherwise = Id -> [CoreExpr] -> Int -> ExprSize
size_up_call Id
f [] Int
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] -> Int -> ExprSize
size_up_app CoreExpr
fun [CoreExpr
arg] (if CoreExpr -> Bool
forall b. Expr b -> Bool
isZeroBitExpr CoreExpr
arg then Int
1 else Int
0)
size_up (Lam Id
b CoreExpr
e)
| Id -> Bool
isId Id
b Bool -> Bool -> Bool
&& Bool -> Bool
not (Id -> Bool
isZeroBitId Id
b) = UnfoldingOpts -> ExprSize -> ExprSize
lamScrutDiscount UnfoldingOpts
opts (CoreExpr -> ExprSize
size_up CoreExpr
e ExprSize -> Int -> ExprSize
`addSizeN` Int
10)
| Bool
otherwise = CoreExpr -> ExprSize
size_up CoreExpr
e
size_up (Let (NonRec Id
binder CoreExpr
rhs) CoreExpr
body)
= (Id, CoreExpr) -> ExprSize
size_up_rhs (Id
binder, CoreExpr
rhs) ExprSize -> ExprSize -> ExprSize
`addSizeNSD`
CoreExpr -> ExprSize
size_up CoreExpr
body ExprSize -> Int -> ExprSize
`addSizeN`
Id -> Int
forall {a}. Num a => Id -> a
size_up_alloc Id
binder
size_up (Let (Rec [(Id, CoreExpr)]
pairs) CoreExpr
body)
= ((Id, CoreExpr) -> ExprSize -> ExprSize)
-> ExprSize -> [(Id, CoreExpr)] -> ExprSize
forall a b. (a -> b -> b) -> b -> [a] -> b
forall (t :: * -> *) a b.
Foldable t =>
(a -> b -> b) -> b -> t a -> b
foldr (ExprSize -> ExprSize -> ExprSize
addSizeNSD (ExprSize -> ExprSize -> ExprSize)
-> ((Id, CoreExpr) -> ExprSize)
-> (Id, CoreExpr)
-> ExprSize
-> ExprSize
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Id, CoreExpr) -> ExprSize
size_up_rhs)
(CoreExpr -> ExprSize
size_up CoreExpr
body ExprSize -> Int -> ExprSize
`addSizeN` [Int] -> Int
forall a. Num a => [a] -> a
forall (t :: * -> *) a. (Foldable t, Num a) => t a -> a
sum (((Id, CoreExpr) -> Int) -> [(Id, CoreExpr)] -> [Int]
forall a b. (a -> b) -> [a] -> [b]
map (Id -> Int
forall {a}. Num a => Id -> a
size_up_alloc (Id -> Int) -> ((Id, CoreExpr) -> Id) -> (Id, CoreExpr) -> Int
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Id, CoreExpr) -> Id
forall a b. (a, b) -> a
fst) [(Id, CoreExpr)]
pairs))
[(Id, CoreExpr)]
pairs
size_up (Case CoreExpr
e Id
_ Type
_ [Alt Id]
alts)
| [Alt Id] -> Bool
forall a. [a] -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null [Alt Id]
alts
= CoreExpr -> ExprSize
size_up CoreExpr
e
size_up (Case CoreExpr
e Id
_ Type
_ [Alt Id]
alts)
| Just Id
v <- CoreExpr -> Maybe Id
is_top_arg CoreExpr
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 a. (a -> a -> a) -> [a] -> a
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 a. (a -> a -> a) -> [a] -> a
forall (t :: * -> *) a. Foldable t => (a -> a -> a) -> t a -> a
foldr1 ExprSize -> ExprSize -> ExprSize
maxSize [ExprSize]
alt_sizes)
where
is_top_arg :: CoreExpr -> Maybe Id
is_top_arg (Var Id
v) | Id
v Id -> [Id] -> Bool
forall a. Eq a => a -> [a] -> 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 CoreExpr
e CoercionR
_) = CoreExpr -> Maybe Id
is_top_arg CoreExpr
e
is_top_arg CoreExpr
_ = Maybe Id
forall a. Maybe a
Nothing
size_up (Case CoreExpr
e Id
_ Type
_ [Alt Id]
alts) = CoreExpr -> ExprSize
size_up CoreExpr
e ExprSize -> ExprSize -> ExprSize
`addSizeNSD`
(Alt Id -> ExprSize -> ExprSize)
-> ExprSize -> [Alt Id] -> ExprSize
forall a b. (a -> b -> b) -> b -> [a] -> b
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
| CoreExpr -> Bool
forall b. Expr b -> Bool
is_inline_scrut CoreExpr
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 -> Bool
not (PrimOp -> Bool
primOpOutOfLine PrimOp
op)
IdDetails
_other -> Bool
False
| Bool
otherwise
= Bool
False
size_up_rhs :: (Id, CoreExpr) -> ExprSize
size_up_rhs (Id
bndr, CoreExpr
rhs)
| Just Int
join_arity <- Id -> Maybe Int
isJoinId_maybe Id
bndr
, ([Id]
_bndrs, CoreExpr
body) <- Int -> CoreExpr -> ([Id], CoreExpr)
forall b. Int -> Expr b -> ([b], Expr b)
collectNBinders Int
join_arity CoreExpr
rhs
= CoreExpr -> ExprSize
size_up CoreExpr
body
| Bool
otherwise
= CoreExpr -> ExprSize
size_up CoreExpr
rhs
size_up_app :: CoreExpr -> [CoreExpr] -> Int -> ExprSize
size_up_app (App CoreExpr
fun CoreExpr
arg) [CoreExpr]
args Int
voids
| CoreExpr -> Bool
forall b. Expr b -> Bool
isTyCoArg CoreExpr
arg = CoreExpr -> [CoreExpr] -> Int -> ExprSize
size_up_app CoreExpr
fun [CoreExpr]
args Int
voids
| CoreExpr -> Bool
forall b. Expr b -> Bool
isZeroBitExpr CoreExpr
arg = CoreExpr -> [CoreExpr] -> Int -> ExprSize
size_up_app CoreExpr
fun (CoreExpr
argCoreExpr -> [CoreExpr] -> [CoreExpr]
forall a. a -> [a] -> [a]
:[CoreExpr]
args) (Int
voids Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
1)
| Bool
otherwise = CoreExpr -> ExprSize
size_up CoreExpr
arg ExprSize -> ExprSize -> ExprSize
`addSizeNSD`
CoreExpr -> [CoreExpr] -> Int -> ExprSize
size_up_app CoreExpr
fun (CoreExpr
argCoreExpr -> [CoreExpr] -> [CoreExpr]
forall a. a -> [a] -> [a]
:[CoreExpr]
args) Int
voids
size_up_app (Var Id
fun) [CoreExpr]
args Int
voids = Id -> [CoreExpr] -> Int -> ExprSize
size_up_call Id
fun [CoreExpr]
args Int
voids
size_up_app (Tick CoreTickish
_ CoreExpr
expr) [CoreExpr]
args Int
voids = CoreExpr -> [CoreExpr] -> Int -> ExprSize
size_up_app CoreExpr
expr [CoreExpr]
args Int
voids
size_up_app (Cast CoreExpr
expr CoercionR
_) [CoreExpr]
args Int
voids = CoreExpr -> [CoreExpr] -> Int -> ExprSize
size_up_app CoreExpr
expr [CoreExpr]
args Int
voids
size_up_app CoreExpr
other [CoreExpr]
args Int
voids = CoreExpr -> ExprSize
size_up CoreExpr
other ExprSize -> Int -> ExprSize
`addSizeN`
Int -> Int -> Int
callSize ([CoreExpr] -> Int
forall a. [a] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [CoreExpr]
args) Int
voids
size_up_call :: Id -> [CoreExpr] -> Int -> ExprSize
size_up_call :: Id -> [CoreExpr] -> Int -> ExprSize
size_up_call Id
fun [CoreExpr]
val_args Int
voids
= case Id -> IdDetails
idDetails Id
fun of
FCallId ForeignCall
_ -> Int -> ExprSize
sizeN (Int -> Int -> Int
callSize ([CoreExpr] -> Int
forall a. [a] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [CoreExpr]
val_args) Int
voids)
DataConWorkId DataCon
dc -> DataCon -> Int -> ExprSize
conSize DataCon
dc ([CoreExpr] -> Int
forall a. [a] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [CoreExpr]
val_args)
PrimOpId PrimOp
op Bool
_ -> PrimOp -> Int -> ExprSize
primOpSize PrimOp
op ([CoreExpr] -> Int
forall a. [a] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [CoreExpr]
val_args)
ClassOpId {} -> UnfoldingOpts -> [Id] -> [CoreExpr] -> ExprSize
classOpSize UnfoldingOpts
opts [Id]
top_args [CoreExpr]
val_args
IdDetails
_ -> UnfoldingOpts -> [Id] -> Id -> Int -> Int -> ExprSize
funSize UnfoldingOpts
opts [Id]
top_args Id
fun ([CoreExpr] -> Int
forall a. [a] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [CoreExpr]
val_args) Int
voids
size_up_alt :: Alt Id -> ExprSize
size_up_alt (Alt AltCon
_con [Id]
_bndrs CoreExpr
rhs) = CoreExpr -> ExprSize
size_up CoreExpr
rhs ExprSize -> Int -> ExprSize
`addSizeN` Int
10
size_up_alloc :: Id -> a
size_up_alloc Id
bndr
| Id -> Bool
isTyVar Id
bndr
Bool -> Bool -> Bool
|| Id -> Bool
isJoinId Id
bndr
Bool -> Bool -> Bool
|| Bool -> Bool
not (Type -> Bool
isBoxedType (Id -> Type
idType Id
bndr))
= a
0
| Bool
otherwise
= a
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
isZeroBitId :: Id -> Bool
isZeroBitId Id
id = Bool -> Bool
not (Id -> Bool
isJoinId Id
id) Bool -> Bool -> Bool
&& HasDebugCallStack => Type -> Bool
Type -> Bool
isZeroBitTy (Id -> Type
idType Id
id)
isZeroBitExpr :: Expr b -> Bool
isZeroBitExpr (Var Id
id) = Id -> Bool
isZeroBitId Id
id
isZeroBitExpr (Tick CoreTickish
_ Expr b
e) = Expr b -> Bool
isZeroBitExpr Expr b
e
isZeroBitExpr Expr b
_ = Bool
False
litSize :: Literal -> Int
litSize :: Literal -> Int
litSize (LitNumber LitNumType
LitNumBigNat 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 :: UnfoldingOpts -> [Id] -> [CoreExpr] -> ExprSize
classOpSize :: UnfoldingOpts -> [Id] -> [CoreExpr] -> ExprSize
classOpSize UnfoldingOpts
_ [Id]
_ []
= ExprSize
sizeZero
classOpSize UnfoldingOpts
opts [Id]
top_args (CoreExpr
arg1 : [CoreExpr]
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
* [CoreExpr] -> Int
forall a. [a] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [CoreExpr]
other_args)
arg_discount :: Bag (Id, Int)
arg_discount = case CoreExpr
arg1 of
Var Id
dict | Id
dict Id -> [Id] -> Bool
forall a. Eq a => a -> [a] -> 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, UnfoldingOpts -> Int
unfoldingDictDiscount UnfoldingOpts
opts)
CoreExpr
_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 :: UnfoldingOpts -> [Id] -> Id -> Int -> Int -> ExprSize
funSize :: UnfoldingOpts -> [Id] -> Id -> Int -> Int -> ExprSize
funSize UnfoldingOpts
opts [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 a. Eq a => a -> [a] -> 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, UnfoldingOpts -> Int
unfoldingFunAppDiscount UnfoldingOpts
opts)
| 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 = UnfoldingOpts -> Int
unfoldingFunAppDiscount UnfoldingOpts
opts
| 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
isUnboxedTupleDataCon 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 :: UnfoldingOpts -> ExprSize -> ExprSize
lamScrutDiscount :: UnfoldingOpts -> ExprSize -> ExprSize
lamScrutDiscount UnfoldingOpts
opts (SizeIs Int
n Bag (Id, Int)
vs Int
_) = Int -> Bag (Id, Int) -> Int -> ExprSize
SizeIs Int
n Bag (Id, Int)
vs (UnfoldingOpts -> Int
unfoldingFunAppDiscount UnfoldingOpts
opts)
lamScrutDiscount UnfoldingOpts
_ 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
forall doc. IsLine doc => String -> doc
text String
"TooBig"
ppr (SizeIs Int
a Bag (Id, Int)
_ Int
c) = SDoc -> SDoc
forall doc. IsLine doc => doc -> doc
brackets (Int -> SDoc
forall doc. IsLine doc => Int -> doc
int Int
a SDoc -> SDoc -> SDoc
forall doc. IsLine doc => doc -> doc -> doc
<+> Int -> SDoc
forall doc. IsLine doc => Int -> doc
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