{-# LANGUAGE CPP #-}
{-# OPTIONS_GHC -fprof-auto #-}
module FloatIn ( floatInwards ) where
#include "HsVersions.h"
import GhcPrelude
import CoreSyn
import MkCore
import HscTypes ( ModGuts(..) )
import CoreUtils
import CoreFVs
import CoreMonad ( CoreM )
import Id ( isOneShotBndr, idType, isJoinId, isJoinId_maybe )
import Var
import Type
import VarSet
import Util
import DynFlags
import Outputable
import BasicTypes ( RecFlag(..), isRec )
floatInwards :: ModGuts -> CoreM ModGuts
floatInwards :: ModGuts -> CoreM ModGuts
floatInwards pgm :: ModGuts
pgm@(ModGuts { mg_binds :: ModGuts -> CoreProgram
mg_binds = CoreProgram
binds })
= do { DynFlags
dflags <- CoreM DynFlags
forall (m :: * -> *). HasDynFlags m => m DynFlags
getDynFlags
; ModGuts -> CoreM ModGuts
forall (m :: * -> *) a. Monad m => a -> m a
return (ModGuts
pgm { mg_binds :: CoreProgram
mg_binds = (Bind CoreBndr -> Bind CoreBndr) -> CoreProgram -> CoreProgram
forall a b. (a -> b) -> [a] -> [b]
map (DynFlags -> Bind CoreBndr -> Bind CoreBndr
fi_top_bind DynFlags
dflags) CoreProgram
binds }) }
where
fi_top_bind :: DynFlags -> Bind CoreBndr -> Bind CoreBndr
fi_top_bind dflags :: DynFlags
dflags (NonRec binder :: CoreBndr
binder rhs :: Expr CoreBndr
rhs)
= CoreBndr -> Expr CoreBndr -> Bind CoreBndr
forall b. b -> Expr b -> Bind b
NonRec CoreBndr
binder (DynFlags -> FloatInBinds -> CoreExprWithFVs -> Expr CoreBndr
fiExpr DynFlags
dflags [] (Expr CoreBndr -> CoreExprWithFVs
freeVars Expr CoreBndr
rhs))
fi_top_bind dflags :: DynFlags
dflags (Rec pairs :: [(CoreBndr, Expr CoreBndr)]
pairs)
= [(CoreBndr, Expr CoreBndr)] -> Bind CoreBndr
forall b. [(b, Expr b)] -> Bind b
Rec [ (CoreBndr
b, DynFlags -> FloatInBinds -> CoreExprWithFVs -> Expr CoreBndr
fiExpr DynFlags
dflags [] (Expr CoreBndr -> CoreExprWithFVs
freeVars Expr CoreBndr
rhs)) | (b :: CoreBndr
b, rhs :: Expr CoreBndr
rhs) <- [(CoreBndr, Expr CoreBndr)]
pairs ]
type FreeVarSet = DIdSet
type BoundVarSet = DIdSet
data FloatInBind = FB BoundVarSet FreeVarSet FloatBind
type FloatInBinds = [FloatInBind]
fiExpr :: DynFlags
-> FloatInBinds
-> CoreExprWithFVs
-> CoreExpr
fiExpr :: DynFlags -> FloatInBinds -> CoreExprWithFVs -> Expr CoreBndr
fiExpr _ to_drop :: FloatInBinds
to_drop (_, AnnLit lit :: Literal
lit) = FloatInBinds -> Expr CoreBndr -> Expr CoreBndr
wrapFloats FloatInBinds
to_drop (Literal -> Expr CoreBndr
forall b. Literal -> Expr b
Lit Literal
lit)
fiExpr _ to_drop :: FloatInBinds
to_drop (_, AnnType ty :: Type
ty) = ASSERT( null to_drop ) Type ty
fiExpr _ to_drop :: FloatInBinds
to_drop (_, AnnVar v :: CoreBndr
v) = FloatInBinds -> Expr CoreBndr -> Expr CoreBndr
wrapFloats FloatInBinds
to_drop (CoreBndr -> Expr CoreBndr
forall b. CoreBndr -> Expr b
Var CoreBndr
v)
fiExpr _ to_drop :: FloatInBinds
to_drop (_, AnnCoercion co :: Coercion
co) = FloatInBinds -> Expr CoreBndr -> Expr CoreBndr
wrapFloats FloatInBinds
to_drop (Coercion -> Expr CoreBndr
forall b. Coercion -> Expr b
Coercion Coercion
co)
fiExpr dflags :: DynFlags
dflags to_drop :: FloatInBinds
to_drop (_, AnnCast expr :: CoreExprWithFVs
expr (co_ann :: FVAnn
co_ann, co :: Coercion
co))
= FloatInBinds -> Expr CoreBndr -> Expr CoreBndr
wrapFloats (FloatInBinds
drop_here FloatInBinds -> FloatInBinds -> FloatInBinds
forall a. [a] -> [a] -> [a]
++ FloatInBinds
co_drop) (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 (DynFlags -> FloatInBinds -> CoreExprWithFVs -> Expr CoreBndr
fiExpr DynFlags
dflags FloatInBinds
e_drop CoreExprWithFVs
expr) Coercion
co
where
[drop_here :: FloatInBinds
drop_here, e_drop :: FloatInBinds
e_drop, co_drop :: FloatInBinds
co_drop]
= DynFlags -> Bool -> [FVAnn] -> FloatInBinds -> [FloatInBinds]
sepBindsByDropPoint DynFlags
dflags Bool
False
[CoreExprWithFVs -> FVAnn
freeVarsOf CoreExprWithFVs
expr, FVAnn -> FVAnn
freeVarsOfAnn FVAnn
co_ann]
FloatInBinds
to_drop
fiExpr dflags :: DynFlags
dflags to_drop :: FloatInBinds
to_drop ann_expr :: CoreExprWithFVs
ann_expr@(_,AnnApp {})
= FloatInBinds -> Expr CoreBndr -> Expr CoreBndr
wrapFloats FloatInBinds
drop_here (Expr CoreBndr -> Expr CoreBndr) -> Expr CoreBndr -> Expr CoreBndr
forall a b. (a -> b) -> a -> b
$ FloatInBinds -> Expr CoreBndr -> Expr CoreBndr
wrapFloats FloatInBinds
extra_drop (Expr CoreBndr -> Expr CoreBndr) -> Expr CoreBndr -> Expr CoreBndr
forall a b. (a -> b) -> a -> b
$
[Tickish CoreBndr] -> Expr CoreBndr -> Expr CoreBndr
mkTicks [Tickish CoreBndr]
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 (DynFlags -> FloatInBinds -> CoreExprWithFVs -> Expr CoreBndr
fiExpr DynFlags
dflags FloatInBinds
fun_drop CoreExprWithFVs
ann_fun)
((FloatInBinds -> CoreExprWithFVs -> Expr CoreBndr)
-> [FloatInBinds] -> [CoreExprWithFVs] -> [Expr CoreBndr]
forall a b c. (a -> b -> c) -> [a] -> [b] -> [c]
zipWith (DynFlags -> FloatInBinds -> CoreExprWithFVs -> Expr CoreBndr
fiExpr DynFlags
dflags) [FloatInBinds]
arg_drops [CoreExprWithFVs]
ann_args)
where
(ann_fun :: CoreExprWithFVs
ann_fun, ann_args :: [CoreExprWithFVs]
ann_args, ticks :: [Tickish CoreBndr]
ticks) = (Tickish CoreBndr -> Bool)
-> CoreExprWithFVs
-> (CoreExprWithFVs, [CoreExprWithFVs], [Tickish CoreBndr])
forall b a.
(Tickish CoreBndr -> Bool)
-> AnnExpr b a -> (AnnExpr b a, [AnnExpr b a], [Tickish CoreBndr])
collectAnnArgsTicks Tickish CoreBndr -> Bool
forall id. Tickish id -> Bool
tickishFloatable CoreExprWithFVs
ann_expr
fun_ty :: Type
fun_ty = Expr CoreBndr -> Type
exprType (CoreExprWithFVs -> Expr CoreBndr
forall bndr annot. AnnExpr bndr annot -> Expr bndr
deAnnotate CoreExprWithFVs
ann_fun)
fun_fvs :: FVAnn
fun_fvs = CoreExprWithFVs -> FVAnn
freeVarsOf CoreExprWithFVs
ann_fun
arg_fvs :: [FVAnn]
arg_fvs = (CoreExprWithFVs -> FVAnn) -> [CoreExprWithFVs] -> [FVAnn]
forall a b. (a -> b) -> [a] -> [b]
map CoreExprWithFVs -> FVAnn
freeVarsOf [CoreExprWithFVs]
ann_args
(drop_here :: FloatInBinds
drop_here : extra_drop :: FloatInBinds
extra_drop : fun_drop :: FloatInBinds
fun_drop : arg_drops :: [FloatInBinds]
arg_drops)
= DynFlags -> Bool -> [FVAnn] -> FloatInBinds -> [FloatInBinds]
sepBindsByDropPoint DynFlags
dflags Bool
False
(FVAnn
extra_fvs FVAnn -> [FVAnn] -> [FVAnn]
forall a. a -> [a] -> [a]
: FVAnn
fun_fvs FVAnn -> [FVAnn] -> [FVAnn]
forall a. a -> [a] -> [a]
: [FVAnn]
arg_fvs)
FloatInBinds
to_drop
(_, extra_fvs :: FVAnn
extra_fvs) = ((Type, FVAnn) -> CoreExprWithFVs -> (Type, FVAnn))
-> (Type, FVAnn) -> [CoreExprWithFVs] -> (Type, FVAnn)
forall (t :: * -> *) b a.
Foldable t =>
(b -> a -> b) -> b -> t a -> b
foldl' (Type, FVAnn) -> CoreExprWithFVs -> (Type, FVAnn)
add_arg (Type
fun_ty, FVAnn
extra_fvs0) [CoreExprWithFVs]
ann_args
extra_fvs0 :: FVAnn
extra_fvs0 = case CoreExprWithFVs
ann_fun of
(_, AnnVar _) -> FVAnn
fun_fvs
_ -> FVAnn
emptyDVarSet
add_arg :: (Type,FreeVarSet) -> CoreExprWithFVs -> (Type,FreeVarSet)
add_arg :: (Type, FVAnn) -> CoreExprWithFVs -> (Type, FVAnn)
add_arg (fun_ty :: Type
fun_ty, extra_fvs :: FVAnn
extra_fvs) (_, AnnType ty :: Type
ty)
= (HasDebugCallStack => Type -> Type -> Type
Type -> Type -> Type
piResultTy Type
fun_ty Type
ty, FVAnn
extra_fvs)
add_arg (fun_ty :: Type
fun_ty, extra_fvs :: FVAnn
extra_fvs) (arg_fvs :: FVAnn
arg_fvs, arg :: AnnExpr' CoreBndr FVAnn
arg)
| AnnExpr' CoreBndr FVAnn -> Type -> Bool
noFloatIntoArg AnnExpr' CoreBndr FVAnn
arg Type
arg_ty
= (Type
res_ty, FVAnn
extra_fvs FVAnn -> FVAnn -> FVAnn
`unionDVarSet` FVAnn
arg_fvs)
| Bool
otherwise
= (Type
res_ty, FVAnn
extra_fvs)
where
(arg_ty :: Type
arg_ty, res_ty :: Type
res_ty) = Type -> (Type, Type)
splitFunTy Type
fun_ty
fiExpr dflags :: DynFlags
dflags to_drop :: FloatInBinds
to_drop lam :: CoreExprWithFVs
lam@(_, AnnLam _ _)
| [CoreBndr] -> Bool
noFloatIntoLam [CoreBndr]
bndrs
= FloatInBinds -> Expr CoreBndr -> Expr CoreBndr
wrapFloats FloatInBinds
to_drop ([CoreBndr] -> Expr CoreBndr -> Expr CoreBndr
forall b. [b] -> Expr b -> Expr b
mkLams [CoreBndr]
bndrs (DynFlags -> FloatInBinds -> CoreExprWithFVs -> Expr CoreBndr
fiExpr DynFlags
dflags [] CoreExprWithFVs
body))
| Bool
otherwise
= [CoreBndr] -> Expr CoreBndr -> Expr CoreBndr
forall b. [b] -> Expr b -> Expr b
mkLams [CoreBndr]
bndrs (DynFlags -> FloatInBinds -> CoreExprWithFVs -> Expr CoreBndr
fiExpr DynFlags
dflags FloatInBinds
to_drop CoreExprWithFVs
body)
where
(bndrs :: [CoreBndr]
bndrs, body :: CoreExprWithFVs
body) = CoreExprWithFVs -> ([CoreBndr], CoreExprWithFVs)
forall bndr annot.
AnnExpr bndr annot -> ([bndr], AnnExpr bndr annot)
collectAnnBndrs CoreExprWithFVs
lam
fiExpr dflags :: DynFlags
dflags to_drop :: FloatInBinds
to_drop (_, AnnTick tickish :: Tickish CoreBndr
tickish expr :: CoreExprWithFVs
expr)
| Tickish CoreBndr
tickish Tickish CoreBndr -> TickishScoping -> Bool
forall id. Tickish id -> TickishScoping -> Bool
`tickishScopesLike` TickishScoping
SoftScope
= Tickish CoreBndr -> Expr CoreBndr -> Expr CoreBndr
forall b. Tickish CoreBndr -> Expr b -> Expr b
Tick Tickish CoreBndr
tickish (DynFlags -> FloatInBinds -> CoreExprWithFVs -> Expr CoreBndr
fiExpr DynFlags
dflags FloatInBinds
to_drop CoreExprWithFVs
expr)
| Bool
otherwise
= FloatInBinds -> Expr CoreBndr -> Expr CoreBndr
wrapFloats FloatInBinds
to_drop (Tickish CoreBndr -> Expr CoreBndr -> Expr CoreBndr
forall b. Tickish CoreBndr -> Expr b -> Expr b
Tick Tickish CoreBndr
tickish (DynFlags -> FloatInBinds -> CoreExprWithFVs -> Expr CoreBndr
fiExpr DynFlags
dflags [] CoreExprWithFVs
expr))
fiExpr dflags :: DynFlags
dflags to_drop :: FloatInBinds
to_drop (_,AnnLet bind :: AnnBind CoreBndr FVAnn
bind body :: CoreExprWithFVs
body)
= DynFlags -> FloatInBinds -> CoreExprWithFVs -> Expr CoreBndr
fiExpr DynFlags
dflags (FloatInBinds
after FloatInBinds -> FloatInBinds -> FloatInBinds
forall a. [a] -> [a] -> [a]
++ FloatInBind
new_float FloatInBind -> FloatInBinds -> FloatInBinds
forall a. a -> [a] -> [a]
: FloatInBinds
before) CoreExprWithFVs
body
where
(before :: FloatInBinds
before, new_float :: FloatInBind
new_float, after :: FloatInBinds
after) = DynFlags
-> FloatInBinds
-> AnnBind CoreBndr FVAnn
-> FVAnn
-> (FloatInBinds, FloatInBind, FloatInBinds)
fiBind DynFlags
dflags FloatInBinds
to_drop AnnBind CoreBndr FVAnn
bind FVAnn
body_fvs
body_fvs :: FVAnn
body_fvs = CoreExprWithFVs -> FVAnn
freeVarsOf CoreExprWithFVs
body
fiExpr dflags :: DynFlags
dflags to_drop :: FloatInBinds
to_drop (_, AnnCase scrut :: CoreExprWithFVs
scrut case_bndr :: CoreBndr
case_bndr _ [(con :: AltCon
con,alt_bndrs :: [CoreBndr]
alt_bndrs,rhs :: CoreExprWithFVs
rhs)])
| HasDebugCallStack => 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)
= FloatInBinds -> Expr CoreBndr -> Expr CoreBndr
wrapFloats FloatInBinds
shared_binds (Expr CoreBndr -> Expr CoreBndr) -> Expr CoreBndr -> Expr CoreBndr
forall a b. (a -> b) -> a -> b
$
DynFlags -> FloatInBinds -> CoreExprWithFVs -> Expr CoreBndr
fiExpr DynFlags
dflags (FloatInBind
case_float FloatInBind -> FloatInBinds -> FloatInBinds
forall a. a -> [a] -> [a]
: FloatInBinds
rhs_binds) CoreExprWithFVs
rhs
where
case_float :: FloatInBind
case_float = FVAnn -> FVAnn -> FloatBind -> FloatInBind
FB ([CoreBndr] -> FVAnn
mkDVarSet (CoreBndr
case_bndr CoreBndr -> [CoreBndr] -> [CoreBndr]
forall a. a -> [a] -> [a]
: [CoreBndr]
alt_bndrs)) FVAnn
scrut_fvs
(Expr CoreBndr -> CoreBndr -> AltCon -> [CoreBndr] -> FloatBind
FloatCase Expr CoreBndr
scrut' CoreBndr
case_bndr AltCon
con [CoreBndr]
alt_bndrs)
scrut' :: Expr CoreBndr
scrut' = DynFlags -> FloatInBinds -> CoreExprWithFVs -> Expr CoreBndr
fiExpr DynFlags
dflags FloatInBinds
scrut_binds CoreExprWithFVs
scrut
rhs_fvs :: FVAnn
rhs_fvs = CoreExprWithFVs -> FVAnn
freeVarsOf CoreExprWithFVs
rhs FVAnn -> [CoreBndr] -> FVAnn
`delDVarSetList` (CoreBndr
case_bndr CoreBndr -> [CoreBndr] -> [CoreBndr]
forall a. a -> [a] -> [a]
: [CoreBndr]
alt_bndrs)
scrut_fvs :: FVAnn
scrut_fvs = CoreExprWithFVs -> FVAnn
freeVarsOf CoreExprWithFVs
scrut
[shared_binds :: FloatInBinds
shared_binds, scrut_binds :: FloatInBinds
scrut_binds, rhs_binds :: FloatInBinds
rhs_binds]
= DynFlags -> Bool -> [FVAnn] -> FloatInBinds -> [FloatInBinds]
sepBindsByDropPoint DynFlags
dflags Bool
False
[FVAnn
scrut_fvs, FVAnn
rhs_fvs]
FloatInBinds
to_drop
fiExpr dflags :: DynFlags
dflags to_drop :: FloatInBinds
to_drop (_, AnnCase scrut :: CoreExprWithFVs
scrut case_bndr :: CoreBndr
case_bndr ty :: Type
ty alts :: [AnnAlt CoreBndr FVAnn]
alts)
= FloatInBinds -> Expr CoreBndr -> Expr CoreBndr
wrapFloats FloatInBinds
drop_here1 (Expr CoreBndr -> Expr CoreBndr) -> Expr CoreBndr -> Expr CoreBndr
forall a b. (a -> b) -> a -> b
$
FloatInBinds -> Expr CoreBndr -> Expr CoreBndr
wrapFloats FloatInBinds
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 (DynFlags -> FloatInBinds -> CoreExprWithFVs -> Expr CoreBndr
fiExpr DynFlags
dflags FloatInBinds
scrut_drops CoreExprWithFVs
scrut) CoreBndr
case_bndr Type
ty
((FloatInBinds -> AnnAlt CoreBndr FVAnn -> Alt CoreBndr)
-> [FloatInBinds] -> [AnnAlt CoreBndr FVAnn] -> [Alt CoreBndr]
forall a b c. (a -> b -> c) -> [a] -> [b] -> [c]
zipWith FloatInBinds -> AnnAlt CoreBndr FVAnn -> Alt CoreBndr
forall a b.
FloatInBinds -> (a, b, CoreExprWithFVs) -> (a, b, Expr CoreBndr)
fi_alt [FloatInBinds]
alts_drops_s [AnnAlt CoreBndr FVAnn]
alts)
where
[drop_here1 :: FloatInBinds
drop_here1, scrut_drops :: FloatInBinds
scrut_drops, alts_drops :: FloatInBinds
alts_drops]
= DynFlags -> Bool -> [FVAnn] -> FloatInBinds -> [FloatInBinds]
sepBindsByDropPoint DynFlags
dflags Bool
False
[FVAnn
scrut_fvs, FVAnn
all_alts_fvs]
FloatInBinds
to_drop
(drop_here2 :: FloatInBinds
drop_here2 : alts_drops_s :: [FloatInBinds]
alts_drops_s)
| [ _ ] <- [AnnAlt CoreBndr FVAnn]
alts = [] FloatInBinds -> [FloatInBinds] -> [FloatInBinds]
forall a. a -> [a] -> [a]
: [FloatInBinds
alts_drops]
| Bool
otherwise = DynFlags -> Bool -> [FVAnn] -> FloatInBinds -> [FloatInBinds]
sepBindsByDropPoint DynFlags
dflags Bool
True [FVAnn]
alts_fvs FloatInBinds
alts_drops
scrut_fvs :: FVAnn
scrut_fvs = CoreExprWithFVs -> FVAnn
freeVarsOf CoreExprWithFVs
scrut
alts_fvs :: [FVAnn]
alts_fvs = (AnnAlt CoreBndr FVAnn -> FVAnn)
-> [AnnAlt CoreBndr FVAnn] -> [FVAnn]
forall a b. (a -> b) -> [a] -> [b]
map AnnAlt CoreBndr FVAnn -> FVAnn
forall a. (a, [CoreBndr], CoreExprWithFVs) -> FVAnn
alt_fvs [AnnAlt CoreBndr FVAnn]
alts
all_alts_fvs :: FVAnn
all_alts_fvs = [FVAnn] -> FVAnn
unionDVarSets [FVAnn]
alts_fvs
alt_fvs :: (a, [CoreBndr], CoreExprWithFVs) -> FVAnn
alt_fvs (_con :: a
_con, args :: [CoreBndr]
args, rhs :: CoreExprWithFVs
rhs)
= (FVAnn -> CoreBndr -> FVAnn) -> FVAnn -> [CoreBndr] -> FVAnn
forall (t :: * -> *) b a.
Foldable t =>
(b -> a -> b) -> b -> t a -> b
foldl' FVAnn -> CoreBndr -> FVAnn
delDVarSet (CoreExprWithFVs -> FVAnn
freeVarsOf CoreExprWithFVs
rhs) (CoreBndr
case_bndrCoreBndr -> [CoreBndr] -> [CoreBndr]
forall a. a -> [a] -> [a]
:[CoreBndr]
args)
fi_alt :: FloatInBinds -> (a, b, CoreExprWithFVs) -> (a, b, Expr CoreBndr)
fi_alt to_drop :: FloatInBinds
to_drop (con :: a
con, args :: b
args, rhs :: CoreExprWithFVs
rhs) = (a
con, b
args, DynFlags -> FloatInBinds -> CoreExprWithFVs -> Expr CoreBndr
fiExpr DynFlags
dflags FloatInBinds
to_drop CoreExprWithFVs
rhs)
fiBind :: DynFlags
-> FloatInBinds
-> CoreBindWithFVs
-> DVarSet
-> ( FloatInBinds
, FloatInBind
, FloatInBinds)
fiBind :: DynFlags
-> FloatInBinds
-> AnnBind CoreBndr FVAnn
-> FVAnn
-> (FloatInBinds, FloatInBind, FloatInBinds)
fiBind dflags :: DynFlags
dflags to_drop :: FloatInBinds
to_drop (AnnNonRec id :: CoreBndr
id ann_rhs :: CoreExprWithFVs
ann_rhs@(rhs_fvs :: FVAnn
rhs_fvs, rhs :: AnnExpr' CoreBndr FVAnn
rhs)) body_fvs :: FVAnn
body_fvs
= ( FloatInBinds
extra_binds FloatInBinds -> FloatInBinds -> FloatInBinds
forall a. [a] -> [a] -> [a]
++ FloatInBinds
shared_binds
, FVAnn -> FVAnn -> FloatBind -> FloatInBind
FB (CoreBndr -> FVAnn
unitDVarSet CoreBndr
id) FVAnn
rhs_fvs'
(Bind CoreBndr -> FloatBind
FloatLet (CoreBndr -> Expr CoreBndr -> Bind CoreBndr
forall b. b -> Expr b -> Bind b
NonRec CoreBndr
id Expr CoreBndr
rhs'))
, FloatInBinds
body_binds )
where
body_fvs2 :: FVAnn
body_fvs2 = FVAnn
body_fvs FVAnn -> CoreBndr -> FVAnn
`delDVarSet` CoreBndr
id
rule_fvs :: FVAnn
rule_fvs = CoreBndr -> FVAnn
bndrRuleAndUnfoldingVarsDSet CoreBndr
id
extra_fvs :: FVAnn
extra_fvs | RecFlag -> CoreBndr -> AnnExpr' CoreBndr FVAnn -> Bool
noFloatIntoRhs RecFlag
NonRecursive CoreBndr
id AnnExpr' CoreBndr FVAnn
rhs
= FVAnn
rule_fvs FVAnn -> FVAnn -> FVAnn
`unionDVarSet` FVAnn
rhs_fvs
| Bool
otherwise
= FVAnn
rule_fvs
[shared_binds :: FloatInBinds
shared_binds, extra_binds :: FloatInBinds
extra_binds, rhs_binds :: FloatInBinds
rhs_binds, body_binds :: FloatInBinds
body_binds]
= DynFlags -> Bool -> [FVAnn] -> FloatInBinds -> [FloatInBinds]
sepBindsByDropPoint DynFlags
dflags Bool
False
[FVAnn
extra_fvs, FVAnn
rhs_fvs, FVAnn
body_fvs2]
FloatInBinds
to_drop
rhs' :: Expr CoreBndr
rhs' = DynFlags
-> FloatInBinds -> CoreBndr -> CoreExprWithFVs -> Expr CoreBndr
fiRhs DynFlags
dflags FloatInBinds
rhs_binds CoreBndr
id CoreExprWithFVs
ann_rhs
rhs_fvs' :: FVAnn
rhs_fvs' = FVAnn
rhs_fvs FVAnn -> FVAnn -> FVAnn
`unionDVarSet` FloatInBinds -> FVAnn
floatedBindsFVs FloatInBinds
rhs_binds FVAnn -> FVAnn -> FVAnn
`unionDVarSet` FVAnn
rule_fvs
fiBind dflags :: DynFlags
dflags to_drop :: FloatInBinds
to_drop (AnnRec bindings :: [(CoreBndr, CoreExprWithFVs)]
bindings) body_fvs :: FVAnn
body_fvs
= ( FloatInBinds
extra_binds FloatInBinds -> FloatInBinds -> FloatInBinds
forall a. [a] -> [a] -> [a]
++ FloatInBinds
shared_binds
, FVAnn -> FVAnn -> FloatBind -> FloatInBind
FB ([CoreBndr] -> FVAnn
mkDVarSet [CoreBndr]
ids) FVAnn
rhs_fvs'
(Bind CoreBndr -> FloatBind
FloatLet ([(CoreBndr, Expr CoreBndr)] -> Bind CoreBndr
forall b. [(b, Expr b)] -> Bind b
Rec ([FloatInBinds]
-> [(CoreBndr, CoreExprWithFVs)] -> [(CoreBndr, Expr CoreBndr)]
fi_bind [FloatInBinds]
rhss_binds [(CoreBndr, CoreExprWithFVs)]
bindings)))
, FloatInBinds
body_binds )
where
(ids :: [CoreBndr]
ids, rhss :: [CoreExprWithFVs]
rhss) = [(CoreBndr, CoreExprWithFVs)] -> ([CoreBndr], [CoreExprWithFVs])
forall a b. [(a, b)] -> ([a], [b])
unzip [(CoreBndr, CoreExprWithFVs)]
bindings
rhss_fvs :: [FVAnn]
rhss_fvs = (CoreExprWithFVs -> FVAnn) -> [CoreExprWithFVs] -> [FVAnn]
forall a b. (a -> b) -> [a] -> [b]
map CoreExprWithFVs -> FVAnn
freeVarsOf [CoreExprWithFVs]
rhss
rule_fvs :: FVAnn
rule_fvs = (CoreBndr -> FVAnn) -> [CoreBndr] -> FVAnn
forall a. (a -> FVAnn) -> [a] -> FVAnn
mapUnionDVarSet CoreBndr -> FVAnn
bndrRuleAndUnfoldingVarsDSet [CoreBndr]
ids
extra_fvs :: FVAnn
extra_fvs = FVAnn
rule_fvs FVAnn -> FVAnn -> FVAnn
`unionDVarSet`
[FVAnn] -> FVAnn
unionDVarSets [ FVAnn
rhs_fvs | (bndr :: CoreBndr
bndr, (rhs_fvs :: FVAnn
rhs_fvs, rhs :: AnnExpr' CoreBndr FVAnn
rhs)) <- [(CoreBndr, CoreExprWithFVs)]
bindings
, RecFlag -> CoreBndr -> AnnExpr' CoreBndr FVAnn -> Bool
noFloatIntoRhs RecFlag
Recursive CoreBndr
bndr AnnExpr' CoreBndr FVAnn
rhs ]
(shared_binds :: FloatInBinds
shared_binds:extra_binds :: FloatInBinds
extra_binds:body_binds :: FloatInBinds
body_binds:rhss_binds :: [FloatInBinds]
rhss_binds)
= DynFlags -> Bool -> [FVAnn] -> FloatInBinds -> [FloatInBinds]
sepBindsByDropPoint DynFlags
dflags Bool
False
(FVAnn
extra_fvsFVAnn -> [FVAnn] -> [FVAnn]
forall a. a -> [a] -> [a]
:FVAnn
body_fvsFVAnn -> [FVAnn] -> [FVAnn]
forall a. a -> [a] -> [a]
:[FVAnn]
rhss_fvs)
FloatInBinds
to_drop
rhs_fvs' :: FVAnn
rhs_fvs' = [FVAnn] -> FVAnn
unionDVarSets [FVAnn]
rhss_fvs FVAnn -> FVAnn -> FVAnn
`unionDVarSet`
[FVAnn] -> FVAnn
unionDVarSets ((FloatInBinds -> FVAnn) -> [FloatInBinds] -> [FVAnn]
forall a b. (a -> b) -> [a] -> [b]
map FloatInBinds -> FVAnn
floatedBindsFVs [FloatInBinds]
rhss_binds) FVAnn -> FVAnn -> FVAnn
`unionDVarSet`
FVAnn
rule_fvs
fi_bind :: [FloatInBinds]
-> [(Id, CoreExprWithFVs)]
-> [(Id, CoreExpr)]
fi_bind :: [FloatInBinds]
-> [(CoreBndr, CoreExprWithFVs)] -> [(CoreBndr, Expr CoreBndr)]
fi_bind to_drops :: [FloatInBinds]
to_drops pairs :: [(CoreBndr, CoreExprWithFVs)]
pairs
= [ (CoreBndr
binder, DynFlags
-> FloatInBinds -> CoreBndr -> CoreExprWithFVs -> Expr CoreBndr
fiRhs DynFlags
dflags FloatInBinds
to_drop CoreBndr
binder CoreExprWithFVs
rhs)
| ((binder :: CoreBndr
binder, rhs :: CoreExprWithFVs
rhs), to_drop :: FloatInBinds
to_drop) <- String
-> [(CoreBndr, CoreExprWithFVs)]
-> [FloatInBinds]
-> [((CoreBndr, CoreExprWithFVs), FloatInBinds)]
forall a b. String -> [a] -> [b] -> [(a, b)]
zipEqual "fi_bind" [(CoreBndr, CoreExprWithFVs)]
pairs [FloatInBinds]
to_drops ]
fiRhs :: DynFlags -> FloatInBinds -> CoreBndr -> CoreExprWithFVs -> CoreExpr
fiRhs :: DynFlags
-> FloatInBinds -> CoreBndr -> CoreExprWithFVs -> Expr CoreBndr
fiRhs dflags :: DynFlags
dflags to_drop :: FloatInBinds
to_drop bndr :: CoreBndr
bndr rhs :: CoreExprWithFVs
rhs
| Just join_arity :: Int
join_arity <- CoreBndr -> Maybe Int
isJoinId_maybe CoreBndr
bndr
, let (bndrs :: [CoreBndr]
bndrs, body :: 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 (DynFlags -> FloatInBinds -> CoreExprWithFVs -> Expr CoreBndr
fiExpr DynFlags
dflags FloatInBinds
to_drop CoreExprWithFVs
body)
| Bool
otherwise
= DynFlags -> FloatInBinds -> CoreExprWithFVs -> Expr CoreBndr
fiExpr DynFlags
dflags FloatInBinds
to_drop CoreExprWithFVs
rhs
noFloatIntoLam :: [Var] -> Bool
noFloatIntoLam :: [CoreBndr] -> Bool
noFloatIntoLam bndrs :: [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 b :: 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 FVAnn -> Bool
noFloatIntoRhs is_rec :: RecFlag
is_rec bndr :: CoreBndr
bndr rhs :: AnnExpr' CoreBndr FVAnn
rhs
| CoreBndr -> Bool
isJoinId CoreBndr
bndr
= RecFlag -> Bool
isRec RecFlag
is_rec
| Bool
otherwise
= AnnExpr' CoreBndr FVAnn -> Type -> Bool
noFloatIntoArg AnnExpr' CoreBndr FVAnn
rhs (CoreBndr -> Type
idType CoreBndr
bndr)
noFloatIntoArg :: CoreExprWithFVs' -> Type -> Bool
noFloatIntoArg :: AnnExpr' CoreBndr FVAnn -> Type -> Bool
noFloatIntoArg expr :: AnnExpr' CoreBndr FVAnn
expr expr_ty :: Type
expr_ty
| HasDebugCallStack => Type -> Bool
Type -> Bool
isUnliftedType Type
expr_ty
= Bool
True
| AnnLam bndr :: CoreBndr
bndr e :: CoreExprWithFVs
e <- AnnExpr' CoreBndr FVAnn
expr
, (bndrs :: [CoreBndr]
bndrs, _) <- 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 FVAnn -> Expr CoreBndr
forall bndr annot. AnnExpr' bndr annot -> Expr bndr
deAnnotate' AnnExpr' CoreBndr FVAnn
expr
sepBindsByDropPoint
:: DynFlags
-> Bool
-> [FreeVarSet]
-> FloatInBinds
-> [FloatInBinds]
type DropBox = (FreeVarSet, FloatInBinds)
sepBindsByDropPoint :: DynFlags -> Bool -> [FVAnn] -> FloatInBinds -> [FloatInBinds]
sepBindsByDropPoint dflags :: DynFlags
dflags is_case :: Bool
is_case drop_pts :: [FVAnn]
drop_pts floaters :: FloatInBinds
floaters
| FloatInBinds -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null FloatInBinds
floaters
= [] FloatInBinds -> [FloatInBinds] -> [FloatInBinds]
forall a. a -> [a] -> [a]
: [[] | FVAnn
_ <- [FVAnn]
drop_pts]
| Bool
otherwise
= ASSERT( drop_pts `lengthAtLeast` 2 )
FloatInBinds -> [DropBox] -> [FloatInBinds]
go FloatInBinds
floaters ((FVAnn -> DropBox) -> [FVAnn] -> [DropBox]
forall a b. (a -> b) -> [a] -> [b]
map (\fvs :: FVAnn
fvs -> (FVAnn
fvs, [])) (FVAnn
emptyDVarSet FVAnn -> [FVAnn] -> [FVAnn]
forall a. a -> [a] -> [a]
: [FVAnn]
drop_pts))
where
n_alts :: Int
n_alts = [FVAnn] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [FVAnn]
drop_pts
go :: FloatInBinds -> [DropBox] -> [FloatInBinds]
go :: FloatInBinds -> [DropBox] -> [FloatInBinds]
go [] drop_boxes :: [DropBox]
drop_boxes = (DropBox -> FloatInBinds) -> [DropBox] -> [FloatInBinds]
forall a b. (a -> b) -> [a] -> [b]
map (FloatInBinds -> FloatInBinds
forall a. [a] -> [a]
reverse (FloatInBinds -> FloatInBinds)
-> (DropBox -> FloatInBinds) -> DropBox -> FloatInBinds
forall b c a. (b -> c) -> (a -> b) -> a -> c
. DropBox -> FloatInBinds
forall a b. (a, b) -> b
snd) [DropBox]
drop_boxes
go (bind_w_fvs :: FloatInBind
bind_w_fvs@(FB bndrs :: FVAnn
bndrs bind_fvs :: FVAnn
bind_fvs bind :: FloatBind
bind) : binds :: FloatInBinds
binds) drop_boxes :: [DropBox]
drop_boxes@(here_box :: DropBox
here_box : fork_boxes :: [DropBox]
fork_boxes)
= FloatInBinds -> [DropBox] -> [FloatInBinds]
go FloatInBinds
binds [DropBox]
new_boxes
where
(used_here :: Bool
used_here : used_in_flags :: [Bool]
used_in_flags) = [ FVAnn
fvs FVAnn -> FVAnn -> Bool
`intersectsDVarSet` FVAnn
bndrs
| (fvs :: FVAnn
fvs, _) <- [DropBox]
drop_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_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
> 1 Bool -> Bool -> Bool
&& Bool -> Bool
not (DynFlags -> FloatBind -> Bool
floatIsDupable DynFlags
dflags 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
> 1
new_boxes :: [DropBox]
new_boxes | Bool
drop_here = (DropBox -> DropBox
insert DropBox
here_box DropBox -> [DropBox] -> [DropBox]
forall a. a -> [a] -> [a]
: [DropBox]
fork_boxes)
| Bool
otherwise = (DropBox
here_box DropBox -> [DropBox] -> [DropBox]
forall a. a -> [a] -> [a]
: [DropBox]
new_fork_boxes)
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 "FloatIn.sepBinds" DropBox -> Bool -> DropBox
insert_maybe
[DropBox]
fork_boxes [Bool]
used_in_flags
insert :: DropBox -> DropBox
insert :: DropBox -> DropBox
insert (fvs :: FVAnn
fvs,drops :: FloatInBinds
drops) = (FVAnn
fvs FVAnn -> FVAnn -> FVAnn
`unionDVarSet` FVAnn
bind_fvs, FloatInBind
bind_w_fvsFloatInBind -> FloatInBinds -> FloatInBinds
forall a. a -> [a] -> [a]
:FloatInBinds
drops)
insert_maybe :: DropBox -> Bool -> DropBox
insert_maybe box :: DropBox
box True = DropBox -> DropBox
insert DropBox
box
insert_maybe box :: DropBox
box False = DropBox
box
go _ _ = String -> [FloatInBinds]
forall a. String -> a
panic "sepBindsByDropPoint/go"
floatedBindsFVs :: FloatInBinds -> FreeVarSet
floatedBindsFVs :: FloatInBinds -> FVAnn
floatedBindsFVs binds :: FloatInBinds
binds = (FloatInBind -> FVAnn) -> FloatInBinds -> FVAnn
forall a. (a -> FVAnn) -> [a] -> FVAnn
mapUnionDVarSet FloatInBind -> FVAnn
fbFVs FloatInBinds
binds
fbFVs :: FloatInBind -> DVarSet
fbFVs :: FloatInBind -> FVAnn
fbFVs (FB _ fvs :: FVAnn
fvs _) = FVAnn
fvs
wrapFloats :: FloatInBinds -> CoreExpr -> CoreExpr
wrapFloats :: FloatInBinds -> Expr CoreBndr -> Expr CoreBndr
wrapFloats [] e :: Expr CoreBndr
e = Expr CoreBndr
e
wrapFloats (FB _ _ fl :: FloatBind
fl : bs :: FloatInBinds
bs) e :: Expr CoreBndr
e = FloatInBinds -> Expr CoreBndr -> Expr CoreBndr
wrapFloats FloatInBinds
bs (FloatBind -> Expr CoreBndr -> Expr CoreBndr
wrapFloat FloatBind
fl Expr CoreBndr
e)
floatIsDupable :: DynFlags -> FloatBind -> Bool
floatIsDupable :: DynFlags -> FloatBind -> Bool
floatIsDupable dflags :: DynFlags
dflags (FloatCase scrut :: Expr CoreBndr
scrut _ _ _) = DynFlags -> Expr CoreBndr -> Bool
exprIsDupable DynFlags
dflags Expr CoreBndr
scrut
floatIsDupable dflags :: DynFlags
dflags (FloatLet (Rec prs :: [(CoreBndr, Expr CoreBndr)]
prs)) = ((CoreBndr, Expr CoreBndr) -> Bool)
-> [(CoreBndr, Expr CoreBndr)] -> Bool
forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
all (DynFlags -> Expr CoreBndr -> Bool
exprIsDupable DynFlags
dflags (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 dflags :: DynFlags
dflags (FloatLet (NonRec _ r :: Expr CoreBndr
r)) = DynFlags -> Expr CoreBndr -> Bool
exprIsDupable DynFlags
dflags Expr CoreBndr
r
floatIsCase :: FloatBind -> Bool
floatIsCase :: FloatBind -> Bool
floatIsCase (FloatCase {}) = Bool
True
floatIsCase (FloatLet {}) = Bool
False