{-# LANGUAGE CPP, BangPatterns, MultiWayIf, ViewPatterns #-}
module OccurAnal (
occurAnalysePgm, occurAnalyseExpr, occurAnalyseExpr_NoBinderSwap
) where
#include "HsVersions.h"
import GhcPrelude
import CoreSyn
import CoreFVs
import CoreUtils ( exprIsTrivial, isDefaultAlt, isExpandableApp,
stripTicksTopE, mkTicks )
import CoreArity ( joinRhsArity )
import Id
import IdInfo
import Name( localiseName )
import BasicTypes
import Module( Module )
import Coercion
import Type
import VarSet
import VarEnv
import Var
import Demand ( argOneShots, argsOneShots )
import Digraph ( SCC(..), Node(..)
, stronglyConnCompFromEdgedVerticesUniq
, stronglyConnCompFromEdgedVerticesUniqR )
import Unique
import UniqFM
import UniqSet
import Util
import Outputable
import Data.List
import Control.Arrow ( second )
occurAnalysePgm :: Module
-> (Id -> Bool)
-> (Activation -> Bool)
-> [CoreRule]
-> CoreProgram -> CoreProgram
occurAnalysePgm :: Module
-> (Id -> Bool)
-> (Activation -> Bool)
-> [CoreRule]
-> CoreProgram
-> CoreProgram
occurAnalysePgm this_mod :: Module
this_mod active_unf :: Id -> Bool
active_unf active_rule :: Activation -> Bool
active_rule imp_rules :: [CoreRule]
imp_rules binds :: CoreProgram
binds
| UsageDetails -> Bool
isEmptyDetails UsageDetails
final_usage
= CoreProgram
occ_anald_binds
| Bool
otherwise
= WARN( True, hang (text "Glomming in" <+> ppr this_mod <> colon)
2 (ppr final_usage ) )
CoreProgram
occ_anald_glommed_binds
where
init_env :: OccEnv
init_env = OccEnv
initOccEnv { occ_rule_act :: Activation -> Bool
occ_rule_act = Activation -> Bool
active_rule
, occ_unf_act :: Id -> Bool
occ_unf_act = Id -> Bool
active_unf }
(final_usage :: UsageDetails
final_usage, occ_anald_binds :: CoreProgram
occ_anald_binds) = OccEnv -> CoreProgram -> (UsageDetails, CoreProgram)
go OccEnv
init_env CoreProgram
binds
(_, occ_anald_glommed_binds :: CoreProgram
occ_anald_glommed_binds) = OccEnv
-> TopLevelFlag
-> ImpRuleEdges
-> [(Id, CoreExpr)]
-> UsageDetails
-> (UsageDetails, CoreProgram)
occAnalRecBind OccEnv
init_env TopLevelFlag
TopLevel
ImpRuleEdges
imp_rule_edges
(CoreProgram -> [(Id, CoreExpr)]
forall b. [Bind b] -> [(b, Expr b)]
flattenBinds CoreProgram
occ_anald_binds)
UsageDetails
initial_uds
initial_uds :: UsageDetails
initial_uds = UsageDetails -> VarSet -> UsageDetails
addManyOccsSet UsageDetails
emptyDetails
([CoreRule] -> VarSet
rulesFreeVars [CoreRule]
imp_rules)
imp_rule_edges :: ImpRuleEdges
imp_rule_edges = (ImpRuleEdges -> ImpRuleEdges -> ImpRuleEdges)
-> ImpRuleEdges -> [ImpRuleEdges] -> ImpRuleEdges
forall (t :: * -> *) a b.
Foldable t =>
(a -> b -> b) -> b -> t a -> b
foldr ((VarSet -> VarSet -> VarSet)
-> ImpRuleEdges -> ImpRuleEdges -> ImpRuleEdges
forall a. (a -> a -> a) -> VarEnv a -> VarEnv a -> VarEnv a
plusVarEnv_C VarSet -> VarSet -> VarSet
unionVarSet) ImpRuleEdges
forall a. VarEnv a
emptyVarEnv
[ (Id -> VarSet) -> VarEnv Id -> ImpRuleEdges
forall a b. (a -> b) -> VarEnv a -> VarEnv b
mapVarEnv (VarSet -> Id -> VarSet
forall a b. a -> b -> a
const VarSet
maps_to) (VarEnv Id -> ImpRuleEdges) -> VarEnv Id -> ImpRuleEdges
forall a b. (a -> b) -> a -> b
$
VarSet -> VarEnv Id
forall a. UniqSet a -> UniqFM a
getUniqSet (CoreExpr -> VarSet
exprFreeIds CoreExpr
arg VarSet -> [Id] -> VarSet
`delVarSetList` CoreRule -> [Id]
ru_bndrs CoreRule
imp_rule)
| CoreRule
imp_rule <- [CoreRule]
imp_rules
, Bool -> Bool
not (CoreRule -> Bool
isBuiltinRule CoreRule
imp_rule)
, let maps_to :: VarSet
maps_to = CoreExpr -> VarSet
exprFreeIds (CoreRule -> CoreExpr
ru_rhs CoreRule
imp_rule)
VarSet -> [Id] -> VarSet
`delVarSetList` CoreRule -> [Id]
ru_bndrs CoreRule
imp_rule
, CoreExpr
arg <- CoreRule -> [CoreExpr]
ru_args CoreRule
imp_rule ]
go :: OccEnv -> [CoreBind] -> (UsageDetails, [CoreBind])
go :: OccEnv -> CoreProgram -> (UsageDetails, CoreProgram)
go _ []
= (UsageDetails
initial_uds, [])
go env :: OccEnv
env (bind :: CoreBind
bind:binds :: CoreProgram
binds)
= (UsageDetails
final_usage, CoreProgram
bind' CoreProgram -> CoreProgram -> CoreProgram
forall a. [a] -> [a] -> [a]
++ CoreProgram
binds')
where
(bs_usage :: UsageDetails
bs_usage, binds' :: CoreProgram
binds') = OccEnv -> CoreProgram -> (UsageDetails, CoreProgram)
go OccEnv
env CoreProgram
binds
(final_usage :: UsageDetails
final_usage, bind' :: CoreProgram
bind') = OccEnv
-> TopLevelFlag
-> ImpRuleEdges
-> CoreBind
-> UsageDetails
-> (UsageDetails, CoreProgram)
occAnalBind OccEnv
env TopLevelFlag
TopLevel ImpRuleEdges
imp_rule_edges CoreBind
bind
UsageDetails
bs_usage
occurAnalyseExpr :: CoreExpr -> CoreExpr
occurAnalyseExpr :: CoreExpr -> CoreExpr
occurAnalyseExpr = Bool -> CoreExpr -> CoreExpr
occurAnalyseExpr' Bool
True
occurAnalyseExpr_NoBinderSwap :: CoreExpr -> CoreExpr
occurAnalyseExpr_NoBinderSwap :: CoreExpr -> CoreExpr
occurAnalyseExpr_NoBinderSwap = Bool -> CoreExpr -> CoreExpr
occurAnalyseExpr' Bool
False
occurAnalyseExpr' :: Bool -> CoreExpr -> CoreExpr
occurAnalyseExpr' :: Bool -> CoreExpr -> CoreExpr
occurAnalyseExpr' enable_binder_swap :: Bool
enable_binder_swap expr :: CoreExpr
expr
= (UsageDetails, CoreExpr) -> CoreExpr
forall a b. (a, b) -> b
snd (OccEnv -> CoreExpr -> (UsageDetails, CoreExpr)
occAnal OccEnv
env CoreExpr
expr)
where
env :: OccEnv
env = OccEnv
initOccEnv { occ_binder_swap :: Bool
occ_binder_swap = Bool
enable_binder_swap }
occAnalBind :: OccEnv
-> TopLevelFlag
-> ImpRuleEdges
-> CoreBind
-> UsageDetails
-> (UsageDetails,
[CoreBind])
occAnalBind :: OccEnv
-> TopLevelFlag
-> ImpRuleEdges
-> CoreBind
-> UsageDetails
-> (UsageDetails, CoreProgram)
occAnalBind env :: OccEnv
env lvl :: TopLevelFlag
lvl top_env :: ImpRuleEdges
top_env (NonRec binder :: Id
binder rhs :: CoreExpr
rhs) body_usage :: UsageDetails
body_usage
= OccEnv
-> TopLevelFlag
-> ImpRuleEdges
-> Id
-> CoreExpr
-> UsageDetails
-> (UsageDetails, CoreProgram)
occAnalNonRecBind OccEnv
env TopLevelFlag
lvl ImpRuleEdges
top_env Id
binder CoreExpr
rhs UsageDetails
body_usage
occAnalBind env :: OccEnv
env lvl :: TopLevelFlag
lvl top_env :: ImpRuleEdges
top_env (Rec pairs :: [(Id, CoreExpr)]
pairs) body_usage :: UsageDetails
body_usage
= OccEnv
-> TopLevelFlag
-> ImpRuleEdges
-> [(Id, CoreExpr)]
-> UsageDetails
-> (UsageDetails, CoreProgram)
occAnalRecBind OccEnv
env TopLevelFlag
lvl ImpRuleEdges
top_env [(Id, CoreExpr)]
pairs UsageDetails
body_usage
occAnalNonRecBind :: OccEnv -> TopLevelFlag -> ImpRuleEdges -> Var -> CoreExpr
-> UsageDetails -> (UsageDetails, [CoreBind])
occAnalNonRecBind :: OccEnv
-> TopLevelFlag
-> ImpRuleEdges
-> Id
-> CoreExpr
-> UsageDetails
-> (UsageDetails, CoreProgram)
occAnalNonRecBind env :: OccEnv
env lvl :: TopLevelFlag
lvl imp_rule_edges :: ImpRuleEdges
imp_rule_edges binder :: Id
binder rhs :: CoreExpr
rhs body_usage :: UsageDetails
body_usage
| Id -> Bool
isTyVar Id
binder
= (UsageDetails
body_usage, [Id -> CoreExpr -> CoreBind
forall b. b -> Expr b -> Bind b
NonRec Id
binder CoreExpr
rhs])
| Bool -> Bool
not (Id
binder Id -> UsageDetails -> Bool
`usedIn` UsageDetails
body_usage)
= (UsageDetails
body_usage, [])
| Bool
otherwise
= (UsageDetails
body_usage' UsageDetails -> UsageDetails -> UsageDetails
`andUDs` UsageDetails
rhs_usage', [Id -> CoreExpr -> CoreBind
forall b. b -> Expr b -> Bind b
NonRec Id
tagged_binder CoreExpr
rhs'])
where
(body_usage' :: UsageDetails
body_usage', tagged_binder :: Id
tagged_binder) = TopLevelFlag -> UsageDetails -> Id -> (UsageDetails, Id)
tagNonRecBinder TopLevelFlag
lvl UsageDetails
body_usage Id
binder
mb_join_arity :: Maybe Int
mb_join_arity = Id -> Maybe Int
willBeJoinId_maybe Id
tagged_binder
(bndrs :: [Id]
bndrs, body :: CoreExpr
body) = CoreExpr -> ([Id], CoreExpr)
forall b. Expr b -> ([b], Expr b)
collectBinders CoreExpr
rhs
(rhs_usage1 :: UsageDetails
rhs_usage1, bndrs' :: [Id]
bndrs', body' :: CoreExpr
body') = OccEnv -> Id -> [Id] -> CoreExpr -> (UsageDetails, [Id], CoreExpr)
occAnalNonRecRhs OccEnv
env Id
tagged_binder [Id]
bndrs CoreExpr
body
rhs' :: CoreExpr
rhs' = [Id] -> CoreExpr -> CoreExpr
forall b. [b] -> Expr b -> Expr b
mkLams (Maybe Int -> [Id] -> [Id]
markJoinOneShots Maybe Int
mb_join_arity [Id]
bndrs') CoreExpr
body'
rhs_usage2 :: UsageDetails
rhs_usage2 = case OccEnv -> RecFlag -> Id -> Maybe UsageDetails
occAnalUnfolding OccEnv
env RecFlag
NonRecursive Id
binder of
Just unf_usage :: UsageDetails
unf_usage -> UsageDetails
rhs_usage1 UsageDetails -> UsageDetails -> UsageDetails
`andUDs` UsageDetails
unf_usage
Nothing -> UsageDetails
rhs_usage1
rules_w_uds :: [(CoreRule, UsageDetails, UsageDetails)]
rules_w_uds = OccEnv
-> Maybe Int
-> RecFlag
-> Id
-> [(CoreRule, UsageDetails, UsageDetails)]
occAnalRules OccEnv
env Maybe Int
mb_join_arity RecFlag
NonRecursive Id
tagged_binder
rule_uds :: [UsageDetails]
rule_uds = ((CoreRule, UsageDetails, UsageDetails) -> UsageDetails)
-> [(CoreRule, UsageDetails, UsageDetails)] -> [UsageDetails]
forall a b. (a -> b) -> [a] -> [b]
map (\(_, l :: UsageDetails
l, r :: UsageDetails
r) -> UsageDetails
l UsageDetails -> UsageDetails -> UsageDetails
`andUDs` UsageDetails
r) [(CoreRule, UsageDetails, UsageDetails)]
rules_w_uds
rhs_usage3 :: UsageDetails
rhs_usage3 = (UsageDetails -> UsageDetails -> UsageDetails)
-> UsageDetails -> [UsageDetails] -> UsageDetails
forall (t :: * -> *) a b.
Foldable t =>
(a -> b -> b) -> b -> t a -> b
foldr UsageDetails -> UsageDetails -> UsageDetails
andUDs UsageDetails
rhs_usage2 [UsageDetails]
rule_uds
rhs_usage4 :: UsageDetails
rhs_usage4 = case ImpRuleEdges -> Id -> Maybe VarSet
forall a. VarEnv a -> Id -> Maybe a
lookupVarEnv ImpRuleEdges
imp_rule_edges Id
binder of
Nothing -> UsageDetails
rhs_usage3
Just vs :: VarSet
vs -> UsageDetails -> VarSet -> UsageDetails
addManyOccsSet UsageDetails
rhs_usage3 VarSet
vs
rhs_usage' :: UsageDetails
rhs_usage' = Maybe Int -> RecFlag -> [Id] -> UsageDetails -> UsageDetails
adjustRhsUsage Maybe Int
mb_join_arity RecFlag
NonRecursive [Id]
bndrs' UsageDetails
rhs_usage4
occAnalRecBind :: OccEnv -> TopLevelFlag -> ImpRuleEdges -> [(Var,CoreExpr)]
-> UsageDetails -> (UsageDetails, [CoreBind])
occAnalRecBind :: OccEnv
-> TopLevelFlag
-> ImpRuleEdges
-> [(Id, CoreExpr)]
-> UsageDetails
-> (UsageDetails, CoreProgram)
occAnalRecBind env :: OccEnv
env lvl :: TopLevelFlag
lvl imp_rule_edges :: ImpRuleEdges
imp_rule_edges pairs :: [(Id, CoreExpr)]
pairs body_usage :: UsageDetails
body_usage
= (SCC Details
-> (UsageDetails, CoreProgram) -> (UsageDetails, CoreProgram))
-> (UsageDetails, CoreProgram)
-> [SCC Details]
-> (UsageDetails, CoreProgram)
forall (t :: * -> *) a b.
Foldable t =>
(a -> b -> b) -> b -> t a -> b
foldr (OccEnv
-> TopLevelFlag
-> SCC Details
-> (UsageDetails, CoreProgram)
-> (UsageDetails, CoreProgram)
occAnalRec OccEnv
env TopLevelFlag
lvl) (UsageDetails
body_usage, []) [SCC Details]
sccs
where
sccs :: [SCC Details]
sccs :: [SCC Details]
sccs = {-# SCC "occAnalBind.scc" #-}
[Node Unique Details] -> [SCC Details]
forall key payload.
Uniquable key =>
[Node key payload] -> [SCC payload]
stronglyConnCompFromEdgedVerticesUniq [Node Unique Details]
nodes
nodes :: [LetrecNode]
nodes :: [Node Unique Details]
nodes = {-# SCC "occAnalBind.assoc" #-}
((Id, CoreExpr) -> Node Unique Details)
-> [(Id, CoreExpr)] -> [Node Unique Details]
forall a b. (a -> b) -> [a] -> [b]
map (OccEnv
-> ImpRuleEdges -> VarSet -> (Id, CoreExpr) -> Node Unique Details
makeNode OccEnv
env ImpRuleEdges
imp_rule_edges VarSet
bndr_set) [(Id, CoreExpr)]
pairs
bndr_set :: VarSet
bndr_set = [Id] -> VarSet
mkVarSet (((Id, CoreExpr) -> Id) -> [(Id, CoreExpr)] -> [Id]
forall a b. (a -> b) -> [a] -> [b]
map (Id, CoreExpr) -> Id
forall a b. (a, b) -> a
fst [(Id, CoreExpr)]
pairs)
occAnalRec :: OccEnv -> TopLevelFlag
-> SCC Details
-> (UsageDetails, [CoreBind])
-> (UsageDetails, [CoreBind])
occAnalRec :: OccEnv
-> TopLevelFlag
-> SCC Details
-> (UsageDetails, CoreProgram)
-> (UsageDetails, CoreProgram)
occAnalRec _ lvl :: TopLevelFlag
lvl (AcyclicSCC (ND { nd_bndr :: Details -> Id
nd_bndr = Id
bndr, nd_rhs :: Details -> CoreExpr
nd_rhs = CoreExpr
rhs
, nd_uds :: Details -> UsageDetails
nd_uds = UsageDetails
rhs_uds, nd_rhs_bndrs :: Details -> [Id]
nd_rhs_bndrs = [Id]
rhs_bndrs }))
(body_uds :: UsageDetails
body_uds, binds :: CoreProgram
binds)
| Bool -> Bool
not (Id
bndr Id -> UsageDetails -> Bool
`usedIn` UsageDetails
body_uds)
= (UsageDetails
body_uds, CoreProgram
binds)
| Bool
otherwise
= (UsageDetails
body_uds' UsageDetails -> UsageDetails -> UsageDetails
`andUDs` UsageDetails
rhs_uds',
Id -> CoreExpr -> CoreBind
forall b. b -> Expr b -> Bind b
NonRec Id
tagged_bndr CoreExpr
rhs CoreBind -> CoreProgram -> CoreProgram
forall a. a -> [a] -> [a]
: CoreProgram
binds)
where
(body_uds' :: UsageDetails
body_uds', tagged_bndr :: Id
tagged_bndr) = TopLevelFlag -> UsageDetails -> Id -> (UsageDetails, Id)
tagNonRecBinder TopLevelFlag
lvl UsageDetails
body_uds Id
bndr
rhs_uds' :: UsageDetails
rhs_uds' = Maybe Int -> RecFlag -> [Id] -> UsageDetails -> UsageDetails
adjustRhsUsage (Id -> Maybe Int
willBeJoinId_maybe Id
tagged_bndr) RecFlag
NonRecursive
[Id]
rhs_bndrs UsageDetails
rhs_uds
occAnalRec env :: OccEnv
env lvl :: TopLevelFlag
lvl (CyclicSCC details_s :: [Details]
details_s) (body_uds :: UsageDetails
body_uds, binds :: CoreProgram
binds)
| Bool -> Bool
not ((Id -> Bool) -> [Id] -> Bool
forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
any (Id -> UsageDetails -> Bool
`usedIn` UsageDetails
body_uds) [Id]
bndrs)
= (UsageDetails
body_uds, CoreProgram
binds)
| Bool
otherwise
=
(UsageDetails
final_uds, [(Id, CoreExpr)] -> CoreBind
forall b. [(b, Expr b)] -> Bind b
Rec [(Id, CoreExpr)]
pairs CoreBind -> CoreProgram -> CoreProgram
forall a. a -> [a] -> [a]
: CoreProgram
binds)
where
bndrs :: [Id]
bndrs = (Details -> Id) -> [Details] -> [Id]
forall a b. (a -> b) -> [a] -> [b]
map Details -> Id
nd_bndr [Details]
details_s
bndr_set :: VarSet
bndr_set = [Id] -> VarSet
mkVarSet [Id]
bndrs
final_uds :: UsageDetails
loop_breaker_nodes :: [LetrecNode]
(final_uds :: UsageDetails
final_uds, loop_breaker_nodes :: [Node Unique Details]
loop_breaker_nodes)
= OccEnv
-> TopLevelFlag
-> VarSet
-> UsageDetails
-> [Details]
-> (UsageDetails, [Node Unique Details])
mkLoopBreakerNodes OccEnv
env TopLevelFlag
lvl VarSet
bndr_set UsageDetails
body_uds [Details]
details_s
weak_fvs :: VarSet
weak_fvs :: VarSet
weak_fvs = (Details -> VarSet) -> [Details] -> VarSet
forall a. (a -> VarSet) -> [a] -> VarSet
mapUnionVarSet Details -> VarSet
nd_weak [Details]
details_s
pairs :: [(Id,CoreExpr)]
pairs :: [(Id, CoreExpr)]
pairs | VarSet -> Bool
isEmptyVarSet VarSet
weak_fvs = Int
-> VarSet
-> VarSet
-> [Node Unique Details]
-> [(Id, CoreExpr)]
-> [(Id, CoreExpr)]
reOrderNodes 0 VarSet
bndr_set VarSet
weak_fvs [Node Unique Details]
loop_breaker_nodes []
| Bool
otherwise = Int
-> VarSet
-> VarSet
-> [Node Unique Details]
-> [(Id, CoreExpr)]
-> [(Id, CoreExpr)]
loopBreakNodes 0 VarSet
bndr_set VarSet
weak_fvs [Node Unique Details]
loop_breaker_nodes []
type Binding = (Id,CoreExpr)
loopBreakNodes :: Int
-> VarSet
-> VarSet
-> [LetrecNode]
-> [Binding]
-> [Binding]
loopBreakNodes :: Int
-> VarSet
-> VarSet
-> [Node Unique Details]
-> [(Id, CoreExpr)]
-> [(Id, CoreExpr)]
loopBreakNodes depth :: Int
depth bndr_set :: VarSet
bndr_set weak_fvs :: VarSet
weak_fvs nodes :: [Node Unique Details]
nodes binds :: [(Id, CoreExpr)]
binds
=
[SCC (Node Unique Details)] -> [(Id, CoreExpr)] -> [(Id, CoreExpr)]
go ([Node Unique Details] -> [SCC (Node Unique Details)]
forall key payload.
Uniquable key =>
[Node key payload] -> [SCC (Node key payload)]
stronglyConnCompFromEdgedVerticesUniqR [Node Unique Details]
nodes) [(Id, CoreExpr)]
binds
where
go :: [SCC (Node Unique Details)] -> [(Id, CoreExpr)] -> [(Id, CoreExpr)]
go [] binds :: [(Id, CoreExpr)]
binds = [(Id, CoreExpr)]
binds
go (scc :: SCC (Node Unique Details)
scc:sccs :: [SCC (Node Unique Details)]
sccs) binds :: [(Id, CoreExpr)]
binds = SCC (Node Unique Details) -> [(Id, CoreExpr)] -> [(Id, CoreExpr)]
loop_break_scc SCC (Node Unique Details)
scc ([SCC (Node Unique Details)] -> [(Id, CoreExpr)] -> [(Id, CoreExpr)]
go [SCC (Node Unique Details)]
sccs [(Id, CoreExpr)]
binds)
loop_break_scc :: SCC (Node Unique Details) -> [(Id, CoreExpr)] -> [(Id, CoreExpr)]
loop_break_scc scc :: SCC (Node Unique Details)
scc binds :: [(Id, CoreExpr)]
binds
= case SCC (Node Unique Details)
scc of
AcyclicSCC node :: Node Unique Details
node -> VarSet -> Node Unique Details -> (Id, CoreExpr)
mk_non_loop_breaker VarSet
weak_fvs Node Unique Details
node (Id, CoreExpr) -> [(Id, CoreExpr)] -> [(Id, CoreExpr)]
forall a. a -> [a] -> [a]
: [(Id, CoreExpr)]
binds
CyclicSCC nodes :: [Node Unique Details]
nodes -> Int
-> VarSet
-> VarSet
-> [Node Unique Details]
-> [(Id, CoreExpr)]
-> [(Id, CoreExpr)]
reOrderNodes Int
depth VarSet
bndr_set VarSet
weak_fvs [Node Unique Details]
nodes [(Id, CoreExpr)]
binds
reOrderNodes :: Int -> VarSet -> VarSet -> [LetrecNode] -> [Binding] -> [Binding]
reOrderNodes :: Int
-> VarSet
-> VarSet
-> [Node Unique Details]
-> [(Id, CoreExpr)]
-> [(Id, CoreExpr)]
reOrderNodes _ _ _ [] _ = String -> [(Id, CoreExpr)]
forall a. String -> a
panic "reOrderNodes"
reOrderNodes _ _ _ [node :: Node Unique Details
node] binds :: [(Id, CoreExpr)]
binds = Node Unique Details -> (Id, CoreExpr)
mk_loop_breaker Node Unique Details
node (Id, CoreExpr) -> [(Id, CoreExpr)] -> [(Id, CoreExpr)]
forall a. a -> [a] -> [a]
: [(Id, CoreExpr)]
binds
reOrderNodes depth :: Int
depth bndr_set :: VarSet
bndr_set weak_fvs :: VarSet
weak_fvs (node :: Node Unique Details
node : nodes :: [Node Unique Details]
nodes) binds :: [(Id, CoreExpr)]
binds
=
Int
-> VarSet
-> VarSet
-> [Node Unique Details]
-> [(Id, CoreExpr)]
-> [(Id, CoreExpr)]
loopBreakNodes Int
new_depth VarSet
bndr_set VarSet
weak_fvs [Node Unique Details]
unchosen ([(Id, CoreExpr)] -> [(Id, CoreExpr)])
-> [(Id, CoreExpr)] -> [(Id, CoreExpr)]
forall a b. (a -> b) -> a -> b
$
((Node Unique Details -> (Id, CoreExpr))
-> [Node Unique Details] -> [(Id, CoreExpr)]
forall a b. (a -> b) -> [a] -> [b]
map Node Unique Details -> (Id, CoreExpr)
mk_loop_breaker [Node Unique Details]
chosen_nodes [(Id, CoreExpr)] -> [(Id, CoreExpr)] -> [(Id, CoreExpr)]
forall a. [a] -> [a] -> [a]
++ [(Id, CoreExpr)]
binds)
where
(chosen_nodes :: [Node Unique Details]
chosen_nodes, unchosen :: [Node Unique Details]
unchosen) = Bool
-> NodeScore
-> [Node Unique Details]
-> [Node Unique Details]
-> [Node Unique Details]
-> ([Node Unique Details], [Node Unique Details])
chooseLoopBreaker Bool
approximate_lb
(Details -> NodeScore
nd_score (Node Unique Details -> Details
forall key payload. Node key payload -> payload
node_payload Node Unique Details
node))
[Node Unique Details
node] [] [Node Unique Details]
nodes
approximate_lb :: Bool
approximate_lb = Int
depth Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
>= 2
new_depth :: Int
new_depth | Bool
approximate_lb = 0
| Bool
otherwise = Int
depthInt -> Int -> Int
forall a. Num a => a -> a -> a
+1
mk_loop_breaker :: LetrecNode -> Binding
mk_loop_breaker :: Node Unique Details -> (Id, CoreExpr)
mk_loop_breaker (Node Unique Details -> Details
forall key payload. Node key payload -> payload
node_payload -> ND { nd_bndr :: Details -> Id
nd_bndr = Id
bndr, nd_rhs :: Details -> CoreExpr
nd_rhs = CoreExpr
rhs})
= (Id
bndr Id -> OccInfo -> Id
`setIdOccInfo` OccInfo
strongLoopBreaker { occ_tail :: TailCallInfo
occ_tail = TailCallInfo
tail_info }, CoreExpr
rhs)
where
tail_info :: TailCallInfo
tail_info = OccInfo -> TailCallInfo
tailCallInfo (Id -> OccInfo
idOccInfo Id
bndr)
mk_non_loop_breaker :: VarSet -> LetrecNode -> Binding
mk_non_loop_breaker :: VarSet -> Node Unique Details -> (Id, CoreExpr)
mk_non_loop_breaker weak_fvs :: VarSet
weak_fvs (Node Unique Details -> Details
forall key payload. Node key payload -> payload
node_payload -> ND { nd_bndr :: Details -> Id
nd_bndr = Id
bndr
, nd_rhs :: Details -> CoreExpr
nd_rhs = CoreExpr
rhs})
| Id
bndr Id -> VarSet -> Bool
`elemVarSet` VarSet
weak_fvs = (Id -> OccInfo -> Id
setIdOccInfo Id
bndr OccInfo
occ', CoreExpr
rhs)
| Bool
otherwise = (Id
bndr, CoreExpr
rhs)
where
occ' :: OccInfo
occ' = OccInfo
weakLoopBreaker { occ_tail :: TailCallInfo
occ_tail = TailCallInfo
tail_info }
tail_info :: TailCallInfo
tail_info = OccInfo -> TailCallInfo
tailCallInfo (Id -> OccInfo
idOccInfo Id
bndr)
chooseLoopBreaker :: Bool
-> NodeScore
-> [LetrecNode]
-> [LetrecNode]
-> [LetrecNode]
-> ([LetrecNode], [LetrecNode])
chooseLoopBreaker :: Bool
-> NodeScore
-> [Node Unique Details]
-> [Node Unique Details]
-> [Node Unique Details]
-> ([Node Unique Details], [Node Unique Details])
chooseLoopBreaker _ _ loop_nodes :: [Node Unique Details]
loop_nodes acc :: [Node Unique Details]
acc []
= ([Node Unique Details]
loop_nodes, [Node Unique Details]
acc)
chooseLoopBreaker approx_lb :: Bool
approx_lb loop_sc :: NodeScore
loop_sc loop_nodes :: [Node Unique Details]
loop_nodes acc :: [Node Unique Details]
acc (node :: Node Unique Details
node : nodes :: [Node Unique Details]
nodes)
| Bool
approx_lb
, NodeScore -> Int
rank NodeScore
sc Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== NodeScore -> Int
rank NodeScore
loop_sc
= Bool
-> NodeScore
-> [Node Unique Details]
-> [Node Unique Details]
-> [Node Unique Details]
-> ([Node Unique Details], [Node Unique Details])
chooseLoopBreaker Bool
approx_lb NodeScore
loop_sc (Node Unique Details
node Node Unique Details
-> [Node Unique Details] -> [Node Unique Details]
forall a. a -> [a] -> [a]
: [Node Unique Details]
loop_nodes) [Node Unique Details]
acc [Node Unique Details]
nodes
| NodeScore
sc NodeScore -> NodeScore -> Bool
`betterLB` NodeScore
loop_sc
= Bool
-> NodeScore
-> [Node Unique Details]
-> [Node Unique Details]
-> [Node Unique Details]
-> ([Node Unique Details], [Node Unique Details])
chooseLoopBreaker Bool
approx_lb NodeScore
sc [Node Unique Details
node] ([Node Unique Details]
loop_nodes [Node Unique Details]
-> [Node Unique Details] -> [Node Unique Details]
forall a. [a] -> [a] -> [a]
++ [Node Unique Details]
acc) [Node Unique Details]
nodes
| Bool
otherwise
= Bool
-> NodeScore
-> [Node Unique Details]
-> [Node Unique Details]
-> [Node Unique Details]
-> ([Node Unique Details], [Node Unique Details])
chooseLoopBreaker Bool
approx_lb NodeScore
loop_sc [Node Unique Details]
loop_nodes (Node Unique Details
node Node Unique Details
-> [Node Unique Details] -> [Node Unique Details]
forall a. a -> [a] -> [a]
: [Node Unique Details]
acc) [Node Unique Details]
nodes
where
sc :: NodeScore
sc = Details -> NodeScore
nd_score (Node Unique Details -> Details
forall key payload. Node key payload -> payload
node_payload Node Unique Details
node)
type ImpRuleEdges = IdEnv IdSet
noImpRuleEdges :: ImpRuleEdges
noImpRuleEdges :: ImpRuleEdges
noImpRuleEdges = ImpRuleEdges
forall a. VarEnv a
emptyVarEnv
type LetrecNode = Node Unique Details
data Details
= ND { Details -> Id
nd_bndr :: Id
, Details -> CoreExpr
nd_rhs :: CoreExpr
, Details -> [Id]
nd_rhs_bndrs :: [CoreBndr]
, Details -> UsageDetails
nd_uds :: UsageDetails
, Details -> VarSet
nd_inl :: IdSet
, Details -> VarSet
nd_weak :: IdSet
, Details -> VarSet
nd_active_rule_fvs :: IdSet
, Details -> NodeScore
nd_score :: NodeScore
}
instance Outputable Details where
ppr :: Details -> SDoc
ppr nd :: Details
nd = String -> SDoc
text "ND" SDoc -> SDoc -> SDoc
<> SDoc -> SDoc
braces
([SDoc] -> SDoc
sep [ String -> SDoc
text "bndr =" SDoc -> SDoc -> SDoc
<+> Id -> SDoc
forall a. Outputable a => a -> SDoc
ppr (Details -> Id
nd_bndr Details
nd)
, String -> SDoc
text "uds =" SDoc -> SDoc -> SDoc
<+> UsageDetails -> SDoc
forall a. Outputable a => a -> SDoc
ppr (Details -> UsageDetails
nd_uds Details
nd)
, String -> SDoc
text "inl =" SDoc -> SDoc -> SDoc
<+> VarSet -> SDoc
forall a. Outputable a => a -> SDoc
ppr (Details -> VarSet
nd_inl Details
nd)
, String -> SDoc
text "weak =" SDoc -> SDoc -> SDoc
<+> VarSet -> SDoc
forall a. Outputable a => a -> SDoc
ppr (Details -> VarSet
nd_weak Details
nd)
, String -> SDoc
text "rule =" SDoc -> SDoc -> SDoc
<+> VarSet -> SDoc
forall a. Outputable a => a -> SDoc
ppr (Details -> VarSet
nd_active_rule_fvs Details
nd)
, String -> SDoc
text "score =" SDoc -> SDoc -> SDoc
<+> NodeScore -> SDoc
forall a. Outputable a => a -> SDoc
ppr (Details -> NodeScore
nd_score Details
nd)
])
type NodeScore = ( Int
, Int
, Bool )
rank :: NodeScore -> Int
rank :: NodeScore -> Int
rank (r :: Int
r, _, _) = Int
r
makeNode :: OccEnv -> ImpRuleEdges -> VarSet
-> (Var, CoreExpr) -> LetrecNode
makeNode :: OccEnv
-> ImpRuleEdges -> VarSet -> (Id, CoreExpr) -> Node Unique Details
makeNode env :: OccEnv
env imp_rule_edges :: ImpRuleEdges
imp_rule_edges bndr_set :: VarSet
bndr_set (bndr :: Id
bndr, rhs :: CoreExpr
rhs)
= Details -> Unique -> [Unique] -> Node Unique Details
forall key payload. payload -> key -> [key] -> Node key payload
DigraphNode Details
details (Id -> Unique
varUnique Id
bndr) (VarSet -> [Unique]
forall elt. UniqSet elt -> [Unique]
nonDetKeysUniqSet VarSet
node_fvs)
where
details :: Details
details = ND :: Id
-> CoreExpr
-> [Id]
-> UsageDetails
-> VarSet
-> VarSet
-> VarSet
-> NodeScore
-> Details
ND { nd_bndr :: Id
nd_bndr = Id
bndr
, nd_rhs :: CoreExpr
nd_rhs = CoreExpr
rhs'
, nd_rhs_bndrs :: [Id]
nd_rhs_bndrs = [Id]
bndrs'
, nd_uds :: UsageDetails
nd_uds = UsageDetails
rhs_usage3
, nd_inl :: VarSet
nd_inl = VarSet
inl_fvs
, nd_weak :: VarSet
nd_weak = VarSet
node_fvs VarSet -> VarSet -> VarSet
`minusVarSet` VarSet
inl_fvs
, nd_active_rule_fvs :: VarSet
nd_active_rule_fvs = VarSet
active_rule_fvs
, nd_score :: NodeScore
nd_score = String -> SDoc -> NodeScore
forall a. HasCallStack => String -> SDoc -> a
pprPanic "makeNodeDetails" (Id -> SDoc
forall a. Outputable a => a -> SDoc
ppr Id
bndr) }
(bndrs :: [Id]
bndrs, body :: CoreExpr
body) = CoreExpr -> ([Id], CoreExpr)
forall b. Expr b -> ([b], Expr b)
collectBinders CoreExpr
rhs
(rhs_usage1 :: UsageDetails
rhs_usage1, bndrs' :: [Id]
bndrs', body' :: CoreExpr
body') = OccEnv -> [Id] -> CoreExpr -> (UsageDetails, [Id], CoreExpr)
occAnalRecRhs OccEnv
env [Id]
bndrs CoreExpr
body
rhs' :: CoreExpr
rhs' = [Id] -> CoreExpr -> CoreExpr
forall b. [b] -> Expr b -> Expr b
mkLams [Id]
bndrs' CoreExpr
body'
rhs_usage2 :: UsageDetails
rhs_usage2 = (UsageDetails -> UsageDetails -> UsageDetails)
-> UsageDetails -> [UsageDetails] -> UsageDetails
forall (t :: * -> *) a b.
Foldable t =>
(a -> b -> b) -> b -> t a -> b
foldr UsageDetails -> UsageDetails -> UsageDetails
andUDs UsageDetails
rhs_usage1 [UsageDetails]
rule_uds
rhs_usage3 :: UsageDetails
rhs_usage3 = case Maybe UsageDetails
mb_unf_uds of
Just unf_uds :: UsageDetails
unf_uds -> UsageDetails
rhs_usage2 UsageDetails -> UsageDetails -> UsageDetails
`andUDs` UsageDetails
unf_uds
Nothing -> UsageDetails
rhs_usage2
node_fvs :: VarSet
node_fvs = VarSet -> UsageDetails -> VarSet
udFreeVars VarSet
bndr_set UsageDetails
rhs_usage3
is_active :: Activation -> Bool
is_active = OccEnv -> Activation -> Bool
occ_rule_act OccEnv
env :: Activation -> Bool
rules_w_uds :: [(CoreRule, UsageDetails, UsageDetails)]
rules_w_uds :: [(CoreRule, UsageDetails, UsageDetails)]
rules_w_uds = OccEnv
-> Maybe Int
-> RecFlag
-> Id
-> [(CoreRule, UsageDetails, UsageDetails)]
occAnalRules OccEnv
env (Int -> Maybe Int
forall a. a -> Maybe a
Just ([Id] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [Id]
bndrs)) RecFlag
Recursive Id
bndr
rules_w_rhs_fvs :: [(Activation, VarSet)]
rules_w_rhs_fvs :: [(Activation, VarSet)]
rules_w_rhs_fvs = ([(Activation, VarSet)] -> [(Activation, VarSet)])
-> (VarSet -> [(Activation, VarSet)] -> [(Activation, VarSet)])
-> Maybe VarSet
-> [(Activation, VarSet)]
-> [(Activation, VarSet)]
forall b a. b -> (a -> b) -> Maybe a -> b
maybe [(Activation, VarSet)] -> [(Activation, VarSet)]
forall a. a -> a
id (\ids :: VarSet
ids -> ((Activation
AlwaysActive, VarSet
ids)(Activation, VarSet)
-> [(Activation, VarSet)] -> [(Activation, VarSet)]
forall a. a -> [a] -> [a]
:))
(ImpRuleEdges -> Id -> Maybe VarSet
forall a. VarEnv a -> Id -> Maybe a
lookupVarEnv ImpRuleEdges
imp_rule_edges Id
bndr)
[ (CoreRule -> Activation
ru_act CoreRule
rule, VarSet -> UsageDetails -> VarSet
udFreeVars VarSet
bndr_set UsageDetails
rhs_uds)
| (rule :: CoreRule
rule, _, rhs_uds :: UsageDetails
rhs_uds) <- [(CoreRule, UsageDetails, UsageDetails)]
rules_w_uds ]
rule_uds :: [UsageDetails]
rule_uds = ((CoreRule, UsageDetails, UsageDetails) -> UsageDetails)
-> [(CoreRule, UsageDetails, UsageDetails)] -> [UsageDetails]
forall a b. (a -> b) -> [a] -> [b]
map (\(_, l :: UsageDetails
l, r :: UsageDetails
r) -> UsageDetails
l UsageDetails -> UsageDetails -> UsageDetails
`andUDs` UsageDetails
r) [(CoreRule, UsageDetails, UsageDetails)]
rules_w_uds
active_rule_fvs :: VarSet
active_rule_fvs = [VarSet] -> VarSet
unionVarSets [VarSet
fvs | (a :: Activation
a,fvs :: VarSet
fvs) <- [(Activation, VarSet)]
rules_w_rhs_fvs
, Activation -> Bool
is_active Activation
a]
mb_unf_uds :: Maybe UsageDetails
mb_unf_uds = OccEnv -> RecFlag -> Id -> Maybe UsageDetails
occAnalUnfolding OccEnv
env RecFlag
Recursive Id
bndr
inl_fvs :: VarSet
inl_fvs = case Maybe UsageDetails
mb_unf_uds of
Nothing -> VarSet -> UsageDetails -> VarSet
udFreeVars VarSet
bndr_set UsageDetails
rhs_usage1
Just unf_uds :: UsageDetails
unf_uds -> VarSet -> UsageDetails -> VarSet
udFreeVars VarSet
bndr_set UsageDetails
unf_uds
mkLoopBreakerNodes :: OccEnv -> TopLevelFlag
-> VarSet
-> UsageDetails
-> [Details]
-> (UsageDetails,
[LetrecNode])
mkLoopBreakerNodes :: OccEnv
-> TopLevelFlag
-> VarSet
-> UsageDetails
-> [Details]
-> (UsageDetails, [Node Unique Details])
mkLoopBreakerNodes env :: OccEnv
env lvl :: TopLevelFlag
lvl bndr_set :: VarSet
bndr_set body_uds :: UsageDetails
body_uds details_s :: [Details]
details_s
= (UsageDetails
final_uds, (Details -> Id -> Node Unique Details)
-> [Details] -> [Id] -> [Node Unique Details]
forall a b c. (a -> b -> c) -> [a] -> [b] -> [c]
zipWith Details -> Id -> Node Unique Details
mk_lb_node [Details]
details_s [Id]
bndrs')
where
(final_uds :: UsageDetails
final_uds, bndrs' :: [Id]
bndrs') = TopLevelFlag
-> UsageDetails
-> [(Id, UsageDetails, [Id])]
-> (UsageDetails, [Id])
tagRecBinders TopLevelFlag
lvl UsageDetails
body_uds
[ ((Details -> Id
nd_bndr Details
nd)
,(Details -> UsageDetails
nd_uds Details
nd)
,(Details -> [Id]
nd_rhs_bndrs Details
nd))
| Details
nd <- [Details]
details_s ]
mk_lb_node :: Details -> Id -> Node Unique Details
mk_lb_node nd :: Details
nd@(ND { nd_bndr :: Details -> Id
nd_bndr = Id
bndr, nd_rhs :: Details -> CoreExpr
nd_rhs = CoreExpr
rhs, nd_inl :: Details -> VarSet
nd_inl = VarSet
inl_fvs }) bndr' :: Id
bndr'
= Details -> Unique -> [Unique] -> Node Unique Details
forall key payload. payload -> key -> [key] -> Node key payload
DigraphNode Details
nd' (Id -> Unique
varUnique Id
bndr) (VarSet -> [Unique]
forall elt. UniqSet elt -> [Unique]
nonDetKeysUniqSet VarSet
lb_deps)
where
nd' :: Details
nd' = Details
nd { nd_bndr :: Id
nd_bndr = Id
bndr', nd_score :: NodeScore
nd_score = NodeScore
score }
score :: NodeScore
score = OccEnv -> Id -> Id -> CoreExpr -> VarSet -> NodeScore
nodeScore OccEnv
env Id
bndr Id
bndr' CoreExpr
rhs VarSet
lb_deps
lb_deps :: VarSet
lb_deps = ImpRuleEdges -> VarSet -> VarSet
extendFvs_ ImpRuleEdges
rule_fv_env VarSet
inl_fvs
rule_fv_env :: IdEnv IdSet
rule_fv_env :: ImpRuleEdges
rule_fv_env = ImpRuleEdges -> ImpRuleEdges
transClosureFV ([(Id, VarSet)] -> ImpRuleEdges
forall a. [(Id, a)] -> VarEnv a
mkVarEnv [(Id, VarSet)]
init_rule_fvs)
init_rule_fvs :: [(Id, VarSet)]
init_rule_fvs
= [ (Id
b, VarSet
trimmed_rule_fvs)
| ND { nd_bndr :: Details -> Id
nd_bndr = Id
b, nd_active_rule_fvs :: Details -> VarSet
nd_active_rule_fvs = VarSet
rule_fvs } <- [Details]
details_s
, let trimmed_rule_fvs :: VarSet
trimmed_rule_fvs = VarSet
rule_fvs VarSet -> VarSet -> VarSet
`intersectVarSet` VarSet
bndr_set
, Bool -> Bool
not (VarSet -> Bool
isEmptyVarSet VarSet
trimmed_rule_fvs) ]
nodeScore :: OccEnv
-> Id
-> Id
-> CoreExpr
-> VarSet
-> NodeScore
nodeScore :: OccEnv -> Id -> Id -> CoreExpr -> VarSet -> NodeScore
nodeScore env :: OccEnv
env old_bndr :: Id
old_bndr new_bndr :: Id
new_bndr bind_rhs :: CoreExpr
bind_rhs lb_deps :: VarSet
lb_deps
| Bool -> Bool
not (Id -> Bool
isId Id
old_bndr)
= (100, 0, Bool
False)
| Id
old_bndr Id -> VarSet -> Bool
`elemVarSet` VarSet
lb_deps
= (0, 0, Bool
True)
| Bool -> Bool
not (OccEnv -> Id -> Bool
occ_unf_act OccEnv
env Id
old_bndr)
= (0, 0, Bool
True)
| CoreExpr -> Bool
exprIsTrivial CoreExpr
rhs
= Int -> NodeScore
mk_score 10
| DFunUnfolding { df_args :: Unfolding -> [CoreExpr]
df_args = [CoreExpr]
args } <- Unfolding
id_unfolding
= (9, [CoreExpr] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [CoreExpr]
args, Bool
is_lb)
| CoreUnfolding { uf_guidance :: Unfolding -> UnfoldingGuidance
uf_guidance = UnfWhen {} } <- Unfolding
id_unfolding
= Int -> NodeScore
mk_score 6
| CoreExpr -> Bool
forall b. Expr b -> Bool
is_con_app CoreExpr
rhs
= Int -> NodeScore
mk_score 5
| Unfolding -> Bool
isStableUnfolding Unfolding
id_unfolding
, Bool
can_unfold
= Int -> NodeScore
mk_score 3
| OccInfo -> Bool
isOneOcc (Id -> OccInfo
idOccInfo Id
new_bndr)
= Int -> NodeScore
mk_score 2
| Bool
can_unfold
= Int -> NodeScore
mk_score 1
| Bool
otherwise
= (0, 0, Bool
is_lb)
where
mk_score :: Int -> NodeScore
mk_score :: Int -> NodeScore
mk_score rank :: Int
rank = (Int
rank, Int
rhs_size, Bool
is_lb)
is_lb :: Bool
is_lb = OccInfo -> Bool
isStrongLoopBreaker (Id -> OccInfo
idOccInfo Id
old_bndr)
rhs :: CoreExpr
rhs = case Unfolding
id_unfolding of
CoreUnfolding { uf_src :: Unfolding -> UnfoldingSource
uf_src = UnfoldingSource
src, uf_tmpl :: Unfolding -> CoreExpr
uf_tmpl = CoreExpr
unf_rhs }
| UnfoldingSource -> Bool
isStableSource UnfoldingSource
src
-> CoreExpr
unf_rhs
_ -> CoreExpr
bind_rhs
rhs_size :: Int
rhs_size = case Unfolding
id_unfolding of
CoreUnfolding { uf_guidance :: Unfolding -> UnfoldingGuidance
uf_guidance = UnfoldingGuidance
guidance }
| UnfIfGoodArgs { ug_size :: UnfoldingGuidance -> Int
ug_size = Int
size } <- UnfoldingGuidance
guidance
-> Int
size
_ -> CoreExpr -> Int
cheapExprSize CoreExpr
rhs
can_unfold :: Bool
can_unfold = Unfolding -> Bool
canUnfold Unfolding
id_unfolding
id_unfolding :: Unfolding
id_unfolding = Id -> Unfolding
realIdUnfolding Id
old_bndr
is_con_app :: Expr b -> Bool
is_con_app (Var v :: Id
v) = Id -> Bool
isConLikeId Id
v
is_con_app (App f :: Expr b
f _) = Expr b -> Bool
is_con_app Expr b
f
is_con_app (Lam _ e :: Expr b
e) = Expr b -> Bool
is_con_app Expr b
e
is_con_app (Tick _ e :: Expr b
e) = Expr b -> Bool
is_con_app Expr b
e
is_con_app _ = Bool
False
maxExprSize :: Int
maxExprSize :: Int
maxExprSize = 20
cheapExprSize :: CoreExpr -> Int
cheapExprSize :: CoreExpr -> Int
cheapExprSize e :: CoreExpr
e
= Int -> CoreExpr -> Int
go 0 CoreExpr
e
where
go :: Int -> CoreExpr -> Int
go n :: Int
n e :: CoreExpr
e | Int
n Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
>= Int
maxExprSize = Int
n
| Bool
otherwise = Int -> CoreExpr -> Int
go1 Int
n CoreExpr
e
go1 :: Int -> CoreExpr -> Int
go1 n :: Int
n (Var {}) = Int
nInt -> Int -> Int
forall a. Num a => a -> a -> a
+1
go1 n :: Int
n (Lit {}) = Int
nInt -> Int -> Int
forall a. Num a => a -> a -> a
+1
go1 n :: Int
n (Type {}) = Int
n
go1 n :: Int
n (Coercion {}) = Int
n
go1 n :: Int
n (Tick _ e :: CoreExpr
e) = Int -> CoreExpr -> Int
go1 Int
n CoreExpr
e
go1 n :: Int
n (Cast e :: CoreExpr
e _) = Int -> CoreExpr -> Int
go1 Int
n CoreExpr
e
go1 n :: Int
n (App f :: CoreExpr
f a :: CoreExpr
a) = Int -> CoreExpr -> Int
go (Int -> CoreExpr -> Int
go1 Int
n CoreExpr
f) CoreExpr
a
go1 n :: Int
n (Lam b :: Id
b e :: CoreExpr
e)
| Id -> Bool
isTyVar Id
b = Int -> CoreExpr -> Int
go1 Int
n CoreExpr
e
| Bool
otherwise = Int -> CoreExpr -> Int
go (Int
nInt -> Int -> Int
forall a. Num a => a -> a -> a
+1) CoreExpr
e
go1 n :: Int
n (Let b :: CoreBind
b e :: CoreExpr
e) = Int -> [CoreExpr] -> Int
gos (Int -> CoreExpr -> Int
go1 Int
n CoreExpr
e) (CoreBind -> [CoreExpr]
forall b. Bind b -> [Expr b]
rhssOfBind CoreBind
b)
go1 n :: Int
n (Case e :: CoreExpr
e _ _ as :: [Alt Id]
as) = Int -> [CoreExpr] -> Int
gos (Int -> CoreExpr -> Int
go1 Int
n CoreExpr
e) ([Alt Id] -> [CoreExpr]
forall b. [Alt b] -> [Expr b]
rhssOfAlts [Alt Id]
as)
gos :: Int -> [CoreExpr] -> Int
gos n :: Int
n [] = Int
n
gos n :: Int
n (e :: CoreExpr
e:es :: [CoreExpr]
es) | Int
n Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
>= Int
maxExprSize = Int
n
| Bool
otherwise = Int -> [CoreExpr] -> Int
gos (Int -> CoreExpr -> Int
go1 Int
n CoreExpr
e) [CoreExpr]
es
betterLB :: NodeScore -> NodeScore -> Bool
betterLB :: NodeScore -> NodeScore -> Bool
betterLB (rank1 :: Int
rank1, size1 :: Int
size1, lb1 :: Bool
lb1) (rank2 :: Int
rank2, size2 :: Int
size2, _)
| Int
rank1 Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
< Int
rank2 = Bool
True
| Int
rank1 Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
> Int
rank2 = Bool
False
| Int
size1 Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
< Int
size2 = Bool
False
| Int
size1 Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
> Int
size2 = Bool
True
| Bool
lb1 = Bool
True
| Bool
otherwise = Bool
False
occAnalRhs :: OccEnv -> RecFlag -> Id -> [CoreBndr] -> CoreExpr
-> (UsageDetails, [CoreBndr], CoreExpr)
occAnalRhs :: OccEnv
-> RecFlag
-> Id
-> [Id]
-> CoreExpr
-> (UsageDetails, [Id], CoreExpr)
occAnalRhs env :: OccEnv
env Recursive _ bndrs :: [Id]
bndrs body :: CoreExpr
body
= OccEnv -> [Id] -> CoreExpr -> (UsageDetails, [Id], CoreExpr)
occAnalRecRhs OccEnv
env [Id]
bndrs CoreExpr
body
occAnalRhs env :: OccEnv
env NonRecursive id :: Id
id bndrs :: [Id]
bndrs body :: CoreExpr
body
= OccEnv -> Id -> [Id] -> CoreExpr -> (UsageDetails, [Id], CoreExpr)
occAnalNonRecRhs OccEnv
env Id
id [Id]
bndrs CoreExpr
body
occAnalRecRhs :: OccEnv -> [CoreBndr] -> CoreExpr
-> (UsageDetails, [CoreBndr], CoreExpr)
occAnalRecRhs :: OccEnv -> [Id] -> CoreExpr -> (UsageDetails, [Id], CoreExpr)
occAnalRecRhs env :: OccEnv
env bndrs :: [Id]
bndrs body :: CoreExpr
body = OccEnv -> [Id] -> CoreExpr -> (UsageDetails, [Id], CoreExpr)
occAnalLamOrRhs (OccEnv -> OccEnv
rhsCtxt OccEnv
env) [Id]
bndrs CoreExpr
body
occAnalNonRecRhs :: OccEnv
-> Id -> [CoreBndr] -> CoreExpr
-> (UsageDetails, [CoreBndr], CoreExpr)
occAnalNonRecRhs :: OccEnv -> Id -> [Id] -> CoreExpr -> (UsageDetails, [Id], CoreExpr)
occAnalNonRecRhs env :: OccEnv
env bndr :: Id
bndr bndrs :: [Id]
bndrs body :: CoreExpr
body
= OccEnv -> [Id] -> CoreExpr -> (UsageDetails, [Id], CoreExpr)
occAnalLamOrRhs OccEnv
rhs_env [Id]
bndrs CoreExpr
body
where
env1 :: OccEnv
env1 | Bool
is_join_point = OccEnv
env
| Bool
certainly_inline = OccEnv
env
| Bool
otherwise = OccEnv -> OccEnv
rhsCtxt OccEnv
env
rhs_env :: OccEnv
rhs_env = OccEnv
env1 { occ_one_shots :: OneShots
occ_one_shots = Demand -> OneShots
argOneShots Demand
dmd }
certainly_inline :: Bool
certainly_inline
= case OccInfo
occ of
OneOcc { occ_in_lam :: OccInfo -> Bool
occ_in_lam = Bool
in_lam, occ_one_br :: OccInfo -> Bool
occ_one_br = Bool
one_br }
-> Bool -> Bool
not Bool
in_lam Bool -> Bool -> Bool
&& Bool
one_br Bool -> Bool -> Bool
&& Bool
active Bool -> Bool -> Bool
&& Bool
not_stable
_ -> Bool
False
is_join_point :: Bool
is_join_point = OccInfo -> Bool
isAlwaysTailCalled OccInfo
occ
occ :: OccInfo
occ = Id -> OccInfo
idOccInfo Id
bndr
dmd :: Demand
dmd = Id -> Demand
idDemandInfo Id
bndr
active :: Bool
active = Activation -> Bool
isAlwaysActive (Id -> Activation
idInlineActivation Id
bndr)
not_stable :: Bool
not_stable = Bool -> Bool
not (Unfolding -> Bool
isStableUnfolding (Id -> Unfolding
idUnfolding Id
bndr))
occAnalUnfolding :: OccEnv
-> RecFlag
-> Id
-> Maybe UsageDetails
occAnalUnfolding :: OccEnv -> RecFlag -> Id -> Maybe UsageDetails
occAnalUnfolding env :: OccEnv
env rec_flag :: RecFlag
rec_flag id :: Id
id
= case Id -> Unfolding
realIdUnfolding Id
id of
CoreUnfolding { uf_tmpl :: Unfolding -> CoreExpr
uf_tmpl = CoreExpr
rhs, uf_src :: Unfolding -> UnfoldingSource
uf_src = UnfoldingSource
src }
| Bool -> Bool
not (UnfoldingSource -> Bool
isStableSource UnfoldingSource
src)
-> Maybe UsageDetails
forall a. Maybe a
Nothing
| Bool
otherwise
-> UsageDetails -> Maybe UsageDetails
forall a. a -> Maybe a
Just (UsageDetails -> Maybe UsageDetails)
-> UsageDetails -> Maybe UsageDetails
forall a b. (a -> b) -> a -> b
$ UsageDetails -> UsageDetails
markAllMany UsageDetails
usage
where
(bndrs :: [Id]
bndrs, body :: CoreExpr
body) = CoreExpr -> ([Id], CoreExpr)
forall b. Expr b -> ([b], Expr b)
collectBinders CoreExpr
rhs
(usage :: UsageDetails
usage, _, _) = OccEnv
-> RecFlag
-> Id
-> [Id]
-> CoreExpr
-> (UsageDetails, [Id], CoreExpr)
occAnalRhs OccEnv
env RecFlag
rec_flag Id
id [Id]
bndrs CoreExpr
body
DFunUnfolding { df_bndrs :: Unfolding -> [Id]
df_bndrs = [Id]
bndrs, df_args :: Unfolding -> [CoreExpr]
df_args = [CoreExpr]
args }
-> UsageDetails -> Maybe UsageDetails
forall a. a -> Maybe a
Just (UsageDetails -> Maybe UsageDetails)
-> UsageDetails -> Maybe UsageDetails
forall a b. (a -> b) -> a -> b
$ UsageDetails -> UsageDetails
zapDetails (UsageDetails -> [Id] -> UsageDetails
delDetailsList UsageDetails
usage [Id]
bndrs)
where
usage :: UsageDetails
usage = [UsageDetails] -> UsageDetails
andUDsList ((CoreExpr -> UsageDetails) -> [CoreExpr] -> [UsageDetails]
forall a b. (a -> b) -> [a] -> [b]
map ((UsageDetails, CoreExpr) -> UsageDetails
forall a b. (a, b) -> a
fst ((UsageDetails, CoreExpr) -> UsageDetails)
-> (CoreExpr -> (UsageDetails, CoreExpr))
-> CoreExpr
-> UsageDetails
forall b c a. (b -> c) -> (a -> b) -> a -> c
. OccEnv -> CoreExpr -> (UsageDetails, CoreExpr)
occAnal OccEnv
env) [CoreExpr]
args)
_ -> Maybe UsageDetails
forall a. Maybe a
Nothing
occAnalRules :: OccEnv
-> Maybe JoinArity
-> RecFlag
-> Id
-> [(CoreRule,
UsageDetails,
UsageDetails)]
occAnalRules :: OccEnv
-> Maybe Int
-> RecFlag
-> Id
-> [(CoreRule, UsageDetails, UsageDetails)]
occAnalRules env :: OccEnv
env mb_expected_join_arity :: Maybe Int
mb_expected_join_arity rec_flag :: RecFlag
rec_flag id :: Id
id
= [ (CoreRule
rule, UsageDetails
lhs_uds, UsageDetails
rhs_uds) | rule :: CoreRule
rule@Rule {} <- Id -> [CoreRule]
idCoreRules Id
id
, let (lhs_uds :: UsageDetails
lhs_uds, rhs_uds :: UsageDetails
rhs_uds) = CoreRule -> (UsageDetails, UsageDetails)
occ_anal_rule CoreRule
rule ]
where
occ_anal_rule :: CoreRule -> (UsageDetails, UsageDetails)
occ_anal_rule (Rule { ru_bndrs :: CoreRule -> [Id]
ru_bndrs = [Id]
bndrs, ru_args :: CoreRule -> [CoreExpr]
ru_args = [CoreExpr]
args, ru_rhs :: CoreRule -> CoreExpr
ru_rhs = CoreExpr
rhs })
= (UsageDetails
lhs_uds, UsageDetails
final_rhs_uds)
where
lhs_uds :: UsageDetails
lhs_uds = UsageDetails -> VarSet -> UsageDetails
addManyOccsSet UsageDetails
emptyDetails (VarSet -> UsageDetails) -> VarSet -> UsageDetails
forall a b. (a -> b) -> a -> b
$
([CoreExpr] -> VarSet
exprsFreeVars [CoreExpr]
args VarSet -> [Id] -> VarSet
`delVarSetList` [Id]
bndrs)
(rhs_bndrs :: [Id]
rhs_bndrs, rhs_body :: CoreExpr
rhs_body) = CoreExpr -> ([Id], CoreExpr)
forall b. Expr b -> ([b], Expr b)
collectBinders CoreExpr
rhs
(rhs_uds :: UsageDetails
rhs_uds, _, _) = OccEnv
-> RecFlag
-> Id
-> [Id]
-> CoreExpr
-> (UsageDetails, [Id], CoreExpr)
occAnalRhs OccEnv
env RecFlag
rec_flag Id
id [Id]
rhs_bndrs CoreExpr
rhs_body
final_rhs_uds :: UsageDetails
final_rhs_uds = [CoreExpr] -> UsageDetails -> UsageDetails
forall a. [a] -> UsageDetails -> UsageDetails
adjust_tail_info [CoreExpr]
args (UsageDetails -> UsageDetails) -> UsageDetails -> UsageDetails
forall a b. (a -> b) -> a -> b
$ UsageDetails -> UsageDetails
markAllMany (UsageDetails -> UsageDetails) -> UsageDetails -> UsageDetails
forall a b. (a -> b) -> a -> b
$
(UsageDetails
rhs_uds UsageDetails -> [Id] -> UsageDetails
`delDetailsList` [Id]
bndrs)
occ_anal_rule _
= (UsageDetails
emptyDetails, UsageDetails
emptyDetails)
adjust_tail_info :: [a] -> UsageDetails -> UsageDetails
adjust_tail_info args :: [a]
args uds :: UsageDetails
uds
= case Maybe Int
mb_expected_join_arity of
Just ar :: Int
ar | [a]
args [a] -> Int -> Bool
forall a. [a] -> Int -> Bool
`lengthIs` Int
ar -> UsageDetails
uds
_ -> UsageDetails -> UsageDetails
markAllNonTailCalled UsageDetails
uds
occAnal :: OccEnv
-> CoreExpr
-> (UsageDetails,
CoreExpr)
occAnal :: OccEnv -> CoreExpr -> (UsageDetails, CoreExpr)
occAnal _ expr :: CoreExpr
expr@(Type _) = (UsageDetails
emptyDetails, CoreExpr
expr)
occAnal _ expr :: CoreExpr
expr@(Lit _) = (UsageDetails
emptyDetails, CoreExpr
expr)
occAnal env :: OccEnv
env expr :: CoreExpr
expr@(Var _) = OccEnv
-> (CoreExpr, [CoreExpr], [Tickish Id]) -> (UsageDetails, CoreExpr)
occAnalApp OccEnv
env (CoreExpr
expr, [], [])
occAnal _ (Coercion co :: Coercion
co)
= (UsageDetails -> VarSet -> UsageDetails
addManyOccsSet UsageDetails
emptyDetails (Coercion -> VarSet
coVarsOfCo Coercion
co), Coercion -> CoreExpr
forall b. Coercion -> Expr b
Coercion Coercion
co)
occAnal env :: OccEnv
env (Tick tickish :: Tickish Id
tickish body :: CoreExpr
body)
| SourceNote{} <- Tickish Id
tickish
= (UsageDetails
usage, Tickish Id -> CoreExpr -> CoreExpr
forall b. Tickish Id -> Expr b -> Expr b
Tick Tickish Id
tickish CoreExpr
body')
| Tickish Id
tickish Tickish Id -> TickishScoping -> Bool
forall id. Tickish id -> TickishScoping -> Bool
`tickishScopesLike` TickishScoping
SoftScope
= (UsageDetails -> UsageDetails
markAllNonTailCalled UsageDetails
usage, Tickish Id -> CoreExpr -> CoreExpr
forall b. Tickish Id -> Expr b -> Expr b
Tick Tickish Id
tickish CoreExpr
body')
| Breakpoint _ ids :: [Id]
ids <- Tickish Id
tickish
= (UsageDetails
usage_lam UsageDetails -> UsageDetails -> UsageDetails
`andUDs` (Id -> UsageDetails -> UsageDetails)
-> UsageDetails -> [Id] -> UsageDetails
forall (t :: * -> *) a b.
Foldable t =>
(a -> b -> b) -> b -> t a -> b
foldr Id -> UsageDetails -> UsageDetails
addManyOccs UsageDetails
emptyDetails [Id]
ids, Tickish Id -> CoreExpr -> CoreExpr
forall b. Tickish Id -> Expr b -> Expr b
Tick Tickish Id
tickish CoreExpr
body')
| Bool
otherwise
= (UsageDetails
usage_lam, Tickish Id -> CoreExpr -> CoreExpr
forall b. Tickish Id -> Expr b -> Expr b
Tick Tickish Id
tickish CoreExpr
body')
where
!(usage :: UsageDetails
usage,body' :: CoreExpr
body') = OccEnv -> CoreExpr -> (UsageDetails, CoreExpr)
occAnal OccEnv
env CoreExpr
body
usage_lam :: UsageDetails
usage_lam = UsageDetails -> UsageDetails
markAllNonTailCalled (UsageDetails -> UsageDetails
markAllInsideLam UsageDetails
usage)
occAnal env :: OccEnv
env (Cast expr :: CoreExpr
expr co :: Coercion
co)
= case OccEnv -> CoreExpr -> (UsageDetails, CoreExpr)
occAnal OccEnv
env CoreExpr
expr of { (usage :: UsageDetails
usage, expr' :: CoreExpr
expr') ->
let usage1 :: UsageDetails
usage1 = Bool -> UsageDetails -> UsageDetails
zapDetailsIf (OccEnv -> Bool
isRhsEnv OccEnv
env) UsageDetails
usage
usage2 :: UsageDetails
usage2 = UsageDetails -> VarSet -> UsageDetails
addManyOccsSet UsageDetails
usage1 (Coercion -> VarSet
coVarsOfCo Coercion
co)
in (UsageDetails -> UsageDetails
markAllNonTailCalled UsageDetails
usage2, CoreExpr -> Coercion -> CoreExpr
forall b. Expr b -> Coercion -> Expr b
Cast CoreExpr
expr' Coercion
co)
}
occAnal env :: OccEnv
env app :: CoreExpr
app@(App _ _)
= OccEnv
-> (CoreExpr, [CoreExpr], [Tickish Id]) -> (UsageDetails, CoreExpr)
occAnalApp OccEnv
env ((Tickish Id -> Bool)
-> CoreExpr -> (CoreExpr, [CoreExpr], [Tickish Id])
forall b.
(Tickish Id -> Bool) -> Expr b -> (Expr b, [Expr b], [Tickish Id])
collectArgsTicks Tickish Id -> Bool
forall id. Tickish id -> Bool
tickishFloatable CoreExpr
app)
occAnal env :: OccEnv
env (Lam x :: Id
x body :: CoreExpr
body)
| Id -> Bool
isTyVar Id
x
= case OccEnv -> CoreExpr -> (UsageDetails, CoreExpr)
occAnal OccEnv
env CoreExpr
body of { (body_usage :: UsageDetails
body_usage, body' :: CoreExpr
body') ->
(UsageDetails -> UsageDetails
markAllNonTailCalled UsageDetails
body_usage, Id -> CoreExpr -> CoreExpr
forall b. b -> Expr b -> Expr b
Lam Id
x CoreExpr
body')
}
occAnal env :: OccEnv
env expr :: CoreExpr
expr@(Lam _ _)
= case OccEnv -> [Id] -> CoreExpr -> (UsageDetails, [Id], CoreExpr)
occAnalLamOrRhs OccEnv
env [Id]
binders CoreExpr
body of { (usage :: UsageDetails
usage, tagged_binders :: [Id]
tagged_binders, body' :: CoreExpr
body') ->
let
expr' :: CoreExpr
expr' = [Id] -> CoreExpr -> CoreExpr
forall b. [b] -> Expr b -> Expr b
mkLams [Id]
tagged_binders CoreExpr
body'
usage1 :: UsageDetails
usage1 = UsageDetails -> UsageDetails
markAllNonTailCalled UsageDetails
usage
one_shot_gp :: Bool
one_shot_gp = (Id -> Bool) -> [Id] -> Bool
forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
all Id -> Bool
isOneShotBndr [Id]
tagged_binders
final_usage :: UsageDetails
final_usage | Bool
one_shot_gp = UsageDetails
usage1
| Bool
otherwise = UsageDetails -> UsageDetails
markAllInsideLam UsageDetails
usage1
in
(UsageDetails
final_usage, CoreExpr
expr') }
where
(binders :: [Id]
binders, body :: CoreExpr
body) = CoreExpr -> ([Id], CoreExpr)
forall b. Expr b -> ([b], Expr b)
collectBinders CoreExpr
expr
occAnal env :: OccEnv
env (Case scrut :: CoreExpr
scrut bndr :: Id
bndr ty :: Type
ty alts :: [Alt Id]
alts)
= case CoreExpr -> [Alt Id] -> (UsageDetails, CoreExpr)
forall a b.
CoreExpr -> [(AltCon, a, b)] -> (UsageDetails, CoreExpr)
occ_anal_scrut CoreExpr
scrut [Alt Id]
alts of { (scrut_usage :: UsageDetails
scrut_usage, scrut' :: CoreExpr
scrut') ->
case (Alt Id -> (UsageDetails, Alt Id))
-> [Alt Id] -> ([UsageDetails], [Alt Id])
forall a b c. (a -> (b, c)) -> [a] -> ([b], [c])
mapAndUnzip Alt Id -> (UsageDetails, Alt Id)
occ_anal_alt [Alt Id]
alts of { (alts_usage_s :: [UsageDetails]
alts_usage_s, alts' :: [Alt Id]
alts') ->
let
alts_usage :: UsageDetails
alts_usage = (UsageDetails -> UsageDetails -> UsageDetails)
-> UsageDetails -> [UsageDetails] -> UsageDetails
forall (t :: * -> *) a b.
Foldable t =>
(a -> b -> b) -> b -> t a -> b
foldr UsageDetails -> UsageDetails -> UsageDetails
orUDs UsageDetails
emptyDetails [UsageDetails]
alts_usage_s
(alts_usage1 :: UsageDetails
alts_usage1, tagged_bndr :: Id
tagged_bndr) = UsageDetails -> Id -> (UsageDetails, Id)
tagLamBinder UsageDetails
alts_usage Id
bndr
total_usage :: UsageDetails
total_usage = UsageDetails -> UsageDetails
markAllNonTailCalled UsageDetails
scrut_usage UsageDetails -> UsageDetails -> UsageDetails
`andUDs` UsageDetails
alts_usage1
in
UsageDetails
total_usage UsageDetails
-> (UsageDetails, CoreExpr) -> (UsageDetails, CoreExpr)
forall a b. a -> b -> b
`seq` (UsageDetails
total_usage, CoreExpr -> Id -> Type -> [Alt Id] -> CoreExpr
forall b. Expr b -> b -> Type -> [Alt b] -> Expr b
Case CoreExpr
scrut' Id
tagged_bndr Type
ty [Alt Id]
alts') }}
where
alt_env :: (OccEnv, Maybe (Id, CoreExpr))
alt_env = OccEnv -> CoreExpr -> Id -> (OccEnv, Maybe (Id, CoreExpr))
mkAltEnv OccEnv
env CoreExpr
scrut Id
bndr
occ_anal_alt :: Alt Id -> (UsageDetails, Alt Id)
occ_anal_alt = (OccEnv, Maybe (Id, CoreExpr)) -> Alt Id -> (UsageDetails, Alt Id)
occAnalAlt (OccEnv, Maybe (Id, CoreExpr))
alt_env
occ_anal_scrut :: CoreExpr -> [(AltCon, a, b)] -> (UsageDetails, CoreExpr)
occ_anal_scrut (Var v :: Id
v) (alt1 :: (AltCon, a, b)
alt1 : other_alts :: [(AltCon, a, b)]
other_alts)
| Bool -> Bool
not ([(AltCon, a, b)] -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null [(AltCon, a, b)]
other_alts) Bool -> Bool -> Bool
|| Bool -> Bool
not ((AltCon, a, b) -> Bool
forall a b. (AltCon, a, b) -> Bool
isDefaultAlt (AltCon, a, b)
alt1)
= (OccEnv -> Id -> Bool -> Int -> UsageDetails
mkOneOcc OccEnv
env Id
v Bool
True 0, Id -> CoreExpr
forall b. Id -> Expr b
Var Id
v)
occ_anal_scrut (Tick t :: Tickish Id
t e :: CoreExpr
e) alts :: [(AltCon, a, b)]
alts
| Tickish Id
t Tickish Id -> TickishScoping -> Bool
forall id. Tickish id -> TickishScoping -> Bool
`tickishScopesLike` TickishScoping
SoftScope
= (CoreExpr -> CoreExpr)
-> (UsageDetails, CoreExpr) -> (UsageDetails, CoreExpr)
forall (a :: * -> * -> *) b c d.
Arrow a =>
a b c -> a (d, b) (d, c)
second (Tickish Id -> CoreExpr -> CoreExpr
forall b. Tickish Id -> Expr b -> Expr b
Tick Tickish Id
t) ((UsageDetails, CoreExpr) -> (UsageDetails, CoreExpr))
-> (UsageDetails, CoreExpr) -> (UsageDetails, CoreExpr)
forall a b. (a -> b) -> a -> b
$ CoreExpr -> [(AltCon, a, b)] -> (UsageDetails, CoreExpr)
occ_anal_scrut CoreExpr
e [(AltCon, a, b)]
alts
occ_anal_scrut scrut :: CoreExpr
scrut _alts :: [(AltCon, a, b)]
_alts
= OccEnv -> CoreExpr -> (UsageDetails, CoreExpr)
occAnal (OccEnv -> OccEnv
vanillaCtxt OccEnv
env) CoreExpr
scrut
occAnal env :: OccEnv
env (Let bind :: CoreBind
bind body :: CoreExpr
body)
= case OccEnv -> CoreExpr -> (UsageDetails, CoreExpr)
occAnal OccEnv
env CoreExpr
body of { (body_usage :: UsageDetails
body_usage, body' :: CoreExpr
body') ->
case OccEnv
-> TopLevelFlag
-> ImpRuleEdges
-> CoreBind
-> UsageDetails
-> (UsageDetails, CoreProgram)
occAnalBind OccEnv
env TopLevelFlag
NotTopLevel
ImpRuleEdges
noImpRuleEdges CoreBind
bind
UsageDetails
body_usage of { (final_usage :: UsageDetails
final_usage, new_binds :: CoreProgram
new_binds) ->
(UsageDetails
final_usage, CoreProgram -> CoreExpr -> CoreExpr
forall b. [Bind b] -> Expr b -> Expr b
mkLets CoreProgram
new_binds CoreExpr
body') }}
occAnalArgs :: OccEnv -> [CoreExpr] -> [OneShots] -> (UsageDetails, [CoreExpr])
occAnalArgs :: OccEnv -> [CoreExpr] -> [OneShots] -> (UsageDetails, [CoreExpr])
occAnalArgs _ [] _
= (UsageDetails
emptyDetails, [])
occAnalArgs env :: OccEnv
env (arg :: CoreExpr
arg:args :: [CoreExpr]
args) one_shots :: [OneShots]
one_shots
| CoreExpr -> Bool
forall b. Expr b -> Bool
isTypeArg CoreExpr
arg
= case OccEnv -> [CoreExpr] -> [OneShots] -> (UsageDetails, [CoreExpr])
occAnalArgs OccEnv
env [CoreExpr]
args [OneShots]
one_shots of { (uds :: UsageDetails
uds, args' :: [CoreExpr]
args') ->
(UsageDetails
uds, CoreExpr
argCoreExpr -> [CoreExpr] -> [CoreExpr]
forall a. a -> [a] -> [a]
:[CoreExpr]
args') }
| Bool
otherwise
= case OccEnv -> [OneShots] -> (OccEnv, [OneShots])
argCtxt OccEnv
env [OneShots]
one_shots of { (arg_env :: OccEnv
arg_env, one_shots' :: [OneShots]
one_shots') ->
case OccEnv -> CoreExpr -> (UsageDetails, CoreExpr)
occAnal OccEnv
arg_env CoreExpr
arg of { (uds1 :: UsageDetails
uds1, arg' :: CoreExpr
arg') ->
case OccEnv -> [CoreExpr] -> [OneShots] -> (UsageDetails, [CoreExpr])
occAnalArgs OccEnv
env [CoreExpr]
args [OneShots]
one_shots' of { (uds2 :: UsageDetails
uds2, args' :: [CoreExpr]
args') ->
(UsageDetails
uds1 UsageDetails -> UsageDetails -> UsageDetails
`andUDs` UsageDetails
uds2, CoreExpr
arg'CoreExpr -> [CoreExpr] -> [CoreExpr]
forall a. a -> [a] -> [a]
:[CoreExpr]
args') }}}
occAnalApp :: OccEnv
-> (Expr CoreBndr, [Arg CoreBndr], [Tickish Id])
-> (UsageDetails, Expr CoreBndr)
occAnalApp :: OccEnv
-> (CoreExpr, [CoreExpr], [Tickish Id]) -> (UsageDetails, CoreExpr)
occAnalApp env :: OccEnv
env (Var fun :: Id
fun, args :: [CoreExpr]
args, ticks :: [Tickish Id]
ticks)
| [Tickish Id] -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null [Tickish Id]
ticks = (UsageDetails
uds, CoreExpr -> [CoreExpr] -> CoreExpr
forall b. Expr b -> [Expr b] -> Expr b
mkApps (Id -> CoreExpr
forall b. Id -> Expr b
Var Id
fun) [CoreExpr]
args')
| Bool
otherwise = (UsageDetails
uds, [Tickish Id] -> CoreExpr -> CoreExpr
mkTicks [Tickish Id]
ticks (CoreExpr -> CoreExpr) -> CoreExpr -> CoreExpr
forall a b. (a -> b) -> a -> b
$ CoreExpr -> [CoreExpr] -> CoreExpr
forall b. Expr b -> [Expr b] -> Expr b
mkApps (Id -> CoreExpr
forall b. Id -> Expr b
Var Id
fun) [CoreExpr]
args')
where
uds :: UsageDetails
uds = UsageDetails
fun_uds UsageDetails -> UsageDetails -> UsageDetails
`andUDs` UsageDetails
final_args_uds
!(args_uds :: UsageDetails
args_uds, args' :: [CoreExpr]
args') = OccEnv -> [CoreExpr] -> [OneShots] -> (UsageDetails, [CoreExpr])
occAnalArgs OccEnv
env [CoreExpr]
args [OneShots]
one_shots
!final_args_uds :: UsageDetails
final_args_uds
| OccEnv -> Bool
isRhsEnv OccEnv
env Bool -> Bool -> Bool
&& Bool
is_exp = UsageDetails -> UsageDetails
markAllNonTailCalled (UsageDetails -> UsageDetails) -> UsageDetails -> UsageDetails
forall a b. (a -> b) -> a -> b
$
UsageDetails -> UsageDetails
markAllInsideLam UsageDetails
args_uds
| Bool
otherwise = UsageDetails -> UsageDetails
markAllNonTailCalled UsageDetails
args_uds
n_val_args :: Int
n_val_args = [CoreExpr] -> Int
forall b. [Arg b] -> Int
valArgCount [CoreExpr]
args
n_args :: Int
n_args = [CoreExpr] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [CoreExpr]
args
fun_uds :: UsageDetails
fun_uds = OccEnv -> Id -> Bool -> Int -> UsageDetails
mkOneOcc OccEnv
env Id
fun (Int
n_val_args Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
> 0) Int
n_args
is_exp :: Bool
is_exp = CheapAppFun
isExpandableApp Id
fun Int
n_val_args
one_shots :: [OneShots]
one_shots = StrictSig -> Int -> [OneShots]
argsOneShots (Id -> StrictSig
idStrictness Id
fun) Int
guaranteed_val_args
guaranteed_val_args :: Int
guaranteed_val_args = Int
n_val_args Int -> Int -> Int
forall a. Num a => a -> a -> a
+ OneShots -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length ((OneShotInfo -> Bool) -> OneShots -> OneShots
forall a. (a -> Bool) -> [a] -> [a]
takeWhile OneShotInfo -> Bool
isOneShotInfo
(OccEnv -> OneShots
occ_one_shots OccEnv
env))
occAnalApp env :: OccEnv
env (fun :: CoreExpr
fun, args :: [CoreExpr]
args, ticks :: [Tickish Id]
ticks)
= (UsageDetails -> UsageDetails
markAllNonTailCalled (UsageDetails
fun_uds UsageDetails -> UsageDetails -> UsageDetails
`andUDs` UsageDetails
args_uds),
[Tickish Id] -> CoreExpr -> CoreExpr
mkTicks [Tickish Id]
ticks (CoreExpr -> CoreExpr) -> CoreExpr -> CoreExpr
forall a b. (a -> b) -> a -> b
$ CoreExpr -> [CoreExpr] -> CoreExpr
forall b. Expr b -> [Expr b] -> Expr b
mkApps CoreExpr
fun' [CoreExpr]
args')
where
!(fun_uds :: UsageDetails
fun_uds, fun' :: CoreExpr
fun') = OccEnv -> CoreExpr -> (UsageDetails, CoreExpr)
occAnal (OccEnv -> [CoreExpr] -> OccEnv
addAppCtxt OccEnv
env [CoreExpr]
args) CoreExpr
fun
!(args_uds :: UsageDetails
args_uds, args' :: [CoreExpr]
args') = OccEnv -> [CoreExpr] -> [OneShots] -> (UsageDetails, [CoreExpr])
occAnalArgs OccEnv
env [CoreExpr]
args []
zapDetailsIf :: Bool
-> UsageDetails
-> UsageDetails
zapDetailsIf :: Bool -> UsageDetails -> UsageDetails
zapDetailsIf True uds :: UsageDetails
uds = UsageDetails -> UsageDetails
zapDetails UsageDetails
uds
zapDetailsIf False uds :: UsageDetails
uds = UsageDetails
uds
occAnalLamOrRhs :: OccEnv -> [CoreBndr] -> CoreExpr
-> (UsageDetails, [CoreBndr], CoreExpr)
occAnalLamOrRhs :: OccEnv -> [Id] -> CoreExpr -> (UsageDetails, [Id], CoreExpr)
occAnalLamOrRhs env :: OccEnv
env [] body :: CoreExpr
body
= case OccEnv -> CoreExpr -> (UsageDetails, CoreExpr)
occAnal OccEnv
env CoreExpr
body of (body_usage :: UsageDetails
body_usage, body' :: CoreExpr
body') -> (UsageDetails
body_usage, [], CoreExpr
body')
occAnalLamOrRhs env :: OccEnv
env (bndr :: Id
bndr:bndrs :: [Id]
bndrs) body :: CoreExpr
body
| Id -> Bool
isTyVar Id
bndr
=
case OccEnv -> [Id] -> CoreExpr -> (UsageDetails, [Id], CoreExpr)
occAnalLamOrRhs OccEnv
env [Id]
bndrs CoreExpr
body of
(body_usage :: UsageDetails
body_usage, bndrs' :: [Id]
bndrs', body' :: CoreExpr
body') -> (UsageDetails
body_usage, Id
bndrId -> [Id] -> [Id]
forall a. a -> [a] -> [a]
:[Id]
bndrs', CoreExpr
body')
occAnalLamOrRhs env :: OccEnv
env binders :: [Id]
binders body :: CoreExpr
body
= case OccEnv -> CoreExpr -> (UsageDetails, CoreExpr)
occAnal OccEnv
env_body CoreExpr
body of { (body_usage :: UsageDetails
body_usage, body' :: CoreExpr
body') ->
let
(final_usage :: UsageDetails
final_usage, tagged_binders :: [Id]
tagged_binders) = UsageDetails -> [Id] -> (UsageDetails, [Id])
tagLamBinders UsageDetails
body_usage [Id]
binders'
in
(UsageDetails
final_usage, [Id]
tagged_binders, CoreExpr
body') }
where
(env_body :: OccEnv
env_body, binders' :: [Id]
binders') = OccEnv -> [Id] -> (OccEnv, [Id])
oneShotGroup OccEnv
env [Id]
binders
occAnalAlt :: (OccEnv, Maybe (Id, CoreExpr))
-> CoreAlt
-> (UsageDetails, Alt IdWithOccInfo)
occAnalAlt :: (OccEnv, Maybe (Id, CoreExpr)) -> Alt Id -> (UsageDetails, Alt Id)
occAnalAlt (env :: OccEnv
env, scrut_bind :: Maybe (Id, CoreExpr)
scrut_bind) (con :: AltCon
con, bndrs :: [Id]
bndrs, rhs :: CoreExpr
rhs)
= case OccEnv -> CoreExpr -> (UsageDetails, CoreExpr)
occAnal OccEnv
env CoreExpr
rhs of { (rhs_usage1 :: UsageDetails
rhs_usage1, rhs1 :: CoreExpr
rhs1) ->
let
(alt_usg :: UsageDetails
alt_usg, tagged_bndrs :: [Id]
tagged_bndrs) = UsageDetails -> [Id] -> (UsageDetails, [Id])
tagLamBinders UsageDetails
rhs_usage1 [Id]
bndrs
(alt_usg' :: UsageDetails
alt_usg', rhs2 :: CoreExpr
rhs2) = OccEnv
-> Maybe (Id, CoreExpr)
-> UsageDetails
-> [Id]
-> CoreExpr
-> (UsageDetails, CoreExpr)
wrapAltRHS OccEnv
env Maybe (Id, CoreExpr)
scrut_bind UsageDetails
alt_usg [Id]
tagged_bndrs CoreExpr
rhs1
in
(UsageDetails
alt_usg', (AltCon
con, [Id]
tagged_bndrs, CoreExpr
rhs2)) }
wrapAltRHS :: OccEnv
-> Maybe (Id, CoreExpr)
-> UsageDetails
-> [Var]
-> CoreExpr
-> (UsageDetails, CoreExpr)
wrapAltRHS :: OccEnv
-> Maybe (Id, CoreExpr)
-> UsageDetails
-> [Id]
-> CoreExpr
-> (UsageDetails, CoreExpr)
wrapAltRHS env :: OccEnv
env (Just (scrut_var :: Id
scrut_var, let_rhs :: CoreExpr
let_rhs)) alt_usg :: UsageDetails
alt_usg bndrs :: [Id]
bndrs alt_rhs :: CoreExpr
alt_rhs
| OccEnv -> Bool
occ_binder_swap OccEnv
env
, Id
scrut_var Id -> UsageDetails -> Bool
`usedIn` UsageDetails
alt_usg
, Bool -> Bool
not Bool
captured
= ( UsageDetails
alt_usg' UsageDetails -> UsageDetails -> UsageDetails
`andUDs` UsageDetails
let_rhs_usg
, CoreBind -> CoreExpr -> CoreExpr
forall b. Bind b -> Expr b -> Expr b
Let (Id -> CoreExpr -> CoreBind
forall b. b -> Expr b -> Bind b
NonRec Id
tagged_scrut_var CoreExpr
let_rhs') CoreExpr
alt_rhs )
where
captured :: Bool
captured = (Id -> Bool) -> [Id] -> Bool
forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
any (Id -> UsageDetails -> Bool
`usedIn` UsageDetails
let_rhs_usg) [Id]
bndrs
(let_rhs_usg :: UsageDetails
let_rhs_usg, let_rhs' :: CoreExpr
let_rhs') = OccEnv -> CoreExpr -> (UsageDetails, CoreExpr)
occAnal OccEnv
env CoreExpr
let_rhs
(alt_usg' :: UsageDetails
alt_usg', tagged_scrut_var :: Id
tagged_scrut_var) = UsageDetails -> Id -> (UsageDetails, Id)
tagLamBinder UsageDetails
alt_usg Id
scrut_var
wrapAltRHS _ _ alt_usg :: UsageDetails
alt_usg _ alt_rhs :: CoreExpr
alt_rhs
= (UsageDetails
alt_usg, CoreExpr
alt_rhs)
data OccEnv
= OccEnv { OccEnv -> OccEncl
occ_encl :: !OccEncl
, OccEnv -> OneShots
occ_one_shots :: !OneShots
, OccEnv -> VarSet
occ_gbl_scrut :: GlobalScruts
, OccEnv -> Id -> Bool
occ_unf_act :: Id -> Bool
, OccEnv -> Activation -> Bool
occ_rule_act :: Activation -> Bool
, OccEnv -> Bool
occ_binder_swap :: !Bool
}
type GlobalScruts = IdSet
data OccEncl
= OccRhs
| OccVanilla
instance Outputable OccEncl where
ppr :: OccEncl -> SDoc
ppr OccRhs = String -> SDoc
text "occRhs"
ppr OccVanilla = String -> SDoc
text "occVanilla"
type OneShots = [OneShotInfo]
initOccEnv :: OccEnv
initOccEnv :: OccEnv
initOccEnv
= $WOccEnv :: OccEncl
-> OneShots
-> VarSet
-> (Id -> Bool)
-> (Activation -> Bool)
-> Bool
-> OccEnv
OccEnv { occ_encl :: OccEncl
occ_encl = OccEncl
OccVanilla
, occ_one_shots :: OneShots
occ_one_shots = []
, occ_gbl_scrut :: VarSet
occ_gbl_scrut = VarSet
emptyVarSet
, occ_unf_act :: Id -> Bool
occ_unf_act = \_ -> Bool
True
, occ_rule_act :: Activation -> Bool
occ_rule_act = \_ -> Bool
True
, occ_binder_swap :: Bool
occ_binder_swap = Bool
True }
vanillaCtxt :: OccEnv -> OccEnv
vanillaCtxt :: OccEnv -> OccEnv
vanillaCtxt env :: OccEnv
env = OccEnv
env { occ_encl :: OccEncl
occ_encl = OccEncl
OccVanilla, occ_one_shots :: OneShots
occ_one_shots = [] }
rhsCtxt :: OccEnv -> OccEnv
rhsCtxt :: OccEnv -> OccEnv
rhsCtxt env :: OccEnv
env = OccEnv
env { occ_encl :: OccEncl
occ_encl = OccEncl
OccRhs, occ_one_shots :: OneShots
occ_one_shots = [] }
argCtxt :: OccEnv -> [OneShots] -> (OccEnv, [OneShots])
argCtxt :: OccEnv -> [OneShots] -> (OccEnv, [OneShots])
argCtxt env :: OccEnv
env []
= (OccEnv
env { occ_encl :: OccEncl
occ_encl = OccEncl
OccVanilla, occ_one_shots :: OneShots
occ_one_shots = [] }, [])
argCtxt env :: OccEnv
env (one_shots :: OneShots
one_shots:one_shots_s :: [OneShots]
one_shots_s)
= (OccEnv
env { occ_encl :: OccEncl
occ_encl = OccEncl
OccVanilla, occ_one_shots :: OneShots
occ_one_shots = OneShots
one_shots }, [OneShots]
one_shots_s)
isRhsEnv :: OccEnv -> Bool
isRhsEnv :: OccEnv -> Bool
isRhsEnv (OccEnv { occ_encl :: OccEnv -> OccEncl
occ_encl = OccEncl
OccRhs }) = Bool
True
isRhsEnv (OccEnv { occ_encl :: OccEnv -> OccEncl
occ_encl = OccEncl
OccVanilla }) = Bool
False
oneShotGroup :: OccEnv -> [CoreBndr]
-> ( OccEnv
, [CoreBndr] )
oneShotGroup :: OccEnv -> [Id] -> (OccEnv, [Id])
oneShotGroup env :: OccEnv
env@(OccEnv { occ_one_shots :: OccEnv -> OneShots
occ_one_shots = OneShots
ctxt }) bndrs :: [Id]
bndrs
= OneShots -> [Id] -> [Id] -> (OccEnv, [Id])
go OneShots
ctxt [Id]
bndrs []
where
go :: OneShots -> [Id] -> [Id] -> (OccEnv, [Id])
go ctxt :: OneShots
ctxt [] rev_bndrs :: [Id]
rev_bndrs
= ( OccEnv
env { occ_one_shots :: OneShots
occ_one_shots = OneShots
ctxt, occ_encl :: OccEncl
occ_encl = OccEncl
OccVanilla }
, [Id] -> [Id]
forall a. [a] -> [a]
reverse [Id]
rev_bndrs )
go [] bndrs :: [Id]
bndrs rev_bndrs :: [Id]
rev_bndrs
= ( OccEnv
env { occ_one_shots :: OneShots
occ_one_shots = [], occ_encl :: OccEncl
occ_encl = OccEncl
OccVanilla }
, [Id] -> [Id]
forall a. [a] -> [a]
reverse [Id]
rev_bndrs [Id] -> [Id] -> [Id]
forall a. [a] -> [a] -> [a]
++ [Id]
bndrs )
go ctxt :: OneShots
ctxt@(one_shot :: OneShotInfo
one_shot : ctxt' :: OneShots
ctxt') (bndr :: Id
bndr : bndrs :: [Id]
bndrs) rev_bndrs :: [Id]
rev_bndrs
| Id -> Bool
isId Id
bndr = OneShots -> [Id] -> [Id] -> (OccEnv, [Id])
go OneShots
ctxt' [Id]
bndrs (Id
bndr'Id -> [Id] -> [Id]
forall a. a -> [a] -> [a]
: [Id]
rev_bndrs)
| Bool
otherwise = OneShots -> [Id] -> [Id] -> (OccEnv, [Id])
go OneShots
ctxt [Id]
bndrs (Id
bndr Id -> [Id] -> [Id]
forall a. a -> [a] -> [a]
: [Id]
rev_bndrs)
where
bndr' :: Id
bndr' = Id -> OneShotInfo -> Id
updOneShotInfo Id
bndr OneShotInfo
one_shot
markJoinOneShots :: Maybe JoinArity -> [Var] -> [Var]
markJoinOneShots :: Maybe Int -> [Id] -> [Id]
markJoinOneShots mb_join_arity :: Maybe Int
mb_join_arity bndrs :: [Id]
bndrs
= case Maybe Int
mb_join_arity of
Nothing -> [Id]
bndrs
Just n :: Int
n -> Int -> [Id] -> [Id]
forall t. (Eq t, Num t) => t -> [Id] -> [Id]
go Int
n [Id]
bndrs
where
go :: t -> [Id] -> [Id]
go 0 bndrs :: [Id]
bndrs = [Id]
bndrs
go _ [] = []
go n :: t
n (b :: Id
b:bs :: [Id]
bs) = Id
b' Id -> [Id] -> [Id]
forall a. a -> [a] -> [a]
: t -> [Id] -> [Id]
go (t
nt -> t -> t
forall a. Num a => a -> a -> a
-1) [Id]
bs
where
b' :: Id
b' | Id -> Bool
isId Id
b = Id -> Id
setOneShotLambda Id
b
| Bool
otherwise = Id
b
addAppCtxt :: OccEnv -> [Arg CoreBndr] -> OccEnv
addAppCtxt :: OccEnv -> [CoreExpr] -> OccEnv
addAppCtxt env :: OccEnv
env@(OccEnv { occ_one_shots :: OccEnv -> OneShots
occ_one_shots = OneShots
ctxt }) args :: [CoreExpr]
args
= OccEnv
env { occ_one_shots :: OneShots
occ_one_shots = Int -> OneShotInfo -> OneShots
forall a. Int -> a -> [a]
replicate ([CoreExpr] -> Int
forall b. [Arg b] -> Int
valArgCount [CoreExpr]
args) OneShotInfo
OneShotLam OneShots -> OneShots -> OneShots
forall a. [a] -> [a] -> [a]
++ OneShots
ctxt }
transClosureFV :: UniqFM VarSet -> UniqFM VarSet
transClosureFV :: ImpRuleEdges -> ImpRuleEdges
transClosureFV env :: ImpRuleEdges
env
| Bool
no_change = ImpRuleEdges
env
| Bool
otherwise = ImpRuleEdges -> ImpRuleEdges
transClosureFV ([(Unique, VarSet)] -> ImpRuleEdges
forall key elt. Uniquable key => [(key, elt)] -> UniqFM elt
listToUFM [(Unique, VarSet)]
new_fv_list)
where
(no_change :: Bool
no_change, new_fv_list :: [(Unique, VarSet)]
new_fv_list) = (Bool -> (Unique, VarSet) -> (Bool, (Unique, VarSet)))
-> Bool -> [(Unique, VarSet)] -> (Bool, [(Unique, VarSet)])
forall (t :: * -> *) a b c.
Traversable t =>
(a -> b -> (a, c)) -> a -> t b -> (a, t c)
mapAccumL Bool -> (Unique, VarSet) -> (Bool, (Unique, VarSet))
forall a. Bool -> (a, VarSet) -> (Bool, (a, VarSet))
bump Bool
True (ImpRuleEdges -> [(Unique, VarSet)]
forall elt. UniqFM elt -> [(Unique, elt)]
nonDetUFMToList ImpRuleEdges
env)
bump :: Bool -> (a, VarSet) -> (Bool, (a, VarSet))
bump no_change :: Bool
no_change (b :: a
b,fvs :: VarSet
fvs)
| Bool
no_change_here = (Bool
no_change, (a
b,VarSet
fvs))
| Bool
otherwise = (Bool
False, (a
b,VarSet
new_fvs))
where
(new_fvs :: VarSet
new_fvs, no_change_here :: Bool
no_change_here) = ImpRuleEdges -> VarSet -> (VarSet, Bool)
extendFvs ImpRuleEdges
env VarSet
fvs
extendFvs_ :: UniqFM VarSet -> VarSet -> VarSet
extendFvs_ :: ImpRuleEdges -> VarSet -> VarSet
extendFvs_ env :: ImpRuleEdges
env s :: VarSet
s = (VarSet, Bool) -> VarSet
forall a b. (a, b) -> a
fst (ImpRuleEdges -> VarSet -> (VarSet, Bool)
extendFvs ImpRuleEdges
env VarSet
s)
extendFvs :: UniqFM VarSet -> VarSet -> (VarSet, Bool)
extendFvs :: ImpRuleEdges -> VarSet -> (VarSet, Bool)
extendFvs env :: ImpRuleEdges
env s :: VarSet
s
| ImpRuleEdges -> Bool
forall elt. UniqFM elt -> Bool
isNullUFM ImpRuleEdges
env
= (VarSet
s, Bool
True)
| Bool
otherwise
= (VarSet
s VarSet -> VarSet -> VarSet
`unionVarSet` VarSet
extras, VarSet
extras VarSet -> VarSet -> Bool
`subVarSet` VarSet
s)
where
extras :: VarSet
extras :: VarSet
extras = (VarSet -> VarSet -> VarSet) -> VarSet -> ImpRuleEdges -> VarSet
forall elt a. (elt -> a -> a) -> a -> UniqFM elt -> a
nonDetFoldUFM VarSet -> VarSet -> VarSet
unionVarSet VarSet
emptyVarSet (ImpRuleEdges -> VarSet) -> ImpRuleEdges -> VarSet
forall a b. (a -> b) -> a -> b
$
(VarSet -> Id -> VarSet)
-> ImpRuleEdges -> VarEnv Id -> ImpRuleEdges
forall elt1 elt2 elt3.
(elt1 -> elt2 -> elt3) -> UniqFM elt1 -> UniqFM elt2 -> UniqFM elt3
intersectUFM_C (\x :: VarSet
x _ -> VarSet
x) ImpRuleEdges
env (VarSet -> VarEnv Id
forall a. UniqSet a -> UniqFM a
getUniqSet VarSet
s)
mkAltEnv :: OccEnv -> CoreExpr -> Id -> (OccEnv, Maybe (Id, CoreExpr))
mkAltEnv :: OccEnv -> CoreExpr -> Id -> (OccEnv, Maybe (Id, CoreExpr))
mkAltEnv env :: OccEnv
env@(OccEnv { occ_gbl_scrut :: OccEnv -> VarSet
occ_gbl_scrut = VarSet
pe }) scrut :: CoreExpr
scrut case_bndr :: Id
case_bndr
= case (Tickish Id -> Bool) -> CoreExpr -> CoreExpr
forall b. (Tickish Id -> Bool) -> Expr b -> Expr b
stripTicksTopE (Bool -> Tickish Id -> Bool
forall a b. a -> b -> a
const Bool
True) CoreExpr
scrut of
Var v :: Id
v -> Id -> CoreExpr -> (OccEnv, Maybe (Id, CoreExpr))
forall b. Id -> b -> (OccEnv, Maybe (Id, b))
add_scrut Id
v CoreExpr
forall b. Expr b
case_bndr'
Cast (Var v :: Id
v) co :: Coercion
co -> Id -> CoreExpr -> (OccEnv, Maybe (Id, CoreExpr))
forall b. Id -> b -> (OccEnv, Maybe (Id, b))
add_scrut Id
v (CoreExpr -> Coercion -> CoreExpr
forall b. Expr b -> Coercion -> Expr b
Cast CoreExpr
forall b. Expr b
case_bndr' (Coercion -> Coercion
mkSymCo Coercion
co))
_ -> (OccEnv
env { occ_encl :: OccEncl
occ_encl = OccEncl
OccVanilla }, Maybe (Id, CoreExpr)
forall a. Maybe a
Nothing)
where
add_scrut :: Id -> b -> (OccEnv, Maybe (Id, b))
add_scrut v :: Id
v rhs :: b
rhs = ( OccEnv
env { occ_encl :: OccEncl
occ_encl = OccEncl
OccVanilla
, occ_gbl_scrut :: VarSet
occ_gbl_scrut = VarSet
pe VarSet -> Id -> VarSet
`extendVarSet` Id
v }
, (Id, b) -> Maybe (Id, b)
forall a. a -> Maybe a
Just (Id -> Id
localise Id
v, b
rhs) )
case_bndr' :: Expr b
case_bndr' = Id -> Expr b
forall b. Id -> Expr b
Var (Id -> Id
zapIdOccInfo Id
case_bndr)
localise :: Id -> Id
localise scrut_var :: Id
scrut_var = Name -> Type -> Id
mkLocalIdOrCoVar (Name -> Name
localiseName (Id -> Name
idName Id
scrut_var))
(Id -> Type
idType Id
scrut_var)
type OccInfoEnv = IdEnv OccInfo
type ZappedSet = OccInfoEnv
data UsageDetails
= UD { UsageDetails -> OccInfoEnv
ud_env :: !OccInfoEnv
, UsageDetails -> OccInfoEnv
ud_z_many :: ZappedSet
, UsageDetails -> OccInfoEnv
ud_z_in_lam :: ZappedSet
, UsageDetails -> OccInfoEnv
ud_z_no_tail :: ZappedSet }
instance Outputable UsageDetails where
ppr :: UsageDetails -> SDoc
ppr ud :: UsageDetails
ud = OccInfoEnv -> SDoc
forall a. Outputable a => a -> SDoc
ppr (UsageDetails -> OccInfoEnv
ud_env (UsageDetails -> UsageDetails
flattenUsageDetails UsageDetails
ud))
andUDs, orUDs
:: UsageDetails -> UsageDetails -> UsageDetails
andUDs :: UsageDetails -> UsageDetails -> UsageDetails
andUDs = (OccInfo -> OccInfo -> OccInfo)
-> UsageDetails -> UsageDetails -> UsageDetails
combineUsageDetailsWith OccInfo -> OccInfo -> OccInfo
addOccInfo
orUDs :: UsageDetails -> UsageDetails -> UsageDetails
orUDs = (OccInfo -> OccInfo -> OccInfo)
-> UsageDetails -> UsageDetails -> UsageDetails
combineUsageDetailsWith OccInfo -> OccInfo -> OccInfo
orOccInfo
andUDsList :: [UsageDetails] -> UsageDetails
andUDsList :: [UsageDetails] -> UsageDetails
andUDsList = (UsageDetails -> UsageDetails -> UsageDetails)
-> UsageDetails -> [UsageDetails] -> UsageDetails
forall (t :: * -> *) b a.
Foldable t =>
(b -> a -> b) -> b -> t a -> b
foldl' UsageDetails -> UsageDetails -> UsageDetails
andUDs UsageDetails
emptyDetails
mkOneOcc :: OccEnv -> Id -> InterestingCxt -> JoinArity -> UsageDetails
mkOneOcc :: OccEnv -> Id -> Bool -> Int -> UsageDetails
mkOneOcc env :: OccEnv
env id :: Id
id int_cxt :: Bool
int_cxt arity :: Int
arity
| Id -> Bool
isLocalId Id
id
= OccInfo -> UsageDetails
singleton (OccInfo -> UsageDetails) -> OccInfo -> UsageDetails
forall a b. (a -> b) -> a -> b
$ $WOneOcc :: Bool -> Bool -> Bool -> TailCallInfo -> OccInfo
OneOcc { occ_in_lam :: Bool
occ_in_lam = Bool
False
, occ_one_br :: Bool
occ_one_br = Bool
True
, occ_int_cxt :: Bool
occ_int_cxt = Bool
int_cxt
, occ_tail :: TailCallInfo
occ_tail = Int -> TailCallInfo
AlwaysTailCalled Int
arity }
| Id
id Id -> VarSet -> Bool
`elemVarSet` OccEnv -> VarSet
occ_gbl_scrut OccEnv
env
= OccInfo -> UsageDetails
singleton OccInfo
noOccInfo
| Bool
otherwise
= UsageDetails
emptyDetails
where
singleton :: OccInfo -> UsageDetails
singleton info :: OccInfo
info = UsageDetails
emptyDetails { ud_env :: OccInfoEnv
ud_env = Id -> OccInfo -> OccInfoEnv
forall a. Id -> a -> VarEnv a
unitVarEnv Id
id OccInfo
info }
addOneOcc :: UsageDetails -> Id -> OccInfo -> UsageDetails
addOneOcc :: UsageDetails -> Id -> OccInfo -> UsageDetails
addOneOcc ud :: UsageDetails
ud id :: Id
id info :: OccInfo
info
= UsageDetails
ud { ud_env :: OccInfoEnv
ud_env = (OccInfo -> OccInfo -> OccInfo)
-> OccInfoEnv -> Id -> OccInfo -> OccInfoEnv
forall a. (a -> a -> a) -> VarEnv a -> Id -> a -> VarEnv a
extendVarEnv_C OccInfo -> OccInfo -> OccInfo
plus_zapped (UsageDetails -> OccInfoEnv
ud_env UsageDetails
ud) Id
id OccInfo
info }
UsageDetails -> (OccInfoEnv -> OccInfoEnv) -> UsageDetails
`alterZappedSets` (OccInfoEnv -> Id -> OccInfoEnv
forall a. VarEnv a -> Id -> VarEnv a
`delVarEnv` Id
id)
where
plus_zapped :: OccInfo -> OccInfo -> OccInfo
plus_zapped old :: OccInfo
old new :: OccInfo
new = UsageDetails -> Id -> OccInfo -> OccInfo
doZapping UsageDetails
ud Id
id OccInfo
old OccInfo -> OccInfo -> OccInfo
`addOccInfo` OccInfo
new
addManyOccsSet :: UsageDetails -> VarSet -> UsageDetails
addManyOccsSet :: UsageDetails -> VarSet -> UsageDetails
addManyOccsSet usage :: UsageDetails
usage id_set :: VarSet
id_set = (Id -> UsageDetails -> UsageDetails)
-> UsageDetails -> VarSet -> UsageDetails
forall elt a. (elt -> a -> a) -> a -> UniqSet elt -> a
nonDetFoldUniqSet Id -> UsageDetails -> UsageDetails
addManyOccs UsageDetails
usage VarSet
id_set
addManyOccs :: Var -> UsageDetails -> UsageDetails
addManyOccs :: Id -> UsageDetails -> UsageDetails
addManyOccs v :: Id
v u :: UsageDetails
u | Id -> Bool
isId Id
v = UsageDetails -> Id -> OccInfo -> UsageDetails
addOneOcc UsageDetails
u Id
v OccInfo
noOccInfo
| Bool
otherwise = UsageDetails
u
delDetails :: UsageDetails -> Id -> UsageDetails
delDetails :: UsageDetails -> Id -> UsageDetails
delDetails ud :: UsageDetails
ud bndr :: Id
bndr
= UsageDetails
ud UsageDetails -> (OccInfoEnv -> OccInfoEnv) -> UsageDetails
`alterUsageDetails` (OccInfoEnv -> Id -> OccInfoEnv
forall a. VarEnv a -> Id -> VarEnv a
`delVarEnv` Id
bndr)
delDetailsList :: UsageDetails -> [Id] -> UsageDetails
delDetailsList :: UsageDetails -> [Id] -> UsageDetails
delDetailsList ud :: UsageDetails
ud bndrs :: [Id]
bndrs
= UsageDetails
ud UsageDetails -> (OccInfoEnv -> OccInfoEnv) -> UsageDetails
`alterUsageDetails` (OccInfoEnv -> [Id] -> OccInfoEnv
forall a. VarEnv a -> [Id] -> VarEnv a
`delVarEnvList` [Id]
bndrs)
emptyDetails :: UsageDetails
emptyDetails :: UsageDetails
emptyDetails = $WUD :: OccInfoEnv
-> OccInfoEnv -> OccInfoEnv -> OccInfoEnv -> UsageDetails
UD { ud_env :: OccInfoEnv
ud_env = OccInfoEnv
forall a. VarEnv a
emptyVarEnv
, ud_z_many :: OccInfoEnv
ud_z_many = OccInfoEnv
forall a. VarEnv a
emptyVarEnv
, ud_z_in_lam :: OccInfoEnv
ud_z_in_lam = OccInfoEnv
forall a. VarEnv a
emptyVarEnv
, ud_z_no_tail :: OccInfoEnv
ud_z_no_tail = OccInfoEnv
forall a. VarEnv a
emptyVarEnv }
isEmptyDetails :: UsageDetails -> Bool
isEmptyDetails :: UsageDetails -> Bool
isEmptyDetails = OccInfoEnv -> Bool
forall elt. UniqFM elt -> Bool
isEmptyVarEnv (OccInfoEnv -> Bool)
-> (UsageDetails -> OccInfoEnv) -> UsageDetails -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. UsageDetails -> OccInfoEnv
ud_env
markAllMany, markAllInsideLam, markAllNonTailCalled, zapDetails
:: UsageDetails -> UsageDetails
markAllMany :: UsageDetails -> UsageDetails
markAllMany ud :: UsageDetails
ud = UsageDetails
ud { ud_z_many :: OccInfoEnv
ud_z_many = UsageDetails -> OccInfoEnv
ud_env UsageDetails
ud }
markAllInsideLam :: UsageDetails -> UsageDetails
markAllInsideLam ud :: UsageDetails
ud = UsageDetails
ud { ud_z_in_lam :: OccInfoEnv
ud_z_in_lam = UsageDetails -> OccInfoEnv
ud_env UsageDetails
ud }
markAllNonTailCalled :: UsageDetails -> UsageDetails
markAllNonTailCalled ud :: UsageDetails
ud = UsageDetails
ud { ud_z_no_tail :: OccInfoEnv
ud_z_no_tail = UsageDetails -> OccInfoEnv
ud_env UsageDetails
ud }
zapDetails :: UsageDetails -> UsageDetails
zapDetails = UsageDetails -> UsageDetails
markAllMany (UsageDetails -> UsageDetails)
-> (UsageDetails -> UsageDetails) -> UsageDetails -> UsageDetails
forall b c a. (b -> c) -> (a -> b) -> a -> c
. UsageDetails -> UsageDetails
markAllNonTailCalled
lookupDetails :: UsageDetails -> Id -> OccInfo
lookupDetails :: UsageDetails -> Id -> OccInfo
lookupDetails ud :: UsageDetails
ud id :: Id
id
| Id -> Bool
isCoVar Id
id
= OccInfo
noOccInfo
| Bool
otherwise
= case OccInfoEnv -> Id -> Maybe OccInfo
forall a. VarEnv a -> Id -> Maybe a
lookupVarEnv (UsageDetails -> OccInfoEnv
ud_env UsageDetails
ud) Id
id of
Just occ :: OccInfo
occ -> UsageDetails -> Id -> OccInfo -> OccInfo
doZapping UsageDetails
ud Id
id OccInfo
occ
Nothing -> OccInfo
IAmDead
usedIn :: Id -> UsageDetails -> Bool
v :: Id
v usedIn :: Id -> UsageDetails -> Bool
`usedIn` ud :: UsageDetails
ud = Id -> Bool
isExportedId Id
v Bool -> Bool -> Bool
|| Id
v Id -> OccInfoEnv -> Bool
forall a. Id -> VarEnv a -> Bool
`elemVarEnv` UsageDetails -> OccInfoEnv
ud_env UsageDetails
ud
udFreeVars :: VarSet -> UsageDetails -> VarSet
udFreeVars :: VarSet -> UsageDetails -> VarSet
udFreeVars bndrs :: VarSet
bndrs ud :: UsageDetails
ud = VarSet -> OccInfoEnv -> VarSet
forall a b. UniqSet a -> UniqFM b -> UniqSet a
restrictUniqSetToUFM VarSet
bndrs (UsageDetails -> OccInfoEnv
ud_env UsageDetails
ud)
combineUsageDetailsWith :: (OccInfo -> OccInfo -> OccInfo)
-> UsageDetails -> UsageDetails -> UsageDetails
combineUsageDetailsWith :: (OccInfo -> OccInfo -> OccInfo)
-> UsageDetails -> UsageDetails -> UsageDetails
combineUsageDetailsWith plus_occ_info :: OccInfo -> OccInfo -> OccInfo
plus_occ_info ud1 :: UsageDetails
ud1 ud2 :: UsageDetails
ud2
| UsageDetails -> Bool
isEmptyDetails UsageDetails
ud1 = UsageDetails
ud2
| UsageDetails -> Bool
isEmptyDetails UsageDetails
ud2 = UsageDetails
ud1
| Bool
otherwise
= $WUD :: OccInfoEnv
-> OccInfoEnv -> OccInfoEnv -> OccInfoEnv -> UsageDetails
UD { ud_env :: OccInfoEnv
ud_env = (OccInfo -> OccInfo -> OccInfo)
-> OccInfoEnv -> OccInfoEnv -> OccInfoEnv
forall a. (a -> a -> a) -> VarEnv a -> VarEnv a -> VarEnv a
plusVarEnv_C OccInfo -> OccInfo -> OccInfo
plus_occ_info (UsageDetails -> OccInfoEnv
ud_env UsageDetails
ud1) (UsageDetails -> OccInfoEnv
ud_env UsageDetails
ud2)
, ud_z_many :: OccInfoEnv
ud_z_many = OccInfoEnv -> OccInfoEnv -> OccInfoEnv
forall a. VarEnv a -> VarEnv a -> VarEnv a
plusVarEnv (UsageDetails -> OccInfoEnv
ud_z_many UsageDetails
ud1) (UsageDetails -> OccInfoEnv
ud_z_many UsageDetails
ud2)
, ud_z_in_lam :: OccInfoEnv
ud_z_in_lam = OccInfoEnv -> OccInfoEnv -> OccInfoEnv
forall a. VarEnv a -> VarEnv a -> VarEnv a
plusVarEnv (UsageDetails -> OccInfoEnv
ud_z_in_lam UsageDetails
ud1) (UsageDetails -> OccInfoEnv
ud_z_in_lam UsageDetails
ud2)
, ud_z_no_tail :: OccInfoEnv
ud_z_no_tail = OccInfoEnv -> OccInfoEnv -> OccInfoEnv
forall a. VarEnv a -> VarEnv a -> VarEnv a
plusVarEnv (UsageDetails -> OccInfoEnv
ud_z_no_tail UsageDetails
ud1) (UsageDetails -> OccInfoEnv
ud_z_no_tail UsageDetails
ud2) }
doZapping :: UsageDetails -> Var -> OccInfo -> OccInfo
doZapping :: UsageDetails -> Id -> OccInfo -> OccInfo
doZapping ud :: UsageDetails
ud var :: Id
var occ :: OccInfo
occ
= UsageDetails -> Unique -> OccInfo -> OccInfo
doZappingByUnique UsageDetails
ud (Id -> Unique
varUnique Id
var) OccInfo
occ
doZappingByUnique :: UsageDetails -> Unique -> OccInfo -> OccInfo
doZappingByUnique :: UsageDetails -> Unique -> OccInfo -> OccInfo
doZappingByUnique ud :: UsageDetails
ud uniq :: Unique
uniq
= (if | (UsageDetails -> OccInfoEnv) -> Bool
forall a. (UsageDetails -> VarEnv a) -> Bool
in_subset UsageDetails -> OccInfoEnv
ud_z_many -> OccInfo -> OccInfo
markMany
| (UsageDetails -> OccInfoEnv) -> Bool
forall a. (UsageDetails -> VarEnv a) -> Bool
in_subset UsageDetails -> OccInfoEnv
ud_z_in_lam -> OccInfo -> OccInfo
markInsideLam
| Bool
otherwise -> OccInfo -> OccInfo
forall a. a -> a
id) (OccInfo -> OccInfo) -> (OccInfo -> OccInfo) -> OccInfo -> OccInfo
forall b c a. (b -> c) -> (a -> b) -> a -> c
.
(if | (UsageDetails -> OccInfoEnv) -> Bool
forall a. (UsageDetails -> VarEnv a) -> Bool
in_subset UsageDetails -> OccInfoEnv
ud_z_no_tail -> OccInfo -> OccInfo
markNonTailCalled
| Bool
otherwise -> OccInfo -> OccInfo
forall a. a -> a
id)
where
in_subset :: (UsageDetails -> VarEnv a) -> Bool
in_subset field :: UsageDetails -> VarEnv a
field = Unique
uniq Unique -> VarEnv a -> Bool
forall a. Unique -> VarEnv a -> Bool
`elemVarEnvByKey` UsageDetails -> VarEnv a
field UsageDetails
ud
alterZappedSets :: UsageDetails -> (ZappedSet -> ZappedSet) -> UsageDetails
alterZappedSets :: UsageDetails -> (OccInfoEnv -> OccInfoEnv) -> UsageDetails
alterZappedSets ud :: UsageDetails
ud f :: OccInfoEnv -> OccInfoEnv
f
= UsageDetails
ud { ud_z_many :: OccInfoEnv
ud_z_many = OccInfoEnv -> OccInfoEnv
f (UsageDetails -> OccInfoEnv
ud_z_many UsageDetails
ud)
, ud_z_in_lam :: OccInfoEnv
ud_z_in_lam = OccInfoEnv -> OccInfoEnv
f (UsageDetails -> OccInfoEnv
ud_z_in_lam UsageDetails
ud)
, ud_z_no_tail :: OccInfoEnv
ud_z_no_tail = OccInfoEnv -> OccInfoEnv
f (UsageDetails -> OccInfoEnv
ud_z_no_tail UsageDetails
ud) }
alterUsageDetails :: UsageDetails -> (OccInfoEnv -> OccInfoEnv) -> UsageDetails
alterUsageDetails :: UsageDetails -> (OccInfoEnv -> OccInfoEnv) -> UsageDetails
alterUsageDetails ud :: UsageDetails
ud f :: OccInfoEnv -> OccInfoEnv
f
= UsageDetails
ud { ud_env :: OccInfoEnv
ud_env = OccInfoEnv -> OccInfoEnv
f (UsageDetails -> OccInfoEnv
ud_env UsageDetails
ud) }
UsageDetails -> (OccInfoEnv -> OccInfoEnv) -> UsageDetails
`alterZappedSets` OccInfoEnv -> OccInfoEnv
f
flattenUsageDetails :: UsageDetails -> UsageDetails
flattenUsageDetails :: UsageDetails -> UsageDetails
flattenUsageDetails ud :: UsageDetails
ud
= UsageDetails
ud { ud_env :: OccInfoEnv
ud_env = (Unique -> OccInfo -> OccInfo) -> OccInfoEnv -> OccInfoEnv
forall elt1 elt2.
(Unique -> elt1 -> elt2) -> UniqFM elt1 -> UniqFM elt2
mapUFM_Directly (UsageDetails -> Unique -> OccInfo -> OccInfo
doZappingByUnique UsageDetails
ud) (UsageDetails -> OccInfoEnv
ud_env UsageDetails
ud) }
UsageDetails -> (OccInfoEnv -> OccInfoEnv) -> UsageDetails
`alterZappedSets` OccInfoEnv -> OccInfoEnv -> OccInfoEnv
forall a b. a -> b -> a
const OccInfoEnv
forall a. VarEnv a
emptyVarEnv
adjustRhsUsage :: Maybe JoinArity -> RecFlag
-> [CoreBndr]
-> UsageDetails -> UsageDetails
adjustRhsUsage :: Maybe Int -> RecFlag -> [Id] -> UsageDetails -> UsageDetails
adjustRhsUsage mb_join_arity :: Maybe Int
mb_join_arity rec_flag :: RecFlag
rec_flag bndrs :: [Id]
bndrs usage :: UsageDetails
usage
= UsageDetails -> UsageDetails
maybe_mark_lam (UsageDetails -> UsageDetails
maybe_drop_tails UsageDetails
usage)
where
maybe_mark_lam :: UsageDetails -> UsageDetails
maybe_mark_lam ud :: UsageDetails
ud | Bool
one_shot = UsageDetails
ud
| Bool
otherwise = UsageDetails -> UsageDetails
markAllInsideLam UsageDetails
ud
maybe_drop_tails :: UsageDetails -> UsageDetails
maybe_drop_tails ud :: UsageDetails
ud | Bool
exact_join = UsageDetails
ud
| Bool
otherwise = UsageDetails -> UsageDetails
markAllNonTailCalled UsageDetails
ud
one_shot :: Bool
one_shot = case Maybe Int
mb_join_arity of
Just join_arity :: Int
join_arity
| RecFlag -> Bool
isRec RecFlag
rec_flag -> Bool
False
| Bool
otherwise -> (Id -> Bool) -> [Id] -> Bool
forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
all Id -> Bool
isOneShotBndr (Int -> [Id] -> [Id]
forall a. Int -> [a] -> [a]
drop Int
join_arity [Id]
bndrs)
Nothing -> (Id -> Bool) -> [Id] -> Bool
forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
all Id -> Bool
isOneShotBndr [Id]
bndrs
exact_join :: Bool
exact_join = case Maybe Int
mb_join_arity of
Just join_arity :: Int
join_arity -> [Id]
bndrs [Id] -> Int -> Bool
forall a. [a] -> Int -> Bool
`lengthIs` Int
join_arity
_ -> Bool
False
type IdWithOccInfo = Id
tagLamBinders :: UsageDetails
-> [Id]
-> (UsageDetails,
[IdWithOccInfo])
tagLamBinders :: UsageDetails -> [Id] -> (UsageDetails, [Id])
tagLamBinders usage :: UsageDetails
usage binders :: [Id]
binders
= UsageDetails
usage' UsageDetails -> (UsageDetails, [Id]) -> (UsageDetails, [Id])
forall a b. a -> b -> b
`seq` (UsageDetails
usage', [Id]
bndrs')
where
(usage' :: UsageDetails
usage', bndrs' :: [Id]
bndrs') = (UsageDetails -> Id -> (UsageDetails, Id))
-> UsageDetails -> [Id] -> (UsageDetails, [Id])
forall (t :: * -> *) a b c.
Traversable t =>
(a -> b -> (a, c)) -> a -> t b -> (a, t c)
mapAccumR UsageDetails -> Id -> (UsageDetails, Id)
tagLamBinder UsageDetails
usage [Id]
binders
tagLamBinder :: UsageDetails
-> Id
-> (UsageDetails,
IdWithOccInfo)
tagLamBinder :: UsageDetails -> Id -> (UsageDetails, Id)
tagLamBinder usage :: UsageDetails
usage bndr :: Id
bndr
= (UsageDetails
usage2, Id
bndr')
where
occ :: OccInfo
occ = UsageDetails -> Id -> OccInfo
lookupDetails UsageDetails
usage Id
bndr
bndr' :: Id
bndr' = OccInfo -> Id -> Id
setBinderOcc (OccInfo -> OccInfo
markNonTailCalled OccInfo
occ) Id
bndr
usage1 :: UsageDetails
usage1 = UsageDetails
usage UsageDetails -> Id -> UsageDetails
`delDetails` Id
bndr
usage2 :: UsageDetails
usage2 | Id -> Bool
isId Id
bndr = UsageDetails -> VarSet -> UsageDetails
addManyOccsSet UsageDetails
usage1 (Id -> VarSet
idUnfoldingVars Id
bndr)
| Bool
otherwise = UsageDetails
usage1
tagNonRecBinder :: TopLevelFlag
-> UsageDetails
-> CoreBndr
-> (UsageDetails,
IdWithOccInfo)
tagNonRecBinder :: TopLevelFlag -> UsageDetails -> Id -> (UsageDetails, Id)
tagNonRecBinder lvl :: TopLevelFlag
lvl usage :: UsageDetails
usage binder :: Id
binder
= let
occ :: OccInfo
occ = UsageDetails -> Id -> OccInfo
lookupDetails UsageDetails
usage Id
binder
will_be_join :: Bool
will_be_join = TopLevelFlag -> UsageDetails -> [Id] -> Bool
decideJoinPointHood TopLevelFlag
lvl UsageDetails
usage [Id
binder]
occ' :: OccInfo
occ' | Bool
will_be_join =
ASSERT(isAlwaysTailCalled occ) occ
| Bool
otherwise = OccInfo -> OccInfo
markNonTailCalled OccInfo
occ
binder' :: Id
binder' = OccInfo -> Id -> Id
setBinderOcc OccInfo
occ' Id
binder
usage' :: UsageDetails
usage' = UsageDetails
usage UsageDetails -> Id -> UsageDetails
`delDetails` Id
binder
in
UsageDetails
usage' UsageDetails -> (UsageDetails, Id) -> (UsageDetails, Id)
forall a b. a -> b -> b
`seq` (UsageDetails
usage', Id
binder')
tagRecBinders :: TopLevelFlag
-> UsageDetails
-> [(CoreBndr,
UsageDetails,
[CoreBndr])]
-> (UsageDetails,
[IdWithOccInfo])
tagRecBinders :: TopLevelFlag
-> UsageDetails
-> [(Id, UsageDetails, [Id])]
-> (UsageDetails, [Id])
tagRecBinders lvl :: TopLevelFlag
lvl body_uds :: UsageDetails
body_uds triples :: [(Id, UsageDetails, [Id])]
triples
= let
(bndrs :: [Id]
bndrs, rhs_udss :: [UsageDetails]
rhs_udss, _) = [(Id, UsageDetails, [Id])] -> ([Id], [UsageDetails], [[Id]])
forall a b c. [(a, b, c)] -> ([a], [b], [c])
unzip3 [(Id, UsageDetails, [Id])]
triples
unadj_uds :: UsageDetails
unadj_uds = (UsageDetails -> UsageDetails -> UsageDetails)
-> UsageDetails -> [UsageDetails] -> UsageDetails
forall (t :: * -> *) a b.
Foldable t =>
(a -> b -> b) -> b -> t a -> b
foldr UsageDetails -> UsageDetails -> UsageDetails
andUDs UsageDetails
body_uds [UsageDetails]
rhs_udss
will_be_joins :: Bool
will_be_joins = TopLevelFlag -> UsageDetails -> [Id] -> Bool
decideJoinPointHood TopLevelFlag
lvl UsageDetails
unadj_uds [Id]
bndrs
rhs_udss' :: [UsageDetails]
rhs_udss' = ((Id, UsageDetails, [Id]) -> UsageDetails)
-> [(Id, UsageDetails, [Id])] -> [UsageDetails]
forall a b. (a -> b) -> [a] -> [b]
map (Id, UsageDetails, [Id]) -> UsageDetails
adjust [(Id, UsageDetails, [Id])]
triples
adjust :: (Id, UsageDetails, [Id]) -> UsageDetails
adjust (bndr :: Id
bndr, rhs_uds :: UsageDetails
rhs_uds, rhs_bndrs :: [Id]
rhs_bndrs)
= Maybe Int -> RecFlag -> [Id] -> UsageDetails -> UsageDetails
adjustRhsUsage Maybe Int
mb_join_arity RecFlag
Recursive [Id]
rhs_bndrs UsageDetails
rhs_uds
where
mb_join_arity :: Maybe Int
mb_join_arity
| Bool
will_be_joins
, let occ :: OccInfo
occ = UsageDetails -> Id -> OccInfo
lookupDetails UsageDetails
unadj_uds Id
bndr
, AlwaysTailCalled arity :: Int
arity <- OccInfo -> TailCallInfo
tailCallInfo OccInfo
occ
= Int -> Maybe Int
forall a. a -> Maybe a
Just Int
arity
| Bool
otherwise
= ASSERT(not will_be_joins)
Maybe Int
forall a. Maybe a
Nothing
adj_uds :: UsageDetails
adj_uds = (UsageDetails -> UsageDetails -> UsageDetails)
-> UsageDetails -> [UsageDetails] -> UsageDetails
forall (t :: * -> *) a b.
Foldable t =>
(a -> b -> b) -> b -> t a -> b
foldr UsageDetails -> UsageDetails -> UsageDetails
andUDs UsageDetails
body_uds [UsageDetails]
rhs_udss'
bndrs' :: [Id]
bndrs' = [ OccInfo -> Id -> Id
setBinderOcc (UsageDetails -> Id -> OccInfo
lookupDetails UsageDetails
adj_uds Id
bndr) Id
bndr
| Id
bndr <- [Id]
bndrs ]
usage' :: UsageDetails
usage' = UsageDetails
adj_uds UsageDetails -> [Id] -> UsageDetails
`delDetailsList` [Id]
bndrs
in
(UsageDetails
usage', [Id]
bndrs')
setBinderOcc :: OccInfo -> CoreBndr -> CoreBndr
setBinderOcc :: OccInfo -> Id -> Id
setBinderOcc occ_info :: OccInfo
occ_info bndr :: Id
bndr
| Id -> Bool
isTyVar Id
bndr = Id
bndr
| Id -> Bool
isExportedId Id
bndr = if OccInfo -> Bool
isManyOccs (Id -> OccInfo
idOccInfo Id
bndr)
then Id
bndr
else Id -> OccInfo -> Id
setIdOccInfo Id
bndr OccInfo
noOccInfo
| Bool
otherwise = Id -> OccInfo -> Id
setIdOccInfo Id
bndr OccInfo
occ_info
decideJoinPointHood :: TopLevelFlag -> UsageDetails
-> [CoreBndr]
-> Bool
decideJoinPointHood :: TopLevelFlag -> UsageDetails -> [Id] -> Bool
decideJoinPointHood TopLevel _ _
= Bool
False
decideJoinPointHood NotTopLevel usage :: UsageDetails
usage bndrs :: [Id]
bndrs
| Id -> Bool
isJoinId ([Id] -> Id
forall a. [a] -> a
head [Id]
bndrs)
= WARN(not all_ok, text "OccurAnal failed to rediscover join point(s):" <+>
ppr bndrs)
Bool
all_ok
| Bool
otherwise
= Bool
all_ok
where
all_ok :: Bool
all_ok =
(Id -> Bool) -> [Id] -> Bool
forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
all Id -> Bool
ok [Id]
bndrs
ok :: Id -> Bool
ok bndr :: Id
bndr
|
AlwaysTailCalled arity :: Int
arity <- OccInfo -> TailCallInfo
tailCallInfo (UsageDetails -> Id -> OccInfo
lookupDetails UsageDetails
usage Id
bndr)
,
(CoreRule -> Bool) -> [CoreRule] -> Bool
forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
all (Int -> CoreRule -> Bool
ok_rule Int
arity) (Id -> [CoreRule]
idCoreRules Id
bndr)
, Int -> Unfolding -> Bool
ok_unfolding Int
arity (Id -> Unfolding
realIdUnfolding Id
bndr)
, Int -> Type -> Bool
isValidJoinPointType Int
arity (Id -> Type
idType Id
bndr)
= Bool
True
| Bool
otherwise
= Bool
False
ok_rule :: Int -> CoreRule -> Bool
ok_rule _ BuiltinRule{} = Bool
False
ok_rule join_arity :: Int
join_arity (Rule { ru_args :: CoreRule -> [CoreExpr]
ru_args = [CoreExpr]
args })
= [CoreExpr]
args [CoreExpr] -> Int -> Bool
forall a. [a] -> Int -> Bool
`lengthIs` Int
join_arity
ok_unfolding :: Int -> Unfolding -> Bool
ok_unfolding join_arity :: Int
join_arity (CoreUnfolding { uf_src :: Unfolding -> UnfoldingSource
uf_src = UnfoldingSource
src, uf_tmpl :: Unfolding -> CoreExpr
uf_tmpl = CoreExpr
rhs })
= Bool -> Bool
not (UnfoldingSource -> Bool
isStableSource UnfoldingSource
src Bool -> Bool -> Bool
&& Int
join_arity Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
> CoreExpr -> Int
joinRhsArity CoreExpr
rhs)
ok_unfolding _ (DFunUnfolding {})
= Bool
False
ok_unfolding _ _
= Bool
True
willBeJoinId_maybe :: CoreBndr -> Maybe JoinArity
willBeJoinId_maybe :: Id -> Maybe Int
willBeJoinId_maybe bndr :: Id
bndr
= case OccInfo -> TailCallInfo
tailCallInfo (Id -> OccInfo
idOccInfo Id
bndr) of
AlwaysTailCalled arity :: Int
arity -> Int -> Maybe Int
forall a. a -> Maybe a
Just Int
arity
_ -> Id -> Maybe Int
isJoinId_maybe Id
bndr
markMany, markInsideLam, markNonTailCalled :: OccInfo -> OccInfo
markMany :: OccInfo -> OccInfo
markMany IAmDead = OccInfo
IAmDead
markMany occ :: OccInfo
occ = $WManyOccs :: TailCallInfo -> OccInfo
ManyOccs { occ_tail :: TailCallInfo
occ_tail = OccInfo -> TailCallInfo
occ_tail OccInfo
occ }
markInsideLam :: OccInfo -> OccInfo
markInsideLam occ :: OccInfo
occ@(OneOcc {}) = OccInfo
occ { occ_in_lam :: Bool
occ_in_lam = Bool
True }
markInsideLam occ :: OccInfo
occ = OccInfo
occ
markNonTailCalled :: OccInfo -> OccInfo
markNonTailCalled IAmDead = OccInfo
IAmDead
markNonTailCalled occ :: OccInfo
occ = OccInfo
occ { occ_tail :: TailCallInfo
occ_tail = TailCallInfo
NoTailCallInfo }
addOccInfo, orOccInfo :: OccInfo -> OccInfo -> OccInfo
addOccInfo :: OccInfo -> OccInfo -> OccInfo
addOccInfo a1 :: OccInfo
a1 a2 :: OccInfo
a2 = ASSERT( not (isDeadOcc a1 || isDeadOcc a2) )
$WManyOccs :: TailCallInfo -> OccInfo
ManyOccs { occ_tail :: TailCallInfo
occ_tail = OccInfo -> TailCallInfo
tailCallInfo OccInfo
a1 TailCallInfo -> TailCallInfo -> TailCallInfo
`andTailCallInfo`
OccInfo -> TailCallInfo
tailCallInfo OccInfo
a2 }
orOccInfo :: OccInfo -> OccInfo -> OccInfo
orOccInfo (OneOcc { occ_in_lam :: OccInfo -> Bool
occ_in_lam = Bool
in_lam1, occ_int_cxt :: OccInfo -> Bool
occ_int_cxt = Bool
int_cxt1
, occ_tail :: OccInfo -> TailCallInfo
occ_tail = TailCallInfo
tail1 })
(OneOcc { occ_in_lam :: OccInfo -> Bool
occ_in_lam = Bool
in_lam2, occ_int_cxt :: OccInfo -> Bool
occ_int_cxt = Bool
int_cxt2
, occ_tail :: OccInfo -> TailCallInfo
occ_tail = TailCallInfo
tail2 })
= $WOneOcc :: Bool -> Bool -> Bool -> TailCallInfo -> OccInfo
OneOcc { occ_one_br :: Bool
occ_one_br = Bool
False
, occ_in_lam :: Bool
occ_in_lam = Bool
in_lam1 Bool -> Bool -> Bool
|| Bool
in_lam2
, occ_int_cxt :: Bool
occ_int_cxt = Bool
int_cxt1 Bool -> Bool -> Bool
&& Bool
int_cxt2
, occ_tail :: TailCallInfo
occ_tail = TailCallInfo
tail1 TailCallInfo -> TailCallInfo -> TailCallInfo
`andTailCallInfo` TailCallInfo
tail2 }
orOccInfo a1 :: OccInfo
a1 a2 :: OccInfo
a2 = ASSERT( not (isDeadOcc a1 || isDeadOcc a2) )
$WManyOccs :: TailCallInfo -> OccInfo
ManyOccs { occ_tail :: TailCallInfo
occ_tail = OccInfo -> TailCallInfo
tailCallInfo OccInfo
a1 TailCallInfo -> TailCallInfo -> TailCallInfo
`andTailCallInfo`
OccInfo -> TailCallInfo
tailCallInfo OccInfo
a2 }
andTailCallInfo :: TailCallInfo -> TailCallInfo -> TailCallInfo
andTailCallInfo :: TailCallInfo -> TailCallInfo -> TailCallInfo
andTailCallInfo info :: TailCallInfo
info@(AlwaysTailCalled arity1 :: Int
arity1) (AlwaysTailCalled arity2 :: Int
arity2)
| Int
arity1 Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
arity2 = TailCallInfo
info
andTailCallInfo _ _ = TailCallInfo
NoTailCallInfo