{-# OPTIONS_GHC -fprof-auto #-}
{-# OPTIONS_GHC -Wno-incomplete-uni-patterns #-}
module GHC.Core.Opt.FloatIn ( floatInwards ) where
import GHC.Prelude
import GHC.Platform
import GHC.Core
import GHC.Core.Make hiding ( wrapFloats )
import GHC.Core.Utils
import GHC.Core.FVs
import GHC.Core.Type
import GHC.Types.Basic ( RecFlag(..), isRec, Levity(Unlifted) )
import GHC.Types.Id ( isOneShotBndr, idType, isJoinId, isJoinId_maybe )
import GHC.Types.Tickish
import GHC.Types.Var
import GHC.Types.Var.Set
import GHC.Utils.Misc
import GHC.Utils.Panic.Plain
import GHC.Utils.Outputable
import Data.List ( mapAccumL )
floatInwards :: Platform -> CoreProgram -> CoreProgram
floatInwards :: Platform -> CoreProgram -> CoreProgram
floatInwards Platform
platform CoreProgram
binds = (Bind CoreBndr -> Bind CoreBndr) -> CoreProgram -> CoreProgram
forall a b. (a -> b) -> [a] -> [b]
map (Platform -> Bind CoreBndr -> Bind CoreBndr
fi_top_bind Platform
platform) CoreProgram
binds
where
fi_top_bind :: Platform -> Bind CoreBndr -> Bind CoreBndr
fi_top_bind Platform
platform (NonRec CoreBndr
binder Expr CoreBndr
rhs)
= CoreBndr -> Expr CoreBndr -> Bind CoreBndr
forall b. b -> Expr b -> Bind b
NonRec CoreBndr
binder (Platform -> RevFloatInBinds -> CoreExprWithFVs -> Expr CoreBndr
fiExpr Platform
platform [] (Expr CoreBndr -> CoreExprWithFVs
freeVars Expr CoreBndr
rhs))
fi_top_bind Platform
platform (Rec [(CoreBndr, Expr CoreBndr)]
pairs)
= [(CoreBndr, Expr CoreBndr)] -> Bind CoreBndr
forall b. [(b, Expr b)] -> Bind b
Rec [ (CoreBndr
b, Platform -> RevFloatInBinds -> CoreExprWithFVs -> Expr CoreBndr
fiExpr Platform
platform [] (Expr CoreBndr -> CoreExprWithFVs
freeVars Expr CoreBndr
rhs)) | (CoreBndr
b, Expr CoreBndr
rhs) <- [(CoreBndr, Expr CoreBndr)]
pairs ]
type FreeVarSet = DVarSet
type BoundVarSet = DIdSet
data FloatInBind = FB BoundVarSet FreeVarSet FloatBind
type FloatInBinds = [FloatInBind]
type RevFloatInBinds = [FloatInBind]
instance Outputable FloatInBind where
ppr :: FloatInBind -> SDoc
ppr (FB BoundVarSet
bvs BoundVarSet
fvs FloatBind
_) = String -> SDoc
text String
"FB" SDoc -> SDoc -> SDoc
<> SDoc -> SDoc
braces ([SDoc] -> SDoc
sep [ String -> SDoc
text String
"bndrs =" SDoc -> SDoc -> SDoc
<+> BoundVarSet -> SDoc
forall a. Outputable a => a -> SDoc
ppr BoundVarSet
bvs
, String -> SDoc
text String
"fvs =" SDoc -> SDoc -> SDoc
<+> BoundVarSet -> SDoc
forall a. Outputable a => a -> SDoc
ppr BoundVarSet
fvs ])
fiExpr :: Platform
-> RevFloatInBinds
-> CoreExprWithFVs
-> CoreExpr
fiExpr :: Platform -> RevFloatInBinds -> CoreExprWithFVs -> Expr CoreBndr
fiExpr Platform
_ RevFloatInBinds
to_drop (BoundVarSet
_, AnnLit Literal
lit) = RevFloatInBinds -> Expr CoreBndr -> Expr CoreBndr
wrapFloats RevFloatInBinds
to_drop (Literal -> Expr CoreBndr
forall b. Literal -> Expr b
Lit Literal
lit)
fiExpr Platform
_ RevFloatInBinds
to_drop (BoundVarSet
_, AnnType Type
ty) = Bool -> Expr CoreBndr -> Expr CoreBndr
forall a. HasCallStack => Bool -> a -> a
assert (RevFloatInBinds -> Bool
forall a. [a] -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null RevFloatInBinds
to_drop) (Expr CoreBndr -> Expr CoreBndr) -> Expr CoreBndr -> Expr CoreBndr
forall a b. (a -> b) -> a -> b
$ Type -> Expr CoreBndr
forall b. Type -> Expr b
Type Type
ty
fiExpr Platform
_ RevFloatInBinds
to_drop (BoundVarSet
_, AnnVar CoreBndr
v) = RevFloatInBinds -> Expr CoreBndr -> Expr CoreBndr
wrapFloats RevFloatInBinds
to_drop (CoreBndr -> Expr CoreBndr
forall b. CoreBndr -> Expr b
Var CoreBndr
v)
fiExpr Platform
_ RevFloatInBinds
to_drop (BoundVarSet
_, AnnCoercion Coercion
co) = RevFloatInBinds -> Expr CoreBndr -> Expr CoreBndr
wrapFloats RevFloatInBinds
to_drop (Coercion -> Expr CoreBndr
forall b. Coercion -> Expr b
Coercion Coercion
co)
fiExpr Platform
platform RevFloatInBinds
to_drop (BoundVarSet
_, AnnCast CoreExprWithFVs
expr (BoundVarSet
co_ann, Coercion
co))
= RevFloatInBinds -> Expr CoreBndr -> Expr CoreBndr
wrapFloats RevFloatInBinds
drop_here (Expr CoreBndr -> Expr CoreBndr) -> Expr CoreBndr -> Expr CoreBndr
forall a b. (a -> b) -> a -> b
$
Expr CoreBndr -> Coercion -> Expr CoreBndr
forall b. Expr b -> Coercion -> Expr b
Cast (Platform -> RevFloatInBinds -> CoreExprWithFVs -> Expr CoreBndr
fiExpr Platform
platform RevFloatInBinds
e_drop CoreExprWithFVs
expr) Coercion
co
where
(RevFloatInBinds
drop_here, [RevFloatInBinds
e_drop])
= Platform
-> Bool
-> RevFloatInBinds
-> BoundVarSet
-> [BoundVarSet]
-> (RevFloatInBinds, [RevFloatInBinds])
sepBindsByDropPoint Platform
platform Bool
False RevFloatInBinds
to_drop
(BoundVarSet -> BoundVarSet
freeVarsOfAnn BoundVarSet
co_ann) [CoreExprWithFVs -> BoundVarSet
freeVarsOf CoreExprWithFVs
expr]
fiExpr Platform
platform RevFloatInBinds
to_drop ann_expr :: CoreExprWithFVs
ann_expr@(BoundVarSet
_,AnnApp {})
= RevFloatInBinds -> Expr CoreBndr -> Expr CoreBndr
wrapFloats RevFloatInBinds
drop_here (Expr CoreBndr -> Expr CoreBndr) -> Expr CoreBndr -> Expr CoreBndr
forall a b. (a -> b) -> a -> b
$
[CoreTickish] -> Expr CoreBndr -> Expr CoreBndr
mkTicks [CoreTickish]
ticks (Expr CoreBndr -> Expr CoreBndr) -> Expr CoreBndr -> Expr CoreBndr
forall a b. (a -> b) -> a -> b
$
Expr CoreBndr -> [Expr CoreBndr] -> Expr CoreBndr
forall b. Expr b -> [Expr b] -> Expr b
mkApps (Platform -> RevFloatInBinds -> CoreExprWithFVs -> Expr CoreBndr
fiExpr Platform
platform RevFloatInBinds
fun_drop CoreExprWithFVs
ann_fun)
(String
-> (RevFloatInBinds -> CoreExprWithFVs -> Expr CoreBndr)
-> [RevFloatInBinds]
-> [CoreExprWithFVs]
-> [Expr CoreBndr]
forall a b c. String -> (a -> b -> c) -> [a] -> [b] -> [c]
zipWithEqual String
"fiExpr" (Platform -> RevFloatInBinds -> CoreExprWithFVs -> Expr CoreBndr
fiExpr Platform
platform) [RevFloatInBinds]
arg_drops [CoreExprWithFVs]
ann_args)
where
(CoreExprWithFVs
ann_fun, [CoreExprWithFVs]
ann_args, [CoreTickish]
ticks) = (CoreTickish -> Bool)
-> CoreExprWithFVs
-> (CoreExprWithFVs, [CoreExprWithFVs], [CoreTickish])
forall b a.
(CoreTickish -> Bool)
-> AnnExpr b a -> (AnnExpr b a, [AnnExpr b a], [CoreTickish])
collectAnnArgsTicks CoreTickish -> Bool
forall (pass :: TickishPass). GenTickish pass -> Bool
tickishFloatable CoreExprWithFVs
ann_expr
fun_fvs :: BoundVarSet
fun_fvs = CoreExprWithFVs -> BoundVarSet
freeVarsOf CoreExprWithFVs
ann_fun
(RevFloatInBinds
drop_here, RevFloatInBinds
fun_drop : [RevFloatInBinds]
arg_drops)
= Platform
-> Bool
-> RevFloatInBinds
-> BoundVarSet
-> [BoundVarSet]
-> (RevFloatInBinds, [RevFloatInBinds])
sepBindsByDropPoint Platform
platform Bool
False RevFloatInBinds
to_drop
BoundVarSet
here_fvs (BoundVarSet
fun_fvs BoundVarSet -> [BoundVarSet] -> [BoundVarSet]
forall a. a -> [a] -> [a]
: [BoundVarSet]
arg_fvs)
(BoundVarSet
here_fvs, [BoundVarSet]
arg_fvs) = (BoundVarSet -> CoreExprWithFVs -> (BoundVarSet, BoundVarSet))
-> BoundVarSet -> [CoreExprWithFVs] -> (BoundVarSet, [BoundVarSet])
forall (t :: * -> *) s a b.
Traversable t =>
(s -> a -> (s, b)) -> s -> t a -> (s, t b)
mapAccumL BoundVarSet -> CoreExprWithFVs -> (BoundVarSet, BoundVarSet)
add_arg BoundVarSet
here_fvs0 [CoreExprWithFVs]
ann_args
here_fvs0 :: BoundVarSet
here_fvs0 = case CoreExprWithFVs
ann_fun of
(BoundVarSet
_, AnnVar CoreBndr
_) -> BoundVarSet
fun_fvs
CoreExprWithFVs
_ -> BoundVarSet
emptyDVarSet
add_arg :: FreeVarSet -> CoreExprWithFVs -> (FreeVarSet,FreeVarSet)
add_arg :: BoundVarSet -> CoreExprWithFVs -> (BoundVarSet, BoundVarSet)
add_arg BoundVarSet
here_fvs (BoundVarSet
arg_fvs, AnnType Type
_)
= (BoundVarSet
here_fvs, BoundVarSet
arg_fvs)
add_arg BoundVarSet
here_fvs (BoundVarSet
arg_fvs, AnnExpr' CoreBndr BoundVarSet
arg)
| AnnExpr' CoreBndr BoundVarSet -> Type -> Bool
noFloatIntoArg AnnExpr' CoreBndr BoundVarSet
arg Type
arg_ty = (BoundVarSet
here_fvs BoundVarSet -> BoundVarSet -> BoundVarSet
`unionDVarSet` BoundVarSet
arg_fvs, BoundVarSet
emptyDVarSet)
| Bool
otherwise = (BoundVarSet
here_fvs, BoundVarSet
arg_fvs)
where
arg_ty :: Type
arg_ty = (() :: Constraint) => Expr CoreBndr -> Type
Expr CoreBndr -> Type
exprType (Expr CoreBndr -> Type) -> Expr CoreBndr -> Type
forall a b. (a -> b) -> a -> b
$ AnnExpr' CoreBndr BoundVarSet -> Expr CoreBndr
forall bndr annot. AnnExpr' bndr annot -> Expr bndr
deAnnotate' AnnExpr' CoreBndr BoundVarSet
arg
fiExpr Platform
platform RevFloatInBinds
to_drop lam :: CoreExprWithFVs
lam@(BoundVarSet
_, AnnLam CoreBndr
_ CoreExprWithFVs
_)
| [CoreBndr] -> Bool
noFloatIntoLam [CoreBndr]
bndrs
= RevFloatInBinds -> Expr CoreBndr -> Expr CoreBndr
wrapFloats RevFloatInBinds
to_drop ([CoreBndr] -> Expr CoreBndr -> Expr CoreBndr
forall b. [b] -> Expr b -> Expr b
mkLams [CoreBndr]
bndrs (Platform -> RevFloatInBinds -> CoreExprWithFVs -> Expr CoreBndr
fiExpr Platform
platform [] CoreExprWithFVs
body))
| Bool
otherwise
= RevFloatInBinds -> Expr CoreBndr -> Expr CoreBndr
wrapFloats RevFloatInBinds
drop_here (Expr CoreBndr -> Expr CoreBndr) -> Expr CoreBndr -> Expr CoreBndr
forall a b. (a -> b) -> a -> b
$
[CoreBndr] -> Expr CoreBndr -> Expr CoreBndr
forall b. [b] -> Expr b -> Expr b
mkLams [CoreBndr]
bndrs (Platform -> RevFloatInBinds -> CoreExprWithFVs -> Expr CoreBndr
fiExpr Platform
platform RevFloatInBinds
body_drop CoreExprWithFVs
body)
where
([CoreBndr]
bndrs, CoreExprWithFVs
body) = CoreExprWithFVs -> ([CoreBndr], CoreExprWithFVs)
forall bndr annot.
AnnExpr bndr annot -> ([bndr], AnnExpr bndr annot)
collectAnnBndrs CoreExprWithFVs
lam
body_fvs :: BoundVarSet
body_fvs = CoreExprWithFVs -> BoundVarSet
freeVarsOf CoreExprWithFVs
body
(RevFloatInBinds
drop_here, [RevFloatInBinds
body_drop]) = Platform
-> Bool
-> RevFloatInBinds
-> BoundVarSet
-> [BoundVarSet]
-> (RevFloatInBinds, [RevFloatInBinds])
sepBindsByDropPoint Platform
platform Bool
False RevFloatInBinds
to_drop
([CoreBndr] -> BoundVarSet
mkDVarSet [CoreBndr]
bndrs) [BoundVarSet
body_fvs]
fiExpr Platform
platform RevFloatInBinds
to_drop (BoundVarSet
_, AnnTick CoreTickish
tickish CoreExprWithFVs
expr)
| CoreTickish
tickish CoreTickish -> TickishScoping -> Bool
forall (pass :: TickishPass).
GenTickish pass -> TickishScoping -> Bool
`tickishScopesLike` TickishScoping
SoftScope
= CoreTickish -> Expr CoreBndr -> Expr CoreBndr
forall b. CoreTickish -> Expr b -> Expr b
Tick CoreTickish
tickish (Platform -> RevFloatInBinds -> CoreExprWithFVs -> Expr CoreBndr
fiExpr Platform
platform RevFloatInBinds
to_drop CoreExprWithFVs
expr)
| Bool
otherwise
= RevFloatInBinds -> Expr CoreBndr -> Expr CoreBndr
wrapFloats RevFloatInBinds
to_drop (CoreTickish -> Expr CoreBndr -> Expr CoreBndr
forall b. CoreTickish -> Expr b -> Expr b
Tick CoreTickish
tickish (Platform -> RevFloatInBinds -> CoreExprWithFVs -> Expr CoreBndr
fiExpr Platform
platform [] CoreExprWithFVs
expr))
fiExpr Platform
platform RevFloatInBinds
to_drop (BoundVarSet
_,AnnLet AnnBind CoreBndr BoundVarSet
bind CoreExprWithFVs
body)
= Platform -> RevFloatInBinds -> CoreExprWithFVs -> Expr CoreBndr
fiExpr Platform
platform (RevFloatInBinds
after RevFloatInBinds -> RevFloatInBinds -> RevFloatInBinds
forall a. [a] -> [a] -> [a]
++ FloatInBind
new_float FloatInBind -> RevFloatInBinds -> RevFloatInBinds
forall a. a -> [a] -> [a]
: RevFloatInBinds
before) CoreExprWithFVs
body
where
(RevFloatInBinds
before, FloatInBind
new_float, RevFloatInBinds
after) = Platform
-> RevFloatInBinds
-> AnnBind CoreBndr BoundVarSet
-> BoundVarSet
-> (RevFloatInBinds, FloatInBind, RevFloatInBinds)
fiBind Platform
platform RevFloatInBinds
to_drop AnnBind CoreBndr BoundVarSet
bind BoundVarSet
body_fvs
body_fvs :: BoundVarSet
body_fvs = CoreExprWithFVs -> BoundVarSet
freeVarsOf CoreExprWithFVs
body
fiExpr Platform
platform RevFloatInBinds
to_drop (BoundVarSet
_, AnnCase CoreExprWithFVs
scrut CoreBndr
case_bndr Type
_ [AnnAlt AltCon
con [CoreBndr]
alt_bndrs CoreExprWithFVs
rhs])
| (() :: Constraint) => Type -> Bool
Type -> Bool
isUnliftedType (CoreBndr -> Type
idType CoreBndr
case_bndr)
, Expr CoreBndr -> Bool
exprOkForSideEffects (CoreExprWithFVs -> Expr CoreBndr
forall bndr annot. AnnExpr bndr annot -> Expr bndr
deAnnotate CoreExprWithFVs
scrut)
= RevFloatInBinds -> Expr CoreBndr -> Expr CoreBndr
wrapFloats RevFloatInBinds
shared_binds (Expr CoreBndr -> Expr CoreBndr) -> Expr CoreBndr -> Expr CoreBndr
forall a b. (a -> b) -> a -> b
$
Platform -> RevFloatInBinds -> CoreExprWithFVs -> Expr CoreBndr
fiExpr Platform
platform (FloatInBind
case_float FloatInBind -> RevFloatInBinds -> RevFloatInBinds
forall a. a -> [a] -> [a]
: RevFloatInBinds
rhs_binds) CoreExprWithFVs
rhs
where
case_float :: FloatInBind
case_float = BoundVarSet -> BoundVarSet -> FloatBind -> FloatInBind
FB BoundVarSet
all_bndrs BoundVarSet
scrut_fvs
(Expr CoreBndr -> CoreBndr -> AltCon -> [CoreBndr] -> FloatBind
FloatCase Expr CoreBndr
scrut' CoreBndr
case_bndr AltCon
con [CoreBndr]
alt_bndrs)
scrut' :: Expr CoreBndr
scrut' = Platform -> RevFloatInBinds -> CoreExprWithFVs -> Expr CoreBndr
fiExpr Platform
platform RevFloatInBinds
scrut_binds CoreExprWithFVs
scrut
rhs_fvs :: BoundVarSet
rhs_fvs = CoreExprWithFVs -> BoundVarSet
freeVarsOf CoreExprWithFVs
rhs
scrut_fvs :: BoundVarSet
scrut_fvs = CoreExprWithFVs -> BoundVarSet
freeVarsOf CoreExprWithFVs
scrut
all_bndrs :: BoundVarSet
all_bndrs = [CoreBndr] -> BoundVarSet
mkDVarSet [CoreBndr]
alt_bndrs BoundVarSet -> CoreBndr -> BoundVarSet
`extendDVarSet` CoreBndr
case_bndr
(RevFloatInBinds
shared_binds, [RevFloatInBinds
scrut_binds, RevFloatInBinds
rhs_binds])
= Platform
-> Bool
-> RevFloatInBinds
-> BoundVarSet
-> [BoundVarSet]
-> (RevFloatInBinds, [RevFloatInBinds])
sepBindsByDropPoint Platform
platform Bool
False RevFloatInBinds
to_drop
BoundVarSet
all_bndrs [BoundVarSet
scrut_fvs, BoundVarSet
rhs_fvs]
fiExpr Platform
platform RevFloatInBinds
to_drop (BoundVarSet
_, AnnCase CoreExprWithFVs
scrut CoreBndr
case_bndr Type
ty [AnnAlt CoreBndr BoundVarSet]
alts)
= RevFloatInBinds -> Expr CoreBndr -> Expr CoreBndr
wrapFloats RevFloatInBinds
drop_here1 (Expr CoreBndr -> Expr CoreBndr) -> Expr CoreBndr -> Expr CoreBndr
forall a b. (a -> b) -> a -> b
$
RevFloatInBinds -> Expr CoreBndr -> Expr CoreBndr
wrapFloats RevFloatInBinds
drop_here2 (Expr CoreBndr -> Expr CoreBndr) -> Expr CoreBndr -> Expr CoreBndr
forall a b. (a -> b) -> a -> b
$
Expr CoreBndr
-> CoreBndr -> Type -> [Alt CoreBndr] -> Expr CoreBndr
forall b. Expr b -> b -> Type -> [Alt b] -> Expr b
Case (Platform -> RevFloatInBinds -> CoreExprWithFVs -> Expr CoreBndr
fiExpr Platform
platform RevFloatInBinds
scrut_drops CoreExprWithFVs
scrut) CoreBndr
case_bndr Type
ty
(String
-> (RevFloatInBinds -> AnnAlt CoreBndr BoundVarSet -> Alt CoreBndr)
-> [RevFloatInBinds]
-> [AnnAlt CoreBndr BoundVarSet]
-> [Alt CoreBndr]
forall a b c. String -> (a -> b -> c) -> [a] -> [b] -> [c]
zipWithEqual String
"fiExpr" RevFloatInBinds -> AnnAlt CoreBndr BoundVarSet -> Alt CoreBndr
fi_alt [RevFloatInBinds]
alts_drops_s [AnnAlt CoreBndr BoundVarSet]
alts)
where
(RevFloatInBinds
drop_here1, [RevFloatInBinds
scrut_drops, RevFloatInBinds
alts_drops])
= Platform
-> Bool
-> RevFloatInBinds
-> BoundVarSet
-> [BoundVarSet]
-> (RevFloatInBinds, [RevFloatInBinds])
sepBindsByDropPoint Platform
platform Bool
False RevFloatInBinds
to_drop
BoundVarSet
all_alt_bndrs [BoundVarSet
scrut_fvs, BoundVarSet
all_alt_fvs]
(RevFloatInBinds
drop_here2, [RevFloatInBinds]
alts_drops_s)
= Platform
-> Bool
-> RevFloatInBinds
-> BoundVarSet
-> [BoundVarSet]
-> (RevFloatInBinds, [RevFloatInBinds])
sepBindsByDropPoint Platform
platform Bool
True RevFloatInBinds
alts_drops BoundVarSet
emptyDVarSet [BoundVarSet]
alts_fvs
scrut_fvs :: BoundVarSet
scrut_fvs = CoreExprWithFVs -> BoundVarSet
freeVarsOf CoreExprWithFVs
scrut
all_alt_bndrs :: BoundVarSet
all_alt_bndrs = (AnnAlt CoreBndr BoundVarSet -> BoundVarSet -> BoundVarSet)
-> BoundVarSet -> [AnnAlt CoreBndr BoundVarSet] -> BoundVarSet
forall a b. (a -> b -> b) -> b -> [a] -> b
forall (t :: * -> *) a b.
Foldable t =>
(a -> b -> b) -> b -> t a -> b
foldr (BoundVarSet -> BoundVarSet -> BoundVarSet
unionDVarSet (BoundVarSet -> BoundVarSet -> BoundVarSet)
-> (AnnAlt CoreBndr BoundVarSet -> BoundVarSet)
-> AnnAlt CoreBndr BoundVarSet
-> BoundVarSet
-> BoundVarSet
forall b c a. (b -> c) -> (a -> b) -> a -> c
. AnnAlt CoreBndr BoundVarSet -> BoundVarSet
forall {annot}. AnnAlt CoreBndr annot -> BoundVarSet
ann_alt_bndrs) (CoreBndr -> BoundVarSet
unitDVarSet CoreBndr
case_bndr) [AnnAlt CoreBndr BoundVarSet]
alts
ann_alt_bndrs :: AnnAlt CoreBndr annot -> BoundVarSet
ann_alt_bndrs (AnnAlt AltCon
_ [CoreBndr]
bndrs AnnExpr CoreBndr annot
_) = [CoreBndr] -> BoundVarSet
mkDVarSet [CoreBndr]
bndrs
alts_fvs :: [DVarSet]
alts_fvs :: [BoundVarSet]
alts_fvs = [CoreExprWithFVs -> BoundVarSet
freeVarsOf CoreExprWithFVs
rhs | AnnAlt AltCon
_ [CoreBndr]
_ CoreExprWithFVs
rhs <- [AnnAlt CoreBndr BoundVarSet]
alts]
all_alt_fvs :: DVarSet
all_alt_fvs :: BoundVarSet
all_alt_fvs = (BoundVarSet -> BoundVarSet -> BoundVarSet)
-> BoundVarSet -> [BoundVarSet] -> BoundVarSet
forall a b. (a -> b -> b) -> b -> [a] -> b
forall (t :: * -> *) a b.
Foldable t =>
(a -> b -> b) -> b -> t a -> b
foldr BoundVarSet -> BoundVarSet -> BoundVarSet
unionDVarSet (CoreBndr -> BoundVarSet
unitDVarSet CoreBndr
case_bndr) [BoundVarSet]
alts_fvs
fi_alt :: RevFloatInBinds -> AnnAlt CoreBndr BoundVarSet -> Alt CoreBndr
fi_alt RevFloatInBinds
to_drop (AnnAlt AltCon
con [CoreBndr]
args CoreExprWithFVs
rhs) = AltCon -> [CoreBndr] -> Expr CoreBndr -> Alt CoreBndr
forall b. AltCon -> [b] -> Expr b -> Alt b
Alt AltCon
con [CoreBndr]
args (Platform -> RevFloatInBinds -> CoreExprWithFVs -> Expr CoreBndr
fiExpr Platform
platform RevFloatInBinds
to_drop CoreExprWithFVs
rhs)
fiBind :: Platform
-> RevFloatInBinds
-> CoreBindWithFVs
-> DVarSet
-> ( RevFloatInBinds
, FloatInBind
, RevFloatInBinds)
fiBind :: Platform
-> RevFloatInBinds
-> AnnBind CoreBndr BoundVarSet
-> BoundVarSet
-> (RevFloatInBinds, FloatInBind, RevFloatInBinds)
fiBind Platform
platform RevFloatInBinds
to_drop (AnnNonRec CoreBndr
id ann_rhs :: CoreExprWithFVs
ann_rhs@(BoundVarSet
rhs_fvs, AnnExpr' CoreBndr BoundVarSet
rhs)) BoundVarSet
body_fvs
= ( RevFloatInBinds
shared_binds
, BoundVarSet -> BoundVarSet -> FloatBind -> FloatInBind
FB (CoreBndr -> BoundVarSet
unitDVarSet CoreBndr
id) BoundVarSet
rhs_fvs'
(Bind CoreBndr -> FloatBind
FloatLet (CoreBndr -> Expr CoreBndr -> Bind CoreBndr
forall b. b -> Expr b -> Bind b
NonRec CoreBndr
id Expr CoreBndr
rhs'))
, RevFloatInBinds
body_binds )
where
body_fvs2 :: BoundVarSet
body_fvs2 = BoundVarSet
body_fvs BoundVarSet -> CoreBndr -> BoundVarSet
`delDVarSet` CoreBndr
id
rule_fvs :: BoundVarSet
rule_fvs = CoreBndr -> BoundVarSet
bndrRuleAndUnfoldingVarsDSet CoreBndr
id
extra_fvs :: BoundVarSet
extra_fvs | RecFlag -> CoreBndr -> AnnExpr' CoreBndr BoundVarSet -> Bool
noFloatIntoRhs RecFlag
NonRecursive CoreBndr
id AnnExpr' CoreBndr BoundVarSet
rhs
= BoundVarSet
rule_fvs BoundVarSet -> BoundVarSet -> BoundVarSet
`unionDVarSet` BoundVarSet
rhs_fvs
| Bool
otherwise
= BoundVarSet
rule_fvs
(RevFloatInBinds
shared_binds, [RevFloatInBinds
rhs_binds, RevFloatInBinds
body_binds])
= Platform
-> Bool
-> RevFloatInBinds
-> BoundVarSet
-> [BoundVarSet]
-> (RevFloatInBinds, [RevFloatInBinds])
sepBindsByDropPoint Platform
platform Bool
False RevFloatInBinds
to_drop
BoundVarSet
extra_fvs [BoundVarSet
rhs_fvs, BoundVarSet
body_fvs2]
rhs' :: Expr CoreBndr
rhs' = Platform
-> RevFloatInBinds -> CoreBndr -> CoreExprWithFVs -> Expr CoreBndr
fiRhs Platform
platform RevFloatInBinds
rhs_binds CoreBndr
id CoreExprWithFVs
ann_rhs
rhs_fvs' :: BoundVarSet
rhs_fvs' = BoundVarSet
rhs_fvs BoundVarSet -> BoundVarSet -> BoundVarSet
`unionDVarSet` RevFloatInBinds -> BoundVarSet
floatedBindsFVs RevFloatInBinds
rhs_binds BoundVarSet -> BoundVarSet -> BoundVarSet
`unionDVarSet` BoundVarSet
rule_fvs
fiBind Platform
platform RevFloatInBinds
to_drop (AnnRec [(CoreBndr, CoreExprWithFVs)]
bindings) BoundVarSet
body_fvs
= ( RevFloatInBinds
shared_binds
, BoundVarSet -> BoundVarSet -> FloatBind -> FloatInBind
FB ([CoreBndr] -> BoundVarSet
mkDVarSet [CoreBndr]
ids) BoundVarSet
rhs_fvs'
(Bind CoreBndr -> FloatBind
FloatLet ([(CoreBndr, Expr CoreBndr)] -> Bind CoreBndr
forall b. [(b, Expr b)] -> Bind b
Rec ([RevFloatInBinds]
-> [(CoreBndr, CoreExprWithFVs)] -> [(CoreBndr, Expr CoreBndr)]
fi_bind [RevFloatInBinds]
rhss_binds [(CoreBndr, CoreExprWithFVs)]
bindings)))
, RevFloatInBinds
body_binds )
where
([CoreBndr]
ids, [CoreExprWithFVs]
rhss) = [(CoreBndr, CoreExprWithFVs)] -> ([CoreBndr], [CoreExprWithFVs])
forall a b. [(a, b)] -> ([a], [b])
unzip [(CoreBndr, CoreExprWithFVs)]
bindings
rhss_fvs :: [BoundVarSet]
rhss_fvs = (CoreExprWithFVs -> BoundVarSet)
-> [CoreExprWithFVs] -> [BoundVarSet]
forall a b. (a -> b) -> [a] -> [b]
map CoreExprWithFVs -> BoundVarSet
freeVarsOf [CoreExprWithFVs]
rhss
rule_fvs :: BoundVarSet
rule_fvs = (CoreBndr -> BoundVarSet) -> [CoreBndr] -> BoundVarSet
forall a. (a -> BoundVarSet) -> [a] -> BoundVarSet
mapUnionDVarSet CoreBndr -> BoundVarSet
bndrRuleAndUnfoldingVarsDSet [CoreBndr]
ids
extra_fvs :: BoundVarSet
extra_fvs = BoundVarSet
rule_fvs BoundVarSet -> BoundVarSet -> BoundVarSet
`unionDVarSet`
[BoundVarSet] -> BoundVarSet
unionDVarSets [ BoundVarSet
rhs_fvs | (CoreBndr
bndr, (BoundVarSet
rhs_fvs, AnnExpr' CoreBndr BoundVarSet
rhs)) <- [(CoreBndr, CoreExprWithFVs)]
bindings
, RecFlag -> CoreBndr -> AnnExpr' CoreBndr BoundVarSet -> Bool
noFloatIntoRhs RecFlag
Recursive CoreBndr
bndr AnnExpr' CoreBndr BoundVarSet
rhs ]
(RevFloatInBinds
shared_binds, RevFloatInBinds
body_binds:[RevFloatInBinds]
rhss_binds)
= Platform
-> Bool
-> RevFloatInBinds
-> BoundVarSet
-> [BoundVarSet]
-> (RevFloatInBinds, [RevFloatInBinds])
sepBindsByDropPoint Platform
platform Bool
False RevFloatInBinds
to_drop
BoundVarSet
extra_fvs (BoundVarSet
body_fvsBoundVarSet -> [BoundVarSet] -> [BoundVarSet]
forall a. a -> [a] -> [a]
:[BoundVarSet]
rhss_fvs)
rhs_fvs' :: BoundVarSet
rhs_fvs' = [BoundVarSet] -> BoundVarSet
unionDVarSets [BoundVarSet]
rhss_fvs BoundVarSet -> BoundVarSet -> BoundVarSet
`unionDVarSet`
[BoundVarSet] -> BoundVarSet
unionDVarSets ((RevFloatInBinds -> BoundVarSet)
-> [RevFloatInBinds] -> [BoundVarSet]
forall a b. (a -> b) -> [a] -> [b]
map RevFloatInBinds -> BoundVarSet
floatedBindsFVs [RevFloatInBinds]
rhss_binds) BoundVarSet -> BoundVarSet -> BoundVarSet
`unionDVarSet`
BoundVarSet
rule_fvs
fi_bind :: [RevFloatInBinds]
-> [(Id, CoreExprWithFVs)]
-> [(Id, CoreExpr)]
fi_bind :: [RevFloatInBinds]
-> [(CoreBndr, CoreExprWithFVs)] -> [(CoreBndr, Expr CoreBndr)]
fi_bind [RevFloatInBinds]
to_drops [(CoreBndr, CoreExprWithFVs)]
pairs
= [ (CoreBndr
binder, Platform
-> RevFloatInBinds -> CoreBndr -> CoreExprWithFVs -> Expr CoreBndr
fiRhs Platform
platform RevFloatInBinds
to_drop CoreBndr
binder CoreExprWithFVs
rhs)
| ((CoreBndr
binder, CoreExprWithFVs
rhs), RevFloatInBinds
to_drop) <- String
-> [(CoreBndr, CoreExprWithFVs)]
-> [RevFloatInBinds]
-> [((CoreBndr, CoreExprWithFVs), RevFloatInBinds)]
forall a b. String -> [a] -> [b] -> [(a, b)]
zipEqual String
"fi_bind" [(CoreBndr, CoreExprWithFVs)]
pairs [RevFloatInBinds]
to_drops ]
fiRhs :: Platform -> RevFloatInBinds -> CoreBndr -> CoreExprWithFVs -> CoreExpr
fiRhs :: Platform
-> RevFloatInBinds -> CoreBndr -> CoreExprWithFVs -> Expr CoreBndr
fiRhs Platform
platform RevFloatInBinds
to_drop CoreBndr
bndr CoreExprWithFVs
rhs
| Just Int
join_arity <- CoreBndr -> Maybe Int
isJoinId_maybe CoreBndr
bndr
, let ([CoreBndr]
bndrs, CoreExprWithFVs
body) = Int -> CoreExprWithFVs -> ([CoreBndr], CoreExprWithFVs)
forall bndr annot.
Int -> AnnExpr bndr annot -> ([bndr], AnnExpr bndr annot)
collectNAnnBndrs Int
join_arity CoreExprWithFVs
rhs
= [CoreBndr] -> Expr CoreBndr -> Expr CoreBndr
forall b. [b] -> Expr b -> Expr b
mkLams [CoreBndr]
bndrs (Platform -> RevFloatInBinds -> CoreExprWithFVs -> Expr CoreBndr
fiExpr Platform
platform RevFloatInBinds
to_drop CoreExprWithFVs
body)
| Bool
otherwise
= Platform -> RevFloatInBinds -> CoreExprWithFVs -> Expr CoreBndr
fiExpr Platform
platform RevFloatInBinds
to_drop CoreExprWithFVs
rhs
noFloatIntoLam :: [Var] -> Bool
noFloatIntoLam :: [CoreBndr] -> Bool
noFloatIntoLam [CoreBndr]
bndrs = (CoreBndr -> Bool) -> [CoreBndr] -> Bool
forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
any CoreBndr -> Bool
bad [CoreBndr]
bndrs
where
bad :: CoreBndr -> Bool
bad CoreBndr
b = CoreBndr -> Bool
isId CoreBndr
b Bool -> Bool -> Bool
&& Bool -> Bool
not (CoreBndr -> Bool
isOneShotBndr CoreBndr
b)
noFloatIntoRhs :: RecFlag -> Id -> CoreExprWithFVs' -> Bool
noFloatIntoRhs :: RecFlag -> CoreBndr -> AnnExpr' CoreBndr BoundVarSet -> Bool
noFloatIntoRhs RecFlag
is_rec CoreBndr
bndr AnnExpr' CoreBndr BoundVarSet
rhs
| CoreBndr -> Bool
isJoinId CoreBndr
bndr
= RecFlag -> Bool
isRec RecFlag
is_rec
| Bool
otherwise
= AnnExpr' CoreBndr BoundVarSet -> Type -> Bool
noFloatIntoArg AnnExpr' CoreBndr BoundVarSet
rhs (CoreBndr -> Type
idType CoreBndr
bndr)
noFloatIntoArg :: CoreExprWithFVs' -> Type -> Bool
noFloatIntoArg :: AnnExpr' CoreBndr BoundVarSet -> Type -> Bool
noFloatIntoArg AnnExpr' CoreBndr BoundVarSet
expr Type
expr_ty
| Just Levity
Unlifted <- (() :: Constraint) => Type -> Maybe Levity
Type -> Maybe Levity
typeLevity_maybe Type
expr_ty
= Bool
True
| AnnLam CoreBndr
bndr CoreExprWithFVs
e <- AnnExpr' CoreBndr BoundVarSet
expr
, ([CoreBndr]
bndrs, CoreExprWithFVs
_) <- CoreExprWithFVs -> ([CoreBndr], CoreExprWithFVs)
forall bndr annot.
AnnExpr bndr annot -> ([bndr], AnnExpr bndr annot)
collectAnnBndrs CoreExprWithFVs
e
= [CoreBndr] -> Bool
noFloatIntoLam (CoreBndr
bndrCoreBndr -> [CoreBndr] -> [CoreBndr]
forall a. a -> [a] -> [a]
:[CoreBndr]
bndrs)
Bool -> Bool -> Bool
|| (CoreBndr -> Bool) -> [CoreBndr] -> Bool
forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
all CoreBndr -> Bool
isTyVar (CoreBndr
bndrCoreBndr -> [CoreBndr] -> [CoreBndr]
forall a. a -> [a] -> [a]
:[CoreBndr]
bndrs)
| Bool
otherwise
= Expr CoreBndr -> Bool
exprIsTrivial Expr CoreBndr
deann_expr Bool -> Bool -> Bool
|| Expr CoreBndr -> Bool
exprIsHNF Expr CoreBndr
deann_expr
where
deann_expr :: Expr CoreBndr
deann_expr = AnnExpr' CoreBndr BoundVarSet -> Expr CoreBndr
forall bndr annot. AnnExpr' bndr annot -> Expr bndr
deAnnotate' AnnExpr' CoreBndr BoundVarSet
expr
sepBindsByDropPoint
:: Platform
-> Bool
-> RevFloatInBinds
-> FreeVarSet
-> [FreeVarSet]
-> ( RevFloatInBinds
, [RevFloatInBinds] )
type DropBox = (FreeVarSet, FloatInBinds)
dropBoxFloats :: DropBox -> RevFloatInBinds
dropBoxFloats :: DropBox -> RevFloatInBinds
dropBoxFloats (BoundVarSet
_, RevFloatInBinds
floats) = RevFloatInBinds -> RevFloatInBinds
forall a. [a] -> [a]
reverse RevFloatInBinds
floats
usedInDropBox :: DIdSet -> DropBox -> Bool
usedInDropBox :: BoundVarSet -> DropBox -> Bool
usedInDropBox BoundVarSet
bndrs (BoundVarSet
db_fvs, RevFloatInBinds
_) = BoundVarSet
db_fvs BoundVarSet -> BoundVarSet -> Bool
`intersectsDVarSet` BoundVarSet
bndrs
initDropBox :: DVarSet -> DropBox
initDropBox :: BoundVarSet -> DropBox
initDropBox BoundVarSet
fvs = (BoundVarSet
fvs, [])
sepBindsByDropPoint :: Platform
-> Bool
-> RevFloatInBinds
-> BoundVarSet
-> [BoundVarSet]
-> (RevFloatInBinds, [RevFloatInBinds])
sepBindsByDropPoint Platform
platform Bool
is_case RevFloatInBinds
floaters BoundVarSet
here_fvs [BoundVarSet]
fork_fvs
| RevFloatInBinds -> Bool
forall a. [a] -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null RevFloatInBinds
floaters
= ([], [[] | BoundVarSet
_ <- [BoundVarSet]
fork_fvs])
| Bool
otherwise
= RevFloatInBinds
-> DropBox -> [DropBox] -> (RevFloatInBinds, [RevFloatInBinds])
go RevFloatInBinds
floaters (BoundVarSet -> DropBox
initDropBox BoundVarSet
here_fvs) ((BoundVarSet -> DropBox) -> [BoundVarSet] -> [DropBox]
forall a b. (a -> b) -> [a] -> [b]
map BoundVarSet -> DropBox
initDropBox [BoundVarSet]
fork_fvs)
where
n_alts :: Int
n_alts = [BoundVarSet] -> Int
forall a. [a] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [BoundVarSet]
fork_fvs
go :: RevFloatInBinds -> DropBox -> [DropBox]
-> (RevFloatInBinds, [RevFloatInBinds])
go :: RevFloatInBinds
-> DropBox -> [DropBox] -> (RevFloatInBinds, [RevFloatInBinds])
go [] DropBox
here_box [DropBox]
fork_boxes
= (DropBox -> RevFloatInBinds
dropBoxFloats DropBox
here_box, (DropBox -> RevFloatInBinds) -> [DropBox] -> [RevFloatInBinds]
forall a b. (a -> b) -> [a] -> [b]
map DropBox -> RevFloatInBinds
dropBoxFloats [DropBox]
fork_boxes)
go (bind_w_fvs :: FloatInBind
bind_w_fvs@(FB BoundVarSet
bndrs BoundVarSet
bind_fvs FloatBind
bind) : RevFloatInBinds
binds) DropBox
here_box [DropBox]
fork_boxes
| Bool
drop_here = RevFloatInBinds
-> DropBox -> [DropBox] -> (RevFloatInBinds, [RevFloatInBinds])
go RevFloatInBinds
binds (DropBox -> DropBox
insert DropBox
here_box) [DropBox]
fork_boxes
| Bool
otherwise = RevFloatInBinds
-> DropBox -> [DropBox] -> (RevFloatInBinds, [RevFloatInBinds])
go RevFloatInBinds
binds DropBox
here_box [DropBox]
new_fork_boxes
where
used_here :: Bool
used_here = BoundVarSet
bndrs BoundVarSet -> DropBox -> Bool
`usedInDropBox` DropBox
here_box
used_in_flags :: [Bool]
used_in_flags = case [DropBox]
fork_boxes of
[] -> []
[DropBox
_] -> [Bool
True]
[DropBox]
_ -> (DropBox -> Bool) -> [DropBox] -> [Bool]
forall a b. (a -> b) -> [a] -> [b]
map (BoundVarSet
bndrs BoundVarSet -> DropBox -> Bool
`usedInDropBox`) [DropBox]
fork_boxes
drop_here :: Bool
drop_here = Bool
used_here Bool -> Bool -> Bool
|| Bool
cant_push
n_used_alts :: Int
n_used_alts = (Bool -> Bool) -> [Bool] -> Int
forall a. (a -> Bool) -> [a] -> Int
count Bool -> Bool
forall a. a -> a
id [Bool]
used_in_flags
cant_push :: Bool
cant_push
| Bool
is_case = (Int
n_alts Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
> Int
1 Bool -> Bool -> Bool
&& Int
n_used_alts Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
n_alts)
Bool -> Bool -> Bool
|| (Int
n_used_alts Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
> Int
1 Bool -> Bool -> Bool
&& Bool -> Bool
not (Platform -> FloatBind -> Bool
floatIsDupable Platform
platform FloatBind
bind))
| Bool
otherwise = FloatBind -> Bool
floatIsCase FloatBind
bind Bool -> Bool -> Bool
|| Int
n_used_alts Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
> Int
1
new_fork_boxes :: [DropBox]
new_fork_boxes = String
-> (DropBox -> Bool -> DropBox) -> [DropBox] -> [Bool] -> [DropBox]
forall a b c. String -> (a -> b -> c) -> [a] -> [b] -> [c]
zipWithEqual String
"FloatIn.sepBinds" DropBox -> Bool -> DropBox
insert_maybe
[DropBox]
fork_boxes [Bool]
used_in_flags
insert :: DropBox -> DropBox
insert :: DropBox -> DropBox
insert (BoundVarSet
fvs,RevFloatInBinds
drops) = (BoundVarSet
fvs BoundVarSet -> BoundVarSet -> BoundVarSet
`unionDVarSet` BoundVarSet
bind_fvs, FloatInBind
bind_w_fvsFloatInBind -> RevFloatInBinds -> RevFloatInBinds
forall a. a -> [a] -> [a]
:RevFloatInBinds
drops)
insert_maybe :: DropBox -> Bool -> DropBox
insert_maybe DropBox
box Bool
True = DropBox -> DropBox
insert DropBox
box
insert_maybe DropBox
box Bool
False = DropBox
box
floatedBindsFVs :: RevFloatInBinds -> FreeVarSet
floatedBindsFVs :: RevFloatInBinds -> BoundVarSet
floatedBindsFVs RevFloatInBinds
binds = (FloatInBind -> BoundVarSet) -> RevFloatInBinds -> BoundVarSet
forall a. (a -> BoundVarSet) -> [a] -> BoundVarSet
mapUnionDVarSet FloatInBind -> BoundVarSet
fbFVs RevFloatInBinds
binds
fbFVs :: FloatInBind -> DVarSet
fbFVs :: FloatInBind -> BoundVarSet
fbFVs (FB BoundVarSet
_ BoundVarSet
fvs FloatBind
_) = BoundVarSet
fvs
wrapFloats :: RevFloatInBinds -> CoreExpr -> CoreExpr
wrapFloats :: RevFloatInBinds -> Expr CoreBndr -> Expr CoreBndr
wrapFloats [] Expr CoreBndr
e = Expr CoreBndr
e
wrapFloats (FB BoundVarSet
_ BoundVarSet
_ FloatBind
fl : RevFloatInBinds
bs) Expr CoreBndr
e = RevFloatInBinds -> Expr CoreBndr -> Expr CoreBndr
wrapFloats RevFloatInBinds
bs (FloatBind -> Expr CoreBndr -> Expr CoreBndr
wrapFloat FloatBind
fl Expr CoreBndr
e)
floatIsDupable :: Platform -> FloatBind -> Bool
floatIsDupable :: Platform -> FloatBind -> Bool
floatIsDupable Platform
platform (FloatCase Expr CoreBndr
scrut CoreBndr
_ AltCon
_ [CoreBndr]
_) = Platform -> Expr CoreBndr -> Bool
exprIsDupable Platform
platform Expr CoreBndr
scrut
floatIsDupable Platform
platform (FloatLet (Rec [(CoreBndr, Expr CoreBndr)]
prs)) = ((CoreBndr, Expr CoreBndr) -> Bool)
-> [(CoreBndr, Expr CoreBndr)] -> Bool
forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
all (Platform -> Expr CoreBndr -> Bool
exprIsDupable Platform
platform (Expr CoreBndr -> Bool)
-> ((CoreBndr, Expr CoreBndr) -> Expr CoreBndr)
-> (CoreBndr, Expr CoreBndr)
-> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (CoreBndr, Expr CoreBndr) -> Expr CoreBndr
forall a b. (a, b) -> b
snd) [(CoreBndr, Expr CoreBndr)]
prs
floatIsDupable Platform
platform (FloatLet (NonRec CoreBndr
_ Expr CoreBndr
r)) = Platform -> Expr CoreBndr -> Bool
exprIsDupable Platform
platform Expr CoreBndr
r
floatIsCase :: FloatBind -> Bool
floatIsCase :: FloatBind -> Bool
floatIsCase (FloatCase {}) = Bool
True
floatIsCase (FloatLet {}) = Bool
False