module GHC.Core.Opt.Simplify.Env (
SimplMode(..), updMode,
smPedanticBottoms, smPlatform,
SimplEnv(..), pprSimplEnv,
seArityOpts, seCaseCase, seCaseFolding, seCaseMerge, seCastSwizzle,
seDoEtaReduction, seEtaExpand, seFloatEnable, seInline, seNames,
seOptCoercionOpts, sePedanticBottoms, sePhase, sePlatform, sePreInline,
seRuleOpts, seRules, seUnfoldingOpts,
mkSimplEnv, extendIdSubst,
extendTvSubst, extendCvSubst,
zapSubstEnv, setSubstEnv, bumpCaseDepth,
getInScope, setInScopeFromE, setInScopeFromF,
setInScopeSet, modifyInScope, addNewInScopeIds,
getSimplRules, enterRecGroupRHSs,
SimplSR(..), mkContEx, substId, lookupRecBndr,
simplNonRecBndr, simplNonRecJoinBndr, simplRecBndrs, simplRecJoinBndrs,
simplBinder, simplBinders,
substTy, substTyVar, getSubst,
substCo, substCoVar,
SimplFloats(..), emptyFloats, isEmptyFloats, mkRecFloats,
mkFloatBind, addLetFloats, addJoinFloats, addFloats,
extendFloats, wrapFloats,
isEmptyJoinFloats, isEmptyLetFloats,
doFloatFromRhs, getTopFloatBinds,
LetFloats, FloatEnable(..), letFloatBinds, emptyLetFloats, unitLetFloat,
addLetFlts, mapLetFloats,
JoinFloat, JoinFloats, emptyJoinFloats,
wrapJoinFloats, wrapJoinFloatsX, unitJoinFloat, addJoinFlts
) where
import GHC.Prelude
import GHC.Core.Coercion.Opt ( OptCoercionOpts )
import GHC.Core.FamInstEnv ( FamInstEnv )
import GHC.Core.Opt.Arity ( ArityOpts(..) )
import GHC.Core.Opt.Simplify.Monad
import GHC.Core.Rules.Config ( RuleOpts(..) )
import GHC.Core
import GHC.Core.Utils
import GHC.Core.Multiplicity ( scaleScaled )
import GHC.Core.Unfold
import GHC.Core.TyCo.Subst (emptyIdSubstEnv)
import GHC.Types.Var
import GHC.Types.Var.Env
import GHC.Types.Var.Set
import GHC.Data.OrdList
import GHC.Data.Graph.UnVar
import GHC.Types.Id as Id
import GHC.Core.Make ( mkWildValBinder, mkCoreLet )
import GHC.Builtin.Types
import qualified GHC.Core.Type as Type
import GHC.Core.Type hiding ( substTy, substTyVar, substTyVarBndr, substCo
, extendTvSubst, extendCvSubst )
import qualified GHC.Core.Coercion as Coercion
import GHC.Core.Coercion hiding ( substCo, substCoVar, substCoVarBndr )
import GHC.Platform ( Platform )
import GHC.Types.Basic
import GHC.Utils.Monad
import GHC.Utils.Outputable
import GHC.Utils.Panic
import GHC.Utils.Panic.Plain
import GHC.Utils.Misc
import GHC.Types.Unique.FM ( pprUniqFM )
import Data.List ( intersperse, mapAccumL )
data SimplEnv
= SimplEnv {
SimplEnv -> SimplMode
seMode :: !SimplMode
, SimplEnv -> (FamInstEnv, FamInstEnv)
seFamEnvs :: !(FamInstEnv, FamInstEnv)
, SimplEnv -> TvSubstEnv
seTvSubst :: TvSubstEnv
, SimplEnv -> CvSubstEnv
seCvSubst :: CvSubstEnv
, SimplEnv -> SimplIdSubst
seIdSubst :: SimplIdSubst
, SimplEnv -> UnVarSet
seRecIds :: !UnVarSet
, SimplEnv -> InScopeSet
seInScope :: !InScopeSet
, SimplEnv -> JoinArity
seCaseDepth :: !Int
}
seArityOpts :: SimplEnv -> ArityOpts
seArityOpts :: SimplEnv -> ArityOpts
seArityOpts SimplEnv
env = SimplMode -> ArityOpts
sm_arity_opts (SimplEnv -> SimplMode
seMode SimplEnv
env)
seCaseCase :: SimplEnv -> Bool
seCaseCase :: SimplEnv -> Bool
seCaseCase SimplEnv
env = SimplMode -> Bool
sm_case_case (SimplEnv -> SimplMode
seMode SimplEnv
env)
seCaseFolding :: SimplEnv -> Bool
seCaseFolding :: SimplEnv -> Bool
seCaseFolding SimplEnv
env = SimplMode -> Bool
sm_case_folding (SimplEnv -> SimplMode
seMode SimplEnv
env)
seCaseMerge :: SimplEnv -> Bool
seCaseMerge :: SimplEnv -> Bool
seCaseMerge SimplEnv
env = SimplMode -> Bool
sm_case_merge (SimplEnv -> SimplMode
seMode SimplEnv
env)
seCastSwizzle :: SimplEnv -> Bool
seCastSwizzle :: SimplEnv -> Bool
seCastSwizzle SimplEnv
env = SimplMode -> Bool
sm_cast_swizzle (SimplEnv -> SimplMode
seMode SimplEnv
env)
seDoEtaReduction :: SimplEnv -> Bool
seDoEtaReduction :: SimplEnv -> Bool
seDoEtaReduction SimplEnv
env = SimplMode -> Bool
sm_do_eta_reduction (SimplEnv -> SimplMode
seMode SimplEnv
env)
seEtaExpand :: SimplEnv -> Bool
seEtaExpand :: SimplEnv -> Bool
seEtaExpand SimplEnv
env = SimplMode -> Bool
sm_eta_expand (SimplEnv -> SimplMode
seMode SimplEnv
env)
seFloatEnable :: SimplEnv -> FloatEnable
seFloatEnable :: SimplEnv -> FloatEnable
seFloatEnable SimplEnv
env = SimplMode -> FloatEnable
sm_float_enable (SimplEnv -> SimplMode
seMode SimplEnv
env)
seInline :: SimplEnv -> Bool
seInline :: SimplEnv -> Bool
seInline SimplEnv
env = SimplMode -> Bool
sm_inline (SimplEnv -> SimplMode
seMode SimplEnv
env)
seNames :: SimplEnv -> [String]
seNames :: SimplEnv -> [String]
seNames SimplEnv
env = SimplMode -> [String]
sm_names (SimplEnv -> SimplMode
seMode SimplEnv
env)
seOptCoercionOpts :: SimplEnv -> OptCoercionOpts
seOptCoercionOpts :: SimplEnv -> OptCoercionOpts
seOptCoercionOpts SimplEnv
env = SimplMode -> OptCoercionOpts
sm_co_opt_opts (SimplEnv -> SimplMode
seMode SimplEnv
env)
sePedanticBottoms :: SimplEnv -> Bool
sePedanticBottoms :: SimplEnv -> Bool
sePedanticBottoms SimplEnv
env = SimplMode -> Bool
smPedanticBottoms (SimplEnv -> SimplMode
seMode SimplEnv
env)
sePhase :: SimplEnv -> CompilerPhase
sePhase :: SimplEnv -> CompilerPhase
sePhase SimplEnv
env = SimplMode -> CompilerPhase
sm_phase (SimplEnv -> SimplMode
seMode SimplEnv
env)
sePlatform :: SimplEnv -> Platform
sePlatform :: SimplEnv -> Platform
sePlatform SimplEnv
env = SimplMode -> Platform
smPlatform (SimplEnv -> SimplMode
seMode SimplEnv
env)
sePreInline :: SimplEnv -> Bool
sePreInline :: SimplEnv -> Bool
sePreInline SimplEnv
env = SimplMode -> Bool
sm_pre_inline (SimplEnv -> SimplMode
seMode SimplEnv
env)
seRuleOpts :: SimplEnv -> RuleOpts
seRuleOpts :: SimplEnv -> RuleOpts
seRuleOpts SimplEnv
env = SimplMode -> RuleOpts
sm_rule_opts (SimplEnv -> SimplMode
seMode SimplEnv
env)
seRules :: SimplEnv -> Bool
seRules :: SimplEnv -> Bool
seRules SimplEnv
env = SimplMode -> Bool
sm_rules (SimplEnv -> SimplMode
seMode SimplEnv
env)
seUnfoldingOpts :: SimplEnv -> UnfoldingOpts
seUnfoldingOpts :: SimplEnv -> UnfoldingOpts
seUnfoldingOpts SimplEnv
env = SimplMode -> UnfoldingOpts
sm_uf_opts (SimplEnv -> SimplMode
seMode SimplEnv
env)
data SimplMode = SimplMode
{ SimplMode -> CompilerPhase
sm_phase :: !CompilerPhase
, SimplMode -> [String]
sm_names :: ![String]
, SimplMode -> Bool
sm_rules :: !Bool
, SimplMode -> Bool
sm_inline :: !Bool
, SimplMode -> Bool
sm_eta_expand :: !Bool
, SimplMode -> Bool
sm_cast_swizzle :: !Bool
, SimplMode -> UnfoldingOpts
sm_uf_opts :: !UnfoldingOpts
, SimplMode -> Bool
sm_case_case :: !Bool
, SimplMode -> Bool
sm_pre_inline :: !Bool
, SimplMode -> FloatEnable
sm_float_enable :: !FloatEnable
, SimplMode -> Bool
sm_do_eta_reduction :: !Bool
, SimplMode -> ArityOpts
sm_arity_opts :: !ArityOpts
, SimplMode -> RuleOpts
sm_rule_opts :: !RuleOpts
, SimplMode -> Bool
sm_case_folding :: !Bool
, SimplMode -> Bool
sm_case_merge :: !Bool
, SimplMode -> OptCoercionOpts
sm_co_opt_opts :: !OptCoercionOpts
}
instance Outputable SimplMode where
ppr :: SimplMode -> SDoc
ppr (SimplMode { sm_phase :: SimplMode -> CompilerPhase
sm_phase = CompilerPhase
p , sm_names :: SimplMode -> [String]
sm_names = [String]
ss
, sm_rules :: SimplMode -> Bool
sm_rules = Bool
r, sm_inline :: SimplMode -> Bool
sm_inline = Bool
i
, sm_cast_swizzle :: SimplMode -> Bool
sm_cast_swizzle = Bool
cs
, sm_eta_expand :: SimplMode -> Bool
sm_eta_expand = Bool
eta, sm_case_case :: SimplMode -> Bool
sm_case_case = Bool
cc })
= forall doc. IsLine doc => String -> doc
text String
"SimplMode" forall doc. IsLine doc => doc -> doc -> doc
<+> forall doc. IsLine doc => doc -> doc
braces (
forall doc. IsLine doc => [doc] -> doc
sep [ forall doc. IsLine doc => String -> doc
text String
"Phase =" forall doc. IsLine doc => doc -> doc -> doc
<+> forall a. Outputable a => a -> SDoc
ppr CompilerPhase
p forall doc. IsLine doc => doc -> doc -> doc
<+>
forall doc. IsLine doc => doc -> doc
brackets (forall doc. IsLine doc => String -> doc
text (forall (t :: * -> *) a. Foldable t => t [a] -> [a]
concat forall a b. (a -> b) -> a -> b
$ forall a. a -> [a] -> [a]
intersperse String
"," [String]
ss)) forall doc. IsLine doc => doc -> doc -> doc
<> forall doc. IsLine doc => doc
comma
, forall {doc}. IsLine doc => Bool -> doc -> doc
pp_flag Bool
i (forall doc. IsLine doc => String -> doc
text String
"inline") forall doc. IsLine doc => doc -> doc -> doc
<> forall doc. IsLine doc => doc
comma
, forall {doc}. IsLine doc => Bool -> doc -> doc
pp_flag Bool
r (forall doc. IsLine doc => String -> doc
text String
"rules") forall doc. IsLine doc => doc -> doc -> doc
<> forall doc. IsLine doc => doc
comma
, forall {doc}. IsLine doc => Bool -> doc -> doc
pp_flag Bool
eta (forall doc. IsLine doc => String -> doc
text String
"eta-expand") forall doc. IsLine doc => doc -> doc -> doc
<> forall doc. IsLine doc => doc
comma
, forall {doc}. IsLine doc => Bool -> doc -> doc
pp_flag Bool
cs (forall doc. IsLine doc => String -> doc
text String
"cast-swizzle") forall doc. IsLine doc => doc -> doc -> doc
<> forall doc. IsLine doc => doc
comma
, forall {doc}. IsLine doc => Bool -> doc -> doc
pp_flag Bool
cc (forall doc. IsLine doc => String -> doc
text String
"case-of-case") ])
where
pp_flag :: Bool -> doc -> doc
pp_flag Bool
f doc
s = forall doc. IsOutput doc => Bool -> doc -> doc
ppUnless Bool
f (forall doc. IsLine doc => String -> doc
text String
"no") forall doc. IsLine doc => doc -> doc -> doc
<+> doc
s
smPedanticBottoms :: SimplMode -> Bool
smPedanticBottoms :: SimplMode -> Bool
smPedanticBottoms SimplMode
opts = ArityOpts -> Bool
ao_ped_bot (SimplMode -> ArityOpts
sm_arity_opts SimplMode
opts)
smPlatform :: SimplMode -> Platform
smPlatform :: SimplMode -> Platform
smPlatform SimplMode
opts = RuleOpts -> Platform
roPlatform (SimplMode -> RuleOpts
sm_rule_opts SimplMode
opts)
data FloatEnable
= FloatDisabled
| FloatNestedOnly
| FloatEnabled
data SimplFloats
= SimplFloats
{
SimplFloats -> LetFloats
sfLetFloats :: LetFloats
, SimplFloats -> JoinFloats
sfJoinFloats :: JoinFloats
, SimplFloats -> InScopeSet
sfInScope :: InScopeSet
}
instance Outputable SimplFloats where
ppr :: SimplFloats -> SDoc
ppr (SimplFloats { sfLetFloats :: SimplFloats -> LetFloats
sfLetFloats = LetFloats
lf, sfJoinFloats :: SimplFloats -> JoinFloats
sfJoinFloats = JoinFloats
jf, sfInScope :: SimplFloats -> InScopeSet
sfInScope = InScopeSet
is })
= forall doc. IsLine doc => String -> doc
text String
"SimplFloats"
forall doc. IsLine doc => doc -> doc -> doc
<+> forall doc. IsLine doc => doc -> doc
braces (forall doc. IsDoc doc => [doc] -> doc
vcat [ forall doc. IsLine doc => String -> doc
text String
"lets: " forall doc. IsLine doc => doc -> doc -> doc
<+> forall a. Outputable a => a -> SDoc
ppr LetFloats
lf
, forall doc. IsLine doc => String -> doc
text String
"joins:" forall doc. IsLine doc => doc -> doc -> doc
<+> forall a. Outputable a => a -> SDoc
ppr JoinFloats
jf
, forall doc. IsLine doc => String -> doc
text String
"in_scope:" forall doc. IsLine doc => doc -> doc -> doc
<+> forall a. Outputable a => a -> SDoc
ppr InScopeSet
is ])
emptyFloats :: SimplEnv -> SimplFloats
emptyFloats :: SimplEnv -> SimplFloats
emptyFloats SimplEnv
env
= SimplFloats { sfLetFloats :: LetFloats
sfLetFloats = LetFloats
emptyLetFloats
, sfJoinFloats :: JoinFloats
sfJoinFloats = JoinFloats
emptyJoinFloats
, sfInScope :: InScopeSet
sfInScope = SimplEnv -> InScopeSet
seInScope SimplEnv
env }
isEmptyFloats :: SimplFloats -> Bool
isEmptyFloats :: SimplFloats -> Bool
isEmptyFloats (SimplFloats { sfLetFloats :: SimplFloats -> LetFloats
sfLetFloats = LetFloats JoinFloats
fs FloatFlag
_
, sfJoinFloats :: SimplFloats -> JoinFloats
sfJoinFloats = JoinFloats
js })
= forall a. HasCallStack => Bool -> SDoc -> a -> a
assertPpr (forall a. OrdList a -> Bool
isNilOL JoinFloats
js) (forall a. Outputable a => a -> SDoc
ppr JoinFloats
js ) forall a b. (a -> b) -> a -> b
$
forall a. OrdList a -> Bool
isNilOL JoinFloats
fs
pprSimplEnv :: SimplEnv -> SDoc
pprSimplEnv :: SimplEnv -> SDoc
pprSimplEnv SimplEnv
env
= forall doc. IsDoc doc => [doc] -> doc
vcat [forall doc. IsLine doc => String -> doc
text String
"TvSubst:" forall doc. IsLine doc => doc -> doc -> doc
<+> forall a. Outputable a => a -> SDoc
ppr (SimplEnv -> TvSubstEnv
seTvSubst SimplEnv
env),
forall doc. IsLine doc => String -> doc
text String
"CvSubst:" forall doc. IsLine doc => doc -> doc -> doc
<+> forall a. Outputable a => a -> SDoc
ppr (SimplEnv -> CvSubstEnv
seCvSubst SimplEnv
env),
forall doc. IsLine doc => String -> doc
text String
"IdSubst:" forall doc. IsLine doc => doc -> doc -> doc
<+> SDoc
id_subst_doc,
forall doc. IsLine doc => String -> doc
text String
"InScope:" forall doc. IsLine doc => doc -> doc -> doc
<+> SDoc
in_scope_vars_doc
]
where
id_subst_doc :: SDoc
id_subst_doc = forall a key. (a -> SDoc) -> UniqFM key a -> SDoc
pprUniqFM forall a. Outputable a => a -> SDoc
ppr (SimplEnv -> SimplIdSubst
seIdSubst SimplEnv
env)
in_scope_vars_doc :: SDoc
in_scope_vars_doc = VarSet -> ([OutId] -> SDoc) -> SDoc
pprVarSet (InScopeSet -> VarSet
getInScopeVars (SimplEnv -> InScopeSet
seInScope SimplEnv
env))
(forall doc. IsDoc doc => [doc] -> doc
vcat forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a b. (a -> b) -> [a] -> [b]
map OutId -> SDoc
ppr_one)
ppr_one :: OutId -> SDoc
ppr_one OutId
v | OutId -> Bool
isId OutId
v = forall a. Outputable a => a -> SDoc
ppr OutId
v forall doc. IsLine doc => doc -> doc -> doc
<+> forall a. Outputable a => a -> SDoc
ppr (IdUnfoldingFun
idUnfolding OutId
v)
| Bool
otherwise = forall a. Outputable a => a -> SDoc
ppr OutId
v
type SimplIdSubst = IdEnv SimplSR
data SimplSR
= DoneEx OutExpr (Maybe JoinArity)
| DoneId OutId
| ContEx TvSubstEnv
CvSubstEnv
SimplIdSubst
InExpr
instance Outputable SimplSR where
ppr :: SimplSR -> SDoc
ppr (DoneId OutId
v) = forall doc. IsLine doc => String -> doc
text String
"DoneId" forall doc. IsLine doc => doc -> doc -> doc
<+> forall a. Outputable a => a -> SDoc
ppr OutId
v
ppr (DoneEx OutExpr
e Maybe JoinArity
mj) = forall doc. IsLine doc => String -> doc
text String
"DoneEx" forall doc. IsLine doc => doc -> doc -> doc
<> SDoc
pp_mj forall doc. IsLine doc => doc -> doc -> doc
<+> forall a. Outputable a => a -> SDoc
ppr OutExpr
e
where
pp_mj :: SDoc
pp_mj = case Maybe JoinArity
mj of
Maybe JoinArity
Nothing -> forall doc. IsOutput doc => doc
empty
Just JoinArity
n -> forall doc. IsLine doc => doc -> doc
parens (forall doc. IsLine doc => JoinArity -> doc
int JoinArity
n)
ppr (ContEx TvSubstEnv
_tv CvSubstEnv
_cv SimplIdSubst
_id OutExpr
e) = forall doc. IsDoc doc => [doc] -> doc
vcat [forall doc. IsLine doc => String -> doc
text String
"ContEx" forall doc. IsLine doc => doc -> doc -> doc
<+> forall a. Outputable a => a -> SDoc
ppr OutExpr
e ]
mkSimplEnv :: SimplMode -> (FamInstEnv, FamInstEnv) -> SimplEnv
mkSimplEnv :: SimplMode -> (FamInstEnv, FamInstEnv) -> SimplEnv
mkSimplEnv SimplMode
mode (FamInstEnv, FamInstEnv)
fam_envs
= SimplEnv { seMode :: SimplMode
seMode = SimplMode
mode
, seFamEnvs :: (FamInstEnv, FamInstEnv)
seFamEnvs = (FamInstEnv, FamInstEnv)
fam_envs
, seInScope :: InScopeSet
seInScope = InScopeSet
init_in_scope
, seTvSubst :: TvSubstEnv
seTvSubst = forall a. VarEnv a
emptyVarEnv
, seCvSubst :: CvSubstEnv
seCvSubst = forall a. VarEnv a
emptyVarEnv
, seIdSubst :: SimplIdSubst
seIdSubst = forall a. VarEnv a
emptyVarEnv
, seRecIds :: UnVarSet
seRecIds = UnVarSet
emptyUnVarSet
, seCaseDepth :: JoinArity
seCaseDepth = JoinArity
0 }
init_in_scope :: InScopeSet
init_in_scope :: InScopeSet
init_in_scope = VarSet -> InScopeSet
mkInScopeSet (OutId -> VarSet
unitVarSet (Kind -> Kind -> OutId
mkWildValBinder Kind
ManyTy Kind
unitTy))
updMode :: (SimplMode -> SimplMode) -> SimplEnv -> SimplEnv
updMode :: (SimplMode -> SimplMode) -> SimplEnv -> SimplEnv
updMode SimplMode -> SimplMode
upd SimplEnv
env
=
let mode :: SimplMode
mode = SimplMode -> SimplMode
upd forall a b. (a -> b) -> a -> b
$! (SimplEnv -> SimplMode
seMode SimplEnv
env)
in SimplEnv
env { seMode :: SimplMode
seMode = SimplMode
mode }
bumpCaseDepth :: SimplEnv -> SimplEnv
bumpCaseDepth :: SimplEnv -> SimplEnv
bumpCaseDepth SimplEnv
env = SimplEnv
env { seCaseDepth :: JoinArity
seCaseDepth = SimplEnv -> JoinArity
seCaseDepth SimplEnv
env forall a. Num a => a -> a -> a
+ JoinArity
1 }
extendIdSubst :: SimplEnv -> Id -> SimplSR -> SimplEnv
extendIdSubst :: SimplEnv -> OutId -> SimplSR -> SimplEnv
extendIdSubst env :: SimplEnv
env@(SimplEnv {seIdSubst :: SimplEnv -> SimplIdSubst
seIdSubst = SimplIdSubst
subst}) OutId
var SimplSR
res
= forall a. HasCallStack => Bool -> SDoc -> a -> a
assertPpr (OutId -> Bool
isId OutId
var Bool -> Bool -> Bool
&& Bool -> Bool
not (OutId -> Bool
isCoVar OutId
var)) (forall a. Outputable a => a -> SDoc
ppr OutId
var) forall a b. (a -> b) -> a -> b
$
SimplEnv
env { seIdSubst :: SimplIdSubst
seIdSubst = forall a. VarEnv a -> OutId -> a -> VarEnv a
extendVarEnv SimplIdSubst
subst OutId
var SimplSR
res }
extendTvSubst :: SimplEnv -> TyVar -> Type -> SimplEnv
extendTvSubst :: SimplEnv -> OutId -> Kind -> SimplEnv
extendTvSubst env :: SimplEnv
env@(SimplEnv {seTvSubst :: SimplEnv -> TvSubstEnv
seTvSubst = TvSubstEnv
tsubst}) OutId
var Kind
res
= forall a. HasCallStack => Bool -> SDoc -> a -> a
assertPpr (OutId -> Bool
isTyVar OutId
var) (forall a. Outputable a => a -> SDoc
ppr OutId
var forall doc. IsDoc doc => doc -> doc -> doc
$$ forall a. Outputable a => a -> SDoc
ppr Kind
res) forall a b. (a -> b) -> a -> b
$
SimplEnv
env {seTvSubst :: TvSubstEnv
seTvSubst = forall a. VarEnv a -> OutId -> a -> VarEnv a
extendVarEnv TvSubstEnv
tsubst OutId
var Kind
res}
extendCvSubst :: SimplEnv -> CoVar -> Coercion -> SimplEnv
extendCvSubst :: SimplEnv -> OutId -> Coercion -> SimplEnv
extendCvSubst env :: SimplEnv
env@(SimplEnv {seCvSubst :: SimplEnv -> CvSubstEnv
seCvSubst = CvSubstEnv
csubst}) OutId
var Coercion
co
= forall a. HasCallStack => Bool -> a -> a
assert (OutId -> Bool
isCoVar OutId
var) forall a b. (a -> b) -> a -> b
$
SimplEnv
env {seCvSubst :: CvSubstEnv
seCvSubst = forall a. VarEnv a -> OutId -> a -> VarEnv a
extendVarEnv CvSubstEnv
csubst OutId
var Coercion
co}
getInScope :: SimplEnv -> InScopeSet
getInScope :: SimplEnv -> InScopeSet
getInScope SimplEnv
env = SimplEnv -> InScopeSet
seInScope SimplEnv
env
setInScopeSet :: SimplEnv -> InScopeSet -> SimplEnv
setInScopeSet :: SimplEnv -> InScopeSet -> SimplEnv
setInScopeSet SimplEnv
env InScopeSet
in_scope = SimplEnv
env {seInScope :: InScopeSet
seInScope = InScopeSet
in_scope}
setInScopeFromE :: SimplEnv -> SimplEnv -> SimplEnv
setInScopeFromE :: SimplEnv -> SimplEnv -> SimplEnv
setInScopeFromE SimplEnv
rhs_env SimplEnv
here_env = SimplEnv
rhs_env { seInScope :: InScopeSet
seInScope = SimplEnv -> InScopeSet
seInScope SimplEnv
here_env }
setInScopeFromF :: SimplEnv -> SimplFloats -> SimplEnv
setInScopeFromF :: SimplEnv -> SimplFloats -> SimplEnv
setInScopeFromF SimplEnv
env SimplFloats
floats = SimplEnv
env { seInScope :: InScopeSet
seInScope = SimplFloats -> InScopeSet
sfInScope SimplFloats
floats }
addNewInScopeIds :: SimplEnv -> [CoreBndr] -> SimplEnv
addNewInScopeIds :: SimplEnv -> [OutId] -> SimplEnv
addNewInScopeIds env :: SimplEnv
env@(SimplEnv { seInScope :: SimplEnv -> InScopeSet
seInScope = InScopeSet
in_scope, seIdSubst :: SimplEnv -> SimplIdSubst
seIdSubst = SimplIdSubst
id_subst }) [OutId]
vs
= let !in_scope1 :: InScopeSet
in_scope1 = InScopeSet
in_scope InScopeSet -> [OutId] -> InScopeSet
`extendInScopeSetList` [OutId]
vs
!id_subst1 :: SimplIdSubst
id_subst1 = SimplIdSubst
id_subst forall a. VarEnv a -> [OutId] -> VarEnv a
`delVarEnvList` [OutId]
vs
in
SimplEnv
env { seInScope :: InScopeSet
seInScope = InScopeSet
in_scope1,
seIdSubst :: SimplIdSubst
seIdSubst = SimplIdSubst
id_subst1 }
modifyInScope :: SimplEnv -> CoreBndr -> SimplEnv
modifyInScope :: SimplEnv -> OutId -> SimplEnv
modifyInScope env :: SimplEnv
env@(SimplEnv {seInScope :: SimplEnv -> InScopeSet
seInScope = InScopeSet
in_scope}) OutId
v
= SimplEnv
env {seInScope :: InScopeSet
seInScope = InScopeSet -> OutId -> InScopeSet
extendInScopeSet InScopeSet
in_scope OutId
v}
enterRecGroupRHSs :: SimplEnv -> [OutBndr] -> (SimplEnv -> SimplM (r, SimplEnv))
-> SimplM (r, SimplEnv)
enterRecGroupRHSs :: forall r.
SimplEnv
-> [OutId]
-> (SimplEnv -> SimplM (r, SimplEnv))
-> SimplM (r, SimplEnv)
enterRecGroupRHSs SimplEnv
env [OutId]
bndrs SimplEnv -> SimplM (r, SimplEnv)
k = do
(r
r, SimplEnv
env'') <- SimplEnv -> SimplM (r, SimplEnv)
k SimplEnv
env{seRecIds :: UnVarSet
seRecIds = [OutId] -> UnVarSet -> UnVarSet
extendUnVarSetList [OutId]
bndrs (SimplEnv -> UnVarSet
seRecIds SimplEnv
env)}
forall (m :: * -> *) a. Monad m => a -> m a
return (r
r, SimplEnv
env''{seRecIds :: UnVarSet
seRecIds = SimplEnv -> UnVarSet
seRecIds SimplEnv
env})
zapSubstEnv :: SimplEnv -> SimplEnv
zapSubstEnv :: SimplEnv -> SimplEnv
zapSubstEnv SimplEnv
env = SimplEnv
env {seTvSubst :: TvSubstEnv
seTvSubst = forall a. VarEnv a
emptyVarEnv, seCvSubst :: CvSubstEnv
seCvSubst = forall a. VarEnv a
emptyVarEnv, seIdSubst :: SimplIdSubst
seIdSubst = forall a. VarEnv a
emptyVarEnv}
setSubstEnv :: SimplEnv -> TvSubstEnv -> CvSubstEnv -> SimplIdSubst -> SimplEnv
setSubstEnv :: SimplEnv -> TvSubstEnv -> CvSubstEnv -> SimplIdSubst -> SimplEnv
setSubstEnv SimplEnv
env TvSubstEnv
tvs CvSubstEnv
cvs SimplIdSubst
ids = SimplEnv
env { seTvSubst :: TvSubstEnv
seTvSubst = TvSubstEnv
tvs, seCvSubst :: CvSubstEnv
seCvSubst = CvSubstEnv
cvs, seIdSubst :: SimplIdSubst
seIdSubst = SimplIdSubst
ids }
mkContEx :: SimplEnv -> InExpr -> SimplSR
mkContEx :: SimplEnv -> OutExpr -> SimplSR
mkContEx (SimplEnv { seTvSubst :: SimplEnv -> TvSubstEnv
seTvSubst = TvSubstEnv
tvs, seCvSubst :: SimplEnv -> CvSubstEnv
seCvSubst = CvSubstEnv
cvs, seIdSubst :: SimplEnv -> SimplIdSubst
seIdSubst = SimplIdSubst
ids }) OutExpr
e = TvSubstEnv -> CvSubstEnv -> SimplIdSubst -> OutExpr -> SimplSR
ContEx TvSubstEnv
tvs CvSubstEnv
cvs SimplIdSubst
ids OutExpr
e
data LetFloats = LetFloats (OrdList OutBind) FloatFlag
type JoinFloat = OutBind
type JoinFloats = OrdList JoinFloat
data FloatFlag
= FltLifted
| FltOkSpec
| FltCareful
instance Outputable LetFloats where
ppr :: LetFloats -> SDoc
ppr (LetFloats JoinFloats
binds FloatFlag
ff) = forall a. Outputable a => a -> SDoc
ppr FloatFlag
ff forall doc. IsDoc doc => doc -> doc -> doc
$$ forall a. Outputable a => a -> SDoc
ppr (forall a. OrdList a -> [a]
fromOL JoinFloats
binds)
instance Outputable FloatFlag where
ppr :: FloatFlag -> SDoc
ppr FloatFlag
FltLifted = forall doc. IsLine doc => String -> doc
text String
"FltLifted"
ppr FloatFlag
FltOkSpec = forall doc. IsLine doc => String -> doc
text String
"FltOkSpec"
ppr FloatFlag
FltCareful = forall doc. IsLine doc => String -> doc
text String
"FltCareful"
andFF :: FloatFlag -> FloatFlag -> FloatFlag
andFF :: FloatFlag -> FloatFlag -> FloatFlag
andFF FloatFlag
FltCareful FloatFlag
_ = FloatFlag
FltCareful
andFF FloatFlag
FltOkSpec FloatFlag
FltCareful = FloatFlag
FltCareful
andFF FloatFlag
FltOkSpec FloatFlag
_ = FloatFlag
FltOkSpec
andFF FloatFlag
FltLifted FloatFlag
flt = FloatFlag
flt
doFloatFromRhs :: FloatEnable -> TopLevelFlag -> RecFlag -> Bool -> SimplFloats -> OutExpr -> Bool
doFloatFromRhs :: FloatEnable
-> TopLevelFlag
-> RecFlag
-> Bool
-> SimplFloats
-> OutExpr
-> Bool
doFloatFromRhs FloatEnable
fe TopLevelFlag
lvl RecFlag
rec Bool
strict_bind (SimplFloats { sfLetFloats :: SimplFloats -> LetFloats
sfLetFloats = LetFloats JoinFloats
fs FloatFlag
ff }) OutExpr
rhs
= TopLevelFlag -> FloatEnable -> Bool
floatEnabled TopLevelFlag
lvl FloatEnable
fe
Bool -> Bool -> Bool
&& Bool -> Bool
not (forall a. OrdList a -> Bool
isNilOL JoinFloats
fs)
Bool -> Bool -> Bool
&& Bool
want_to_float
Bool -> Bool -> Bool
&& Bool
can_float
where
want_to_float :: Bool
want_to_float = TopLevelFlag -> Bool
isTopLevel TopLevelFlag
lvl Bool -> Bool -> Bool
|| OutExpr -> Bool
exprIsCheap OutExpr
rhs Bool -> Bool -> Bool
|| OutExpr -> Bool
exprIsExpandable OutExpr
rhs
can_float :: Bool
can_float = case FloatFlag
ff of
FloatFlag
FltLifted -> Bool
True
FloatFlag
FltOkSpec -> TopLevelFlag -> Bool
isNotTopLevel TopLevelFlag
lvl Bool -> Bool -> Bool
&& RecFlag -> Bool
isNonRec RecFlag
rec
FloatFlag
FltCareful -> TopLevelFlag -> Bool
isNotTopLevel TopLevelFlag
lvl Bool -> Bool -> Bool
&& RecFlag -> Bool
isNonRec RecFlag
rec Bool -> Bool -> Bool
&& Bool
strict_bind
floatEnabled :: TopLevelFlag -> FloatEnable -> Bool
floatEnabled :: TopLevelFlag -> FloatEnable -> Bool
floatEnabled TopLevelFlag
_ FloatEnable
FloatDisabled = Bool
False
floatEnabled TopLevelFlag
lvl FloatEnable
FloatNestedOnly = Bool -> Bool
not (TopLevelFlag -> Bool
isTopLevel TopLevelFlag
lvl)
floatEnabled TopLevelFlag
_ FloatEnable
FloatEnabled = Bool
True
emptyLetFloats :: LetFloats
emptyLetFloats :: LetFloats
emptyLetFloats = JoinFloats -> FloatFlag -> LetFloats
LetFloats forall a. OrdList a
nilOL FloatFlag
FltLifted
isEmptyLetFloats :: LetFloats -> Bool
isEmptyLetFloats :: LetFloats -> Bool
isEmptyLetFloats (LetFloats JoinFloats
fs FloatFlag
_) = forall a. OrdList a -> Bool
isNilOL JoinFloats
fs
emptyJoinFloats :: JoinFloats
emptyJoinFloats :: JoinFloats
emptyJoinFloats = forall a. OrdList a
nilOL
isEmptyJoinFloats :: JoinFloats -> Bool
isEmptyJoinFloats :: JoinFloats -> Bool
isEmptyJoinFloats = forall a. OrdList a -> Bool
isNilOL
unitLetFloat :: OutBind -> LetFloats
unitLetFloat :: Bind OutId -> LetFloats
unitLetFloat Bind OutId
bind = forall a. HasCallStack => Bool -> a -> a
assert (forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
all (Bool -> Bool
not forall b c a. (b -> c) -> (a -> b) -> a -> c
. OutId -> Bool
isJoinId) (forall b. Bind b -> [b]
bindersOf Bind OutId
bind)) forall a b. (a -> b) -> a -> b
$
JoinFloats -> FloatFlag -> LetFloats
LetFloats (forall a. a -> OrdList a
unitOL Bind OutId
bind) (Bind OutId -> FloatFlag
flag Bind OutId
bind)
where
flag :: Bind OutId -> FloatFlag
flag (Rec {}) = FloatFlag
FltLifted
flag (NonRec OutId
bndr OutExpr
rhs)
| Bool -> Bool
not (OutId -> Bool
isStrictId OutId
bndr) = FloatFlag
FltLifted
| OutExpr -> Bool
exprIsTickedString OutExpr
rhs = FloatFlag
FltLifted
| OutExpr -> Bool
exprOkForSpeculation OutExpr
rhs = FloatFlag
FltOkSpec
| Bool
otherwise = FloatFlag
FltCareful
unitJoinFloat :: OutBind -> JoinFloats
unitJoinFloat :: Bind OutId -> JoinFloats
unitJoinFloat Bind OutId
bind = forall a. HasCallStack => Bool -> a -> a
assert (forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
all OutId -> Bool
isJoinId (forall b. Bind b -> [b]
bindersOf Bind OutId
bind)) forall a b. (a -> b) -> a -> b
$
forall a. a -> OrdList a
unitOL Bind OutId
bind
mkFloatBind :: SimplEnv -> OutBind -> (SimplFloats, SimplEnv)
mkFloatBind :: SimplEnv -> Bind OutId -> (SimplFloats, SimplEnv)
mkFloatBind SimplEnv
env Bind OutId
bind
= (SimplFloats
floats, SimplEnv
env { seInScope :: InScopeSet
seInScope = InScopeSet
in_scope' })
where
floats :: SimplFloats
floats
| Bind OutId -> Bool
isJoinBind Bind OutId
bind
= SimplFloats { sfLetFloats :: LetFloats
sfLetFloats = LetFloats
emptyLetFloats
, sfJoinFloats :: JoinFloats
sfJoinFloats = Bind OutId -> JoinFloats
unitJoinFloat Bind OutId
bind
, sfInScope :: InScopeSet
sfInScope = InScopeSet
in_scope' }
| Bool
otherwise
= SimplFloats { sfLetFloats :: LetFloats
sfLetFloats = Bind OutId -> LetFloats
unitLetFloat Bind OutId
bind
, sfJoinFloats :: JoinFloats
sfJoinFloats = JoinFloats
emptyJoinFloats
, sfInScope :: InScopeSet
sfInScope = InScopeSet
in_scope' }
!in_scope' :: InScopeSet
in_scope' = SimplEnv -> InScopeSet
seInScope SimplEnv
env InScopeSet -> Bind OutId -> InScopeSet
`extendInScopeSetBind` Bind OutId
bind
extendFloats :: SimplFloats -> OutBind -> SimplFloats
extendFloats :: SimplFloats -> Bind OutId -> SimplFloats
extendFloats (SimplFloats { sfLetFloats :: SimplFloats -> LetFloats
sfLetFloats = LetFloats
floats
, sfJoinFloats :: SimplFloats -> JoinFloats
sfJoinFloats = JoinFloats
jfloats
, sfInScope :: SimplFloats -> InScopeSet
sfInScope = InScopeSet
in_scope })
Bind OutId
bind
| Bind OutId -> Bool
isJoinBind Bind OutId
bind
= SimplFloats { sfInScope :: InScopeSet
sfInScope = InScopeSet
in_scope'
, sfLetFloats :: LetFloats
sfLetFloats = LetFloats
floats
, sfJoinFloats :: JoinFloats
sfJoinFloats = JoinFloats
jfloats' }
| Bool
otherwise
= SimplFloats { sfInScope :: InScopeSet
sfInScope = InScopeSet
in_scope'
, sfLetFloats :: LetFloats
sfLetFloats = LetFloats
floats'
, sfJoinFloats :: JoinFloats
sfJoinFloats = JoinFloats
jfloats }
where
in_scope' :: InScopeSet
in_scope' = InScopeSet
in_scope InScopeSet -> Bind OutId -> InScopeSet
`extendInScopeSetBind` Bind OutId
bind
floats' :: LetFloats
floats' = LetFloats
floats LetFloats -> LetFloats -> LetFloats
`addLetFlts` Bind OutId -> LetFloats
unitLetFloat Bind OutId
bind
jfloats' :: JoinFloats
jfloats' = JoinFloats
jfloats JoinFloats -> JoinFloats -> JoinFloats
`addJoinFlts` Bind OutId -> JoinFloats
unitJoinFloat Bind OutId
bind
addLetFloats :: SimplFloats -> LetFloats -> SimplFloats
addLetFloats :: SimplFloats -> LetFloats -> SimplFloats
addLetFloats SimplFloats
floats LetFloats
let_floats
= SimplFloats
floats { sfLetFloats :: LetFloats
sfLetFloats = SimplFloats -> LetFloats
sfLetFloats SimplFloats
floats LetFloats -> LetFloats -> LetFloats
`addLetFlts` LetFloats
let_floats
, sfInScope :: InScopeSet
sfInScope = SimplFloats -> InScopeSet
sfInScope SimplFloats
floats InScopeSet -> LetFloats -> InScopeSet
`extendInScopeFromLF` LetFloats
let_floats }
extendInScopeFromLF :: InScopeSet -> LetFloats -> InScopeSet
extendInScopeFromLF :: InScopeSet -> LetFloats -> InScopeSet
extendInScopeFromLF InScopeSet
in_scope (LetFloats JoinFloats
binds FloatFlag
_)
= forall b a. (b -> a -> b) -> b -> OrdList a -> b
foldlOL InScopeSet -> Bind OutId -> InScopeSet
extendInScopeSetBind InScopeSet
in_scope JoinFloats
binds
addJoinFloats :: SimplFloats -> JoinFloats -> SimplFloats
addJoinFloats :: SimplFloats -> JoinFloats -> SimplFloats
addJoinFloats SimplFloats
floats JoinFloats
join_floats
= SimplFloats
floats { sfJoinFloats :: JoinFloats
sfJoinFloats = SimplFloats -> JoinFloats
sfJoinFloats SimplFloats
floats JoinFloats -> JoinFloats -> JoinFloats
`addJoinFlts` JoinFloats
join_floats
, sfInScope :: InScopeSet
sfInScope = forall b a. (b -> a -> b) -> b -> OrdList a -> b
foldlOL InScopeSet -> Bind OutId -> InScopeSet
extendInScopeSetBind
(SimplFloats -> InScopeSet
sfInScope SimplFloats
floats) JoinFloats
join_floats }
addFloats :: SimplFloats -> SimplFloats -> SimplFloats
addFloats :: SimplFloats -> SimplFloats -> SimplFloats
addFloats (SimplFloats { sfLetFloats :: SimplFloats -> LetFloats
sfLetFloats = LetFloats
lf1, sfJoinFloats :: SimplFloats -> JoinFloats
sfJoinFloats = JoinFloats
jf1 })
(SimplFloats { sfLetFloats :: SimplFloats -> LetFloats
sfLetFloats = LetFloats
lf2, sfJoinFloats :: SimplFloats -> JoinFloats
sfJoinFloats = JoinFloats
jf2, sfInScope :: SimplFloats -> InScopeSet
sfInScope = InScopeSet
in_scope })
= SimplFloats { sfLetFloats :: LetFloats
sfLetFloats = LetFloats
lf1 LetFloats -> LetFloats -> LetFloats
`addLetFlts` LetFloats
lf2
, sfJoinFloats :: JoinFloats
sfJoinFloats = JoinFloats
jf1 JoinFloats -> JoinFloats -> JoinFloats
`addJoinFlts` JoinFloats
jf2
, sfInScope :: InScopeSet
sfInScope = InScopeSet
in_scope }
addLetFlts :: LetFloats -> LetFloats -> LetFloats
addLetFlts :: LetFloats -> LetFloats -> LetFloats
addLetFlts (LetFloats JoinFloats
bs1 FloatFlag
l1) (LetFloats JoinFloats
bs2 FloatFlag
l2)
= JoinFloats -> FloatFlag -> LetFloats
LetFloats (JoinFloats
bs1 forall a. OrdList a -> OrdList a -> OrdList a
`appOL` JoinFloats
bs2) (FloatFlag
l1 FloatFlag -> FloatFlag -> FloatFlag
`andFF` FloatFlag
l2)
letFloatBinds :: LetFloats -> [CoreBind]
letFloatBinds :: LetFloats -> [Bind OutId]
letFloatBinds (LetFloats JoinFloats
bs FloatFlag
_) = forall a. OrdList a -> [a]
fromOL JoinFloats
bs
addJoinFlts :: JoinFloats -> JoinFloats -> JoinFloats
addJoinFlts :: JoinFloats -> JoinFloats -> JoinFloats
addJoinFlts = forall a. OrdList a -> OrdList a -> OrdList a
appOL
mkRecFloats :: SimplFloats -> SimplFloats
mkRecFloats :: SimplFloats -> SimplFloats
mkRecFloats floats :: SimplFloats
floats@(SimplFloats { sfLetFloats :: SimplFloats -> LetFloats
sfLetFloats = LetFloats JoinFloats
bs FloatFlag
_ff
, sfJoinFloats :: SimplFloats -> JoinFloats
sfJoinFloats = JoinFloats
jbs
, sfInScope :: SimplFloats -> InScopeSet
sfInScope = InScopeSet
in_scope })
= forall a. HasCallStack => Bool -> SDoc -> a -> a
assertPpr (forall a. OrdList a -> Bool
isNilOL JoinFloats
bs Bool -> Bool -> Bool
|| forall a. OrdList a -> Bool
isNilOL JoinFloats
jbs) (forall a. Outputable a => a -> SDoc
ppr SimplFloats
floats) forall a b. (a -> b) -> a -> b
$
SimplFloats { sfLetFloats :: LetFloats
sfLetFloats = LetFloats
floats'
, sfJoinFloats :: JoinFloats
sfJoinFloats = JoinFloats
jfloats'
, sfInScope :: InScopeSet
sfInScope = InScopeSet
in_scope }
where
!floats' :: LetFloats
floats' | forall a. OrdList a -> Bool
isNilOL JoinFloats
bs = LetFloats
emptyLetFloats
| Bool
otherwise = Bind OutId -> LetFloats
unitLetFloat (forall b. [(b, Expr b)] -> Bind b
Rec (forall b. [Bind b] -> [(b, Expr b)]
flattenBinds (forall a. OrdList a -> [a]
fromOL JoinFloats
bs)))
!jfloats' :: JoinFloats
jfloats' | forall a. OrdList a -> Bool
isNilOL JoinFloats
jbs = JoinFloats
emptyJoinFloats
| Bool
otherwise = Bind OutId -> JoinFloats
unitJoinFloat (forall b. [(b, Expr b)] -> Bind b
Rec (forall b. [Bind b] -> [(b, Expr b)]
flattenBinds (forall a. OrdList a -> [a]
fromOL JoinFloats
jbs)))
wrapFloats :: SimplFloats -> OutExpr -> OutExpr
wrapFloats :: SimplFloats -> OutExpr -> OutExpr
wrapFloats (SimplFloats { sfLetFloats :: SimplFloats -> LetFloats
sfLetFloats = LetFloats JoinFloats
bs FloatFlag
flag
, sfJoinFloats :: SimplFloats -> JoinFloats
sfJoinFloats = JoinFloats
jbs }) OutExpr
body
= forall a b. (a -> b -> b) -> b -> OrdList a -> b
foldrOL Bind OutId -> OutExpr -> OutExpr
mk_let (JoinFloats -> OutExpr -> OutExpr
wrapJoinFloats JoinFloats
jbs OutExpr
body) JoinFloats
bs
where
mk_let :: Bind OutId -> OutExpr -> OutExpr
mk_let | FloatFlag
FltCareful <- FloatFlag
flag = Bind OutId -> OutExpr -> OutExpr
mkCoreLet
| Bool
otherwise = forall b. Bind b -> Expr b -> Expr b
Let
wrapJoinFloatsX :: SimplFloats -> OutExpr -> (SimplFloats, OutExpr)
wrapJoinFloatsX :: SimplFloats -> OutExpr -> (SimplFloats, OutExpr)
wrapJoinFloatsX SimplFloats
floats OutExpr
body
= ( SimplFloats
floats { sfJoinFloats :: JoinFloats
sfJoinFloats = JoinFloats
emptyJoinFloats }
, JoinFloats -> OutExpr -> OutExpr
wrapJoinFloats (SimplFloats -> JoinFloats
sfJoinFloats SimplFloats
floats) OutExpr
body )
wrapJoinFloats :: JoinFloats -> OutExpr -> OutExpr
wrapJoinFloats :: JoinFloats -> OutExpr -> OutExpr
wrapJoinFloats JoinFloats
join_floats OutExpr
body
= forall a b. (a -> b -> b) -> b -> OrdList a -> b
foldrOL forall b. Bind b -> Expr b -> Expr b
Let OutExpr
body JoinFloats
join_floats
getTopFloatBinds :: SimplFloats -> [CoreBind]
getTopFloatBinds :: SimplFloats -> [Bind OutId]
getTopFloatBinds (SimplFloats { sfLetFloats :: SimplFloats -> LetFloats
sfLetFloats = LetFloats
lbs
, sfJoinFloats :: SimplFloats -> JoinFloats
sfJoinFloats = JoinFloats
jbs})
= forall a. HasCallStack => Bool -> a -> a
assert (forall a. OrdList a -> Bool
isNilOL JoinFloats
jbs) forall a b. (a -> b) -> a -> b
$
LetFloats -> [Bind OutId]
letFloatBinds LetFloats
lbs
{-# INLINE mapLetFloats #-}
mapLetFloats :: LetFloats -> ((Id,CoreExpr) -> (Id,CoreExpr)) -> LetFloats
mapLetFloats :: LetFloats -> ((OutId, OutExpr) -> (OutId, OutExpr)) -> LetFloats
mapLetFloats (LetFloats JoinFloats
fs FloatFlag
ff) (OutId, OutExpr) -> (OutId, OutExpr)
fun
= JoinFloats -> FloatFlag -> LetFloats
LetFloats JoinFloats
fs1 FloatFlag
ff
where
app :: Bind OutId -> Bind OutId
app (NonRec OutId
b OutExpr
e) = case (OutId, OutExpr) -> (OutId, OutExpr)
fun (OutId
b,OutExpr
e) of (OutId
b',OutExpr
e') -> forall b. b -> Expr b -> Bind b
NonRec OutId
b' OutExpr
e'
app (Rec [(OutId, OutExpr)]
bs) = forall b. [(b, Expr b)] -> Bind b
Rec (forall a b. (a -> b) -> [a] -> [b]
strictMap (OutId, OutExpr) -> (OutId, OutExpr)
fun [(OutId, OutExpr)]
bs)
!fs1 :: JoinFloats
fs1 = (forall a b. (a -> b) -> OrdList a -> OrdList b
mapOL' Bind OutId -> Bind OutId
app JoinFloats
fs)
substId :: SimplEnv -> InId -> SimplSR
substId :: SimplEnv -> OutId -> SimplSR
substId (SimplEnv { seInScope :: SimplEnv -> InScopeSet
seInScope = InScopeSet
in_scope, seIdSubst :: SimplEnv -> SimplIdSubst
seIdSubst = SimplIdSubst
ids }) OutId
v
= case forall a. VarEnv a -> OutId -> Maybe a
lookupVarEnv SimplIdSubst
ids OutId
v of
Maybe SimplSR
Nothing -> OutId -> SimplSR
DoneId (InScopeSet -> OutId -> OutId
refineFromInScope InScopeSet
in_scope OutId
v)
Just (DoneId OutId
v) -> OutId -> SimplSR
DoneId (InScopeSet -> OutId -> OutId
refineFromInScope InScopeSet
in_scope OutId
v)
Just SimplSR
res -> SimplSR
res
refineFromInScope :: InScopeSet -> Var -> Var
refineFromInScope :: InScopeSet -> OutId -> OutId
refineFromInScope InScopeSet
in_scope OutId
v
| OutId -> Bool
isLocalId OutId
v = case InScopeSet -> OutId -> Maybe OutId
lookupInScope InScopeSet
in_scope OutId
v of
Just OutId
v' -> OutId
v'
Maybe OutId
Nothing -> forall a. HasCallStack => String -> SDoc -> a
pprPanic String
"refineFromInScope" (forall a. Outputable a => a -> SDoc
ppr InScopeSet
in_scope forall doc. IsDoc doc => doc -> doc -> doc
$$ forall a. Outputable a => a -> SDoc
ppr OutId
v)
| Bool
otherwise = OutId
v
lookupRecBndr :: SimplEnv -> InId -> OutId
lookupRecBndr :: SimplEnv -> OutId -> OutId
lookupRecBndr (SimplEnv { seInScope :: SimplEnv -> InScopeSet
seInScope = InScopeSet
in_scope, seIdSubst :: SimplEnv -> SimplIdSubst
seIdSubst = SimplIdSubst
ids }) OutId
v
= case forall a. VarEnv a -> OutId -> Maybe a
lookupVarEnv SimplIdSubst
ids OutId
v of
Just (DoneId OutId
v) -> OutId
v
Just SimplSR
_ -> forall a. HasCallStack => String -> SDoc -> a
pprPanic String
"lookupRecBndr" (forall a. Outputable a => a -> SDoc
ppr OutId
v)
Maybe SimplSR
Nothing -> InScopeSet -> OutId -> OutId
refineFromInScope InScopeSet
in_scope OutId
v
simplBinders :: SimplEnv -> [InBndr] -> SimplM (SimplEnv, [OutBndr])
simplBinders :: SimplEnv -> [OutId] -> SimplM (SimplEnv, [OutId])
simplBinders !SimplEnv
env [OutId]
bndrs = forall (m :: * -> *) (t :: * -> *) acc x y.
(Monad m, Traversable t) =>
(acc -> x -> m (acc, y)) -> acc -> t x -> m (acc, t y)
mapAccumLM SimplEnv -> OutId -> SimplM (SimplEnv, OutId)
simplBinder SimplEnv
env [OutId]
bndrs
simplBinder :: SimplEnv -> InBndr -> SimplM (SimplEnv, OutBndr)
simplBinder :: SimplEnv -> OutId -> SimplM (SimplEnv, OutId)
simplBinder !SimplEnv
env OutId
bndr
| OutId -> Bool
isTyVar OutId
bndr = do { let (SimplEnv
env', OutId
tv) = SimplEnv -> OutId -> (SimplEnv, OutId)
substTyVarBndr SimplEnv
env OutId
bndr
; OutId -> ()
seqTyVar OutId
tv seq :: forall a b. a -> b -> b
`seq` forall (m :: * -> *) a. Monad m => a -> m a
return (SimplEnv
env', OutId
tv) }
| Bool
otherwise = do { let (SimplEnv
env', OutId
id) = SimplEnv -> OutId -> (SimplEnv, OutId)
substIdBndr SimplEnv
env OutId
bndr
; OutId -> ()
seqId OutId
id seq :: forall a b. a -> b -> b
`seq` forall (m :: * -> *) a. Monad m => a -> m a
return (SimplEnv
env', OutId
id) }
simplNonRecBndr :: SimplEnv -> InBndr -> SimplM (SimplEnv, OutBndr)
simplNonRecBndr :: SimplEnv -> OutId -> SimplM (SimplEnv, OutId)
simplNonRecBndr !SimplEnv
env OutId
id
= do { let (!SimplEnv
env1, OutId
id1) = SimplEnv -> OutId -> (SimplEnv, OutId)
substIdBndr SimplEnv
env OutId
id
; OutId -> ()
seqId OutId
id1 seq :: forall a b. a -> b -> b
`seq` forall (m :: * -> *) a. Monad m => a -> m a
return (SimplEnv
env1, OutId
id1) }
simplRecBndrs :: SimplEnv -> [InBndr] -> SimplM SimplEnv
simplRecBndrs :: SimplEnv -> [OutId] -> SimplM SimplEnv
simplRecBndrs env :: SimplEnv
env@(SimplEnv {}) [OutId]
ids
= forall a. HasCallStack => Bool -> a -> a
assert (forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
all (Bool -> Bool
not forall b c a. (b -> c) -> (a -> b) -> a -> c
. OutId -> Bool
isJoinId) [OutId]
ids) forall a b. (a -> b) -> a -> b
$
do { let (!SimplEnv
env1, [OutId]
ids1) = forall (t :: * -> *) s a b.
Traversable t =>
(s -> a -> (s, b)) -> s -> t a -> (s, t b)
mapAccumL SimplEnv -> OutId -> (SimplEnv, OutId)
substIdBndr SimplEnv
env [OutId]
ids
; [OutId] -> ()
seqIds [OutId]
ids1 seq :: forall a b. a -> b -> b
`seq` forall (m :: * -> *) a. Monad m => a -> m a
return SimplEnv
env1 }
substIdBndr :: SimplEnv -> InBndr -> (SimplEnv, OutBndr)
substIdBndr :: SimplEnv -> OutId -> (SimplEnv, OutId)
substIdBndr SimplEnv
env OutId
bndr
| OutId -> Bool
isCoVar OutId
bndr = SimplEnv -> OutId -> (SimplEnv, OutId)
substCoVarBndr SimplEnv
env OutId
bndr
| Bool
otherwise = SimplEnv -> OutId -> (SimplEnv, OutId)
substNonCoVarIdBndr SimplEnv
env OutId
bndr
substNonCoVarIdBndr
:: SimplEnv
-> InBndr
-> (SimplEnv, OutBndr)
substNonCoVarIdBndr :: SimplEnv -> OutId -> (SimplEnv, OutId)
substNonCoVarIdBndr SimplEnv
env OutId
id = SimplEnv -> OutId -> (OutId -> OutId) -> (SimplEnv, OutId)
subst_id_bndr SimplEnv
env OutId
id (\OutId
x -> OutId
x)
{-# INLINE subst_id_bndr #-}
subst_id_bndr :: SimplEnv
-> InBndr
-> (OutId -> OutId)
-> (SimplEnv, OutBndr)
subst_id_bndr :: SimplEnv -> OutId -> (OutId -> OutId) -> (SimplEnv, OutId)
subst_id_bndr env :: SimplEnv
env@(SimplEnv { seInScope :: SimplEnv -> InScopeSet
seInScope = InScopeSet
in_scope, seIdSubst :: SimplEnv -> SimplIdSubst
seIdSubst = SimplIdSubst
id_subst })
OutId
old_id OutId -> OutId
adjust_type
= forall a. HasCallStack => Bool -> SDoc -> a -> a
assertPpr (Bool -> Bool
not (OutId -> Bool
isCoVar OutId
old_id)) (forall a. Outputable a => a -> SDoc
ppr OutId
old_id)
(SimplEnv
env { seInScope :: InScopeSet
seInScope = InScopeSet
new_in_scope,
seIdSubst :: SimplIdSubst
seIdSubst = SimplIdSubst
new_subst }, OutId
new_id)
where
!id1 :: OutId
id1 = InScopeSet -> OutId -> OutId
uniqAway InScopeSet
in_scope OutId
old_id
!id2 :: OutId
id2 = SimplEnv -> OutId -> OutId
substIdType SimplEnv
env OutId
id1
!id3 :: OutId
id3 = OutId -> OutId
zapFragileIdInfo OutId
id2
!new_id :: OutId
new_id = OutId -> OutId
adjust_type OutId
id3
!new_subst :: SimplIdSubst
new_subst | OutId
new_id forall a. Eq a => a -> a -> Bool
/= OutId
old_id
= forall a. VarEnv a -> OutId -> a -> VarEnv a
extendVarEnv SimplIdSubst
id_subst OutId
old_id (OutId -> SimplSR
DoneId OutId
new_id)
| Bool
otherwise
= forall a. VarEnv a -> OutId -> VarEnv a
delVarEnv SimplIdSubst
id_subst OutId
old_id
!new_in_scope :: InScopeSet
new_in_scope = InScopeSet
in_scope InScopeSet -> OutId -> InScopeSet
`extendInScopeSet` OutId
new_id
seqTyVar :: TyVar -> ()
seqTyVar :: OutId -> ()
seqTyVar OutId
b = OutId
b seq :: forall a b. a -> b -> b
`seq` ()
seqId :: Id -> ()
seqId :: OutId -> ()
seqId OutId
id = Kind -> ()
seqType (OutId -> Kind
idType OutId
id) seq :: forall a b. a -> b -> b
`seq`
HasDebugCallStack => OutId -> IdInfo
idInfo OutId
id seq :: forall a b. a -> b -> b
`seq`
()
seqIds :: [Id] -> ()
seqIds :: [OutId] -> ()
seqIds [] = ()
seqIds (OutId
id:[OutId]
ids) = OutId -> ()
seqId OutId
id seq :: forall a b. a -> b -> b
`seq` [OutId] -> ()
seqIds [OutId]
ids
simplNonRecJoinBndr :: SimplEnv -> InBndr
-> Mult -> OutType
-> SimplM (SimplEnv, OutBndr)
simplNonRecJoinBndr :: SimplEnv -> OutId -> Kind -> Kind -> SimplM (SimplEnv, OutId)
simplNonRecJoinBndr SimplEnv
env OutId
id Kind
mult Kind
res_ty
= do { let (SimplEnv
env1, OutId
id1) = Kind -> Kind -> SimplEnv -> OutId -> (SimplEnv, OutId)
simplJoinBndr Kind
mult Kind
res_ty SimplEnv
env OutId
id
; OutId -> ()
seqId OutId
id1 seq :: forall a b. a -> b -> b
`seq` forall (m :: * -> *) a. Monad m => a -> m a
return (SimplEnv
env1, OutId
id1) }
simplRecJoinBndrs :: SimplEnv -> [InBndr]
-> Mult -> OutType
-> SimplM SimplEnv
simplRecJoinBndrs :: SimplEnv -> [OutId] -> Kind -> Kind -> SimplM SimplEnv
simplRecJoinBndrs env :: SimplEnv
env@(SimplEnv {}) [OutId]
ids Kind
mult Kind
res_ty
= forall a. HasCallStack => Bool -> a -> a
assert (forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
all OutId -> Bool
isJoinId [OutId]
ids) forall a b. (a -> b) -> a -> b
$
do { let (SimplEnv
env1, [OutId]
ids1) = forall (t :: * -> *) s a b.
Traversable t =>
(s -> a -> (s, b)) -> s -> t a -> (s, t b)
mapAccumL (Kind -> Kind -> SimplEnv -> OutId -> (SimplEnv, OutId)
simplJoinBndr Kind
mult Kind
res_ty) SimplEnv
env [OutId]
ids
; [OutId] -> ()
seqIds [OutId]
ids1 seq :: forall a b. a -> b -> b
`seq` forall (m :: * -> *) a. Monad m => a -> m a
return SimplEnv
env1 }
simplJoinBndr :: Mult -> OutType
-> SimplEnv -> InBndr
-> (SimplEnv, OutBndr)
simplJoinBndr :: Kind -> Kind -> SimplEnv -> OutId -> (SimplEnv, OutId)
simplJoinBndr Kind
mult Kind
res_ty SimplEnv
env OutId
id
= SimplEnv -> OutId -> (OutId -> OutId) -> (SimplEnv, OutId)
subst_id_bndr SimplEnv
env OutId
id (Kind -> Kind -> OutId -> OutId
adjustJoinPointType Kind
mult Kind
res_ty)
adjustJoinPointType :: Mult
-> Type
-> Id
-> Id
adjustJoinPointType :: Kind -> Kind -> OutId -> OutId
adjustJoinPointType Kind
mult Kind
new_res_ty OutId
join_id
= forall a. HasCallStack => Bool -> a -> a
assert (OutId -> Bool
isJoinId OutId
join_id) forall a b. (a -> b) -> a -> b
$
OutId -> Kind -> OutId
setIdType OutId
join_id Kind
new_join_ty
where
orig_ar :: JoinArity
orig_ar = OutId -> JoinArity
idJoinArity OutId
join_id
orig_ty :: Kind
orig_ty = OutId -> Kind
idType OutId
join_id
new_join_ty :: Kind
new_join_ty = JoinArity -> Kind -> Kind
go JoinArity
orig_ar Kind
orig_ty :: Type
go :: JoinArity -> Kind -> Kind
go JoinArity
0 Kind
_ = Kind
new_res_ty
go JoinArity
n Kind
ty | Just (PiTyBinder
arg_bndr, Kind
res_ty) <- Kind -> Maybe (PiTyBinder, Kind)
splitPiTy_maybe Kind
ty
= PiTyBinder -> Kind -> Kind
mkPiTy (PiTyBinder -> PiTyBinder
scale_bndr PiTyBinder
arg_bndr) forall a b. (a -> b) -> a -> b
$
JoinArity -> Kind -> Kind
go (JoinArity
nforall a. Num a => a -> a -> a
-JoinArity
1) Kind
res_ty
| Bool
otherwise
= forall a. HasCallStack => String -> SDoc -> a
pprPanic String
"adjustJoinPointType" (forall a. Outputable a => a -> SDoc
ppr JoinArity
orig_ar forall doc. IsLine doc => doc -> doc -> doc
<+> forall a. Outputable a => a -> SDoc
ppr Kind
orig_ty)
scale_bndr :: PiTyBinder -> PiTyBinder
scale_bndr (Anon Scaled Kind
t FunTyFlag
af) = (Scaled Kind -> FunTyFlag -> PiTyBinder
Anon forall a b. (a -> b) -> a -> b
$! (forall a. Kind -> Scaled a -> Scaled a
scaleScaled Kind
mult Scaled Kind
t)) FunTyFlag
af
scale_bndr b :: PiTyBinder
b@(Named ForAllTyBinder
_) = PiTyBinder
b
getSubst :: SimplEnv -> Subst
getSubst :: SimplEnv -> Subst
getSubst (SimplEnv { seInScope :: SimplEnv -> InScopeSet
seInScope = InScopeSet
in_scope, seTvSubst :: SimplEnv -> TvSubstEnv
seTvSubst = TvSubstEnv
tv_env
, seCvSubst :: SimplEnv -> CvSubstEnv
seCvSubst = CvSubstEnv
cv_env })
= InScopeSet -> TvSubstEnv -> CvSubstEnv -> IdSubstEnv -> Subst
mkSubst InScopeSet
in_scope TvSubstEnv
tv_env CvSubstEnv
cv_env IdSubstEnv
emptyIdSubstEnv
substTy :: HasDebugCallStack => SimplEnv -> Type -> Type
substTy :: HasDebugCallStack => SimplEnv -> Kind -> Kind
substTy SimplEnv
env Kind
ty = HasDebugCallStack => Subst -> Kind -> Kind
Type.substTy (SimplEnv -> Subst
getSubst SimplEnv
env) Kind
ty
substTyVar :: SimplEnv -> TyVar -> Type
substTyVar :: SimplEnv -> OutId -> Kind
substTyVar SimplEnv
env OutId
tv = Subst -> OutId -> Kind
Type.substTyVar (SimplEnv -> Subst
getSubst SimplEnv
env) OutId
tv
substTyVarBndr :: SimplEnv -> TyVar -> (SimplEnv, TyVar)
substTyVarBndr :: SimplEnv -> OutId -> (SimplEnv, OutId)
substTyVarBndr SimplEnv
env OutId
tv
= case HasDebugCallStack => Subst -> OutId -> (Subst, OutId)
Type.substTyVarBndr (SimplEnv -> Subst
getSubst SimplEnv
env) OutId
tv of
(Subst InScopeSet
in_scope' IdSubstEnv
_ TvSubstEnv
tv_env' CvSubstEnv
cv_env', OutId
tv')
-> (SimplEnv
env { seInScope :: InScopeSet
seInScope = InScopeSet
in_scope', seTvSubst :: TvSubstEnv
seTvSubst = TvSubstEnv
tv_env', seCvSubst :: CvSubstEnv
seCvSubst = CvSubstEnv
cv_env' }, OutId
tv')
substCoVar :: SimplEnv -> CoVar -> Coercion
substCoVar :: SimplEnv -> OutId -> Coercion
substCoVar SimplEnv
env OutId
tv = Subst -> OutId -> Coercion
Coercion.substCoVar (SimplEnv -> Subst
getSubst SimplEnv
env) OutId
tv
substCoVarBndr :: SimplEnv -> CoVar -> (SimplEnv, CoVar)
substCoVarBndr :: SimplEnv -> OutId -> (SimplEnv, OutId)
substCoVarBndr SimplEnv
env OutId
cv
= case HasDebugCallStack => Subst -> OutId -> (Subst, OutId)
Coercion.substCoVarBndr (SimplEnv -> Subst
getSubst SimplEnv
env) OutId
cv of
(Subst InScopeSet
in_scope' IdSubstEnv
_ TvSubstEnv
tv_env' CvSubstEnv
cv_env', OutId
cv')
-> (SimplEnv
env { seInScope :: InScopeSet
seInScope = InScopeSet
in_scope', seTvSubst :: TvSubstEnv
seTvSubst = TvSubstEnv
tv_env', seCvSubst :: CvSubstEnv
seCvSubst = CvSubstEnv
cv_env' }, OutId
cv')
substCo :: SimplEnv -> Coercion -> Coercion
substCo :: SimplEnv -> Coercion -> Coercion
substCo SimplEnv
env Coercion
co = HasDebugCallStack => Subst -> Coercion -> Coercion
Coercion.substCo (SimplEnv -> Subst
getSubst SimplEnv
env) Coercion
co
substIdType :: SimplEnv -> Id -> Id
substIdType :: SimplEnv -> OutId -> OutId
substIdType (SimplEnv { seInScope :: SimplEnv -> InScopeSet
seInScope = InScopeSet
in_scope, seTvSubst :: SimplEnv -> TvSubstEnv
seTvSubst = TvSubstEnv
tv_env, seCvSubst :: SimplEnv -> CvSubstEnv
seCvSubst = CvSubstEnv
cv_env }) OutId
id
| (forall a. VarEnv a -> Bool
isEmptyVarEnv TvSubstEnv
tv_env Bool -> Bool -> Bool
&& forall a. VarEnv a -> Bool
isEmptyVarEnv CvSubstEnv
cv_env)
Bool -> Bool -> Bool
|| Bool
no_free_vars
= OutId
id
| Bool
otherwise = (Kind -> Kind) -> OutId -> OutId
Id.updateIdTypeAndMult (Subst -> Kind -> Kind
Type.substTyUnchecked Subst
subst) OutId
id
where
no_free_vars :: Bool
no_free_vars = Kind -> Bool
noFreeVarsOfType Kind
old_ty Bool -> Bool -> Bool
&& Kind -> Bool
noFreeVarsOfType Kind
old_w
subst :: Subst
subst = InScopeSet -> IdSubstEnv -> TvSubstEnv -> CvSubstEnv -> Subst
Subst InScopeSet
in_scope IdSubstEnv
emptyIdSubstEnv TvSubstEnv
tv_env CvSubstEnv
cv_env
old_ty :: Kind
old_ty = OutId -> Kind
idType OutId
id
old_w :: Kind
old_w = OutId -> Kind
varMult OutId
id