module CallArity
( callArityAnalProgram
, callArityRHS
) where
import GhcPrelude
import VarSet
import VarEnv
import DynFlags ( DynFlags )
import BasicTypes
import CoreSyn
import Id
import CoreArity ( typeArity )
import CoreUtils ( exprIsCheap, exprIsTrivial )
import UnVarGraph
import Demand
import Util
import Control.Arrow ( first, second )
callArityAnalProgram :: DynFlags -> CoreProgram -> CoreProgram
callArityAnalProgram :: DynFlags -> CoreProgram -> CoreProgram
callArityAnalProgram _dflags :: DynFlags
_dflags binds :: CoreProgram
binds = CoreProgram
binds'
where
(_, binds' :: CoreProgram
binds') = [Var] -> VarSet -> CoreProgram -> (CallArityRes, CoreProgram)
callArityTopLvl [] VarSet
emptyVarSet CoreProgram
binds
callArityTopLvl :: [Var] -> VarSet -> [CoreBind] -> (CallArityRes, [CoreBind])
callArityTopLvl :: [Var] -> VarSet -> CoreProgram -> (CallArityRes, CoreProgram)
callArityTopLvl exported :: [Var]
exported _ []
= ( CallArityRes -> CallArityRes
calledMultipleTimes (CallArityRes -> CallArityRes) -> CallArityRes -> CallArityRes
forall a b. (a -> b) -> a -> b
$ (UnVarGraph
emptyUnVarGraph, [(Var, Arity)] -> VarEnv Arity
forall a. [(Var, a)] -> VarEnv a
mkVarEnv ([(Var, Arity)] -> VarEnv Arity) -> [(Var, Arity)] -> VarEnv Arity
forall a b. (a -> b) -> a -> b
$ [(Var
v, 0) | Var
v <- [Var]
exported])
, [] )
callArityTopLvl exported :: [Var]
exported int1 :: VarSet
int1 (b :: CoreBind
b:bs :: CoreProgram
bs)
= (CallArityRes
ae2, CoreBind
b'CoreBind -> CoreProgram -> CoreProgram
forall a. a -> [a] -> [a]
:CoreProgram
bs')
where
int2 :: [Var]
int2 = CoreBind -> [Var]
forall b. Bind b -> [b]
bindersOf CoreBind
b
exported' :: [Var]
exported' = (Var -> Bool) -> [Var] -> [Var]
forall a. (a -> Bool) -> [a] -> [a]
filter Var -> Bool
isExportedId [Var]
int2 [Var] -> [Var] -> [Var]
forall a. [a] -> [a] -> [a]
++ [Var]
exported
int' :: VarSet
int' = VarSet
int1 VarSet -> CoreBind -> VarSet
`addInterestingBinds` CoreBind
b
(ae1 :: CallArityRes
ae1, bs' :: CoreProgram
bs') = [Var] -> VarSet -> CoreProgram -> (CallArityRes, CoreProgram)
callArityTopLvl [Var]
exported' VarSet
int' CoreProgram
bs
(ae2 :: CallArityRes
ae2, b' :: CoreBind
b') = VarSet
-> CallArityRes -> VarSet -> CoreBind -> (CallArityRes, CoreBind)
callArityBind (CoreBind -> VarSet
boringBinds CoreBind
b) CallArityRes
ae1 VarSet
int1 CoreBind
b
callArityRHS :: CoreExpr -> CoreExpr
callArityRHS :: CoreExpr -> CoreExpr
callArityRHS = (CallArityRes, CoreExpr) -> CoreExpr
forall a b. (a, b) -> b
snd ((CallArityRes, CoreExpr) -> CoreExpr)
-> (CoreExpr -> (CallArityRes, CoreExpr)) -> CoreExpr -> CoreExpr
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Arity -> VarSet -> CoreExpr -> (CallArityRes, CoreExpr)
callArityAnal 0 VarSet
emptyVarSet
callArityAnal ::
Arity ->
VarSet ->
CoreExpr ->
(CallArityRes, CoreExpr)
callArityAnal :: Arity -> VarSet -> CoreExpr -> (CallArityRes, CoreExpr)
callArityAnal _ _ e :: CoreExpr
e@(Lit _)
= (CallArityRes
emptyArityRes, CoreExpr
e)
callArityAnal _ _ e :: CoreExpr
e@(Type _)
= (CallArityRes
emptyArityRes, CoreExpr
e)
callArityAnal _ _ e :: CoreExpr
e@(Coercion _)
= (CallArityRes
emptyArityRes, CoreExpr
e)
callArityAnal arity :: Arity
arity int :: VarSet
int (Tick t :: Tickish Var
t e :: CoreExpr
e)
= (CoreExpr -> CoreExpr)
-> (CallArityRes, CoreExpr) -> (CallArityRes, CoreExpr)
forall (a :: * -> * -> *) b c d.
Arrow a =>
a b c -> a (d, b) (d, c)
second (Tickish Var -> CoreExpr -> CoreExpr
forall b. Tickish Var -> Expr b -> Expr b
Tick Tickish Var
t) ((CallArityRes, CoreExpr) -> (CallArityRes, CoreExpr))
-> (CallArityRes, CoreExpr) -> (CallArityRes, CoreExpr)
forall a b. (a -> b) -> a -> b
$ Arity -> VarSet -> CoreExpr -> (CallArityRes, CoreExpr)
callArityAnal Arity
arity VarSet
int CoreExpr
e
callArityAnal arity :: Arity
arity int :: VarSet
int (Cast e :: CoreExpr
e co :: Coercion
co)
= (CoreExpr -> CoreExpr)
-> (CallArityRes, CoreExpr) -> (CallArityRes, CoreExpr)
forall (a :: * -> * -> *) b c d.
Arrow a =>
a b c -> a (d, b) (d, c)
second (\e :: CoreExpr
e -> CoreExpr -> Coercion -> CoreExpr
forall b. Expr b -> Coercion -> Expr b
Cast CoreExpr
e Coercion
co) ((CallArityRes, CoreExpr) -> (CallArityRes, CoreExpr))
-> (CallArityRes, CoreExpr) -> (CallArityRes, CoreExpr)
forall a b. (a -> b) -> a -> b
$ Arity -> VarSet -> CoreExpr -> (CallArityRes, CoreExpr)
callArityAnal Arity
arity VarSet
int CoreExpr
e
callArityAnal arity :: Arity
arity int :: VarSet
int e :: CoreExpr
e@(Var v :: Var
v)
| Var
v Var -> VarSet -> Bool
`elemVarSet` VarSet
int
= (Var -> Arity -> CallArityRes
unitArityRes Var
v Arity
arity, CoreExpr
e)
| Bool
otherwise
= (CallArityRes
emptyArityRes, CoreExpr
e)
callArityAnal arity :: Arity
arity int :: VarSet
int (Lam v :: Var
v e :: CoreExpr
e) | Bool -> Bool
not (Var -> Bool
isId Var
v)
= (CoreExpr -> CoreExpr)
-> (CallArityRes, CoreExpr) -> (CallArityRes, CoreExpr)
forall (a :: * -> * -> *) b c d.
Arrow a =>
a b c -> a (d, b) (d, c)
second (Var -> CoreExpr -> CoreExpr
forall b. b -> Expr b -> Expr b
Lam Var
v) ((CallArityRes, CoreExpr) -> (CallArityRes, CoreExpr))
-> (CallArityRes, CoreExpr) -> (CallArityRes, CoreExpr)
forall a b. (a -> b) -> a -> b
$ Arity -> VarSet -> CoreExpr -> (CallArityRes, CoreExpr)
callArityAnal Arity
arity (VarSet
int VarSet -> Var -> VarSet
`delVarSet` Var
v) CoreExpr
e
callArityAnal 0 int :: VarSet
int (Lam v :: Var
v e :: CoreExpr
e)
= (CallArityRes
ae', Var -> CoreExpr -> CoreExpr
forall b. b -> Expr b -> Expr b
Lam Var
v CoreExpr
e')
where
(ae :: CallArityRes
ae, e' :: CoreExpr
e') = Arity -> VarSet -> CoreExpr -> (CallArityRes, CoreExpr)
callArityAnal 0 (VarSet
int VarSet -> Var -> VarSet
`delVarSet` Var
v) CoreExpr
e
ae' :: CallArityRes
ae' = CallArityRes -> CallArityRes
calledMultipleTimes CallArityRes
ae
callArityAnal arity :: Arity
arity int :: VarSet
int (Lam v :: Var
v e :: CoreExpr
e)
= (CallArityRes
ae, Var -> CoreExpr -> CoreExpr
forall b. b -> Expr b -> Expr b
Lam Var
v CoreExpr
e')
where
(ae :: CallArityRes
ae, e' :: CoreExpr
e') = Arity -> VarSet -> CoreExpr -> (CallArityRes, CoreExpr)
callArityAnal (Arity
arity Arity -> Arity -> Arity
forall a. Num a => a -> a -> a
- 1) (VarSet
int VarSet -> Var -> VarSet
`delVarSet` Var
v) CoreExpr
e
callArityAnal arity :: Arity
arity int :: VarSet
int (App e :: CoreExpr
e (Type t :: Type
t))
= (CoreExpr -> CoreExpr)
-> (CallArityRes, CoreExpr) -> (CallArityRes, CoreExpr)
forall (a :: * -> * -> *) b c d.
Arrow a =>
a b c -> a (d, b) (d, c)
second (\e :: CoreExpr
e -> CoreExpr -> CoreExpr -> CoreExpr
forall b. Expr b -> Expr b -> Expr b
App CoreExpr
e (Type -> CoreExpr
forall b. Type -> Expr b
Type Type
t)) ((CallArityRes, CoreExpr) -> (CallArityRes, CoreExpr))
-> (CallArityRes, CoreExpr) -> (CallArityRes, CoreExpr)
forall a b. (a -> b) -> a -> b
$ Arity -> VarSet -> CoreExpr -> (CallArityRes, CoreExpr)
callArityAnal Arity
arity VarSet
int CoreExpr
e
callArityAnal arity :: Arity
arity int :: VarSet
int (App e1 :: CoreExpr
e1 e2 :: CoreExpr
e2)
= (CallArityRes
final_ae, CoreExpr -> CoreExpr -> CoreExpr
forall b. Expr b -> Expr b -> Expr b
App CoreExpr
e1' CoreExpr
e2')
where
(ae1 :: CallArityRes
ae1, e1' :: CoreExpr
e1') = Arity -> VarSet -> CoreExpr -> (CallArityRes, CoreExpr)
callArityAnal (Arity
arity Arity -> Arity -> Arity
forall a. Num a => a -> a -> a
+ 1) VarSet
int CoreExpr
e1
(ae2 :: CallArityRes
ae2, e2' :: CoreExpr
e2') = Arity -> VarSet -> CoreExpr -> (CallArityRes, CoreExpr)
callArityAnal 0 VarSet
int CoreExpr
e2
ae2' :: CallArityRes
ae2' | CoreExpr -> Bool
exprIsTrivial CoreExpr
e2 = CallArityRes -> CallArityRes
calledMultipleTimes CallArityRes
ae2
| Bool
otherwise = CallArityRes
ae2
final_ae :: CallArityRes
final_ae = CallArityRes
ae1 CallArityRes -> CallArityRes -> CallArityRes
`both` CallArityRes
ae2'
callArityAnal arity :: Arity
arity int :: VarSet
int (Case scrut :: CoreExpr
scrut bndr :: Var
bndr ty :: Type
ty alts :: [Alt Var]
alts)
=
(CallArityRes
final_ae, CoreExpr -> Var -> Type -> [Alt Var] -> CoreExpr
forall b. Expr b -> b -> Type -> [Alt b] -> Expr b
Case CoreExpr
scrut' Var
bndr Type
ty [Alt Var]
alts')
where
(alt_aes :: [CallArityRes]
alt_aes, alts' :: [Alt Var]
alts') = [(CallArityRes, Alt Var)] -> ([CallArityRes], [Alt Var])
forall a b. [(a, b)] -> ([a], [b])
unzip ([(CallArityRes, Alt Var)] -> ([CallArityRes], [Alt Var]))
-> [(CallArityRes, Alt Var)] -> ([CallArityRes], [Alt Var])
forall a b. (a -> b) -> a -> b
$ (Alt Var -> (CallArityRes, Alt Var))
-> [Alt Var] -> [(CallArityRes, Alt Var)]
forall a b. (a -> b) -> [a] -> [b]
map Alt Var -> (CallArityRes, Alt Var)
forall a b. (a, b, CoreExpr) -> (CallArityRes, (a, b, CoreExpr))
go [Alt Var]
alts
go :: (a, b, CoreExpr) -> (CallArityRes, (a, b, CoreExpr))
go (dc :: a
dc, bndrs :: b
bndrs, e :: CoreExpr
e) = let (ae :: CallArityRes
ae, e' :: CoreExpr
e') = Arity -> VarSet -> CoreExpr -> (CallArityRes, CoreExpr)
callArityAnal Arity
arity VarSet
int CoreExpr
e
in (CallArityRes
ae, (a
dc, b
bndrs, CoreExpr
e'))
alt_ae :: CallArityRes
alt_ae = [CallArityRes] -> CallArityRes
lubRess [CallArityRes]
alt_aes
(scrut_ae :: CallArityRes
scrut_ae, scrut' :: CoreExpr
scrut') = Arity -> VarSet -> CoreExpr -> (CallArityRes, CoreExpr)
callArityAnal 0 VarSet
int CoreExpr
scrut
final_ae :: CallArityRes
final_ae = CallArityRes
scrut_ae CallArityRes -> CallArityRes -> CallArityRes
`both` CallArityRes
alt_ae
callArityAnal arity :: Arity
arity int :: VarSet
int (Let bind :: CoreBind
bind e :: CoreExpr
e)
=
(CallArityRes
final_ae, CoreBind -> CoreExpr -> CoreExpr
forall b. Bind b -> Expr b -> Expr b
Let CoreBind
bind' CoreExpr
e')
where
int_body :: VarSet
int_body = VarSet
int VarSet -> CoreBind -> VarSet
`addInterestingBinds` CoreBind
bind
(ae_body :: CallArityRes
ae_body, e' :: CoreExpr
e') = Arity -> VarSet -> CoreExpr -> (CallArityRes, CoreExpr)
callArityAnal Arity
arity VarSet
int_body CoreExpr
e
(final_ae :: CallArityRes
final_ae, bind' :: CoreBind
bind') = VarSet
-> CallArityRes -> VarSet -> CoreBind -> (CallArityRes, CoreBind)
callArityBind (CoreBind -> VarSet
boringBinds CoreBind
bind) CallArityRes
ae_body VarSet
int CoreBind
bind
isInteresting :: Var -> Bool
isInteresting :: Var -> Bool
isInteresting v :: Var
v = Bool -> Bool
not (Bool -> Bool) -> Bool -> Bool
forall a b. (a -> b) -> a -> b
$ [OneShotInfo] -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null (Type -> [OneShotInfo]
typeArity (Var -> Type
idType Var
v))
interestingBinds :: CoreBind -> [Var]
interestingBinds :: CoreBind -> [Var]
interestingBinds = (Var -> Bool) -> [Var] -> [Var]
forall a. (a -> Bool) -> [a] -> [a]
filter Var -> Bool
isInteresting ([Var] -> [Var]) -> (CoreBind -> [Var]) -> CoreBind -> [Var]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. CoreBind -> [Var]
forall b. Bind b -> [b]
bindersOf
boringBinds :: CoreBind -> VarSet
boringBinds :: CoreBind -> VarSet
boringBinds = [Var] -> VarSet
mkVarSet ([Var] -> VarSet) -> (CoreBind -> [Var]) -> CoreBind -> VarSet
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Var -> Bool) -> [Var] -> [Var]
forall a. (a -> Bool) -> [a] -> [a]
filter (Bool -> Bool
not (Bool -> Bool) -> (Var -> Bool) -> Var -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Var -> Bool
isInteresting) ([Var] -> [Var]) -> (CoreBind -> [Var]) -> CoreBind -> [Var]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. CoreBind -> [Var]
forall b. Bind b -> [b]
bindersOf
addInterestingBinds :: VarSet -> CoreBind -> VarSet
addInterestingBinds :: VarSet -> CoreBind -> VarSet
addInterestingBinds int :: VarSet
int bind :: CoreBind
bind
= VarSet
int VarSet -> [Var] -> VarSet
`delVarSetList` CoreBind -> [Var]
forall b. Bind b -> [b]
bindersOf CoreBind
bind
VarSet -> [Var] -> VarSet
`extendVarSetList` CoreBind -> [Var]
interestingBinds CoreBind
bind
callArityBind :: VarSet -> CallArityRes -> VarSet -> CoreBind -> (CallArityRes, CoreBind)
callArityBind :: VarSet
-> CallArityRes -> VarSet -> CoreBind -> (CallArityRes, CoreBind)
callArityBind boring_vars :: VarSet
boring_vars ae_body :: CallArityRes
ae_body int :: VarSet
int (NonRec v :: Var
v rhs :: CoreExpr
rhs)
| Bool
otherwise
=
(CallArityRes
final_ae, Var -> CoreExpr -> CoreBind
forall b. b -> Expr b -> Bind b
NonRec Var
v' CoreExpr
rhs')
where
is_thunk :: Bool
is_thunk = Bool -> Bool
not (CoreExpr -> Bool
exprIsCheap CoreExpr
rhs)
boring :: Bool
boring = Var
v Var -> VarSet -> Bool
`elemVarSet` VarSet
boring_vars
(arity :: Arity
arity, called_once :: Bool
called_once)
| Bool
boring = (0, Bool
False)
| Bool
otherwise = CallArityRes -> Var -> (Arity, Bool)
lookupCallArityRes CallArityRes
ae_body Var
v
safe_arity :: Arity
safe_arity | Bool
called_once = Arity
arity
| Bool
is_thunk = 0
| Bool
otherwise = Arity
arity
trimmed_arity :: Arity
trimmed_arity = Var -> Arity -> Arity
trimArity Var
v Arity
safe_arity
(ae_rhs :: CallArityRes
ae_rhs, rhs' :: CoreExpr
rhs') = Arity -> VarSet -> CoreExpr -> (CallArityRes, CoreExpr)
callArityAnal Arity
trimmed_arity VarSet
int CoreExpr
rhs
ae_rhs' :: CallArityRes
ae_rhs'| Bool
called_once = CallArityRes
ae_rhs
| Arity
safe_arity Arity -> Arity -> Bool
forall a. Eq a => a -> a -> Bool
== 0 = CallArityRes
ae_rhs
| Bool
otherwise = CallArityRes -> CallArityRes
calledMultipleTimes CallArityRes
ae_rhs
called_by_v :: UnVarSet
called_by_v = CallArityRes -> UnVarSet
domRes CallArityRes
ae_rhs'
called_with_v :: UnVarSet
called_with_v
| Bool
boring = CallArityRes -> UnVarSet
domRes CallArityRes
ae_body
| Bool
otherwise = CallArityRes -> Var -> UnVarSet
calledWith CallArityRes
ae_body Var
v UnVarSet -> Var -> UnVarSet
`delUnVarSet` Var
v
final_ae :: CallArityRes
final_ae = UnVarSet -> UnVarSet -> CallArityRes -> CallArityRes
addCrossCoCalls UnVarSet
called_by_v UnVarSet
called_with_v (CallArityRes -> CallArityRes) -> CallArityRes -> CallArityRes
forall a b. (a -> b) -> a -> b
$ CallArityRes
ae_rhs' CallArityRes -> CallArityRes -> CallArityRes
`lubRes` Var -> CallArityRes -> CallArityRes
resDel Var
v CallArityRes
ae_body
v' :: Var
v' = Var
v Var -> Arity -> Var
`setIdCallArity` Arity
trimmed_arity
callArityBind boring_vars :: VarSet
boring_vars ae_body :: CallArityRes
ae_body int :: VarSet
int b :: CoreBind
b@(Rec binds :: [(Var, CoreExpr)]
binds)
=
(CallArityRes
final_ae, [(Var, CoreExpr)] -> CoreBind
forall b. [(b, Expr b)] -> Bind b
Rec [(Var, CoreExpr)]
binds')
where
any_boring :: Bool
any_boring = (Var -> Bool) -> [Var] -> Bool
forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
any (Var -> VarSet -> Bool
`elemVarSet` VarSet
boring_vars) [ Var
i | (i :: Var
i, _) <- [(Var, CoreExpr)]
binds]
int_body :: VarSet
int_body = VarSet
int VarSet -> CoreBind -> VarSet
`addInterestingBinds` CoreBind
b
(ae_rhs :: CallArityRes
ae_rhs, binds' :: [(Var, CoreExpr)]
binds') = [(Var, Maybe (Bool, Arity, CallArityRes), CoreExpr)]
-> (CallArityRes, [(Var, CoreExpr)])
fix [(Var, Maybe (Bool, Arity, CallArityRes), CoreExpr)]
forall a. [(Var, Maybe a, CoreExpr)]
initial_binds
final_ae :: CallArityRes
final_ae = CoreBind -> [Var]
forall b. Bind b -> [b]
bindersOf CoreBind
b [Var] -> CallArityRes -> CallArityRes
`resDelList` CallArityRes
ae_rhs
initial_binds :: [(Var, Maybe a, CoreExpr)]
initial_binds = [(Var
i,Maybe a
forall a. Maybe a
Nothing,CoreExpr
e) | (i :: Var
i,e :: CoreExpr
e) <- [(Var, CoreExpr)]
binds]
fix :: [(Id, Maybe (Bool, Arity, CallArityRes), CoreExpr)] -> (CallArityRes, [(Id, CoreExpr)])
fix :: [(Var, Maybe (Bool, Arity, CallArityRes), CoreExpr)]
-> (CallArityRes, [(Var, CoreExpr)])
fix ann_binds :: [(Var, Maybe (Bool, Arity, CallArityRes), CoreExpr)]
ann_binds
|
Bool
any_change
= [(Var, Maybe (Bool, Arity, CallArityRes), CoreExpr)]
-> (CallArityRes, [(Var, CoreExpr)])
fix [(Var, Maybe (Bool, Arity, CallArityRes), CoreExpr)]
ann_binds'
| Bool
otherwise
= (CallArityRes
ae, ((Var, Maybe (Bool, Arity, CallArityRes), CoreExpr)
-> (Var, CoreExpr))
-> [(Var, Maybe (Bool, Arity, CallArityRes), CoreExpr)]
-> [(Var, CoreExpr)]
forall a b. (a -> b) -> [a] -> [b]
map (\(i :: Var
i, _, e :: CoreExpr
e) -> (Var
i, CoreExpr
e)) [(Var, Maybe (Bool, Arity, CallArityRes), CoreExpr)]
ann_binds')
where
aes_old :: [(Var, CallArityRes)]
aes_old = [ (Var
i,CallArityRes
ae) | (i :: Var
i, Just (_,_,ae :: CallArityRes
ae), _) <- [(Var, Maybe (Bool, Arity, CallArityRes), CoreExpr)]
ann_binds ]
ae :: CallArityRes
ae = Bool -> [(Var, CallArityRes)] -> CallArityRes -> CallArityRes
callArityRecEnv Bool
any_boring [(Var, CallArityRes)]
aes_old CallArityRes
ae_body
rerun :: (Var, Maybe (Bool, Arity, CallArityRes), CoreExpr)
-> (Bool, (Var, Maybe (Bool, Arity, CallArityRes), CoreExpr))
rerun (i :: Var
i, mbLastRun :: Maybe (Bool, Arity, CallArityRes)
mbLastRun, rhs :: CoreExpr
rhs)
| Var
i Var -> VarSet -> Bool
`elemVarSet` VarSet
int_body Bool -> Bool -> Bool
&& Bool -> Bool
not (Var
i Var -> UnVarSet -> Bool
`elemUnVarSet` CallArityRes -> UnVarSet
domRes CallArityRes
ae)
= (Bool
False, (Var
i, Maybe (Bool, Arity, CallArityRes)
forall a. Maybe a
Nothing, CoreExpr
rhs))
| Just (old_called_once :: Bool
old_called_once, old_arity :: Arity
old_arity, _) <- Maybe (Bool, Arity, CallArityRes)
mbLastRun
, Bool
called_once Bool -> Bool -> Bool
forall a. Eq a => a -> a -> Bool
== Bool
old_called_once
, Arity
new_arity Arity -> Arity -> Bool
forall a. Eq a => a -> a -> Bool
== Arity
old_arity
= (Bool
False, (Var
i, Maybe (Bool, Arity, CallArityRes)
mbLastRun, CoreExpr
rhs))
| Bool
otherwise
= let is_thunk :: Bool
is_thunk = Bool -> Bool
not (CoreExpr -> Bool
exprIsCheap CoreExpr
rhs)
safe_arity :: Arity
safe_arity | Bool
is_thunk = 0
| Bool
otherwise = Arity
new_arity
trimmed_arity :: Arity
trimmed_arity = Var -> Arity -> Arity
trimArity Var
i Arity
safe_arity
(ae_rhs :: CallArityRes
ae_rhs, rhs' :: CoreExpr
rhs') = Arity -> VarSet -> CoreExpr -> (CallArityRes, CoreExpr)
callArityAnal Arity
trimmed_arity VarSet
int_body CoreExpr
rhs
ae_rhs' :: CallArityRes
ae_rhs' | Bool
called_once = CallArityRes
ae_rhs
| Arity
safe_arity Arity -> Arity -> Bool
forall a. Eq a => a -> a -> Bool
== 0 = CallArityRes
ae_rhs
| Bool
otherwise = CallArityRes -> CallArityRes
calledMultipleTimes CallArityRes
ae_rhs
i' :: Var
i' = Var
i Var -> Arity -> Var
`setIdCallArity` Arity
trimmed_arity
in (Bool
True, (Var
i', (Bool, Arity, CallArityRes) -> Maybe (Bool, Arity, CallArityRes)
forall a. a -> Maybe a
Just (Bool
called_once, Arity
new_arity, CallArityRes
ae_rhs'), CoreExpr
rhs'))
where
(new_arity :: Arity
new_arity, called_once :: Bool
called_once) | Var
i Var -> VarSet -> Bool
`elemVarSet` VarSet
boring_vars = (0, Bool
False)
| Bool
otherwise = CallArityRes -> Var -> (Arity, Bool)
lookupCallArityRes CallArityRes
ae Var
i
(changes :: [Bool]
changes, ann_binds' :: [(Var, Maybe (Bool, Arity, CallArityRes), CoreExpr)]
ann_binds') = [(Bool, (Var, Maybe (Bool, Arity, CallArityRes), CoreExpr))]
-> ([Bool], [(Var, Maybe (Bool, Arity, CallArityRes), CoreExpr)])
forall a b. [(a, b)] -> ([a], [b])
unzip ([(Bool, (Var, Maybe (Bool, Arity, CallArityRes), CoreExpr))]
-> ([Bool], [(Var, Maybe (Bool, Arity, CallArityRes), CoreExpr)]))
-> [(Bool, (Var, Maybe (Bool, Arity, CallArityRes), CoreExpr))]
-> ([Bool], [(Var, Maybe (Bool, Arity, CallArityRes), CoreExpr)])
forall a b. (a -> b) -> a -> b
$ ((Var, Maybe (Bool, Arity, CallArityRes), CoreExpr)
-> (Bool, (Var, Maybe (Bool, Arity, CallArityRes), CoreExpr)))
-> [(Var, Maybe (Bool, Arity, CallArityRes), CoreExpr)]
-> [(Bool, (Var, Maybe (Bool, Arity, CallArityRes), CoreExpr))]
forall a b. (a -> b) -> [a] -> [b]
map (Var, Maybe (Bool, Arity, CallArityRes), CoreExpr)
-> (Bool, (Var, Maybe (Bool, Arity, CallArityRes), CoreExpr))
rerun [(Var, Maybe (Bool, Arity, CallArityRes), CoreExpr)]
ann_binds
any_change :: Bool
any_change = [Bool] -> Bool
forall (t :: * -> *). Foldable t => t Bool -> Bool
or [Bool]
changes
callArityRecEnv :: Bool -> [(Var, CallArityRes)] -> CallArityRes -> CallArityRes
callArityRecEnv :: Bool -> [(Var, CallArityRes)] -> CallArityRes -> CallArityRes
callArityRecEnv any_boring :: Bool
any_boring ae_rhss :: [(Var, CallArityRes)]
ae_rhss ae_body :: CallArityRes
ae_body
=
CallArityRes
ae_new
where
vars :: [Var]
vars = ((Var, CallArityRes) -> Var) -> [(Var, CallArityRes)] -> [Var]
forall a b. (a -> b) -> [a] -> [b]
map (Var, CallArityRes) -> Var
forall a b. (a, b) -> a
fst [(Var, CallArityRes)]
ae_rhss
ae_combined :: CallArityRes
ae_combined = [CallArityRes] -> CallArityRes
lubRess (((Var, CallArityRes) -> CallArityRes)
-> [(Var, CallArityRes)] -> [CallArityRes]
forall a b. (a -> b) -> [a] -> [b]
map (Var, CallArityRes) -> CallArityRes
forall a b. (a, b) -> b
snd [(Var, CallArityRes)]
ae_rhss) CallArityRes -> CallArityRes -> CallArityRes
`lubRes` CallArityRes
ae_body
cross_calls :: UnVarGraph
cross_calls
| Bool
any_boring = UnVarSet -> UnVarGraph
completeGraph (CallArityRes -> UnVarSet
domRes CallArityRes
ae_combined)
| [(Var, CallArityRes)] -> Arity -> Bool
forall a. [a] -> Arity -> Bool
lengthExceeds [(Var, CallArityRes)]
ae_rhss 25 = UnVarSet -> UnVarGraph
completeGraph (CallArityRes -> UnVarSet
domRes CallArityRes
ae_combined)
| Bool
otherwise = [UnVarGraph] -> UnVarGraph
unionUnVarGraphs ([UnVarGraph] -> UnVarGraph) -> [UnVarGraph] -> UnVarGraph
forall a b. (a -> b) -> a -> b
$ ((Var, CallArityRes) -> UnVarGraph)
-> [(Var, CallArityRes)] -> [UnVarGraph]
forall a b. (a -> b) -> [a] -> [b]
map (Var, CallArityRes) -> UnVarGraph
cross_call [(Var, CallArityRes)]
ae_rhss
cross_call :: (Var, CallArityRes) -> UnVarGraph
cross_call (v :: Var
v, ae_rhs :: CallArityRes
ae_rhs) = UnVarSet -> UnVarSet -> UnVarGraph
completeBipartiteGraph UnVarSet
called_by_v UnVarSet
called_with_v
where
is_thunk :: Bool
is_thunk = Var -> Arity
idCallArity Var
v Arity -> Arity -> Bool
forall a. Eq a => a -> a -> Bool
== 0
ae_before_v :: CallArityRes
ae_before_v | Bool
is_thunk = [CallArityRes] -> CallArityRes
lubRess (((Var, CallArityRes) -> CallArityRes)
-> [(Var, CallArityRes)] -> [CallArityRes]
forall a b. (a -> b) -> [a] -> [b]
map (Var, CallArityRes) -> CallArityRes
forall a b. (a, b) -> b
snd ([(Var, CallArityRes)] -> [CallArityRes])
-> [(Var, CallArityRes)] -> [CallArityRes]
forall a b. (a -> b) -> a -> b
$ ((Var, CallArityRes) -> Bool)
-> [(Var, CallArityRes)] -> [(Var, CallArityRes)]
forall a. (a -> Bool) -> [a] -> [a]
filter ((Var -> Var -> Bool
forall a. Eq a => a -> a -> Bool
/= Var
v) (Var -> Bool)
-> ((Var, CallArityRes) -> Var) -> (Var, CallArityRes) -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Var, CallArityRes) -> Var
forall a b. (a, b) -> a
fst) [(Var, CallArityRes)]
ae_rhss) CallArityRes -> CallArityRes -> CallArityRes
`lubRes` CallArityRes
ae_body
| Bool
otherwise = CallArityRes
ae_combined
called_with_v :: UnVarSet
called_with_v
= [UnVarSet] -> UnVarSet
unionUnVarSets ([UnVarSet] -> UnVarSet) -> [UnVarSet] -> UnVarSet
forall a b. (a -> b) -> a -> b
$ (Var -> UnVarSet) -> [Var] -> [UnVarSet]
forall a b. (a -> b) -> [a] -> [b]
map (CallArityRes -> Var -> UnVarSet
calledWith CallArityRes
ae_before_v) [Var]
vars
called_by_v :: UnVarSet
called_by_v = CallArityRes -> UnVarSet
domRes CallArityRes
ae_rhs
ae_new :: CallArityRes
ae_new = (UnVarGraph -> UnVarGraph) -> CallArityRes -> CallArityRes
forall (a :: * -> * -> *) b c d.
Arrow a =>
a b c -> a (b, d) (c, d)
first (UnVarGraph
cross_calls UnVarGraph -> UnVarGraph -> UnVarGraph
`unionUnVarGraph`) CallArityRes
ae_combined
trimArity :: Id -> Arity -> Arity
trimArity :: Var -> Arity -> Arity
trimArity v :: Var
v a :: Arity
a = [Arity] -> Arity
forall (t :: * -> *) a. (Foldable t, Ord a) => t a -> a
minimum [Arity
a, Arity
max_arity_by_type, Arity
max_arity_by_strsig]
where
max_arity_by_type :: Arity
max_arity_by_type = [OneShotInfo] -> Arity
forall (t :: * -> *) a. Foldable t => t a -> Arity
length (Type -> [OneShotInfo]
typeArity (Var -> Type
idType Var
v))
max_arity_by_strsig :: Arity
max_arity_by_strsig
| DmdResult -> Bool
isBotRes DmdResult
result_info = [Demand] -> Arity
forall (t :: * -> *) a. Foldable t => t a -> Arity
length [Demand]
demands
| Bool
otherwise = Arity
a
(demands :: [Demand]
demands, result_info :: DmdResult
result_info) = StrictSig -> ([Demand], DmdResult)
splitStrictSig (Var -> StrictSig
idStrictness Var
v)
type CallArityRes = (UnVarGraph, VarEnv Arity)
emptyArityRes :: CallArityRes
emptyArityRes :: CallArityRes
emptyArityRes = (UnVarGraph
emptyUnVarGraph, VarEnv Arity
forall a. VarEnv a
emptyVarEnv)
unitArityRes :: Var -> Arity -> CallArityRes
unitArityRes :: Var -> Arity -> CallArityRes
unitArityRes v :: Var
v arity :: Arity
arity = (UnVarGraph
emptyUnVarGraph, Var -> Arity -> VarEnv Arity
forall a. Var -> a -> VarEnv a
unitVarEnv Var
v Arity
arity)
resDelList :: [Var] -> CallArityRes -> CallArityRes
resDelList :: [Var] -> CallArityRes -> CallArityRes
resDelList vs :: [Var]
vs ae :: CallArityRes
ae = (Var -> CallArityRes -> CallArityRes)
-> CallArityRes -> [Var] -> CallArityRes
forall (t :: * -> *) a b.
Foldable t =>
(a -> b -> b) -> b -> t a -> b
foldr Var -> CallArityRes -> CallArityRes
resDel CallArityRes
ae [Var]
vs
resDel :: Var -> CallArityRes -> CallArityRes
resDel :: Var -> CallArityRes -> CallArityRes
resDel v :: Var
v (g :: UnVarGraph
g, ae :: VarEnv Arity
ae) = (UnVarGraph
g UnVarGraph -> Var -> UnVarGraph
`delNode` Var
v, VarEnv Arity
ae VarEnv Arity -> Var -> VarEnv Arity
forall a. VarEnv a -> Var -> VarEnv a
`delVarEnv` Var
v)
domRes :: CallArityRes -> UnVarSet
domRes :: CallArityRes -> UnVarSet
domRes (_, ae :: VarEnv Arity
ae) = VarEnv Arity -> UnVarSet
forall a. VarEnv a -> UnVarSet
varEnvDom VarEnv Arity
ae
lookupCallArityRes :: CallArityRes -> Var -> (Arity, Bool)
lookupCallArityRes :: CallArityRes -> Var -> (Arity, Bool)
lookupCallArityRes (g :: UnVarGraph
g, ae :: VarEnv Arity
ae) v :: Var
v
= case VarEnv Arity -> Var -> Maybe Arity
forall a. VarEnv a -> Var -> Maybe a
lookupVarEnv VarEnv Arity
ae Var
v of
Just a :: Arity
a -> (Arity
a, Bool -> Bool
not (UnVarGraph
g UnVarGraph -> Var -> Bool
`hasLoopAt` Var
v))
Nothing -> (0, Bool
False)
calledWith :: CallArityRes -> Var -> UnVarSet
calledWith :: CallArityRes -> Var -> UnVarSet
calledWith (g :: UnVarGraph
g, _) v :: Var
v = UnVarGraph -> Var -> UnVarSet
neighbors UnVarGraph
g Var
v
addCrossCoCalls :: UnVarSet -> UnVarSet -> CallArityRes -> CallArityRes
addCrossCoCalls :: UnVarSet -> UnVarSet -> CallArityRes -> CallArityRes
addCrossCoCalls set1 :: UnVarSet
set1 set2 :: UnVarSet
set2 = (UnVarGraph -> UnVarGraph) -> CallArityRes -> CallArityRes
forall (a :: * -> * -> *) b c d.
Arrow a =>
a b c -> a (b, d) (c, d)
first (UnVarSet -> UnVarSet -> UnVarGraph
completeBipartiteGraph UnVarSet
set1 UnVarSet
set2 UnVarGraph -> UnVarGraph -> UnVarGraph
`unionUnVarGraph`)
calledMultipleTimes :: CallArityRes -> CallArityRes
calledMultipleTimes :: CallArityRes -> CallArityRes
calledMultipleTimes res :: CallArityRes
res = (UnVarGraph -> UnVarGraph) -> CallArityRes -> CallArityRes
forall (a :: * -> * -> *) b c d.
Arrow a =>
a b c -> a (b, d) (c, d)
first (UnVarGraph -> UnVarGraph -> UnVarGraph
forall a b. a -> b -> a
const (UnVarSet -> UnVarGraph
completeGraph (CallArityRes -> UnVarSet
domRes CallArityRes
res))) CallArityRes
res
both :: CallArityRes -> CallArityRes -> CallArityRes
both :: CallArityRes -> CallArityRes -> CallArityRes
both r1 :: CallArityRes
r1 r2 :: CallArityRes
r2 = UnVarSet -> UnVarSet -> CallArityRes -> CallArityRes
addCrossCoCalls (CallArityRes -> UnVarSet
domRes CallArityRes
r1) (CallArityRes -> UnVarSet
domRes CallArityRes
r2) (CallArityRes -> CallArityRes) -> CallArityRes -> CallArityRes
forall a b. (a -> b) -> a -> b
$ CallArityRes
r1 CallArityRes -> CallArityRes -> CallArityRes
`lubRes` CallArityRes
r2
lubRes :: CallArityRes -> CallArityRes -> CallArityRes
lubRes :: CallArityRes -> CallArityRes -> CallArityRes
lubRes (g1 :: UnVarGraph
g1, ae1 :: VarEnv Arity
ae1) (g2 :: UnVarGraph
g2, ae2 :: VarEnv Arity
ae2) = (UnVarGraph
g1 UnVarGraph -> UnVarGraph -> UnVarGraph
`unionUnVarGraph` UnVarGraph
g2, VarEnv Arity
ae1 VarEnv Arity -> VarEnv Arity -> VarEnv Arity
`lubArityEnv` VarEnv Arity
ae2)
lubArityEnv :: VarEnv Arity -> VarEnv Arity -> VarEnv Arity
lubArityEnv :: VarEnv Arity -> VarEnv Arity -> VarEnv Arity
lubArityEnv = (Arity -> Arity -> Arity)
-> VarEnv Arity -> VarEnv Arity -> VarEnv Arity
forall a. (a -> a -> a) -> VarEnv a -> VarEnv a -> VarEnv a
plusVarEnv_C Arity -> Arity -> Arity
forall a. Ord a => a -> a -> a
min
lubRess :: [CallArityRes] -> CallArityRes
lubRess :: [CallArityRes] -> CallArityRes
lubRess = (CallArityRes -> CallArityRes -> CallArityRes)
-> CallArityRes -> [CallArityRes] -> CallArityRes
forall (t :: * -> *) b a.
Foldable t =>
(b -> a -> b) -> b -> t a -> b
foldl' CallArityRes -> CallArityRes -> CallArityRes
lubRes CallArityRes
emptyArityRes